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()->must_use_ignition_turbo()) {
    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 
    146   // Check the whitelist for Crankshaft.
    147   if (!info()->shared_info()->PassesFilter(FLAG_hydrogen_filter)) {
    148     return AbortOptimization(kHydrogenFilter);
    149   }
    150 
    151   Scope* scope = info()->scope();
    152   if (LUnallocated::TooManyParameters(scope->num_parameters())) {
    153     // Crankshaft would require too many Lithium operands.
    154     return AbortOptimization(kTooManyParameters);
    155   }
    156 
    157   if (info()->is_osr() &&
    158       LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
    159                                                   scope->num_stack_slots())) {
    160     // Crankshaft would require too many Lithium operands.
    161     return AbortOptimization(kTooManyParametersLocals);
    162   }
    163 
    164   if (IsGeneratorFunction(info()->shared_info()->kind())) {
    165     // Crankshaft does not support generators.
    166     return AbortOptimization(kGenerator);
    167   }
    168 
    169   if (FLAG_trace_hydrogen) {
    170     isolate()->GetHTracer()->TraceCompilation(info());
    171   }
    172 
    173   // Optimization could have been disabled by the parser. Note that this check
    174   // is only needed because the Hydrogen graph builder is missing some bailouts.
    175   if (info()->shared_info()->optimization_disabled()) {
    176     return AbortOptimization(
    177         info()->shared_info()->disable_optimization_reason());
    178   }
    179 
    180   HOptimizedGraphBuilder* graph_builder =
    181       (FLAG_hydrogen_track_positions || isolate()->is_profiling() ||
    182        FLAG_trace_ic)
    183           ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
    184           : new (info()->zone()) HOptimizedGraphBuilder(info(), false);
    185 
    186   // Type-check the function.
    187   AstTyper(info()->isolate(), info()->zone(), info()->closure(),
    188            info()->scope(), info()->osr_ast_id(), info()->literal(),
    189            graph_builder->bounds())
    190       .Run();
    191 
    192   graph_ = graph_builder->CreateGraph();
    193 
    194   if (isolate()->has_pending_exception()) {
    195     return FAILED;
    196   }
    197 
    198   if (graph_ == NULL) return FAILED;
    199 
    200   if (info()->dependencies()->HasAborted()) {
    201     // Dependency has changed during graph creation. Let's try again later.
    202     return RetryOptimization(kBailedOutDueToDependencyChange);
    203   }
    204 
    205   return SUCCEEDED;
    206 }
    207 
    208 HCompilationJob::Status HCompilationJob::ExecuteJobImpl() {
    209   DCHECK(graph_ != NULL);
    210   BailoutReason bailout_reason = kNoReason;
    211 
    212   if (graph_->Optimize(&bailout_reason)) {
    213     chunk_ = LChunk::NewChunk(graph_);
    214     if (chunk_ != NULL) return SUCCEEDED;
    215   } else if (bailout_reason != kNoReason) {
    216     info()->AbortOptimization(bailout_reason);
    217   }
    218 
    219   return FAILED;
    220 }
    221 
    222 HCompilationJob::Status HCompilationJob::FinalizeJobImpl() {
    223   DCHECK(chunk_ != NULL);
    224   DCHECK(graph_ != NULL);
    225   {
    226     // Deferred handles reference objects that were accessible during
    227     // graph creation.  To make sure that we don't encounter inconsistencies
    228     // between graph creation and code generation, we disallow accessing
    229     // objects through deferred handles during the latter, with exceptions.
    230     DisallowDeferredHandleDereference no_deferred_handle_deref;
    231     Handle<Code> optimized_code = chunk_->Codegen();
    232     if (optimized_code.is_null()) {
    233       if (info()->bailout_reason() == kNoReason) {
    234         return AbortOptimization(kCodeGenerationFailed);
    235       }
    236       return FAILED;
    237     }
    238     RegisterWeakObjectsInOptimizedCode(optimized_code);
    239     info()->SetCode(optimized_code);
    240   }
    241   // Add to the weak list of optimized code objects.
    242   info()->context()->native_context()->AddOptimizedCode(*info()->code());
    243   return SUCCEEDED;
    244 }
    245 
    246 HBasicBlock::HBasicBlock(HGraph* graph)
    247     : block_id_(graph->GetNextBlockID()),
    248       graph_(graph),
    249       phis_(4, graph->zone()),
    250       first_(NULL),
    251       last_(NULL),
    252       end_(NULL),
    253       loop_information_(NULL),
    254       predecessors_(2, graph->zone()),
    255       dominator_(NULL),
    256       dominated_blocks_(4, graph->zone()),
    257       last_environment_(NULL),
    258       argument_count_(-1),
    259       first_instruction_index_(-1),
    260       last_instruction_index_(-1),
    261       deleted_phis_(4, graph->zone()),
    262       parent_loop_header_(NULL),
    263       inlined_entry_block_(NULL),
    264       is_inline_return_target_(false),
    265       is_reachable_(true),
    266       dominates_loop_successors_(false),
    267       is_osr_entry_(false),
    268       is_ordered_(false) { }
    269 
    270 
    271 Isolate* HBasicBlock::isolate() const {
    272   return graph_->isolate();
    273 }
    274 
    275 
    276 void HBasicBlock::MarkUnreachable() {
    277   is_reachable_ = false;
    278 }
    279 
    280 
    281 void HBasicBlock::AttachLoopInformation() {
    282   DCHECK(!IsLoopHeader());
    283   loop_information_ = new(zone()) HLoopInformation(this, zone());
    284 }
    285 
    286 
    287 void HBasicBlock::DetachLoopInformation() {
    288   DCHECK(IsLoopHeader());
    289   loop_information_ = NULL;
    290 }
    291 
    292 
    293 void HBasicBlock::AddPhi(HPhi* phi) {
    294   DCHECK(!IsStartBlock());
    295   phis_.Add(phi, zone());
    296   phi->SetBlock(this);
    297 }
    298 
    299 
    300 void HBasicBlock::RemovePhi(HPhi* phi) {
    301   DCHECK(phi->block() == this);
    302   DCHECK(phis_.Contains(phi));
    303   phi->Kill();
    304   phis_.RemoveElement(phi);
    305   phi->SetBlock(NULL);
    306 }
    307 
    308 
    309 void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
    310   DCHECK(!IsStartBlock() || !IsFinished());
    311   DCHECK(!instr->IsLinked());
    312   DCHECK(!IsFinished());
    313 
    314   if (position.IsKnown()) {
    315     instr->set_position(position);
    316   }
    317   if (first_ == NULL) {
    318     DCHECK(last_environment() != NULL);
    319     DCHECK(!last_environment()->ast_id().IsNone());
    320     HBlockEntry* entry = new(zone()) HBlockEntry();
    321     entry->InitializeAsFirst(this);
    322     if (position.IsKnown()) {
    323       entry->set_position(position);
    324     } else {
    325       DCHECK(!FLAG_hydrogen_track_positions ||
    326              !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
    327     }
    328     first_ = last_ = entry;
    329   }
    330   instr->InsertAfter(last_);
    331 }
    332 
    333 
    334 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
    335   if (graph()->IsInsideNoSideEffectsScope()) {
    336     merged_index = HPhi::kInvalidMergedIndex;
    337   }
    338   HPhi* phi = new(zone()) HPhi(merged_index, zone());
    339   AddPhi(phi);
    340   return phi;
    341 }
    342 
    343 
    344 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
    345                                        RemovableSimulate removable) {
    346   DCHECK(HasEnvironment());
    347   HEnvironment* environment = last_environment();
    348   DCHECK(ast_id.IsNone() ||
    349          ast_id == BailoutId::StubEntry() ||
    350          environment->closure()->shared()->VerifyBailoutId(ast_id));
    351 
    352   int push_count = environment->push_count();
    353   int pop_count = environment->pop_count();
    354 
    355   HSimulate* instr =
    356       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
    357 #ifdef DEBUG
    358   instr->set_closure(environment->closure());
    359 #endif
    360   // Order of pushed values: newest (top of stack) first. This allows
    361   // HSimulate::MergeWith() to easily append additional pushed values
    362   // that are older (from further down the stack).
    363   for (int i = 0; i < push_count; ++i) {
    364     instr->AddPushedValue(environment->ExpressionStackAt(i));
    365   }
    366   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
    367                                       zone());
    368        !it.Done();
    369        it.Advance()) {
    370     int index = it.Current();
    371     instr->AddAssignedValue(index, environment->Lookup(index));
    372   }
    373   environment->ClearHistory();
    374   return instr;
    375 }
    376 
    377 
    378 void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
    379   DCHECK(!IsFinished());
    380   AddInstruction(end, position);
    381   end_ = end;
    382   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    383     it.Current()->RegisterPredecessor(this);
    384   }
    385 }
    386 
    387 
    388 void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
    389                        FunctionState* state, bool add_simulate) {
    390   bool drop_extra = state != NULL &&
    391       state->inlining_kind() == NORMAL_RETURN;
    392 
    393   if (block->IsInlineReturnTarget()) {
    394     HEnvironment* env = last_environment();
    395     int argument_count = env->arguments_environment()->parameter_count();
    396     AddInstruction(new(zone())
    397                    HLeaveInlined(state->entry(), argument_count),
    398                    position);
    399     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    400   }
    401 
    402   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
    403   HGoto* instr = new(zone()) HGoto(block);
    404   Finish(instr, position);
    405 }
    406 
    407 
    408 void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
    409                                   SourcePosition position) {
    410   HBasicBlock* target = state->function_return();
    411   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
    412 
    413   DCHECK(target->IsInlineReturnTarget());
    414   DCHECK(return_value != NULL);
    415   HEnvironment* env = last_environment();
    416   int argument_count = env->arguments_environment()->parameter_count();
    417   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
    418                  position);
    419   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    420   last_environment()->Push(return_value);
    421   AddNewSimulate(BailoutId::None(), position);
    422   HGoto* instr = new(zone()) HGoto(target);
    423   Finish(instr, position);
    424 }
    425 
    426 
    427 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
    428   DCHECK(!HasEnvironment());
    429   DCHECK(first() == NULL);
    430   UpdateEnvironment(env);
    431 }
    432 
    433 
    434 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
    435   last_environment_ = env;
    436   graph()->update_maximum_environment_size(env->first_expression_index());
    437 }
    438 
    439 
    440 void HBasicBlock::SetJoinId(BailoutId ast_id) {
    441   int length = predecessors_.length();
    442   DCHECK(length > 0);
    443   for (int i = 0; i < length; i++) {
    444     HBasicBlock* predecessor = predecessors_[i];
    445     DCHECK(predecessor->end()->IsGoto());
    446     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
    447     DCHECK(i != 0 ||
    448            (predecessor->last_environment()->closure().is_null() ||
    449             predecessor->last_environment()->closure()->shared()
    450               ->VerifyBailoutId(ast_id)));
    451     simulate->set_ast_id(ast_id);
    452     predecessor->last_environment()->set_ast_id(ast_id);
    453   }
    454 }
    455 
    456 
    457 bool HBasicBlock::Dominates(HBasicBlock* other) const {
    458   HBasicBlock* current = other->dominator();
    459   while (current != NULL) {
    460     if (current == this) return true;
    461     current = current->dominator();
    462   }
    463   return false;
    464 }
    465 
    466 
    467 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
    468   if (this == other) return true;
    469   return Dominates(other);
    470 }
    471 
    472 
    473 int HBasicBlock::LoopNestingDepth() const {
    474   const HBasicBlock* current = this;
    475   int result  = (current->IsLoopHeader()) ? 1 : 0;
    476   while (current->parent_loop_header() != NULL) {
    477     current = current->parent_loop_header();
    478     result++;
    479   }
    480   return result;
    481 }
    482 
    483 
    484 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
    485   DCHECK(IsLoopHeader());
    486 
    487   SetJoinId(stmt->EntryId());
    488   if (predecessors()->length() == 1) {
    489     // This is a degenerated loop.
    490     DetachLoopInformation();
    491     return;
    492   }
    493 
    494   // Only the first entry into the loop is from outside the loop. All other
    495   // entries must be back edges.
    496   for (int i = 1; i < predecessors()->length(); ++i) {
    497     loop_information()->RegisterBackEdge(predecessors()->at(i));
    498   }
    499 }
    500 
    501 
    502 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
    503   DCHECK(IsFinished());
    504   HBasicBlock* succ_block = end()->SuccessorAt(succ);
    505 
    506   DCHECK(succ_block->predecessors()->length() == 1);
    507   succ_block->MarkUnreachable();
    508 }
    509 
    510 
    511 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
    512   if (HasPredecessor()) {
    513     // Only loop header blocks can have a predecessor added after
    514     // instructions have been added to the block (they have phis for all
    515     // values in the environment, these phis may be eliminated later).
    516     DCHECK(IsLoopHeader() || first_ == NULL);
    517     HEnvironment* incoming_env = pred->last_environment();
    518     if (IsLoopHeader()) {
    519       DCHECK_EQ(phis()->length(), incoming_env->length());
    520       for (int i = 0; i < phis_.length(); ++i) {
    521         phis_[i]->AddInput(incoming_env->values()->at(i));
    522       }
    523     } else {
    524       last_environment()->AddIncomingEdge(this, pred->last_environment());
    525     }
    526   } else if (!HasEnvironment() && !IsFinished()) {
    527     DCHECK(!IsLoopHeader());
    528     SetInitialEnvironment(pred->last_environment()->Copy());
    529   }
    530 
    531   predecessors_.Add(pred, zone());
    532 }
    533 
    534 
    535 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
    536   DCHECK(!dominated_blocks_.Contains(block));
    537   // Keep the list of dominated blocks sorted such that if there is two
    538   // succeeding block in this list, the predecessor is before the successor.
    539   int index = 0;
    540   while (index < dominated_blocks_.length() &&
    541          dominated_blocks_[index]->block_id() < block->block_id()) {
    542     ++index;
    543   }
    544   dominated_blocks_.InsertAt(index, block, zone());
    545 }
    546 
    547 
    548 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
    549   if (dominator_ == NULL) {
    550     dominator_ = other;
    551     other->AddDominatedBlock(this);
    552   } else if (other->dominator() != NULL) {
    553     HBasicBlock* first = dominator_;
    554     HBasicBlock* second = other;
    555 
    556     while (first != second) {
    557       if (first->block_id() > second->block_id()) {
    558         first = first->dominator();
    559       } else {
    560         second = second->dominator();
    561       }
    562       DCHECK(first != NULL && second != NULL);
    563     }
    564 
    565     if (dominator_ != first) {
    566       DCHECK(dominator_->dominated_blocks_.Contains(this));
    567       dominator_->dominated_blocks_.RemoveElement(this);
    568       dominator_ = first;
    569       first->AddDominatedBlock(this);
    570     }
    571   }
    572 }
    573 
    574 
    575 void HBasicBlock::AssignLoopSuccessorDominators() {
    576   // Mark blocks that dominate all subsequent reachable blocks inside their
    577   // loop. Exploit the fact that blocks are sorted in reverse post order. When
    578   // the loop is visited in increasing block id order, if the number of
    579   // non-loop-exiting successor edges at the dominator_candidate block doesn't
    580   // exceed the number of previously encountered predecessor edges, there is no
    581   // path from the loop header to any block with higher id that doesn't go
    582   // through the dominator_candidate block. In this case, the
    583   // dominator_candidate block is guaranteed to dominate all blocks reachable
    584   // from it with higher ids.
    585   HBasicBlock* last = loop_information()->GetLastBackEdge();
    586   int outstanding_successors = 1;  // one edge from the pre-header
    587   // Header always dominates everything.
    588   MarkAsLoopSuccessorDominator();
    589   for (int j = block_id(); j <= last->block_id(); ++j) {
    590     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
    591     for (HPredecessorIterator it(dominator_candidate); !it.Done();
    592          it.Advance()) {
    593       HBasicBlock* predecessor = it.Current();
    594       // Don't count back edges.
    595       if (predecessor->block_id() < dominator_candidate->block_id()) {
    596         outstanding_successors--;
    597       }
    598     }
    599 
    600     // If more successors than predecessors have been seen in the loop up to
    601     // now, it's not possible to guarantee that the current block dominates
    602     // all of the blocks with higher IDs. In this case, assume conservatively
    603     // that those paths through loop that don't go through the current block
    604     // contain all of the loop's dependencies. Also be careful to record
    605     // dominator information about the current loop that's being processed,
    606     // and not nested loops, which will be processed when
    607     // AssignLoopSuccessorDominators gets called on their header.
    608     DCHECK(outstanding_successors >= 0);
    609     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
    610     if (outstanding_successors == 0 &&
    611         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
    612       dominator_candidate->MarkAsLoopSuccessorDominator();
    613     }
    614     HControlInstruction* end = dominator_candidate->end();
    615     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    616       HBasicBlock* successor = it.Current();
    617       // Only count successors that remain inside the loop and don't loop back
    618       // to a loop header.
    619       if (successor->block_id() > dominator_candidate->block_id() &&
    620           successor->block_id() <= last->block_id()) {
    621         // Backwards edges must land on loop headers.
    622         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
    623                successor->IsLoopHeader());
    624         outstanding_successors++;
    625       }
    626     }
    627   }
    628 }
    629 
    630 
    631 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
    632   for (int i = 0; i < predecessors_.length(); ++i) {
    633     if (predecessors_[i] == predecessor) return i;
    634   }
    635   UNREACHABLE();
    636   return -1;
    637 }
    638 
    639 
    640 #ifdef DEBUG
    641 void HBasicBlock::Verify() {
    642   // Check that every block is finished.
    643   DCHECK(IsFinished());
    644   DCHECK(block_id() >= 0);
    645 
    646   // Check that the incoming edges are in edge split form.
    647   if (predecessors_.length() > 1) {
    648     for (int i = 0; i < predecessors_.length(); ++i) {
    649       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
    650     }
    651   }
    652 }
    653 #endif
    654 
    655 
    656 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
    657   this->back_edges_.Add(block, block->zone());
    658   AddBlock(block);
    659 }
    660 
    661 
    662 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
    663   int max_id = -1;
    664   HBasicBlock* result = NULL;
    665   for (int i = 0; i < back_edges_.length(); ++i) {
    666     HBasicBlock* cur = back_edges_[i];
    667     if (cur->block_id() > max_id) {
    668       max_id = cur->block_id();
    669       result = cur;
    670     }
    671   }
    672   return result;
    673 }
    674 
    675 
    676 void HLoopInformation::AddBlock(HBasicBlock* block) {
    677   if (block == loop_header()) return;
    678   if (block->parent_loop_header() == loop_header()) return;
    679   if (block->parent_loop_header() != NULL) {
    680     AddBlock(block->parent_loop_header());
    681   } else {
    682     block->set_parent_loop_header(loop_header());
    683     blocks_.Add(block, block->zone());
    684     for (int i = 0; i < block->predecessors()->length(); ++i) {
    685       AddBlock(block->predecessors()->at(i));
    686     }
    687   }
    688 }
    689 
    690 
    691 #ifdef DEBUG
    692 
    693 // Checks reachability of the blocks in this graph and stores a bit in
    694 // the BitVector "reachable()" for every block that can be reached
    695 // from the start block of the graph. If "dont_visit" is non-null, the given
    696 // block is treated as if it would not be part of the graph. "visited_count()"
    697 // returns the number of reachable blocks.
    698 class ReachabilityAnalyzer BASE_EMBEDDED {
    699  public:
    700   ReachabilityAnalyzer(HBasicBlock* entry_block,
    701                        int block_count,
    702                        HBasicBlock* dont_visit)
    703       : visited_count_(0),
    704         stack_(16, entry_block->zone()),
    705         reachable_(block_count, entry_block->zone()),
    706         dont_visit_(dont_visit) {
    707     PushBlock(entry_block);
    708     Analyze();
    709   }
    710 
    711   int visited_count() const { return visited_count_; }
    712   const BitVector* reachable() const { return &reachable_; }
    713 
    714  private:
    715   void PushBlock(HBasicBlock* block) {
    716     if (block != NULL && block != dont_visit_ &&
    717         !reachable_.Contains(block->block_id())) {
    718       reachable_.Add(block->block_id());
    719       stack_.Add(block, block->zone());
    720       visited_count_++;
    721     }
    722   }
    723 
    724   void Analyze() {
    725     while (!stack_.is_empty()) {
    726       HControlInstruction* end = stack_.RemoveLast()->end();
    727       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    728         PushBlock(it.Current());
    729       }
    730     }
    731   }
    732 
    733   int visited_count_;
    734   ZoneList<HBasicBlock*> stack_;
    735   BitVector reachable_;
    736   HBasicBlock* dont_visit_;
    737 };
    738 
    739 
    740 void HGraph::Verify(bool do_full_verify) const {
    741   Heap::RelocationLock relocation_lock(isolate()->heap());
    742   AllowHandleDereference allow_deref;
    743   AllowDeferredHandleDereference allow_deferred_deref;
    744   for (int i = 0; i < blocks_.length(); i++) {
    745     HBasicBlock* block = blocks_.at(i);
    746 
    747     block->Verify();
    748 
    749     // Check that every block contains at least one node and that only the last
    750     // node is a control instruction.
    751     HInstruction* current = block->first();
    752     DCHECK(current != NULL && current->IsBlockEntry());
    753     while (current != NULL) {
    754       DCHECK((current->next() == NULL) == current->IsControlInstruction());
    755       DCHECK(current->block() == block);
    756       current->Verify();
    757       current = current->next();
    758     }
    759 
    760     // Check that successors are correctly set.
    761     HBasicBlock* first = block->end()->FirstSuccessor();
    762     HBasicBlock* second = block->end()->SecondSuccessor();
    763     DCHECK(second == NULL || first != NULL);
    764 
    765     // Check that the predecessor array is correct.
    766     if (first != NULL) {
    767       DCHECK(first->predecessors()->Contains(block));
    768       if (second != NULL) {
    769         DCHECK(second->predecessors()->Contains(block));
    770       }
    771     }
    772 
    773     // Check that phis have correct arguments.
    774     for (int j = 0; j < block->phis()->length(); j++) {
    775       HPhi* phi = block->phis()->at(j);
    776       phi->Verify();
    777     }
    778 
    779     // Check that all join blocks have predecessors that end with an
    780     // unconditional goto and agree on their environment node id.
    781     if (block->predecessors()->length() >= 2) {
    782       BailoutId id =
    783           block->predecessors()->first()->last_environment()->ast_id();
    784       for (int k = 0; k < block->predecessors()->length(); k++) {
    785         HBasicBlock* predecessor = block->predecessors()->at(k);
    786         DCHECK(predecessor->end()->IsGoto() ||
    787                predecessor->end()->IsDeoptimize());
    788         DCHECK(predecessor->last_environment()->ast_id() == id);
    789       }
    790     }
    791   }
    792 
    793   // Check special property of first block to have no predecessors.
    794   DCHECK(blocks_.at(0)->predecessors()->is_empty());
    795 
    796   if (do_full_verify) {
    797     // Check that the graph is fully connected.
    798     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
    799     DCHECK(analyzer.visited_count() == blocks_.length());
    800 
    801     // Check that entry block dominator is NULL.
    802     DCHECK(entry_block_->dominator() == NULL);
    803 
    804     // Check dominators.
    805     for (int i = 0; i < blocks_.length(); ++i) {
    806       HBasicBlock* block = blocks_.at(i);
    807       if (block->dominator() == NULL) {
    808         // Only start block may have no dominator assigned to.
    809         DCHECK(i == 0);
    810       } else {
    811         // Assert that block is unreachable if dominator must not be visited.
    812         ReachabilityAnalyzer dominator_analyzer(entry_block_,
    813                                                 blocks_.length(),
    814                                                 block->dominator());
    815         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
    816       }
    817     }
    818   }
    819 }
    820 
    821 #endif
    822 
    823 
    824 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
    825                                int32_t value) {
    826   if (!pointer->is_set()) {
    827     // Can't pass GetInvalidContext() to HConstant::New, because that will
    828     // recursively call GetConstant
    829     HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
    830     constant->InsertAfter(entry_block()->first());
    831     pointer->set(constant);
    832     return constant;
    833   }
    834   return ReinsertConstantIfNecessary(pointer->get());
    835 }
    836 
    837 
    838 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
    839   if (!constant->IsLinked()) {
    840     // The constant was removed from the graph. Reinsert.
    841     constant->ClearFlag(HValue::kIsDead);
    842     constant->InsertAfter(entry_block()->first());
    843   }
    844   return constant;
    845 }
    846 
    847 
    848 HConstant* HGraph::GetConstant0() {
    849   return GetConstant(&constant_0_, 0);
    850 }
    851 
    852 
    853 HConstant* HGraph::GetConstant1() {
    854   return GetConstant(&constant_1_, 1);
    855 }
    856 
    857 
    858 HConstant* HGraph::GetConstantMinus1() {
    859   return GetConstant(&constant_minus1_, -1);
    860 }
    861 
    862 
    863 HConstant* HGraph::GetConstantBool(bool value) {
    864   return value ? GetConstantTrue() : GetConstantFalse();
    865 }
    866 
    867 #define DEFINE_GET_CONSTANT(Name, name, constant, type, htype, boolean_value, \
    868                             undetectable)                                     \
    869   HConstant* HGraph::GetConstant##Name() {                                    \
    870     if (!constant_##name##_.is_set()) {                                       \
    871       HConstant* constant = new (zone()) HConstant(                           \
    872           Unique<Object>::CreateImmovable(isolate()->factory()->constant()),  \
    873           Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),   \
    874           false, Representation::Tagged(), htype, true, boolean_value,        \
    875           undetectable, ODDBALL_TYPE);                                        \
    876       constant->InsertAfter(entry_block()->first());                          \
    877       constant_##name##_.set(constant);                                       \
    878     }                                                                         \
    879     return ReinsertConstantIfNecessary(constant_##name##_.get());             \
    880   }
    881 
    882 DEFINE_GET_CONSTANT(Undefined, undefined, undefined_value, undefined,
    883                     HType::Undefined(), false, true)
    884 DEFINE_GET_CONSTANT(True, true, true_value, boolean, HType::Boolean(), true,
    885                     false)
    886 DEFINE_GET_CONSTANT(False, false, false_value, boolean, HType::Boolean(), false,
    887                     false)
    888 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole_value, the_hole, HType::None(),
    889                     false, false)
    890 DEFINE_GET_CONSTANT(Null, null, null_value, null, HType::Null(), false, true)
    891 DEFINE_GET_CONSTANT(OptimizedOut, optimized_out, optimized_out, optimized_out,
    892                     HType::None(), false, false)
    893 
    894 #undef DEFINE_GET_CONSTANT
    895 
    896 #define DEFINE_IS_CONSTANT(Name, name)                                         \
    897 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
    898   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
    899 }
    900 DEFINE_IS_CONSTANT(Undefined, undefined)
    901 DEFINE_IS_CONSTANT(0, 0)
    902 DEFINE_IS_CONSTANT(1, 1)
    903 DEFINE_IS_CONSTANT(Minus1, minus1)
    904 DEFINE_IS_CONSTANT(True, true)
    905 DEFINE_IS_CONSTANT(False, false)
    906 DEFINE_IS_CONSTANT(Hole, the_hole)
    907 DEFINE_IS_CONSTANT(Null, null)
    908 
    909 #undef DEFINE_IS_CONSTANT
    910 
    911 
    912 HConstant* HGraph::GetInvalidContext() {
    913   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
    914 }
    915 
    916 
    917 bool HGraph::IsStandardConstant(HConstant* constant) {
    918   if (IsConstantUndefined(constant)) return true;
    919   if (IsConstant0(constant)) return true;
    920   if (IsConstant1(constant)) return true;
    921   if (IsConstantMinus1(constant)) return true;
    922   if (IsConstantTrue(constant)) return true;
    923   if (IsConstantFalse(constant)) return true;
    924   if (IsConstantHole(constant)) return true;
    925   if (IsConstantNull(constant)) return true;
    926   return false;
    927 }
    928 
    929 
    930 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
    931 
    932 
    933 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
    934     : needs_compare_(true) {
    935   Initialize(builder);
    936 }
    937 
    938 
    939 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
    940                                     HIfContinuation* continuation)
    941     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
    942   InitializeDontCreateBlocks(builder);
    943   continuation->Continue(&first_true_block_, &first_false_block_);
    944 }
    945 
    946 
    947 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
    948     HGraphBuilder* builder) {
    949   builder_ = builder;
    950   finished_ = false;
    951   did_then_ = false;
    952   did_else_ = false;
    953   did_else_if_ = false;
    954   did_and_ = false;
    955   did_or_ = false;
    956   captured_ = false;
    957   pending_merge_block_ = false;
    958   split_edge_merge_block_ = NULL;
    959   merge_at_join_blocks_ = NULL;
    960   normal_merge_at_join_block_count_ = 0;
    961   deopt_merge_at_join_block_count_ = 0;
    962 }
    963 
    964 
    965 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
    966   InitializeDontCreateBlocks(builder);
    967   HEnvironment* env = builder->environment();
    968   first_true_block_ = builder->CreateBasicBlock(env->Copy());
    969   first_false_block_ = builder->CreateBasicBlock(env->Copy());
    970 }
    971 
    972 
    973 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
    974     HControlInstruction* compare) {
    975   DCHECK(did_then_ == did_else_);
    976   if (did_else_) {
    977     // Handle if-then-elseif
    978     did_else_if_ = true;
    979     did_else_ = false;
    980     did_then_ = false;
    981     did_and_ = false;
    982     did_or_ = false;
    983     pending_merge_block_ = false;
    984     split_edge_merge_block_ = NULL;
    985     HEnvironment* env = builder()->environment();
    986     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    987     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
    988   }
    989   if (split_edge_merge_block_ != NULL) {
    990     HEnvironment* env = first_false_block_->last_environment();
    991     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
    992     if (did_or_) {
    993       compare->SetSuccessorAt(0, split_edge);
    994       compare->SetSuccessorAt(1, first_false_block_);
    995     } else {
    996       compare->SetSuccessorAt(0, first_true_block_);
    997       compare->SetSuccessorAt(1, split_edge);
    998     }
    999     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
   1000   } else {
   1001     compare->SetSuccessorAt(0, first_true_block_);
   1002     compare->SetSuccessorAt(1, first_false_block_);
   1003   }
   1004   builder()->FinishCurrentBlock(compare);
   1005   needs_compare_ = false;
   1006   return compare;
   1007 }
   1008 
   1009 
   1010 void HGraphBuilder::IfBuilder::Or() {
   1011   DCHECK(!needs_compare_);
   1012   DCHECK(!did_and_);
   1013   did_or_ = true;
   1014   HEnvironment* env = first_false_block_->last_environment();
   1015   if (split_edge_merge_block_ == NULL) {
   1016     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
   1017     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
   1018     first_true_block_ = split_edge_merge_block_;
   1019   }
   1020   builder()->set_current_block(first_false_block_);
   1021   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
   1022 }
   1023 
   1024 
   1025 void HGraphBuilder::IfBuilder::And() {
   1026   DCHECK(!needs_compare_);
   1027   DCHECK(!did_or_);
   1028   did_and_ = true;
   1029   HEnvironment* env = first_false_block_->last_environment();
   1030   if (split_edge_merge_block_ == NULL) {
   1031     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
   1032     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
   1033     first_false_block_ = split_edge_merge_block_;
   1034   }
   1035   builder()->set_current_block(first_true_block_);
   1036   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
   1037 }
   1038 
   1039 
   1040 void HGraphBuilder::IfBuilder::CaptureContinuation(
   1041     HIfContinuation* continuation) {
   1042   DCHECK(!did_else_if_);
   1043   DCHECK(!finished_);
   1044   DCHECK(!captured_);
   1045 
   1046   HBasicBlock* true_block = NULL;
   1047   HBasicBlock* false_block = NULL;
   1048   Finish(&true_block, &false_block);
   1049   DCHECK(true_block != NULL);
   1050   DCHECK(false_block != NULL);
   1051   continuation->Capture(true_block, false_block);
   1052   captured_ = true;
   1053   builder()->set_current_block(NULL);
   1054   End();
   1055 }
   1056 
   1057 
   1058 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
   1059   DCHECK(!did_else_if_);
   1060   DCHECK(!finished_);
   1061   DCHECK(!captured_);
   1062   HBasicBlock* true_block = NULL;
   1063   HBasicBlock* false_block = NULL;
   1064   Finish(&true_block, &false_block);
   1065   merge_at_join_blocks_ = NULL;
   1066   if (true_block != NULL && !true_block->IsFinished()) {
   1067     DCHECK(continuation->IsTrueReachable());
   1068     builder()->GotoNoSimulate(true_block, continuation->true_branch());
   1069   }
   1070   if (false_block != NULL && !false_block->IsFinished()) {
   1071     DCHECK(continuation->IsFalseReachable());
   1072     builder()->GotoNoSimulate(false_block, continuation->false_branch());
   1073   }
   1074   captured_ = true;
   1075   End();
   1076 }
   1077 
   1078 
   1079 void HGraphBuilder::IfBuilder::Then() {
   1080   DCHECK(!captured_);
   1081   DCHECK(!finished_);
   1082   did_then_ = true;
   1083   if (needs_compare_) {
   1084     // Handle if's without any expressions, they jump directly to the "else"
   1085     // branch. However, we must pretend that the "then" branch is reachable,
   1086     // so that the graph builder visits it and sees any live range extending
   1087     // constructs within it.
   1088     HConstant* constant_false = builder()->graph()->GetConstantFalse();
   1089     ToBooleanHints boolean_type = ToBooleanHint::kBoolean;
   1090     HBranch* branch = builder()->New<HBranch>(
   1091         constant_false, boolean_type, first_true_block_, first_false_block_);
   1092     builder()->FinishCurrentBlock(branch);
   1093   }
   1094   builder()->set_current_block(first_true_block_);
   1095   pending_merge_block_ = true;
   1096 }
   1097 
   1098 
   1099 void HGraphBuilder::IfBuilder::Else() {
   1100   DCHECK(did_then_);
   1101   DCHECK(!captured_);
   1102   DCHECK(!finished_);
   1103   AddMergeAtJoinBlock(false);
   1104   builder()->set_current_block(first_false_block_);
   1105   pending_merge_block_ = true;
   1106   did_else_ = true;
   1107 }
   1108 
   1109 void HGraphBuilder::IfBuilder::Deopt(DeoptimizeReason reason) {
   1110   DCHECK(did_then_);
   1111   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
   1112   AddMergeAtJoinBlock(true);
   1113 }
   1114 
   1115 
   1116 void HGraphBuilder::IfBuilder::Return(HValue* value) {
   1117   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
   1118   builder()->FinishExitCurrentBlock(
   1119       builder()->New<HReturn>(value, parameter_count));
   1120   AddMergeAtJoinBlock(false);
   1121 }
   1122 
   1123 
   1124 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
   1125   if (!pending_merge_block_) return;
   1126   HBasicBlock* block = builder()->current_block();
   1127   DCHECK(block == NULL || !block->IsFinished());
   1128   MergeAtJoinBlock* record = new (builder()->zone())
   1129       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
   1130   merge_at_join_blocks_ = record;
   1131   if (block != NULL) {
   1132     DCHECK(block->end() == NULL);
   1133     if (deopt) {
   1134       normal_merge_at_join_block_count_++;
   1135     } else {
   1136       deopt_merge_at_join_block_count_++;
   1137     }
   1138   }
   1139   builder()->set_current_block(NULL);
   1140   pending_merge_block_ = false;
   1141 }
   1142 
   1143 
   1144 void HGraphBuilder::IfBuilder::Finish() {
   1145   DCHECK(!finished_);
   1146   if (!did_then_) {
   1147     Then();
   1148   }
   1149   AddMergeAtJoinBlock(false);
   1150   if (!did_else_) {
   1151     Else();
   1152     AddMergeAtJoinBlock(false);
   1153   }
   1154   finished_ = true;
   1155 }
   1156 
   1157 
   1158 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
   1159                                       HBasicBlock** else_continuation) {
   1160   Finish();
   1161 
   1162   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
   1163   if (else_continuation != NULL) {
   1164     *else_continuation = else_record->block_;
   1165   }
   1166   MergeAtJoinBlock* then_record = else_record->next_;
   1167   if (then_continuation != NULL) {
   1168     *then_continuation = then_record->block_;
   1169   }
   1170   DCHECK(then_record->next_ == NULL);
   1171 }
   1172 
   1173 
   1174 void HGraphBuilder::IfBuilder::EndUnreachable() {
   1175   if (captured_) return;
   1176   Finish();
   1177   builder()->set_current_block(nullptr);
   1178 }
   1179 
   1180 
   1181 void HGraphBuilder::IfBuilder::End() {
   1182   if (captured_) return;
   1183   Finish();
   1184 
   1185   int total_merged_blocks = normal_merge_at_join_block_count_ +
   1186     deopt_merge_at_join_block_count_;
   1187   DCHECK(total_merged_blocks >= 1);
   1188   HBasicBlock* merge_block =
   1189       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
   1190 
   1191   // Merge non-deopt blocks first to ensure environment has right size for
   1192   // padding.
   1193   MergeAtJoinBlock* current = merge_at_join_blocks_;
   1194   while (current != NULL) {
   1195     if (!current->deopt_ && current->block_ != NULL) {
   1196       // If there is only one block that makes it through to the end of the
   1197       // if, then just set it as the current block and continue rather then
   1198       // creating an unnecessary merge block.
   1199       if (total_merged_blocks == 1) {
   1200         builder()->set_current_block(current->block_);
   1201         return;
   1202       }
   1203       builder()->GotoNoSimulate(current->block_, merge_block);
   1204     }
   1205     current = current->next_;
   1206   }
   1207 
   1208   // Merge deopt blocks, padding when necessary.
   1209   current = merge_at_join_blocks_;
   1210   while (current != NULL) {
   1211     if (current->deopt_ && current->block_ != NULL) {
   1212       current->block_->FinishExit(
   1213           HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
   1214           SourcePosition::Unknown());
   1215     }
   1216     current = current->next_;
   1217   }
   1218   builder()->set_current_block(merge_block);
   1219 }
   1220 
   1221 
   1222 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
   1223   Initialize(builder, NULL, kWhileTrue, NULL);
   1224 }
   1225 
   1226 
   1227 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1228                                         LoopBuilder::Direction direction) {
   1229   Initialize(builder, context, direction, builder->graph()->GetConstant1());
   1230 }
   1231 
   1232 
   1233 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1234                                         LoopBuilder::Direction direction,
   1235                                         HValue* increment_amount) {
   1236   Initialize(builder, context, direction, increment_amount);
   1237   increment_amount_ = increment_amount;
   1238 }
   1239 
   1240 
   1241 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
   1242                                             HValue* context,
   1243                                             Direction direction,
   1244                                             HValue* increment_amount) {
   1245   builder_ = builder;
   1246   context_ = context;
   1247   direction_ = direction;
   1248   increment_amount_ = increment_amount;
   1249 
   1250   finished_ = false;
   1251   header_block_ = builder->CreateLoopHeaderBlock();
   1252   body_block_ = NULL;
   1253   exit_block_ = NULL;
   1254   exit_trampoline_block_ = NULL;
   1255 }
   1256 
   1257 
   1258 HValue* HGraphBuilder::LoopBuilder::BeginBody(
   1259     HValue* initial,
   1260     HValue* terminating,
   1261     Token::Value token) {
   1262   DCHECK(direction_ != kWhileTrue);
   1263   HEnvironment* env = builder_->environment();
   1264   phi_ = header_block_->AddNewPhi(env->values()->length());
   1265   phi_->AddInput(initial);
   1266   env->Push(initial);
   1267   builder_->GotoNoSimulate(header_block_);
   1268 
   1269   HEnvironment* body_env = env->Copy();
   1270   HEnvironment* exit_env = env->Copy();
   1271   // Remove the phi from the expression stack
   1272   body_env->Pop();
   1273   exit_env->Pop();
   1274   body_block_ = builder_->CreateBasicBlock(body_env);
   1275   exit_block_ = builder_->CreateBasicBlock(exit_env);
   1276 
   1277   builder_->set_current_block(header_block_);
   1278   env->Pop();
   1279   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
   1280           phi_, terminating, token, body_block_, exit_block_));
   1281 
   1282   builder_->set_current_block(body_block_);
   1283   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
   1284     Isolate* isolate = builder_->isolate();
   1285     HValue* one = builder_->graph()->GetConstant1();
   1286     if (direction_ == kPreIncrement) {
   1287       increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
   1288     } else {
   1289       increment_ = HSub::New(isolate, zone(), context_, phi_, one);
   1290     }
   1291     increment_->ClearFlag(HValue::kCanOverflow);
   1292     builder_->AddInstruction(increment_);
   1293     return increment_;
   1294   } else {
   1295     return phi_;
   1296   }
   1297 }
   1298 
   1299 
   1300 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
   1301   DCHECK(direction_ == kWhileTrue);
   1302   HEnvironment* env = builder_->environment();
   1303   builder_->GotoNoSimulate(header_block_);
   1304   builder_->set_current_block(header_block_);
   1305   env->Drop(drop_count);
   1306 }
   1307 
   1308 
   1309 void HGraphBuilder::LoopBuilder::Break() {
   1310   if (exit_trampoline_block_ == NULL) {
   1311     // Its the first time we saw a break.
   1312     if (direction_ == kWhileTrue) {
   1313       HEnvironment* env = builder_->environment()->Copy();
   1314       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1315     } else {
   1316       HEnvironment* env = exit_block_->last_environment()->Copy();
   1317       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1318       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
   1319     }
   1320   }
   1321 
   1322   builder_->GotoNoSimulate(exit_trampoline_block_);
   1323   builder_->set_current_block(NULL);
   1324 }
   1325 
   1326 
   1327 void HGraphBuilder::LoopBuilder::EndBody() {
   1328   DCHECK(!finished_);
   1329 
   1330   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
   1331     Isolate* isolate = builder_->isolate();
   1332     if (direction_ == kPostIncrement) {
   1333       increment_ =
   1334           HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
   1335     } else {
   1336       increment_ =
   1337           HSub::New(isolate, zone(), context_, phi_, increment_amount_);
   1338     }
   1339     increment_->ClearFlag(HValue::kCanOverflow);
   1340     builder_->AddInstruction(increment_);
   1341   }
   1342 
   1343   if (direction_ != kWhileTrue) {
   1344     // Push the new increment value on the expression stack to merge into
   1345     // the phi.
   1346     builder_->environment()->Push(increment_);
   1347   }
   1348   HBasicBlock* last_block = builder_->current_block();
   1349   builder_->GotoNoSimulate(last_block, header_block_);
   1350   header_block_->loop_information()->RegisterBackEdge(last_block);
   1351 
   1352   if (exit_trampoline_block_ != NULL) {
   1353     builder_->set_current_block(exit_trampoline_block_);
   1354   } else {
   1355     builder_->set_current_block(exit_block_);
   1356   }
   1357   finished_ = true;
   1358 }
   1359 
   1360 
   1361 HGraph* HGraphBuilder::CreateGraph() {
   1362   DCHECK(!FLAG_minimal);
   1363   graph_ = new (zone()) HGraph(info_, descriptor_);
   1364   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
   1365   CompilationPhase phase("H_Block building", info_);
   1366   set_current_block(graph()->entry_block());
   1367   if (!BuildGraph()) return NULL;
   1368   graph()->FinalizeUniqueness();
   1369   return graph_;
   1370 }
   1371 
   1372 
   1373 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
   1374   DCHECK(current_block() != NULL);
   1375   DCHECK(!FLAG_hydrogen_track_positions || position_.IsKnown() ||
   1376          !info_->IsOptimizing());
   1377   current_block()->AddInstruction(instr, source_position());
   1378   if (graph()->IsInsideNoSideEffectsScope()) {
   1379     instr->SetFlag(HValue::kHasNoObservableSideEffects);
   1380   }
   1381   return instr;
   1382 }
   1383 
   1384 
   1385 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
   1386   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
   1387          position_.IsKnown());
   1388   current_block()->Finish(last, source_position());
   1389   if (last->IsReturn() || last->IsAbnormalExit()) {
   1390     set_current_block(NULL);
   1391   }
   1392 }
   1393 
   1394 
   1395 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
   1396   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
   1397          position_.IsKnown());
   1398   current_block()->FinishExit(instruction, source_position());
   1399   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
   1400     set_current_block(NULL);
   1401   }
   1402 }
   1403 
   1404 
   1405 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
   1406   if (FLAG_native_code_counters && counter->Enabled()) {
   1407     HValue* reference = Add<HConstant>(ExternalReference(counter));
   1408     HValue* old_value =
   1409         Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
   1410     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
   1411     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
   1412     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
   1413                           new_value, STORE_TO_INITIALIZED_ENTRY);
   1414   }
   1415 }
   1416 
   1417 
   1418 void HGraphBuilder::AddSimulate(BailoutId id,
   1419                                 RemovableSimulate removable) {
   1420   DCHECK(current_block() != NULL);
   1421   DCHECK(!graph()->IsInsideNoSideEffectsScope());
   1422   current_block()->AddNewSimulate(id, source_position(), removable);
   1423 }
   1424 
   1425 
   1426 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   1427   HBasicBlock* b = graph()->CreateBasicBlock();
   1428   b->SetInitialEnvironment(env);
   1429   return b;
   1430 }
   1431 
   1432 
   1433 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
   1434   HBasicBlock* header = graph()->CreateBasicBlock();
   1435   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
   1436   header->SetInitialEnvironment(entry_env);
   1437   header->AttachLoopInformation();
   1438   return header;
   1439 }
   1440 
   1441 
   1442 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
   1443   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
   1444 
   1445   HValue* bit_field2 =
   1446       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
   1447   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
   1448 }
   1449 
   1450 
   1451 HValue* HGraphBuilder::BuildEnumLength(HValue* map) {
   1452   NoObservableSideEffectsScope scope(this);
   1453   HValue* bit_field3 =
   1454       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
   1455   return BuildDecodeField<Map::EnumLengthBits>(bit_field3);
   1456 }
   1457 
   1458 
   1459 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
   1460   if (obj->type().IsHeapObject()) return obj;
   1461   return Add<HCheckHeapObject>(obj);
   1462 }
   1463 
   1464 void HGraphBuilder::FinishExitWithHardDeoptimization(DeoptimizeReason reason) {
   1465   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
   1466   FinishExitCurrentBlock(New<HAbnormalExit>());
   1467 }
   1468 
   1469 
   1470 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
   1471   if (!string->type().IsString()) {
   1472     DCHECK(!string->IsConstant() ||
   1473            !HConstant::cast(string)->HasStringValue());
   1474     BuildCheckHeapObject(string);
   1475     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
   1476   }
   1477   return string;
   1478 }
   1479 
   1480 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* checked) {
   1481   if (object->type().IsJSObject()) return object;
   1482   HValue* function = checked->ActualValue();
   1483   if (function->IsConstant() &&
   1484       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   1485     Handle<JSFunction> f = Handle<JSFunction>::cast(
   1486         HConstant::cast(function)->handle(isolate()));
   1487     SharedFunctionInfo* shared = f->shared();
   1488     if (is_strict(shared->language_mode()) || shared->native()) return object;
   1489   }
   1490   return Add<HWrapReceiver>(object, checked);
   1491 }
   1492 
   1493 
   1494 HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(
   1495     HValue* object, HValue* elements, ElementsKind kind, HValue* length,
   1496     HValue* capacity, HValue* key) {
   1497   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
   1498   HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
   1499   Add<HBoundsCheck>(key, max_capacity);
   1500 
   1501   HValue* new_capacity = BuildNewElementsCapacity(key);
   1502   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, kind,
   1503                                                    length, new_capacity);
   1504   return new_elements;
   1505 }
   1506 
   1507 
   1508 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
   1509     HValue* object,
   1510     HValue* elements,
   1511     ElementsKind kind,
   1512     HValue* length,
   1513     HValue* key,
   1514     bool is_js_array,
   1515     PropertyAccessType access_type) {
   1516   IfBuilder length_checker(this);
   1517 
   1518   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
   1519   length_checker.If<HCompareNumericAndBranch>(key, length, token);
   1520 
   1521   length_checker.Then();
   1522 
   1523   HValue* current_capacity = AddLoadFixedArrayLength(elements);
   1524 
   1525   if (top_info()->IsStub()) {
   1526     IfBuilder capacity_checker(this);
   1527     capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
   1528                                                   Token::GTE);
   1529     capacity_checker.Then();
   1530     HValue* new_elements = BuildCheckAndGrowElementsCapacity(
   1531         object, elements, kind, length, current_capacity, key);
   1532     environment()->Push(new_elements);
   1533     capacity_checker.Else();
   1534     environment()->Push(elements);
   1535     capacity_checker.End();
   1536   } else {
   1537     HValue* result = Add<HMaybeGrowElements>(
   1538         object, elements, key, current_capacity, is_js_array, kind);
   1539     environment()->Push(result);
   1540   }
   1541 
   1542   if (is_js_array) {
   1543     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
   1544     new_length->ClearFlag(HValue::kCanOverflow);
   1545 
   1546     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
   1547                           new_length);
   1548   }
   1549 
   1550   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
   1551     HValue* checked_elements = environment()->Top();
   1552 
   1553     // Write zero to ensure that the new element is initialized with some smi.
   1554     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), nullptr,
   1555                      kind);
   1556   }
   1557 
   1558   length_checker.Else();
   1559   Add<HBoundsCheck>(key, length);
   1560 
   1561   environment()->Push(elements);
   1562   length_checker.End();
   1563 
   1564   return environment()->Pop();
   1565 }
   1566 
   1567 
   1568 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
   1569                                                 HValue* elements,
   1570                                                 ElementsKind kind,
   1571                                                 HValue* length) {
   1572   Factory* factory = isolate()->factory();
   1573 
   1574   IfBuilder cow_checker(this);
   1575 
   1576   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
   1577   cow_checker.Then();
   1578 
   1579   HValue* capacity = AddLoadFixedArrayLength(elements);
   1580 
   1581   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
   1582                                                    kind, length, capacity);
   1583 
   1584   environment()->Push(new_elements);
   1585 
   1586   cow_checker.Else();
   1587 
   1588   environment()->Push(elements);
   1589 
   1590   cow_checker.End();
   1591 
   1592   return environment()->Pop();
   1593 }
   1594 
   1595 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
   1596   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
   1597   HValue* seed = Add<HConstant>(seed_value);
   1598   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
   1599 
   1600   // hash = ~hash + (hash << 15);
   1601   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
   1602   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
   1603                                            graph()->GetConstantMinus1());
   1604   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
   1605 
   1606   // hash = hash ^ (hash >> 12);
   1607   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
   1608   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1609 
   1610   // hash = hash + (hash << 2);
   1611   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
   1612   hash = AddUncasted<HAdd>(hash, shifted_hash);
   1613 
   1614   // hash = hash ^ (hash >> 4);
   1615   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
   1616   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1617 
   1618   // hash = hash * 2057;
   1619   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
   1620   hash->ClearFlag(HValue::kCanOverflow);
   1621 
   1622   // hash = hash ^ (hash >> 16);
   1623   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
   1624   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1625 }
   1626 
   1627 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
   1628                                                            HValue* elements,
   1629                                                            HValue* key,
   1630                                                            HValue* hash) {
   1631   HValue* capacity =
   1632       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
   1633                       nullptr, nullptr, FAST_ELEMENTS);
   1634 
   1635   HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
   1636   mask->ChangeRepresentation(Representation::Integer32());
   1637   mask->ClearFlag(HValue::kCanOverflow);
   1638 
   1639   HValue* entry = hash;
   1640   HValue* count = graph()->GetConstant1();
   1641   Push(entry);
   1642   Push(count);
   1643 
   1644   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
   1645                                               graph()->CreateBasicBlock());
   1646   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
   1647                                                graph()->CreateBasicBlock());
   1648   LoopBuilder probe_loop(this);
   1649   probe_loop.BeginBody(2);  // Drop entry, count from last environment to
   1650                             // appease live range building without simulates.
   1651 
   1652   count = Pop();
   1653   entry = Pop();
   1654   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
   1655   int entry_size = SeededNumberDictionary::kEntrySize;
   1656   HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
   1657   base_index->ClearFlag(HValue::kCanOverflow);
   1658   int start_offset = SeededNumberDictionary::kElementsStartIndex;
   1659   HValue* key_index =
   1660       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
   1661   key_index->ClearFlag(HValue::kCanOverflow);
   1662 
   1663   HValue* candidate_key =
   1664       Add<HLoadKeyed>(elements, key_index, nullptr, nullptr, FAST_ELEMENTS);
   1665   IfBuilder if_undefined(this);
   1666   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
   1667                                              graph()->GetConstantUndefined());
   1668   if_undefined.Then();
   1669   {
   1670     // element == undefined means "not found". Call the runtime.
   1671     // TODO(jkummerow): walk the prototype chain instead.
   1672     Add<HPushArguments>(receiver, key);
   1673     Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
   1674                            2));
   1675   }
   1676   if_undefined.Else();
   1677   {
   1678     IfBuilder if_match(this);
   1679     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
   1680     if_match.Then();
   1681     if_match.Else();
   1682 
   1683     // Update non-internalized string in the dictionary with internalized key?
   1684     IfBuilder if_update_with_internalized(this);
   1685     HValue* smi_check =
   1686         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
   1687     if_update_with_internalized.And();
   1688     HValue* map = AddLoadMap(candidate_key, smi_check);
   1689     HValue* instance_type =
   1690         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   1691     HValue* not_internalized_bit = AddUncasted<HBitwise>(
   1692         Token::BIT_AND, instance_type,
   1693         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
   1694     if_update_with_internalized.If<HCompareNumericAndBranch>(
   1695         not_internalized_bit, graph()->GetConstant0(), Token::NE);
   1696     if_update_with_internalized.And();
   1697     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
   1698         candidate_key, graph()->GetConstantHole());
   1699     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
   1700                                                                key, Token::EQ);
   1701     if_update_with_internalized.Then();
   1702     // Replace a key that is a non-internalized string by the equivalent
   1703     // internalized string for faster further lookups.
   1704     Add<HStoreKeyed>(elements, key_index, key, nullptr, FAST_ELEMENTS);
   1705     if_update_with_internalized.Else();
   1706 
   1707     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
   1708     if_match.JoinContinuation(&found_key_match_continuation);
   1709 
   1710     IfBuilder found_key_match(this, &found_key_match_continuation);
   1711     found_key_match.Then();
   1712     // Key at current probe matches. Relevant bits in the |details| field must
   1713     // be zero, otherwise the dictionary element requires special handling.
   1714     HValue* details_index =
   1715         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
   1716     details_index->ClearFlag(HValue::kCanOverflow);
   1717     HValue* details = Add<HLoadKeyed>(elements, details_index, nullptr, nullptr,
   1718                                       FAST_ELEMENTS);
   1719     int details_mask = PropertyDetails::KindField::kMask;
   1720     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
   1721                                     Add<HConstant>(details_mask));
   1722     IfBuilder details_compare(this);
   1723     details_compare.If<HCompareNumericAndBranch>(details, New<HConstant>(kData),
   1724                                                  Token::EQ);
   1725     details_compare.Then();
   1726     HValue* result_index =
   1727         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
   1728     result_index->ClearFlag(HValue::kCanOverflow);
   1729     Push(Add<HLoadKeyed>(elements, result_index, nullptr, nullptr,
   1730                          FAST_ELEMENTS));
   1731     details_compare.Else();
   1732     Add<HPushArguments>(receiver, key);
   1733     Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
   1734                            2));
   1735     details_compare.End();
   1736 
   1737     found_key_match.Else();
   1738     found_key_match.JoinContinuation(&return_or_loop_continuation);
   1739   }
   1740   if_undefined.JoinContinuation(&return_or_loop_continuation);
   1741 
   1742   IfBuilder return_or_loop(this, &return_or_loop_continuation);
   1743   return_or_loop.Then();
   1744   probe_loop.Break();
   1745 
   1746   return_or_loop.Else();
   1747   entry = AddUncasted<HAdd>(entry, count);
   1748   entry->ClearFlag(HValue::kCanOverflow);
   1749   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
   1750   count->ClearFlag(HValue::kCanOverflow);
   1751   Push(entry);
   1752   Push(count);
   1753 
   1754   probe_loop.EndBody();
   1755 
   1756   return_or_loop.End();
   1757 
   1758   return Pop();
   1759 }
   1760 
   1761 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value,
   1762                                                    HValue* done) {
   1763   NoObservableSideEffectsScope scope(this);
   1764 
   1765   // Allocate the JSIteratorResult object.
   1766   HValue* result =
   1767       Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
   1768                      NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0());
   1769 
   1770   // Initialize the JSIteratorResult object.
   1771   HValue* native_context = BuildGetNativeContext();
   1772   HValue* map = Add<HLoadNamedField>(
   1773       native_context, nullptr,
   1774       HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
   1775   Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
   1776   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   1777   Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
   1778                         empty_fixed_array);
   1779   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
   1780                         empty_fixed_array);
   1781   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
   1782                                     JSIteratorResult::kValueOffset),
   1783                         value);
   1784   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
   1785                                     JSIteratorResult::kDoneOffset),
   1786                         done);
   1787   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
   1788   return result;
   1789 }
   1790 
   1791 
   1792 HValue* HGraphBuilder::BuildNumberToString(HValue* object, AstType* type) {
   1793   NoObservableSideEffectsScope scope(this);
   1794 
   1795   // Convert constant numbers at compile time.
   1796   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
   1797     Handle<Object> number = HConstant::cast(object)->handle(isolate());
   1798     Handle<String> result = isolate()->factory()->NumberToString(number);
   1799     return Add<HConstant>(result);
   1800   }
   1801 
   1802   // Create a joinable continuation.
   1803   HIfContinuation found(graph()->CreateBasicBlock(),
   1804                         graph()->CreateBasicBlock());
   1805 
   1806   // Load the number string cache.
   1807   HValue* number_string_cache =
   1808       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
   1809 
   1810   // Make the hash mask from the length of the number string cache. It
   1811   // contains two elements (number and string) for each cache entry.
   1812   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
   1813   mask->set_type(HType::Smi());
   1814   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
   1815   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
   1816 
   1817   // Check whether object is a smi.
   1818   IfBuilder if_objectissmi(this);
   1819   if_objectissmi.If<HIsSmiAndBranch>(object);
   1820   if_objectissmi.Then();
   1821   {
   1822     // Compute hash for smi similar to smi_get_hash().
   1823     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
   1824 
   1825     // Load the key.
   1826     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1827     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
   1828                                   nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1829 
   1830     // Check if object == key.
   1831     IfBuilder if_objectiskey(this);
   1832     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
   1833     if_objectiskey.Then();
   1834     {
   1835       // Make the key_index available.
   1836       Push(key_index);
   1837     }
   1838     if_objectiskey.JoinContinuation(&found);
   1839   }
   1840   if_objectissmi.Else();
   1841   {
   1842     if (type->Is(AstType::SignedSmall())) {
   1843       if_objectissmi.Deopt(DeoptimizeReason::kExpectedSmi);
   1844     } else {
   1845       // Check if the object is a heap number.
   1846       IfBuilder if_objectisnumber(this);
   1847       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
   1848           object, isolate()->factory()->heap_number_map());
   1849       if_objectisnumber.Then();
   1850       {
   1851         // Compute hash for heap number similar to double_get_hash().
   1852         HValue* low = Add<HLoadNamedField>(
   1853             object, objectisnumber,
   1854             HObjectAccess::ForHeapNumberValueLowestBits());
   1855         HValue* high = Add<HLoadNamedField>(
   1856             object, objectisnumber,
   1857             HObjectAccess::ForHeapNumberValueHighestBits());
   1858         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
   1859         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
   1860 
   1861         // Load the key.
   1862         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1863         HValue* key =
   1864             Add<HLoadKeyed>(number_string_cache, key_index, nullptr, nullptr,
   1865                             FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1866 
   1867         // Check if the key is a heap number and compare it with the object.
   1868         IfBuilder if_keyisnotsmi(this);
   1869         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
   1870         if_keyisnotsmi.Then();
   1871         {
   1872           IfBuilder if_keyisheapnumber(this);
   1873           if_keyisheapnumber.If<HCompareMap>(
   1874               key, isolate()->factory()->heap_number_map());
   1875           if_keyisheapnumber.Then();
   1876           {
   1877             // Check if values of key and object match.
   1878             IfBuilder if_keyeqobject(this);
   1879             if_keyeqobject.If<HCompareNumericAndBranch>(
   1880                 Add<HLoadNamedField>(key, keyisnotsmi,
   1881                                      HObjectAccess::ForHeapNumberValue()),
   1882                 Add<HLoadNamedField>(object, objectisnumber,
   1883                                      HObjectAccess::ForHeapNumberValue()),
   1884                 Token::EQ);
   1885             if_keyeqobject.Then();
   1886             {
   1887               // Make the key_index available.
   1888               Push(key_index);
   1889             }
   1890             if_keyeqobject.JoinContinuation(&found);
   1891           }
   1892           if_keyisheapnumber.JoinContinuation(&found);
   1893         }
   1894         if_keyisnotsmi.JoinContinuation(&found);
   1895       }
   1896       if_objectisnumber.Else();
   1897       {
   1898         if (type->Is(AstType::Number())) {
   1899           if_objectisnumber.Deopt(DeoptimizeReason::kExpectedHeapNumber);
   1900         }
   1901       }
   1902       if_objectisnumber.JoinContinuation(&found);
   1903     }
   1904   }
   1905   if_objectissmi.JoinContinuation(&found);
   1906 
   1907   // Check for cache hit.
   1908   IfBuilder if_found(this, &found);
   1909   if_found.Then();
   1910   {
   1911     // Count number to string operation in native code.
   1912     AddIncrementCounter(isolate()->counters()->number_to_string_native());
   1913 
   1914     // Load the value in case of cache hit.
   1915     HValue* key_index = Pop();
   1916     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
   1917     Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr, nullptr,
   1918                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
   1919   }
   1920   if_found.Else();
   1921   {
   1922     // Cache miss, fallback to runtime.
   1923     Add<HPushArguments>(object);
   1924     Push(Add<HCallRuntime>(
   1925             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
   1926             1));
   1927   }
   1928   if_found.End();
   1929 
   1930   return Pop();
   1931 }
   1932 
   1933 HValue* HGraphBuilder::BuildToNumber(HValue* input) {
   1934   if (input->type().IsTaggedNumber() ||
   1935       input->representation().IsSpecialization()) {
   1936     return input;
   1937   }
   1938   Callable callable = CodeFactory::ToNumber(isolate());
   1939   HValue* stub = Add<HConstant>(callable.code());
   1940   HValue* values[] = {input};
   1941   HCallWithDescriptor* instr = Add<HCallWithDescriptor>(
   1942       stub, 0, callable.descriptor(), ArrayVector(values));
   1943   instr->set_type(HType::TaggedNumber());
   1944   return instr;
   1945 }
   1946 
   1947 
   1948 HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
   1949   NoObservableSideEffectsScope scope(this);
   1950 
   1951   // Create a joinable continuation.
   1952   HIfContinuation wrap(graph()->CreateBasicBlock(),
   1953                        graph()->CreateBasicBlock());
   1954 
   1955   // Determine the proper global constructor function required to wrap
   1956   // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
   1957   // which case we just return it.  Deopts to Runtime::kToObject if {receiver}
   1958   // is undefined or null.
   1959   IfBuilder receiver_is_smi(this);
   1960   receiver_is_smi.If<HIsSmiAndBranch>(receiver);
   1961   receiver_is_smi.Then();
   1962   {
   1963     // Use global Number function.
   1964     Push(Add<HConstant>(Context::NUMBER_FUNCTION_INDEX));
   1965   }
   1966   receiver_is_smi.Else();
   1967   {
   1968     // Determine {receiver} map and instance type.
   1969     HValue* receiver_map =
   1970         Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
   1971     HValue* receiver_instance_type = Add<HLoadNamedField>(
   1972         receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
   1973 
   1974     // First check whether {receiver} is already a spec object (fast case).
   1975     IfBuilder receiver_is_not_spec_object(this);
   1976     receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
   1977         receiver_instance_type, Add<HConstant>(FIRST_JS_RECEIVER_TYPE),
   1978         Token::LT);
   1979     receiver_is_not_spec_object.Then();
   1980     {
   1981       // Load the constructor function index from the {receiver} map.
   1982       HValue* constructor_function_index = Add<HLoadNamedField>(
   1983           receiver_map, nullptr,
   1984           HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());
   1985 
   1986       // Check if {receiver} has a constructor (null and undefined have no
   1987       // constructors, so we deoptimize to the runtime to throw an exception).
   1988       IfBuilder constructor_function_index_is_invalid(this);
   1989       constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
   1990           constructor_function_index,
   1991           Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
   1992       constructor_function_index_is_invalid.ThenDeopt(
   1993           DeoptimizeReason::kUndefinedOrNullInToObject);
   1994       constructor_function_index_is_invalid.End();
   1995 
   1996       // Use the global constructor function.
   1997       Push(constructor_function_index);
   1998     }
   1999     receiver_is_not_spec_object.JoinContinuation(&wrap);
   2000   }
   2001   receiver_is_smi.JoinContinuation(&wrap);
   2002 
   2003   // Wrap the receiver if necessary.
   2004   IfBuilder if_wrap(this, &wrap);
   2005   if_wrap.Then();
   2006   {
   2007     // Grab the constructor function index.
   2008     HValue* constructor_index = Pop();
   2009 
   2010     // Load native context.
   2011     HValue* native_context = BuildGetNativeContext();
   2012 
   2013     // Determine the initial map for the global constructor.
   2014     HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
   2015                                           nullptr, nullptr, FAST_ELEMENTS);
   2016     HValue* constructor_initial_map = Add<HLoadNamedField>(
   2017         constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
   2018     // Allocate and initialize a JSValue wrapper.
   2019     HValue* value =
   2020         BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
   2021                       JS_VALUE_TYPE, HAllocationMode());
   2022     Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
   2023                           constructor_initial_map);
   2024     HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   2025     Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
   2026                           empty_fixed_array);
   2027     Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
   2028                           empty_fixed_array);
   2029     Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
   2030                                      JSValue::kValueOffset),
   2031                           receiver);
   2032     Push(value);
   2033   }
   2034   if_wrap.Else();
   2035   { Push(receiver); }
   2036   if_wrap.End();
   2037   return Pop();
   2038 }
   2039 
   2040 
   2041 HAllocate* HGraphBuilder::BuildAllocate(
   2042     HValue* object_size,
   2043     HType type,
   2044     InstanceType instance_type,
   2045     HAllocationMode allocation_mode) {
   2046   // Compute the effective allocation size.
   2047   HValue* size = object_size;
   2048   if (allocation_mode.CreateAllocationMementos()) {
   2049     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
   2050     size->ClearFlag(HValue::kCanOverflow);
   2051   }
   2052 
   2053   // Perform the actual allocation.
   2054   HAllocate* object = Add<HAllocate>(
   2055       size, type, allocation_mode.GetPretenureMode(), instance_type,
   2056       graph()->GetConstant0(), allocation_mode.feedback_site());
   2057 
   2058   // Setup the allocation memento.
   2059   if (allocation_mode.CreateAllocationMementos()) {
   2060     BuildCreateAllocationMemento(
   2061         object, object_size, allocation_mode.current_site());
   2062   }
   2063 
   2064   return object;
   2065 }
   2066 
   2067 
   2068 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
   2069                                              HValue* right_length) {
   2070   // Compute the combined string length and check against max string length.
   2071   HValue* length = AddUncasted<HAdd>(left_length, right_length);
   2072   // Check that length <= kMaxLength <=> length < MaxLength + 1.
   2073   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
   2074   if (top_info()->IsStub() || !isolate()->IsStringLengthOverflowIntact()) {
   2075     // This is a mitigation for crbug.com/627934; the real fix
   2076     // will be to migrate the StringAddStub to TurboFan one day.
   2077     IfBuilder if_invalid(this);
   2078     if_invalid.If<HCompareNumericAndBranch>(length, max_length, Token::GT);
   2079     if_invalid.Then();
   2080     {
   2081       Add<HCallRuntime>(
   2082           Runtime::FunctionForId(Runtime::kThrowInvalidStringLength), 0);
   2083     }
   2084     if_invalid.End();
   2085   } else {
   2086     graph()->MarkDependsOnStringLengthOverflow();
   2087     Add<HBoundsCheck>(length, max_length);
   2088   }
   2089   return length;
   2090 }
   2091 
   2092 
   2093 HValue* HGraphBuilder::BuildCreateConsString(
   2094     HValue* length,
   2095     HValue* left,
   2096     HValue* right,
   2097     HAllocationMode allocation_mode) {
   2098   // Determine the string instance types.
   2099   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
   2100   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
   2101 
   2102   // Allocate the cons string object. HAllocate does not care whether we
   2103   // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
   2104   // CONS_STRING_TYPE here. Below we decide whether the cons string is
   2105   // one-byte or two-byte and set the appropriate map.
   2106   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
   2107                                             CONS_ONE_BYTE_STRING_TYPE));
   2108   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
   2109                                     HType::String(), CONS_STRING_TYPE,
   2110                                     allocation_mode);
   2111 
   2112   // Compute intersection and difference of instance types.
   2113   HValue* anded_instance_types = AddUncasted<HBitwise>(
   2114       Token::BIT_AND, left_instance_type, right_instance_type);
   2115   HValue* xored_instance_types = AddUncasted<HBitwise>(
   2116       Token::BIT_XOR, left_instance_type, right_instance_type);
   2117 
   2118   // We create a one-byte cons string if
   2119   // 1. both strings are one-byte, or
   2120   // 2. at least one of the strings is two-byte, but happens to contain only
   2121   //    one-byte characters.
   2122   // To do this, we check
   2123   // 1. if both strings are one-byte, or if the one-byte data hint is set in
   2124   //    both strings, or
   2125   // 2. if one of the strings has the one-byte data hint set and the other
   2126   //    string is one-byte.
   2127   IfBuilder if_onebyte(this);
   2128   STATIC_ASSERT(kOneByteStringTag != 0);
   2129   STATIC_ASSERT(kOneByteDataHintMask != 0);
   2130   if_onebyte.If<HCompareNumericAndBranch>(
   2131       AddUncasted<HBitwise>(
   2132           Token::BIT_AND, anded_instance_types,
   2133           Add<HConstant>(static_cast<int32_t>(
   2134                   kStringEncodingMask | kOneByteDataHintMask))),
   2135       graph()->GetConstant0(), Token::NE);
   2136   if_onebyte.Or();
   2137   STATIC_ASSERT(kOneByteStringTag != 0 &&
   2138                 kOneByteDataHintTag != 0 &&
   2139                 kOneByteDataHintTag != kOneByteStringTag);
   2140   if_onebyte.If<HCompareNumericAndBranch>(
   2141       AddUncasted<HBitwise>(
   2142           Token::BIT_AND, xored_instance_types,
   2143           Add<HConstant>(static_cast<int32_t>(
   2144                   kOneByteStringTag | kOneByteDataHintTag))),
   2145       Add<HConstant>(static_cast<int32_t>(
   2146               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
   2147   if_onebyte.Then();
   2148   {
   2149     // We can safely skip the write barrier for storing the map here.
   2150     Add<HStoreNamedField>(
   2151         result, HObjectAccess::ForMap(),
   2152         Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
   2153   }
   2154   if_onebyte.Else();
   2155   {
   2156     // We can safely skip the write barrier for storing the map here.
   2157     Add<HStoreNamedField>(
   2158         result, HObjectAccess::ForMap(),
   2159         Add<HConstant>(isolate()->factory()->cons_string_map()));
   2160   }
   2161   if_onebyte.End();
   2162 
   2163   // Initialize the cons string fields.
   2164   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2165                         Add<HConstant>(String::kEmptyHashField));
   2166   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2167   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
   2168   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
   2169 
   2170   // Count the native string addition.
   2171   AddIncrementCounter(isolate()->counters()->string_add_native());
   2172 
   2173   return result;
   2174 }
   2175 
   2176 
   2177 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
   2178                                             HValue* src_offset,
   2179                                             String::Encoding src_encoding,
   2180                                             HValue* dst,
   2181                                             HValue* dst_offset,
   2182                                             String::Encoding dst_encoding,
   2183                                             HValue* length) {
   2184   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
   2185          src_encoding == String::ONE_BYTE_ENCODING);
   2186   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   2187   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
   2188   {
   2189     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
   2190     HValue* value =
   2191         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
   2192     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
   2193     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
   2194   }
   2195   loop.EndBody();
   2196 }
   2197 
   2198 
   2199 HValue* HGraphBuilder::BuildObjectSizeAlignment(
   2200     HValue* unaligned_size, int header_size) {
   2201   DCHECK((header_size & kObjectAlignmentMask) == 0);
   2202   HValue* size = AddUncasted<HAdd>(
   2203       unaligned_size, Add<HConstant>(static_cast<int32_t>(
   2204           header_size + kObjectAlignmentMask)));
   2205   size->ClearFlag(HValue::kCanOverflow);
   2206   return AddUncasted<HBitwise>(
   2207       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
   2208           ~kObjectAlignmentMask)));
   2209 }
   2210 
   2211 
   2212 HValue* HGraphBuilder::BuildUncheckedStringAdd(
   2213     HValue* left,
   2214     HValue* right,
   2215     HAllocationMode allocation_mode) {
   2216   // Determine the string lengths.
   2217   HValue* left_length = AddLoadStringLength(left);
   2218   HValue* right_length = AddLoadStringLength(right);
   2219 
   2220   // Compute the combined string length.
   2221   HValue* length = BuildAddStringLengths(left_length, right_length);
   2222 
   2223   // Do some manual constant folding here.
   2224   if (left_length->IsConstant()) {
   2225     HConstant* c_left_length = HConstant::cast(left_length);
   2226     DCHECK_NE(0, c_left_length->Integer32Value());
   2227     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2228       // The right string contains at least one character.
   2229       return BuildCreateConsString(length, left, right, allocation_mode);
   2230     }
   2231   } else if (right_length->IsConstant()) {
   2232     HConstant* c_right_length = HConstant::cast(right_length);
   2233     DCHECK_NE(0, c_right_length->Integer32Value());
   2234     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2235       // The left string contains at least one character.
   2236       return BuildCreateConsString(length, left, right, allocation_mode);
   2237     }
   2238   }
   2239 
   2240   // Check if we should create a cons string.
   2241   IfBuilder if_createcons(this);
   2242   if_createcons.If<HCompareNumericAndBranch>(
   2243       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
   2244   if_createcons.And();
   2245   if_createcons.If<HCompareNumericAndBranch>(
   2246       length, Add<HConstant>(ConsString::kMaxLength), Token::LTE);
   2247   if_createcons.Then();
   2248   {
   2249     // Create a cons string.
   2250     Push(BuildCreateConsString(length, left, right, allocation_mode));
   2251   }
   2252   if_createcons.Else();
   2253   {
   2254     // Determine the string instance types.
   2255     HValue* left_instance_type = AddLoadStringInstanceType(left);
   2256     HValue* right_instance_type = AddLoadStringInstanceType(right);
   2257 
   2258     // Compute union and difference of instance types.
   2259     HValue* ored_instance_types = AddUncasted<HBitwise>(
   2260         Token::BIT_OR, left_instance_type, right_instance_type);
   2261     HValue* xored_instance_types = AddUncasted<HBitwise>(
   2262         Token::BIT_XOR, left_instance_type, right_instance_type);
   2263 
   2264     // Check if both strings have the same encoding and both are
   2265     // sequential.
   2266     IfBuilder if_sameencodingandsequential(this);
   2267     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2268         AddUncasted<HBitwise>(
   2269             Token::BIT_AND, xored_instance_types,
   2270             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2271         graph()->GetConstant0(), Token::EQ);
   2272     if_sameencodingandsequential.And();
   2273     STATIC_ASSERT(kSeqStringTag == 0);
   2274     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2275         AddUncasted<HBitwise>(
   2276             Token::BIT_AND, ored_instance_types,
   2277             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
   2278         graph()->GetConstant0(), Token::EQ);
   2279     if_sameencodingandsequential.Then();
   2280     {
   2281       HConstant* string_map =
   2282           Add<HConstant>(isolate()->factory()->string_map());
   2283       HConstant* one_byte_string_map =
   2284           Add<HConstant>(isolate()->factory()->one_byte_string_map());
   2285 
   2286       // Determine map and size depending on whether result is one-byte string.
   2287       IfBuilder if_onebyte(this);
   2288       STATIC_ASSERT(kOneByteStringTag != 0);
   2289       if_onebyte.If<HCompareNumericAndBranch>(
   2290           AddUncasted<HBitwise>(
   2291               Token::BIT_AND, ored_instance_types,
   2292               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2293           graph()->GetConstant0(), Token::NE);
   2294       if_onebyte.Then();
   2295       {
   2296         // Allocate sequential one-byte string object.
   2297         Push(length);
   2298         Push(one_byte_string_map);
   2299       }
   2300       if_onebyte.Else();
   2301       {
   2302         // Allocate sequential two-byte string object.
   2303         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
   2304         size->ClearFlag(HValue::kCanOverflow);
   2305         size->SetFlag(HValue::kUint32);
   2306         Push(size);
   2307         Push(string_map);
   2308       }
   2309       if_onebyte.End();
   2310       HValue* map = Pop();
   2311 
   2312       // Calculate the number of bytes needed for the characters in the
   2313       // string while observing object alignment.
   2314       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
   2315       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
   2316 
   2317       IfBuilder if_size(this);
   2318       if_size.If<HCompareNumericAndBranch>(
   2319           size, Add<HConstant>(kMaxRegularHeapObjectSize), Token::LT);
   2320       if_size.Then();
   2321       {
   2322         // Allocate the string object. HAllocate does not care whether we pass
   2323         // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
   2324         HAllocate* result =
   2325             BuildAllocate(size, HType::String(), STRING_TYPE, allocation_mode);
   2326         Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
   2327 
   2328         // Initialize the string fields.
   2329         Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2330                               Add<HConstant>(String::kEmptyHashField));
   2331         Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2332 
   2333         // Copy characters to the result string.
   2334         IfBuilder if_twobyte(this);
   2335         if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
   2336         if_twobyte.Then();
   2337         {
   2338           // Copy characters from the left string.
   2339           BuildCopySeqStringChars(
   2340               left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
   2341               graph()->GetConstant0(), String::TWO_BYTE_ENCODING, left_length);
   2342 
   2343           // Copy characters from the right string.
   2344           BuildCopySeqStringChars(
   2345               right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
   2346               left_length, String::TWO_BYTE_ENCODING, right_length);
   2347         }
   2348         if_twobyte.Else();
   2349         {
   2350           // Copy characters from the left string.
   2351           BuildCopySeqStringChars(
   2352               left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
   2353               graph()->GetConstant0(), String::ONE_BYTE_ENCODING, left_length);
   2354 
   2355           // Copy characters from the right string.
   2356           BuildCopySeqStringChars(
   2357               right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
   2358               left_length, String::ONE_BYTE_ENCODING, right_length);
   2359         }
   2360         if_twobyte.End();
   2361 
   2362         // Count the native string addition.
   2363         AddIncrementCounter(isolate()->counters()->string_add_native());
   2364 
   2365         // Return the sequential string.
   2366         Push(result);
   2367       }
   2368       if_size.Else();
   2369       {
   2370         // Fallback to the runtime to add the two strings. The string has to be
   2371         // allocated in LO space.
   2372         Add<HPushArguments>(left, right);
   2373         Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
   2374       }
   2375       if_size.End();
   2376     }
   2377     if_sameencodingandsequential.Else();
   2378     {
   2379       // Fallback to the runtime to add the two strings.
   2380       Add<HPushArguments>(left, right);
   2381       Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
   2382     }
   2383     if_sameencodingandsequential.End();
   2384   }
   2385   if_createcons.End();
   2386 
   2387   return Pop();
   2388 }
   2389 
   2390 
   2391 HValue* HGraphBuilder::BuildStringAdd(
   2392     HValue* left,
   2393     HValue* right,
   2394     HAllocationMode allocation_mode) {
   2395   NoObservableSideEffectsScope no_effects(this);
   2396 
   2397   // Determine string lengths.
   2398   HValue* left_length = AddLoadStringLength(left);
   2399   HValue* right_length = AddLoadStringLength(right);
   2400 
   2401   // Check if left string is empty.
   2402   IfBuilder if_leftempty(this);
   2403   if_leftempty.If<HCompareNumericAndBranch>(
   2404       left_length, graph()->GetConstant0(), Token::EQ);
   2405   if_leftempty.Then();
   2406   {
   2407     // Count the native string addition.
   2408     AddIncrementCounter(isolate()->counters()->string_add_native());
   2409 
   2410     // Just return the right string.
   2411     Push(right);
   2412   }
   2413   if_leftempty.Else();
   2414   {
   2415     // Check if right string is empty.
   2416     IfBuilder if_rightempty(this);
   2417     if_rightempty.If<HCompareNumericAndBranch>(
   2418         right_length, graph()->GetConstant0(), Token::EQ);
   2419     if_rightempty.Then();
   2420     {
   2421       // Count the native string addition.
   2422       AddIncrementCounter(isolate()->counters()->string_add_native());
   2423 
   2424       // Just return the left string.
   2425       Push(left);
   2426     }
   2427     if_rightempty.Else();
   2428     {
   2429       // Add the two non-empty strings.
   2430       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
   2431     }
   2432     if_rightempty.End();
   2433   }
   2434   if_leftempty.End();
   2435 
   2436   return Pop();
   2437 }
   2438 
   2439 
   2440 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   2441     HValue* checked_object,
   2442     HValue* key,
   2443     HValue* val,
   2444     bool is_js_array,
   2445     ElementsKind elements_kind,
   2446     PropertyAccessType access_type,
   2447     LoadKeyedHoleMode load_mode,
   2448     KeyedAccessStoreMode store_mode) {
   2449   DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
   2450          checked_object->IsCheckMaps());
   2451   DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array);
   2452   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
   2453   // on a HElementsTransition instruction. The flag can also be removed if the
   2454   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
   2455   // ElementsKind transitions. Finally, the dependency can be removed for stores
   2456   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
   2457   // generated store code.
   2458   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
   2459       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
   2460     checked_object->ClearDependsOnFlag(kElementsKind);
   2461   }
   2462 
   2463   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
   2464   bool fast_elements = IsFastObjectElementsKind(elements_kind);
   2465   HValue* elements = AddLoadElements(checked_object);
   2466   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
   2467       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
   2468     HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2469         elements, isolate()->factory()->fixed_array_map());
   2470     check_cow_map->ClearDependsOnFlag(kElementsKind);
   2471   }
   2472   HInstruction* length = NULL;
   2473   if (is_js_array) {
   2474     length = Add<HLoadNamedField>(
   2475         checked_object->ActualValue(), checked_object,
   2476         HObjectAccess::ForArrayLength(elements_kind));
   2477   } else {
   2478     length = AddLoadFixedArrayLength(elements);
   2479   }
   2480   length->set_type(HType::Smi());
   2481   HValue* checked_key = NULL;
   2482   if (IsFixedTypedArrayElementsKind(elements_kind)) {
   2483     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
   2484 
   2485     HValue* external_pointer = Add<HLoadNamedField>(
   2486         elements, nullptr,
   2487         HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
   2488     HValue* base_pointer = Add<HLoadNamedField>(
   2489         elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
   2490     HValue* backing_store = AddUncasted<HAdd>(external_pointer, base_pointer,
   2491                                               AddOfExternalAndTagged);
   2492 
   2493     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
   2494       NoObservableSideEffectsScope no_effects(this);
   2495       IfBuilder length_checker(this);
   2496       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
   2497       length_checker.Then();
   2498       IfBuilder negative_checker(this);
   2499       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
   2500           key, graph()->GetConstant0(), Token::GTE);
   2501       negative_checker.Then();
   2502       HInstruction* result = AddElementAccess(
   2503           backing_store, key, val, bounds_check, checked_object->ActualValue(),
   2504           elements_kind, access_type);
   2505       negative_checker.ElseDeopt(DeoptimizeReason::kNegativeKeyEncountered);
   2506       negative_checker.End();
   2507       length_checker.End();
   2508       return result;
   2509     } else {
   2510       DCHECK(store_mode == STANDARD_STORE);
   2511       checked_key = Add<HBoundsCheck>(key, length);
   2512       return AddElementAccess(backing_store, checked_key, val, checked_object,
   2513                               checked_object->ActualValue(), elements_kind,
   2514                               access_type);
   2515     }
   2516   }
   2517   DCHECK(fast_smi_only_elements ||
   2518          fast_elements ||
   2519          IsFastDoubleElementsKind(elements_kind));
   2520 
   2521   // In case val is stored into a fast smi array, assure that the value is a smi
   2522   // before manipulating the backing store. Otherwise the actual store may
   2523   // deopt, leaving the backing store in an invalid state.
   2524   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
   2525       !val->type().IsSmi()) {
   2526     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
   2527   }
   2528 
   2529   if (IsGrowStoreMode(store_mode)) {
   2530     NoObservableSideEffectsScope no_effects(this);
   2531     Representation representation = HStoreKeyed::RequiredValueRepresentation(
   2532         elements_kind, STORE_TO_INITIALIZED_ENTRY);
   2533     val = AddUncasted<HForceRepresentation>(val, representation);
   2534     elements = BuildCheckForCapacityGrow(checked_object, elements,
   2535                                          elements_kind, length, key,
   2536                                          is_js_array, access_type);
   2537     checked_key = key;
   2538   } else {
   2539     checked_key = Add<HBoundsCheck>(key, length);
   2540 
   2541     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
   2542       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
   2543         NoObservableSideEffectsScope no_effects(this);
   2544         elements = BuildCopyElementsOnWrite(checked_object, elements,
   2545                                             elements_kind, length);
   2546       } else {
   2547         HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2548             elements, isolate()->factory()->fixed_array_map());
   2549         check_cow_map->ClearDependsOnFlag(kElementsKind);
   2550       }
   2551     }
   2552   }
   2553   return AddElementAccess(elements, checked_key, val, checked_object, nullptr,
   2554                           elements_kind, access_type, load_mode);
   2555 }
   2556 
   2557 
   2558 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
   2559                                                   HValue* capacity) {
   2560   int elements_size = IsFastDoubleElementsKind(kind)
   2561       ? kDoubleSize
   2562       : kPointerSize;
   2563 
   2564   HConstant* elements_size_value = Add<HConstant>(elements_size);
   2565   HInstruction* mul =
   2566       HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
   2567                     elements_size_value);
   2568   AddInstruction(mul);
   2569   mul->ClearFlag(HValue::kCanOverflow);
   2570 
   2571   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
   2572 
   2573   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
   2574   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
   2575   total_size->ClearFlag(HValue::kCanOverflow);
   2576   return total_size;
   2577 }
   2578 
   2579 
   2580 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
   2581   int base_size = JSArray::kSize;
   2582   if (mode == TRACK_ALLOCATION_SITE) {
   2583     base_size += AllocationMemento::kSize;
   2584   }
   2585   HConstant* size_in_bytes = Add<HConstant>(base_size);
   2586   return Add<HAllocate>(size_in_bytes, HType::JSArray(), NOT_TENURED,
   2587                         JS_OBJECT_TYPE, graph()->GetConstant0());
   2588 }
   2589 
   2590 
   2591 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
   2592     ElementsKind kind,
   2593     int capacity) {
   2594   int base_size = IsFastDoubleElementsKind(kind)
   2595       ? FixedDoubleArray::SizeFor(capacity)
   2596       : FixedArray::SizeFor(capacity);
   2597 
   2598   return Add<HConstant>(base_size);
   2599 }
   2600 
   2601 
   2602 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
   2603                                                 HValue* size_in_bytes) {
   2604   InstanceType instance_type = IsFastDoubleElementsKind(kind)
   2605       ? FIXED_DOUBLE_ARRAY_TYPE
   2606       : FIXED_ARRAY_TYPE;
   2607 
   2608   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
   2609                         instance_type, graph()->GetConstant0());
   2610 }
   2611 
   2612 
   2613 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
   2614                                                   ElementsKind kind,
   2615                                                   HValue* capacity) {
   2616   Factory* factory = isolate()->factory();
   2617   Handle<Map> map = IsFastDoubleElementsKind(kind)
   2618       ? factory->fixed_double_array_map()
   2619       : factory->fixed_array_map();
   2620 
   2621   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
   2622   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
   2623                         capacity);
   2624 }
   2625 
   2626 
   2627 HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
   2628                                                        HValue* capacity) {
   2629   // The HForceRepresentation is to prevent possible deopt on int-smi
   2630   // conversion after allocation but before the new object fields are set.
   2631   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
   2632   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
   2633   HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
   2634   BuildInitializeElementsHeader(new_array, kind, capacity);
   2635   return new_array;
   2636 }
   2637 
   2638 
   2639 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
   2640                                        HValue* array_map,
   2641                                        HValue* elements,
   2642                                        AllocationSiteMode mode,
   2643                                        ElementsKind elements_kind,
   2644                                        HValue* allocation_site_payload,
   2645                                        HValue* length_field) {
   2646   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
   2647 
   2648   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   2649 
   2650   Add<HStoreNamedField>(
   2651       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
   2652 
   2653   Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(),
   2654                         elements != nullptr ? elements : empty_fixed_array);
   2655 
   2656   Add<HStoreNamedField>(
   2657       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
   2658 
   2659   if (mode == TRACK_ALLOCATION_SITE) {
   2660     BuildCreateAllocationMemento(
   2661         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
   2662   }
   2663 }
   2664 
   2665 
   2666 HInstruction* HGraphBuilder::AddElementAccess(
   2667     HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
   2668     HValue* backing_store_owner, ElementsKind elements_kind,
   2669     PropertyAccessType access_type, LoadKeyedHoleMode load_mode) {
   2670   if (access_type == STORE) {
   2671     DCHECK(val != NULL);
   2672     if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
   2673       val = Add<HClampToUint8>(val);
   2674     }
   2675     return Add<HStoreKeyed>(elements, checked_key, val, backing_store_owner,
   2676                             elements_kind, STORE_TO_INITIALIZED_ENTRY);
   2677   }
   2678 
   2679   DCHECK(access_type == LOAD);
   2680   DCHECK(val == NULL);
   2681   HLoadKeyed* load =
   2682       Add<HLoadKeyed>(elements, checked_key, dependency, backing_store_owner,
   2683                       elements_kind, load_mode);
   2684   if (elements_kind == UINT32_ELEMENTS) {
   2685     graph()->RecordUint32Instruction(load);
   2686   }
   2687   return load;
   2688 }
   2689 
   2690 
   2691 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
   2692                                            HValue* dependency) {
   2693   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
   2694 }
   2695 
   2696 
   2697 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
   2698                                                 HValue* dependency) {
   2699   return Add<HLoadNamedField>(
   2700       object, dependency, HObjectAccess::ForElementsPointer());
   2701 }
   2702 
   2703 
   2704 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
   2705     HValue* array,
   2706     HValue* dependency) {
   2707   return Add<HLoadNamedField>(
   2708       array, dependency, HObjectAccess::ForFixedArrayLength());
   2709 }
   2710 
   2711 
   2712 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
   2713                                                    ElementsKind kind,
   2714                                                    HValue* dependency) {
   2715   return Add<HLoadNamedField>(
   2716       array, dependency, HObjectAccess::ForArrayLength(kind));
   2717 }
   2718 
   2719 
   2720 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
   2721   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
   2722                                                 graph_->GetConstant1());
   2723 
   2724   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
   2725   new_capacity->ClearFlag(HValue::kCanOverflow);
   2726 
   2727   HValue* min_growth = Add<HConstant>(16);
   2728 
   2729   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
   2730   new_capacity->ClearFlag(HValue::kCanOverflow);
   2731 
   2732   return new_capacity;
   2733 }
   2734 
   2735 
   2736 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
   2737                                                  HValue* elements,
   2738                                                  ElementsKind kind,
   2739                                                  ElementsKind new_kind,
   2740                                                  HValue* length,
   2741                                                  HValue* new_capacity) {
   2742   Add<HBoundsCheck>(
   2743       new_capacity,
   2744       Add<HConstant>((kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
   2745                      ElementsKindToShiftSize(new_kind)));
   2746 
   2747   HValue* new_elements =
   2748       BuildAllocateAndInitializeArray(new_kind, new_capacity);
   2749 
   2750   BuildCopyElements(elements, kind, new_elements,
   2751                     new_kind, length, new_capacity);
   2752 
   2753   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   2754                         new_elements);
   2755 
   2756   return new_elements;
   2757 }
   2758 
   2759 
   2760 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
   2761                                                ElementsKind elements_kind,
   2762                                                HValue* from,
   2763                                                HValue* to,
   2764                                                HValue* value) {
   2765   if (to == NULL) {
   2766     to = AddLoadFixedArrayLength(elements);
   2767   }
   2768 
   2769   // Special loop unfolding case
   2770   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
   2771                 kElementLoopUnrollThreshold);
   2772   int initial_capacity = -1;
   2773   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
   2774     int constant_from = from->GetInteger32Constant();
   2775     int constant_to = to->GetInteger32Constant();
   2776 
   2777     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
   2778       initial_capacity = constant_to;
   2779     }
   2780   }
   2781 
   2782   if (initial_capacity >= 0) {
   2783     for (int i = 0; i < initial_capacity; i++) {
   2784       HInstruction* key = Add<HConstant>(i);
   2785       Add<HStoreKeyed>(elements, key, value, nullptr, elements_kind);
   2786     }
   2787   } else {
   2788     // Carefully loop backwards so that the "from" remains live through the loop
   2789     // rather than the to. This often corresponds to keeping length live rather
   2790     // then capacity, which helps register allocation, since length is used more
   2791     // other than capacity after filling with holes.
   2792     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2793 
   2794     HValue* key = builder.BeginBody(to, from, Token::GT);
   2795 
   2796     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2797     adjusted_key->ClearFlag(HValue::kCanOverflow);
   2798 
   2799     Add<HStoreKeyed>(elements, adjusted_key, value, nullptr, elements_kind);
   2800 
   2801     builder.EndBody();
   2802   }
   2803 }
   2804 
   2805 
   2806 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
   2807                                               ElementsKind elements_kind,
   2808                                               HValue* from,
   2809                                               HValue* to) {
   2810   // Fast elements kinds need to be initialized in case statements below cause a
   2811   // garbage collection.
   2812 
   2813   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   2814                      ? graph()->GetConstantHole()
   2815                      : Add<HConstant>(HConstant::kHoleNaN);
   2816 
   2817   // Since we're about to store a hole value, the store instruction below must
   2818   // assume an elements kind that supports heap object values.
   2819   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   2820     elements_kind = FAST_HOLEY_ELEMENTS;
   2821   }
   2822 
   2823   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
   2824 }
   2825 
   2826 
   2827 void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
   2828                                         HValue* to_properties, HValue* length,
   2829                                         HValue* capacity) {
   2830   ElementsKind kind = FAST_ELEMENTS;
   2831 
   2832   BuildFillElementsWithValue(to_properties, kind, length, capacity,
   2833                              graph()->GetConstantUndefined());
   2834 
   2835   LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2836 
   2837   HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
   2838 
   2839   key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2840   key->ClearFlag(HValue::kCanOverflow);
   2841 
   2842   HValue* element =
   2843       Add<HLoadKeyed>(from_properties, key, nullptr, nullptr, kind);
   2844 
   2845   Add<HStoreKeyed>(to_properties, key, element, nullptr, kind);
   2846 
   2847   builder.EndBody();
   2848 }
   2849 
   2850 
   2851 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
   2852                                       ElementsKind from_elements_kind,
   2853                                       HValue* to_elements,
   2854                                       ElementsKind to_elements_kind,
   2855                                       HValue* length,
   2856                                       HValue* capacity) {
   2857   int constant_capacity = -1;
   2858   if (capacity != NULL &&
   2859       capacity->IsConstant() &&
   2860       HConstant::cast(capacity)->HasInteger32Value()) {
   2861     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
   2862     if (constant_candidate <= kElementLoopUnrollThreshold) {
   2863       constant_capacity = constant_candidate;
   2864     }
   2865   }
   2866 
   2867   bool pre_fill_with_holes =
   2868     IsFastDoubleElementsKind(from_elements_kind) &&
   2869     IsFastObjectElementsKind(to_elements_kind);
   2870   if (pre_fill_with_holes) {
   2871     // If the copy might trigger a GC, make sure that the FixedArray is
   2872     // pre-initialized with holes to make sure that it's always in a
   2873     // consistent state.
   2874     BuildFillElementsWithHole(to_elements, to_elements_kind,
   2875                               graph()->GetConstant0(), NULL);
   2876   }
   2877 
   2878   if (constant_capacity != -1) {
   2879     // Unroll the loop for small elements kinds.
   2880     for (int i = 0; i < constant_capacity; i++) {
   2881       HValue* key_constant = Add<HConstant>(i);
   2882       HInstruction* value = Add<HLoadKeyed>(
   2883           from_elements, key_constant, nullptr, nullptr, from_elements_kind);
   2884       Add<HStoreKeyed>(to_elements, key_constant, value, nullptr,
   2885                        to_elements_kind);
   2886     }
   2887   } else {
   2888     if (!pre_fill_with_holes &&
   2889         (capacity == NULL || !length->Equals(capacity))) {
   2890       BuildFillElementsWithHole(to_elements, to_elements_kind,
   2891                                 length, NULL);
   2892     }
   2893 
   2894     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2895 
   2896     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
   2897                                     Token::GT);
   2898 
   2899     key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2900     key->ClearFlag(HValue::kCanOverflow);
   2901 
   2902     HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr, nullptr,
   2903                                       from_elements_kind, ALLOW_RETURN_HOLE);
   2904 
   2905     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
   2906                          IsFastSmiElementsKind(to_elements_kind))
   2907       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
   2908 
   2909     if (IsHoleyElementsKind(from_elements_kind) &&
   2910         from_elements_kind != to_elements_kind) {
   2911       IfBuilder if_hole(this);
   2912       if_hole.If<HCompareHoleAndBranch>(element);
   2913       if_hole.Then();
   2914       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
   2915                                      ? Add<HConstant>(HConstant::kHoleNaN)
   2916                                      : graph()->GetConstantHole();
   2917       Add<HStoreKeyed>(to_elements, key, hole_constant, nullptr, kind);
   2918       if_hole.Else();
   2919       HStoreKeyed* store =
   2920           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
   2921       store->SetFlag(HValue::kTruncatingToNumber);
   2922       if_hole.End();
   2923     } else {
   2924       HStoreKeyed* store =
   2925           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
   2926       store->SetFlag(HValue::kTruncatingToNumber);
   2927     }
   2928 
   2929     builder.EndBody();
   2930   }
   2931 
   2932   Counters* counters = isolate()->counters();
   2933   AddIncrementCounter(counters->inlined_copied_elements());
   2934 }
   2935 
   2936 void HGraphBuilder::BuildCreateAllocationMemento(
   2937     HValue* previous_object,
   2938     HValue* previous_object_size,
   2939     HValue* allocation_site) {
   2940   DCHECK(allocation_site != NULL);
   2941   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
   2942       previous_object, previous_object_size, HType::HeapObject());
   2943   AddStoreMapConstant(
   2944       allocation_memento, isolate()->factory()->allocation_memento_map());
   2945   Add<HStoreNamedField>(
   2946       allocation_memento,
   2947       HObjectAccess::ForAllocationMementoSite(),
   2948       allocation_site);
   2949   if (FLAG_allocation_site_pretenuring) {
   2950     HValue* memento_create_count =
   2951         Add<HLoadNamedField>(allocation_site, nullptr,
   2952                              HObjectAccess::ForAllocationSiteOffset(
   2953                                  AllocationSite::kPretenureCreateCountOffset));
   2954     memento_create_count = AddUncasted<HAdd>(
   2955         memento_create_count, graph()->GetConstant1());
   2956     // This smi value is reset to zero after every gc, overflow isn't a problem
   2957     // since the counter is bounded by the new space size.
   2958     memento_create_count->ClearFlag(HValue::kCanOverflow);
   2959     Add<HStoreNamedField>(
   2960         allocation_site, HObjectAccess::ForAllocationSiteOffset(
   2961             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
   2962   }
   2963 }
   2964 
   2965 
   2966 HInstruction* HGraphBuilder::BuildGetNativeContext() {
   2967   return Add<HLoadNamedField>(
   2968       context(), nullptr,
   2969       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   2970 }
   2971 
   2972 
   2973 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
   2974   // Get the global object, then the native context
   2975   HInstruction* context = Add<HLoadNamedField>(
   2976       closure, nullptr, HObjectAccess::ForFunctionContextPointer());
   2977   return Add<HLoadNamedField>(
   2978       context, nullptr,
   2979       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   2980 }
   2981 
   2982 
   2983 HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) {
   2984   HValue* script_context = context();
   2985   if (depth != NULL) {
   2986     HValue* zero = graph()->GetConstant0();
   2987 
   2988     Push(script_context);
   2989     Push(depth);
   2990 
   2991     LoopBuilder loop(this);
   2992     loop.BeginBody(2);  // Drop script_context and depth from last environment
   2993                         // to appease live range building without simulates.
   2994     depth = Pop();
   2995     script_context = Pop();
   2996 
   2997     script_context = Add<HLoadNamedField>(
   2998         script_context, nullptr,
   2999         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   3000     depth = AddUncasted<HSub>(depth, graph()->GetConstant1());
   3001     depth->ClearFlag(HValue::kCanOverflow);
   3002 
   3003     IfBuilder if_break(this);
   3004     if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ);
   3005     if_break.Then();
   3006     {
   3007       Push(script_context);  // The result.
   3008       loop.Break();
   3009     }
   3010     if_break.Else();
   3011     {
   3012       Push(script_context);
   3013       Push(depth);
   3014     }
   3015     loop.EndBody();
   3016     if_break.End();
   3017 
   3018     script_context = Pop();
   3019   } else if (depth_value > 0) {
   3020     // Unroll the above loop.
   3021     for (int i = 0; i < depth_value; i++) {
   3022       script_context = Add<HLoadNamedField>(
   3023           script_context, nullptr,
   3024           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   3025     }
   3026   }
   3027   return script_context;
   3028 }
   3029 
   3030 
   3031 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
   3032   HInstruction* native_context = BuildGetNativeContext();
   3033   HInstruction* index =
   3034       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
   3035   return Add<HLoadKeyed>(native_context, index, nullptr, nullptr,
   3036                          FAST_ELEMENTS);
   3037 }
   3038 
   3039 
   3040 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
   3041                                                          HValue* checked_object,
   3042                                                          FieldIndex index) {
   3043   NoObservableSideEffectsScope scope(this);
   3044   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
   3045       index.offset(), Representation::Tagged());
   3046   HInstruction* buffer = Add<HLoadNamedField>(
   3047       object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
   3048   HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);
   3049 
   3050   HInstruction* flags = Add<HLoadNamedField>(
   3051       buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
   3052   HValue* was_neutered_mask =
   3053       Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
   3054   HValue* was_neutered_test =
   3055       AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
   3056 
   3057   IfBuilder if_was_neutered(this);
   3058   if_was_neutered.If<HCompareNumericAndBranch>(
   3059       was_neutered_test, graph()->GetConstant0(), Token::NE);
   3060   if_was_neutered.Then();
   3061   Push(graph()->GetConstant0());
   3062   if_was_neutered.Else();
   3063   Push(field);
   3064   if_was_neutered.End();
   3065 
   3066   return Pop();
   3067 }
   3068 
   3069 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
   3070   HValue* native_context = BuildGetNativeContext();
   3071   HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
   3072   return Add<HLoadNamedField>(native_context, nullptr, function_access);
   3073 }
   3074 
   3075 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
   3076                                                bool track_positions)
   3077     : HGraphBuilder(info, CallInterfaceDescriptor(), track_positions),
   3078       function_state_(NULL),
   3079       initial_function_state_(this, info, NORMAL_RETURN, -1,
   3080                               TailCallMode::kAllow),
   3081       ast_context_(NULL),
   3082       break_scope_(NULL),
   3083       inlined_count_(0),
   3084       globals_(10, info->zone()),
   3085       osr_(new (info->zone()) HOsrBuilder(this)),
   3086       bounds_(info->zone()) {
   3087   // This is not initialized in the initializer list because the
   3088   // constructor for the initial state relies on function_state_ == NULL
   3089   // to know it's the initial state.
   3090   function_state_ = &initial_function_state_;
   3091   InitializeAstVisitor(info->isolate());
   3092 }
   3093 
   3094 
   3095 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
   3096                                                 HBasicBlock* second,
   3097                                                 BailoutId join_id) {
   3098   if (first == NULL) {
   3099     return second;
   3100   } else if (second == NULL) {
   3101     return first;
   3102   } else {
   3103     HBasicBlock* join_block = graph()->CreateBasicBlock();
   3104     Goto(first, join_block);
   3105     Goto(second, join_block);
   3106     join_block->SetJoinId(join_id);
   3107     return join_block;
   3108   }
   3109 }
   3110 
   3111 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
   3112                                                   BailoutId continue_id,
   3113                                                   HBasicBlock* exit_block,
   3114                                                   HBasicBlock* continue_block) {
   3115   if (continue_block != NULL) {
   3116     if (exit_block != NULL) Goto(exit_block, continue_block);
   3117     continue_block->SetJoinId(continue_id);
   3118     return continue_block;
   3119   }
   3120   return exit_block;
   3121 }
   3122 
   3123 
   3124 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
   3125                                                 HBasicBlock* loop_entry,
   3126                                                 HBasicBlock* body_exit,
   3127                                                 HBasicBlock* loop_successor,
   3128                                                 HBasicBlock* break_block) {
   3129   if (body_exit != NULL) Goto(body_exit, loop_entry);
   3130   loop_entry->PostProcessLoopHeader(statement);
   3131   if (break_block != NULL) {
   3132     if (loop_successor != NULL) Goto(loop_successor, break_block);
   3133     break_block->SetJoinId(statement->ExitId());
   3134     return break_block;
   3135   }
   3136   return loop_successor;
   3137 }
   3138 
   3139 
   3140 // Build a new loop header block and set it as the current block.
   3141 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
   3142   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   3143   Goto(loop_entry);
   3144   set_current_block(loop_entry);
   3145   return loop_entry;
   3146 }
   3147 
   3148 
   3149 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
   3150     IterationStatement* statement) {
   3151   HBasicBlock* loop_entry;
   3152 
   3153   if (osr()->HasOsrEntryAt(statement)) {
   3154     loop_entry = osr()->BuildOsrLoopEntry(statement);
   3155     if (function_state()->IsInsideDoExpressionScope()) {
   3156       Bailout(kDoExpressionUnmodelable);
   3157     }
   3158   } else {
   3159     loop_entry = BuildLoopEntry();
   3160   }
   3161   return loop_entry;
   3162 }
   3163 
   3164 
   3165 void HBasicBlock::FinishExit(HControlInstruction* instruction,
   3166                              SourcePosition position) {
   3167   Finish(instruction, position);
   3168   ClearEnvironment();
   3169 }
   3170 
   3171 
   3172 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
   3173   return os << "B" << b.block_id();
   3174 }
   3175 
   3176 HGraph::HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor)
   3177     : isolate_(info->isolate()),
   3178       next_block_id_(0),
   3179       entry_block_(NULL),
   3180       blocks_(8, info->zone()),
   3181       values_(16, info->zone()),
   3182       phi_list_(NULL),
   3183       uint32_instructions_(NULL),
   3184       osr_(NULL),
   3185       info_(info),
   3186       descriptor_(descriptor),
   3187       zone_(info->zone()),
   3188       allow_code_motion_(false),
   3189       use_optimistic_licm_(false),
   3190       depends_on_empty_array_proto_elements_(false),
   3191       depends_on_string_length_overflow_(false),
   3192       type_change_checksum_(0),
   3193       maximum_environment_size_(0),
   3194       no_side_effects_scope_count_(0),
   3195       disallow_adding_new_values_(false) {
   3196   if (info->IsStub()) {
   3197     // For stubs, explicitly add the context to the environment.
   3198     start_environment_ =
   3199         new (zone_) HEnvironment(zone_, descriptor.GetParameterCount() + 1);
   3200   } else {
   3201     start_environment_ =
   3202         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
   3203   }
   3204   start_environment_->set_ast_id(BailoutId::FunctionContext());
   3205   entry_block_ = CreateBasicBlock();
   3206   entry_block_->SetInitialEnvironment(start_environment_);
   3207 }
   3208 
   3209 
   3210 HBasicBlock* HGraph::CreateBasicBlock() {
   3211   HBasicBlock* result = new(zone()) HBasicBlock(this);
   3212   blocks_.Add(result, zone());
   3213   return result;
   3214 }
   3215 
   3216 
   3217 void HGraph::FinalizeUniqueness() {
   3218   DisallowHeapAllocation no_gc;
   3219   for (int i = 0; i < blocks()->length(); ++i) {
   3220     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
   3221       it.Current()->FinalizeUniqueness();
   3222     }
   3223   }
   3224 }
   3225 
   3226 
   3227 // Block ordering was implemented with two mutually recursive methods,
   3228 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
   3229 // The recursion could lead to stack overflow so the algorithm has been
   3230 // implemented iteratively.
   3231 // At a high level the algorithm looks like this:
   3232 //
   3233 // Postorder(block, loop_header) : {
   3234 //   if (block has already been visited or is of another loop) return;
   3235 //   mark block as visited;
   3236 //   if (block is a loop header) {
   3237 //     VisitLoopMembers(block, loop_header);
   3238 //     VisitSuccessorsOfLoopHeader(block);
   3239 //   } else {
   3240 //     VisitSuccessors(block)
   3241 //   }
   3242 //   put block in result list;
   3243 // }
   3244 //
   3245 // VisitLoopMembers(block, outer_loop_header) {
   3246 //   foreach (block b in block loop members) {
   3247 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
   3248 //     if (b is loop header) VisitLoopMembers(b);
   3249 //   }
   3250 // }
   3251 //
   3252 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
   3253 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
   3254 // }
   3255 //
   3256 // VisitSuccessorsOfLoopHeader(block) {
   3257 //   foreach (block b in block successors) Postorder(b, block)
   3258 // }
   3259 //
   3260 // VisitSuccessors(block, loop_header) {
   3261 //   foreach (block b in block successors) Postorder(b, loop_header)
   3262 // }
   3263 //
   3264 // The ordering is started calling Postorder(entry, NULL).
   3265 //
   3266 // Each instance of PostorderProcessor represents the "stack frame" of the
   3267 // recursion, and particularly keeps the state of the loop (iteration) of the
   3268 // "Visit..." function it represents.
   3269 // To recycle memory we keep all the frames in a double linked list but
   3270 // this means that we cannot use constructors to initialize the frames.
   3271 //
   3272 class PostorderProcessor : public ZoneObject {
   3273  public:
   3274   // Back link (towards the stack bottom).
   3275   PostorderProcessor* parent() {return father_; }
   3276   // Forward link (towards the stack top).
   3277   PostorderProcessor* child() {return child_; }
   3278   HBasicBlock* block() { return block_; }
   3279   HLoopInformation* loop() { return loop_; }
   3280   HBasicBlock* loop_header() { return loop_header_; }
   3281 
   3282   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
   3283                                                   HBasicBlock* block) {
   3284     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
   3285     return result->SetupSuccessors(zone, block, NULL);
   3286   }
   3287 
   3288   PostorderProcessor* PerformStep(Zone* zone,
   3289                                   ZoneList<HBasicBlock*>* order) {
   3290     PostorderProcessor* next =
   3291         PerformNonBacktrackingStep(zone, order);
   3292     if (next != NULL) {
   3293       return next;
   3294     } else {
   3295       return Backtrack(zone, order);
   3296     }
   3297   }
   3298 
   3299  private:
   3300   explicit PostorderProcessor(PostorderProcessor* father)
   3301       : father_(father), child_(NULL), successor_iterator(NULL) { }
   3302 
   3303   // Each enum value states the cycle whose state is kept by this instance.
   3304   enum LoopKind {
   3305     NONE,
   3306     SUCCESSORS,
   3307     SUCCESSORS_OF_LOOP_HEADER,
   3308     LOOP_MEMBERS,
   3309     SUCCESSORS_OF_LOOP_MEMBER
   3310   };
   3311 
   3312   // Each "Setup..." method is like a constructor for a cycle state.
   3313   PostorderProcessor* SetupSuccessors(Zone* zone,
   3314                                       HBasicBlock* block,
   3315                                       HBasicBlock* loop_header) {
   3316     if (block == NULL || block->IsOrdered() ||
   3317         block->parent_loop_header() != loop_header) {
   3318       kind_ = NONE;
   3319       block_ = NULL;
   3320       loop_ = NULL;
   3321       loop_header_ = NULL;
   3322       return this;
   3323     } else {
   3324       block_ = block;
   3325       loop_ = NULL;
   3326       block->MarkAsOrdered();
   3327 
   3328       if (block->IsLoopHeader()) {
   3329         kind_ = SUCCESSORS_OF_LOOP_HEADER;
   3330         loop_header_ = block;
   3331         InitializeSuccessors();
   3332         PostorderProcessor* result = Push(zone);
   3333         return result->SetupLoopMembers(zone, block, block->loop_information(),
   3334                                         loop_header);
   3335       } else {
   3336         DCHECK(block->IsFinished());
   3337         kind_ = SUCCESSORS;
   3338         loop_header_ = loop_header;
   3339         InitializeSuccessors();
   3340         return this;
   3341       }
   3342     }
   3343   }
   3344 
   3345   PostorderProcessor* SetupLoopMembers(Zone* zone,
   3346                                        HBasicBlock* block,
   3347                                        HLoopInformation* loop,
   3348                                        HBasicBlock* loop_header) {
   3349     kind_ = LOOP_MEMBERS;
   3350     block_ = block;
   3351     loop_ = loop;
   3352     loop_header_ = loop_header;
   3353     InitializeLoopMembers();
   3354     return this;
   3355   }
   3356 
   3357   PostorderProcessor* SetupSuccessorsOfLoopMember(
   3358       HBasicBlock* block,
   3359       HLoopInformation* loop,
   3360       HBasicBlock* loop_header) {
   3361     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
   3362     block_ = block;
   3363     loop_ = loop;
   3364     loop_header_ = loop_header;
   3365     InitializeSuccessors();
   3366     return this;
   3367   }
   3368 
   3369   // This method "allocates" a new stack frame.
   3370   PostorderProcessor* Push(Zone* zone) {
   3371     if (child_ == NULL) {
   3372       child_ = new(zone) PostorderProcessor(this);
   3373     }
   3374     return child_;
   3375   }
   3376 
   3377   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
   3378     DCHECK(block_->end()->FirstSuccessor() == NULL ||
   3379            order->Contains(block_->end()->FirstSuccessor()) ||
   3380            block_->end()->FirstSuccessor()->IsLoopHeader());
   3381     DCHECK(block_->end()->SecondSuccessor() == NULL ||
   3382            order->Contains(block_->end()->SecondSuccessor()) ||
   3383            block_->end()->SecondSuccessor()->IsLoopHeader());
   3384     order->Add(block_, zone);
   3385   }
   3386 
   3387   // This method is the basic block to walk up the stack.
   3388   PostorderProcessor* Pop(Zone* zone,
   3389                           ZoneList<HBasicBlock*>* order) {
   3390     switch (kind_) {
   3391       case SUCCESSORS:
   3392       case SUCCESSORS_OF_LOOP_HEADER:
   3393         ClosePostorder(order, zone);
   3394         return father_;
   3395       case LOOP_MEMBERS:
   3396         return father_;
   3397       case SUCCESSORS_OF_LOOP_MEMBER:
   3398         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
   3399           // In this case we need to perform a LOOP_MEMBERS cycle so we
   3400           // initialize it and return this instead of father.
   3401           return SetupLoopMembers(zone, block(),
   3402                                   block()->loop_information(), loop_header_);
   3403         } else {
   3404           return father_;
   3405         }
   3406       case NONE:
   3407         return father_;
   3408     }
   3409     UNREACHABLE();
   3410     return NULL;
   3411   }
   3412 
   3413   // Walks up the stack.
   3414   PostorderProcessor* Backtrack(Zone* zone,
   3415                                 ZoneList<HBasicBlock*>* order) {
   3416     PostorderProcessor* parent = Pop(zone, order);
   3417     while (parent != NULL) {
   3418       PostorderProcessor* next =
   3419           parent->PerformNonBacktrackingStep(zone, order);
   3420       if (next != NULL) {
   3421         return next;
   3422       } else {
   3423         parent = parent->Pop(zone, order);
   3424       }
   3425     }
   3426     return NULL;
   3427   }
   3428 
   3429   PostorderProcessor* PerformNonBacktrackingStep(
   3430       Zone* zone,
   3431       ZoneList<HBasicBlock*>* order) {
   3432     HBasicBlock* next_block;
   3433     switch (kind_) {
   3434       case SUCCESSORS:
   3435         next_block = AdvanceSuccessors();
   3436         if (next_block != NULL) {
   3437           PostorderProcessor* result = Push(zone);
   3438           return result->SetupSuccessors(zone, next_block, loop_header_);
   3439         }
   3440         break;
   3441       case SUCCESSORS_OF_LOOP_HEADER:
   3442         next_block = AdvanceSuccessors();
   3443         if (next_block != NULL) {
   3444           PostorderProcessor* result = Push(zone);
   3445           return result->SetupSuccessors(zone, next_block, block());
   3446         }
   3447         break;
   3448       case LOOP_MEMBERS:
   3449         next_block = AdvanceLoopMembers();
   3450         if (next_block != NULL) {
   3451           PostorderProcessor* result = Push(zone);
   3452           return result->SetupSuccessorsOfLoopMember(next_block,
   3453                                                      loop_, loop_header_);
   3454         }
   3455         break;
   3456       case SUCCESSORS_OF_LOOP_MEMBER:
   3457         next_block = AdvanceSuccessors();
   3458         if (next_block != NULL) {
   3459           PostorderProcessor* result = Push(zone);
   3460           return result->SetupSuccessors(zone, next_block, loop_header_);
   3461         }
   3462         break;
   3463       case NONE:
   3464         return NULL;
   3465     }
   3466     return NULL;
   3467   }
   3468 
   3469   // The following two methods implement a "foreach b in successors" cycle.
   3470   void InitializeSuccessors() {
   3471     loop_index = 0;
   3472     loop_length = 0;
   3473     successor_iterator = HSuccessorIterator(block_->end());
   3474   }
   3475 
   3476   HBasicBlock* AdvanceSuccessors() {
   3477     if (!successor_iterator.Done()) {
   3478       HBasicBlock* result = successor_iterator.Current();
   3479       successor_iterator.Advance();
   3480       return result;
   3481     }
   3482     return NULL;
   3483   }
   3484 
   3485   // The following two methods implement a "foreach b in loop members" cycle.
   3486   void InitializeLoopMembers() {
   3487     loop_index = 0;
   3488     loop_length = loop_->blocks()->length();
   3489   }
   3490 
   3491   HBasicBlock* AdvanceLoopMembers() {
   3492     if (loop_index < loop_length) {
   3493       HBasicBlock* result = loop_->blocks()->at(loop_index);
   3494       loop_index++;
   3495       return result;
   3496     } else {
   3497       return NULL;
   3498     }
   3499   }
   3500 
   3501   LoopKind kind_;
   3502   PostorderProcessor* father_;
   3503   PostorderProcessor* child_;
   3504   HLoopInformation* loop_;
   3505   HBasicBlock* block_;
   3506   HBasicBlock* loop_header_;
   3507   int loop_index;
   3508   int loop_length;
   3509   HSuccessorIterator successor_iterator;
   3510 };
   3511 
   3512 
   3513 void HGraph::OrderBlocks() {
   3514   CompilationPhase phase("H_Block ordering", info());
   3515 
   3516 #ifdef DEBUG
   3517   // Initially the blocks must not be ordered.
   3518   for (int i = 0; i < blocks_.length(); ++i) {
   3519     DCHECK(!blocks_[i]->IsOrdered());
   3520   }
   3521 #endif
   3522 
   3523   PostorderProcessor* postorder =
   3524       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
   3525   blocks_.Rewind(0);
   3526   while (postorder) {
   3527     postorder = postorder->PerformStep(zone(), &blocks_);
   3528   }
   3529 
   3530 #ifdef DEBUG
   3531   // Now all blocks must be marked as ordered.
   3532   for (int i = 0; i < blocks_.length(); ++i) {
   3533     DCHECK(blocks_[i]->IsOrdered());
   3534   }
   3535 #endif
   3536 
   3537   // Reverse block list and assign block IDs.
   3538   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
   3539     HBasicBlock* bi = blocks_[i];
   3540     HBasicBlock* bj = blocks_[j];
   3541     bi->set_block_id(j);
   3542     bj->set_block_id(i);
   3543     blocks_[i] = bj;
   3544     blocks_[j] = bi;
   3545   }
   3546 }
   3547 
   3548 
   3549 void HGraph::AssignDominators() {
   3550   HPhase phase("H_Assign dominators", this);
   3551   for (int i = 0; i < blocks_.length(); ++i) {
   3552     HBasicBlock* block = blocks_[i];
   3553     if (block->IsLoopHeader()) {
   3554       // Only the first predecessor of a loop header is from outside the loop.
   3555       // All others are back edges, and thus cannot dominate the loop header.
   3556       block->AssignCommonDominator(block->predecessors()->first());
   3557       block->AssignLoopSuccessorDominators();
   3558     } else {
   3559       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
   3560         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
   3561       }
   3562     }
   3563   }
   3564 }
   3565 
   3566 
   3567 bool HGraph::CheckArgumentsPhiUses() {
   3568   int block_count = blocks_.length();
   3569   for (int i = 0; i < block_count; ++i) {
   3570     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3571       HPhi* phi = blocks_[i]->phis()->at(j);
   3572       // We don't support phi uses of arguments for now.
   3573       if (phi->CheckFlag(HValue::kIsArguments)) return false;
   3574     }
   3575   }
   3576   return true;
   3577 }
   3578 
   3579 
   3580 bool HGraph::CheckConstPhiUses() {
   3581   int block_count = blocks_.length();
   3582   for (int i = 0; i < block_count; ++i) {
   3583     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3584       HPhi* phi = blocks_[i]->phis()->at(j);
   3585       // Check for the hole value (from an uninitialized const).
   3586       for (int k = 0; k < phi->OperandCount(); k++) {
   3587         if (phi->OperandAt(k) == GetConstantHole()) return false;
   3588       }
   3589     }
   3590   }
   3591   return true;
   3592 }
   3593 
   3594 
   3595 void HGraph::CollectPhis() {
   3596   int block_count = blocks_.length();
   3597   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
   3598   for (int i = 0; i < block_count; ++i) {
   3599     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3600       HPhi* phi = blocks_[i]->phis()->at(j);
   3601       phi_list_->Add(phi, zone());
   3602     }
   3603   }
   3604 }
   3605 
   3606 
   3607 // Implementation of utility class to encapsulate the translation state for
   3608 // a (possibly inlined) function.
   3609 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
   3610                              CompilationInfo* info, InliningKind inlining_kind,
   3611                              int inlining_id, TailCallMode tail_call_mode)
   3612     : owner_(owner),
   3613       compilation_info_(info),
   3614       call_context_(NULL),
   3615       inlining_kind_(inlining_kind),
   3616       tail_call_mode_(tail_call_mode),
   3617       function_return_(NULL),
   3618       test_context_(NULL),
   3619       entry_(NULL),
   3620       arguments_object_(NULL),
   3621       arguments_elements_(NULL),
   3622       inlining_id_(inlining_id),
   3623       outer_source_position_(SourcePosition::Unknown()),
   3624       do_expression_scope_count_(0),
   3625       outer_(owner->function_state()) {
   3626   if (outer_ != NULL) {
   3627     // State for an inline function.
   3628     if (owner->ast_context()->IsTest()) {
   3629       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
   3630       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
   3631       if_true->MarkAsInlineReturnTarget(owner->current_block());
   3632       if_false->MarkAsInlineReturnTarget(owner->current_block());
   3633       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
   3634       Expression* cond = outer_test_context->condition();
   3635       // The AstContext constructor pushed on the context stack.  This newed
   3636       // instance is the reason that AstContext can't be BASE_EMBEDDED.
   3637       test_context_ = new TestContext(owner, cond, if_true, if_false);
   3638     } else {
   3639       function_return_ = owner->graph()->CreateBasicBlock();
   3640       function_return()->MarkAsInlineReturnTarget(owner->current_block());
   3641     }
   3642     // Set this after possibly allocating a new TestContext above.
   3643     call_context_ = owner->ast_context();
   3644   }
   3645 
   3646   // Push on the state stack.
   3647   owner->set_function_state(this);
   3648 
   3649   if (owner->is_tracking_positions()) {
   3650     outer_source_position_ = owner->source_position();
   3651     owner->EnterInlinedSource(inlining_id);
   3652     owner->SetSourcePosition(info->shared_info()->start_position());
   3653   }
   3654 }
   3655 
   3656 
   3657 FunctionState::~FunctionState() {
   3658   delete test_context_;
   3659   owner_->set_function_state(outer_);
   3660 
   3661   if (owner_->is_tracking_positions()) {
   3662     owner_->set_source_position(outer_source_position_);
   3663     owner_->EnterInlinedSource(outer_->inlining_id());
   3664   }
   3665 }
   3666 
   3667 
   3668 // Implementation of utility classes to represent an expression's context in
   3669 // the AST.
   3670 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
   3671     : owner_(owner),
   3672       kind_(kind),
   3673       outer_(owner->ast_context()),
   3674       typeof_mode_(NOT_INSIDE_TYPEOF) {
   3675   owner->set_ast_context(this);  // Push.
   3676 #ifdef DEBUG
   3677   DCHECK_EQ(JS_FUNCTION, owner->environment()->frame_type());
   3678   original_length_ = owner->environment()->length();
   3679 #endif
   3680 }
   3681 
   3682 
   3683 AstContext::~AstContext() {
   3684   owner_->set_ast_context(outer_);  // Pop.
   3685 }
   3686 
   3687 
   3688 EffectContext::~EffectContext() {
   3689   DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL ||
   3690          (owner()->environment()->length() == original_length_ &&
   3691           (owner()->environment()->frame_type() == JS_FUNCTION ||
   3692            owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION)));
   3693 }
   3694 
   3695 
   3696 ValueContext::~ValueContext() {
   3697   DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL ||
   3698          (owner()->environment()->length() == original_length_ + 1 &&
   3699           (owner()->environment()->frame_type() == JS_FUNCTION ||
   3700            owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION)));
   3701 }
   3702 
   3703 
   3704 void EffectContext::ReturnValue(HValue* value) {
   3705   // The value is simply ignored.
   3706 }
   3707 
   3708 
   3709 void ValueContext::ReturnValue(HValue* value) {
   3710   // The value is tracked in the bailout environment, and communicated
   3711   // through the environment as the result of the expression.
   3712   if (value->CheckFlag(HValue::kIsArguments)) {
   3713     if (flag_ == ARGUMENTS_FAKED) {
   3714       value = owner()->graph()->GetConstantUndefined();
   3715     } else if (!arguments_allowed()) {
   3716       owner()->Bailout(kBadValueContextForArgumentsValue);
   3717     }
   3718   }
   3719   owner()->Push(value);
   3720 }
   3721 
   3722 
   3723 void TestContext::ReturnValue(HValue* value) {
   3724   BuildBranch(value);
   3725 }
   3726 
   3727 
   3728 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   3729   DCHECK(!instr->IsControlInstruction());
   3730   owner()->AddInstruction(instr);
   3731   if (instr->HasObservableSideEffects()) {
   3732     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   3733   }
   3734 }
   3735 
   3736 
   3737 void EffectContext::ReturnControl(HControlInstruction* instr,
   3738                                   BailoutId ast_id) {
   3739   DCHECK(!instr->HasObservableSideEffects());
   3740   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   3741   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   3742   instr->SetSuccessorAt(0, empty_true);
   3743   instr->SetSuccessorAt(1, empty_false);
   3744   owner()->FinishCurrentBlock(instr);
   3745   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
   3746   owner()->set_current_block(join);
   3747 }
   3748 
   3749 
   3750 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
   3751                                        BailoutId ast_id) {
   3752   HBasicBlock* true_branch = NULL;
   3753   HBasicBlock* false_branch = NULL;
   3754   continuation->Continue(&true_branch, &false_branch);
   3755   if (!continuation->IsTrueReachable()) {
   3756     owner()->set_current_block(false_branch);
   3757   } else if (!continuation->IsFalseReachable()) {
   3758     owner()->set_current_block(true_branch);
   3759   } else {
   3760     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
   3761     owner()->set_current_block(join);
   3762   }
   3763 }
   3764 
   3765 
   3766 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   3767   DCHECK(!instr->IsControlInstruction());
   3768   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   3769     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   3770   }
   3771   owner()->AddInstruction(instr);
   3772   owner()->Push(instr);
   3773   if (instr->HasObservableSideEffects()) {
   3774     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   3775   }
   3776 }
   3777 
   3778 
   3779 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   3780   DCHECK(!instr->HasObservableSideEffects());
   3781   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   3782     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   3783   }
   3784   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
   3785   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
   3786   instr->SetSuccessorAt(0, materialize_true);
   3787   instr->SetSuccessorAt(1, materialize_false);
   3788   owner()->FinishCurrentBlock(instr);
   3789   owner()->set_current_block(materialize_true);
   3790   owner()->Push(owner()->graph()->GetConstantTrue());
   3791   owner()->set_current_block(materialize_false);
   3792   owner()->Push(owner()->graph()->GetConstantFalse());
   3793   HBasicBlock* join =
   3794     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   3795   owner()->set_current_block(join);
   3796 }
   3797 
   3798 
   3799 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
   3800                                       BailoutId ast_id) {
   3801   HBasicBlock* materialize_true = NULL;
   3802   HBasicBlock* materialize_false = NULL;
   3803   continuation->Continue(&materialize_true, &materialize_false);
   3804   if (continuation->IsTrueReachable()) {
   3805     owner()->set_current_block(materialize_true);
   3806     owner()->Push(owner()->graph()->GetConstantTrue());
   3807     owner()->set_current_block(materialize_true);
   3808   }
   3809   if (continuation->IsFalseReachable()) {
   3810     owner()->set_current_block(materialize_false);
   3811     owner()->Push(owner()->graph()->GetConstantFalse());
   3812     owner()->set_current_block(materialize_false);
   3813   }
   3814   if (continuation->TrueAndFalseReachable()) {
   3815     HBasicBlock* join =
   3816         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   3817     owner()->set_current_block(join);
   3818   }
   3819 }
   3820 
   3821 
   3822 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   3823   DCHECK(!instr->IsControlInstruction());
   3824   HOptimizedGraphBuilder* builder = owner();
   3825   builder->AddInstruction(instr);
   3826   // We expect a simulate after every expression with side effects, though
   3827   // this one isn't actually needed (and wouldn't work if it were targeted).
   3828   if (instr->HasObservableSideEffects()) {
   3829     builder->Push(instr);
   3830     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   3831     builder->Pop();
   3832   }
   3833   BuildBranch(instr);
   3834 }
   3835 
   3836 
   3837 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   3838   DCHECK(!instr->HasObservableSideEffects());
   3839   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   3840   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   3841   instr->SetSuccessorAt(0, empty_true);
   3842   instr->SetSuccessorAt(1, empty_false);
   3843   owner()->FinishCurrentBlock(instr);
   3844   owner()->Goto(empty_true, if_true(), owner()->function_state());
   3845   owner()->Goto(empty_false, if_false(), owner()->function_state());
   3846   owner()->set_current_block(NULL);
   3847 }
   3848 
   3849 
   3850 void TestContext::ReturnContinuation(HIfContinuation* continuation,
   3851                                      BailoutId ast_id) {
   3852   HBasicBlock* true_branch = NULL;
   3853   HBasicBlock* false_branch = NULL;
   3854   continuation->Continue(&true_branch, &false_branch);
   3855   if (continuation->IsTrueReachable()) {
   3856     owner()->Goto(true_branch, if_true(), owner()->function_state());
   3857   }
   3858   if (continuation->IsFalseReachable()) {
   3859     owner()->Goto(false_branch, if_false(), owner()->function_state());
   3860   }
   3861   owner()->set_current_block(NULL);
   3862 }
   3863 
   3864 
   3865 void TestContext::BuildBranch(HValue* value) {
   3866   // We expect the graph to be in edge-split form: there is no edge that
   3867   // connects a branch node to a join node.  We conservatively ensure that
   3868   // property by always adding an empty block on the outgoing edges of this
   3869   // branch.
   3870   HOptimizedGraphBuilder* builder = owner();
   3871   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
   3872     builder->Bailout(kArgumentsObjectValueInATestContext);
   3873   }
   3874   ToBooleanHints expected(condition()->to_boolean_types());
   3875   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
   3876 }
   3877 
   3878 
   3879 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
   3880 #define CHECK_BAILOUT(call)                     \
   3881   do {                                          \
   3882     call;                                       \
   3883     if (HasStackOverflow()) return;             \
   3884   } while (false)
   3885 
   3886 
   3887 #define CHECK_ALIVE(call)                                       \
   3888   do {                                                          \
   3889     call;                                                       \
   3890     if (HasStackOverflow() || current_block() == NULL) return;  \
   3891   } while (false)
   3892 
   3893 
   3894 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
   3895   do {                                                                \
   3896     call;                                                             \
   3897     if (HasStackOverflow() || current_block() == NULL) return value;  \
   3898   } while (false)
   3899 
   3900 
   3901 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
   3902   current_info()->AbortOptimization(reason);
   3903   SetStackOverflow();
   3904 }
   3905 
   3906 
   3907 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
   3908   EffectContext for_effect(this);
   3909   Visit(expr);
   3910 }
   3911 
   3912 
   3913 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
   3914                                            ArgumentsAllowedFlag flag) {
   3915   ValueContext for_value(this, flag);
   3916   Visit(expr);
   3917 }
   3918 
   3919 
   3920 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
   3921   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   3922   for_value.set_typeof_mode(INSIDE_TYPEOF);
   3923   Visit(expr);
   3924 }
   3925 
   3926 
   3927 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
   3928                                              HBasicBlock* true_block,
   3929                                              HBasicBlock* false_block) {
   3930   TestContext for_control(this, expr, true_block, false_block);
   3931   Visit(expr);
   3932 }
   3933 
   3934 
   3935 void HOptimizedGraphBuilder::VisitExpressions(
   3936     ZoneList<Expression*>* exprs) {
   3937   for (int i = 0; i < exprs->length(); ++i) {
   3938     CHECK_ALIVE(VisitForValue(exprs->at(i)));
   3939   }
   3940 }
   3941 
   3942 
   3943 void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
   3944                                               ArgumentsAllowedFlag flag) {
   3945   for (int i = 0; i < exprs->length(); ++i) {
   3946     CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
   3947   }
   3948 }
   3949 
   3950 
   3951 bool HOptimizedGraphBuilder::BuildGraph() {
   3952   if (IsDerivedConstructor(current_info()->literal()->kind())) {
   3953     Bailout(kSuperReference);
   3954     return false;
   3955   }
   3956 
   3957   DeclarationScope* scope = current_info()->scope();
   3958   SetUpScope(scope);
   3959 
   3960   // Add an edge to the body entry.  This is warty: the graph's start
   3961   // environment will be used by the Lithium translation as the initial
   3962   // environment on graph entry, but it has now been mutated by the
   3963   // Hydrogen translation of the instructions in the start block.  This
   3964   // environment uses values which have not been defined yet.  These
   3965   // Hydrogen instructions will then be replayed by the Lithium
   3966   // translation, so they cannot have an environment effect.  The edge to
   3967   // the body's entry block (along with some special logic for the start
   3968   // block in HInstruction::InsertAfter) seals the start block from
   3969   // getting unwanted instructions inserted.
   3970   //
   3971   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
   3972   // Make the Hydrogen instructions in the initial block into Hydrogen
   3973   // values (but not instructions), present in the initial environment and
   3974   // not replayed by the Lithium translation.
   3975   HEnvironment* initial_env = environment()->CopyWithoutHistory();
   3976   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   3977   Goto(body_entry);
   3978   body_entry->SetJoinId(BailoutId::FunctionEntry());
   3979   set_current_block(body_entry);
   3980 
   3981   VisitDeclarations(scope->declarations());
   3982   Add<HSimulate>(BailoutId::Declarations());
   3983 
   3984   Add<HStackCheck>(HStackCheck::kFunctionEntry);
   3985 
   3986   VisitStatements(current_info()->literal()->body());
   3987   if (HasStackOverflow()) return false;
   3988 
   3989   if (current_block() != NULL) {
   3990     Add<HReturn>(graph()->GetConstantUndefined());
   3991     set_current_block(NULL);
   3992   }
   3993 
   3994   // If the checksum of the number of type info changes is the same as the
   3995   // last time this function was compiled, then this recompile is likely not
   3996   // due to missing/inadequate type feedback, but rather too aggressive
   3997   // optimization. Disable optimistic LICM in that case.
   3998   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
   3999   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   4000   Handle<TypeFeedbackInfo> type_info(
   4001       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   4002   int checksum = type_info->own_type_change_checksum();
   4003   int composite_checksum = graph()->update_type_change_checksum(checksum);
   4004   graph()->set_use_optimistic_licm(
   4005       !type_info->matches_inlined_type_change_checksum(composite_checksum));
   4006   type_info->set_inlined_type_change_checksum(composite_checksum);
   4007 
   4008   // Set this predicate early to avoid handle deref during graph optimization.
   4009   graph()->set_allow_code_motion(
   4010       current_info()->IsStub() ||
   4011       current_info()->shared_info()->opt_count() + 1 < FLAG_max_opt_count);
   4012 
   4013   // Perform any necessary OSR-specific cleanups or changes to the graph.
   4014   osr()->FinishGraph();
   4015 
   4016   return true;
   4017 }
   4018 
   4019 
   4020 bool HGraph::Optimize(BailoutReason* bailout_reason) {
   4021   OrderBlocks();
   4022   AssignDominators();
   4023 
   4024   // We need to create a HConstant "zero" now so that GVN will fold every
   4025   // zero-valued constant in the graph together.
   4026   // The constant is needed to make idef-based bounds check work: the pass
   4027   // evaluates relations with "zero" and that zero cannot be created after GVN.
   4028   GetConstant0();
   4029 
   4030 #ifdef DEBUG
   4031   // Do a full verify after building the graph and computing dominators.
   4032   Verify(true);
   4033 #endif
   4034 
   4035   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
   4036     Run<HEnvironmentLivenessAnalysisPhase>();
   4037   }
   4038 
   4039   if (!CheckConstPhiUses()) {
   4040     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
   4041     return false;
   4042   }
   4043   Run<HRedundantPhiEliminationPhase>();
   4044   if (!CheckArgumentsPhiUses()) {
   4045     *bailout_reason = kUnsupportedPhiUseOfArguments;
   4046     return false;
   4047   }
   4048 
   4049   // Find and mark unreachable code to simplify optimizations, especially gvn,
   4050   // where unreachable code could unnecessarily defeat LICM.
   4051   Run<HMarkUnreachableBlocksPhase>();
   4052 
   4053   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4054   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
   4055 
   4056   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
   4057 
   4058   CollectPhis();
   4059 
   4060   if (has_osr()) osr()->FinishOsrValues();
   4061 
   4062   Run<HInferRepresentationPhase>();
   4063 
   4064   // Remove HSimulate instructions that have turned out not to be needed
   4065   // after all by folding them into the following HSimulate.
   4066   // This must happen after inferring representations.
   4067   Run<HMergeRemovableSimulatesPhase>();
   4068 
   4069   Run<HRepresentationChangesPhase>();
   4070 
   4071   Run<HInferTypesPhase>();
   4072 
   4073   // Must be performed before canonicalization to ensure that Canonicalize
   4074   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
   4075   // zero.
   4076   Run<HUint32AnalysisPhase>();
   4077 
   4078   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
   4079 
   4080   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
   4081 
   4082   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
   4083 
   4084   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
   4085 
   4086   Run<HRangeAnalysisPhase>();
   4087 
   4088   // Eliminate redundant stack checks on backwards branches.
   4089   Run<HStackCheckEliminationPhase>();
   4090 
   4091   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
   4092   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
   4093   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4094 
   4095   RestoreActualValues();
   4096 
   4097   // Find unreachable code a second time, GVN and other optimizations may have
   4098   // made blocks unreachable that were previously reachable.
   4099   Run<HMarkUnreachableBlocksPhase>();
   4100 
   4101   return true;
   4102 }
   4103 
   4104 
   4105 void HGraph::RestoreActualValues() {
   4106   HPhase phase("H_Restore actual values", this);
   4107 
   4108   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
   4109     HBasicBlock* block = blocks()->at(block_index);
   4110 
   4111 #ifdef DEBUG
   4112     for (int i = 0; i < block->phis()->length(); i++) {
   4113       HPhi* phi = block->phis()->at(i);
   4114       DCHECK(phi->ActualValue() == phi);
   4115     }
   4116 #endif
   4117 
   4118     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
   4119       HInstruction* instruction = it.Current();
   4120       if (instruction->ActualValue() == instruction) continue;
   4121       if (instruction->CheckFlag(HValue::kIsDead)) {
   4122         // The instruction was marked as deleted but left in the graph
   4123         // as a control flow dependency point for subsequent
   4124         // instructions.
   4125         instruction->DeleteAndReplaceWith(instruction->ActualValue());
   4126       } else {
   4127         DCHECK(instruction->IsInformativeDefinition());
   4128         if (instruction->IsPurelyInformativeDefinition()) {
   4129           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
   4130         } else {
   4131           instruction->ReplaceAllUsesWith(instruction->ActualValue());
   4132         }
   4133       }
   4134     }
   4135   }
   4136 }
   4137 
   4138 
   4139 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
   4140   ZoneList<HValue*> arguments(count, zone());
   4141   for (int i = 0; i < count; ++i) {
   4142     arguments.Add(Pop(), zone());
   4143   }
   4144 
   4145   HPushArguments* push_args = New<HPushArguments>();
   4146   while (!arguments.is_empty()) {
   4147     push_args->AddInput(arguments.RemoveLast());
   4148   }
   4149   AddInstruction(push_args);
   4150 }
   4151 
   4152 
   4153 template <class Instruction>
   4154 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
   4155   PushArgumentsFromEnvironment(call->argument_count());
   4156   return call;
   4157 }
   4158 
   4159 void HOptimizedGraphBuilder::SetUpScope(DeclarationScope* scope) {
   4160   HEnvironment* prolog_env = environment();
   4161   int parameter_count = environment()->parameter_count();
   4162   ZoneList<HValue*> parameters(parameter_count, zone());
   4163   for (int i = 0; i < parameter_count; ++i) {
   4164     HInstruction* parameter = Add<HParameter>(static_cast<unsigned>(i));
   4165     parameters.Add(parameter, zone());
   4166     environment()->Bind(i, parameter);
   4167   }
   4168 
   4169   HConstant* undefined_constant = graph()->GetConstantUndefined();
   4170   // Initialize specials and locals to undefined.
   4171   for (int i = parameter_count + 1; i < environment()->length(); ++i) {
   4172     environment()->Bind(i, undefined_constant);
   4173   }
   4174   Add<HPrologue>();
   4175 
   4176   HEnvironment* initial_env = environment()->CopyWithoutHistory();
   4177   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   4178   GotoNoSimulate(body_entry);
   4179   set_current_block(body_entry);
   4180 
   4181   // Initialize context of prolog environment to undefined.
   4182   prolog_env->BindContext(undefined_constant);
   4183 
   4184   // First special is HContext.
   4185   HInstruction* context = Add<HContext>();
   4186   environment()->BindContext(context);
   4187 
   4188   // Create an arguments object containing the initial parameters.  Set the
   4189   // initial values of parameters including "this" having parameter index 0.
   4190   DCHECK_EQ(scope->num_parameters() + 1, parameter_count);
   4191   HArgumentsObject* arguments_object = New<HArgumentsObject>(parameter_count);
   4192   for (int i = 0; i < parameter_count; ++i) {
   4193     HValue* parameter = parameters.at(i);
   4194     arguments_object->AddArgument(parameter, zone());
   4195   }
   4196 
   4197   AddInstruction(arguments_object);
   4198 
   4199   // Handle the arguments and arguments shadow variables specially (they do
   4200   // not have declarations).
   4201   if (scope->arguments() != NULL) {
   4202     environment()->Bind(scope->arguments(), arguments_object);
   4203   }
   4204 
   4205   if (scope->rest_parameter() != nullptr) {
   4206     return Bailout(kRestParameter);
   4207   }
   4208 
   4209   if (scope->this_function_var() != nullptr ||
   4210       scope->new_target_var() != nullptr) {
   4211     return Bailout(kSuperReference);
   4212   }
   4213 
   4214   // Trace the call.
   4215   if (FLAG_trace && top_info()->IsOptimizing()) {
   4216     Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kTraceEnter), 0);
   4217   }
   4218 }
   4219 
   4220 
   4221 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
   4222   for (int i = 0; i < statements->length(); i++) {
   4223     Statement* stmt = statements->at(i);
   4224     CHECK_ALIVE(Visit(stmt));
   4225     if (stmt->IsJump()) break;
   4226   }
   4227 }
   4228 
   4229 
   4230 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
   4231   DCHECK(!HasStackOverflow());
   4232   DCHECK(current_block() != NULL);
   4233   DCHECK(current_block()->HasPredecessor());
   4234 
   4235   Scope* outer_scope = scope();
   4236   Scope* scope = stmt->scope();
   4237   BreakAndContinueInfo break_info(stmt, outer_scope);
   4238 
   4239   { BreakAndContinueScope push(&break_info, this);
   4240     if (scope != NULL) {
   4241       if (scope->NeedsContext()) {
   4242         // Load the function object.
   4243         DeclarationScope* declaration_scope = scope->GetDeclarationScope();
   4244         HInstruction* function;
   4245         HValue* outer_context = environment()->context();
   4246         if (declaration_scope->is_script_scope() ||
   4247             declaration_scope->is_eval_scope()) {
   4248           function = new (zone())
   4249               HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
   4250                                HLoadContextSlot::kNoCheck);
   4251         } else {
   4252           function = New<HThisFunction>();
   4253         }
   4254         AddInstruction(function);
   4255         // Allocate a block context and store it to the stack frame.
   4256         HValue* scope_info = Add<HConstant>(scope->scope_info());
   4257         Add<HPushArguments>(scope_info, function);
   4258         HInstruction* inner_context = Add<HCallRuntime>(
   4259             Runtime::FunctionForId(Runtime::kPushBlockContext), 2);
   4260         inner_context->SetFlag(HValue::kHasNoObservableSideEffects);
   4261         set_scope(scope);
   4262         environment()->BindContext(inner_context);
   4263       }
   4264       VisitDeclarations(scope->declarations());
   4265       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
   4266     }
   4267     CHECK_BAILOUT(VisitStatements(stmt->statements()));
   4268   }
   4269   set_scope(outer_scope);
   4270   if (scope != NULL && current_block() != NULL &&
   4271       scope->ContextLocalCount() > 0) {
   4272     HValue* inner_context = environment()->context();
   4273     HValue* outer_context = Add<HLoadNamedField>(
   4274         inner_context, nullptr,
   4275         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4276 
   4277     environment()->BindContext(outer_context);
   4278   }
   4279   HBasicBlock* break_block = break_info.break_block();
   4280   if (break_block != NULL) {
   4281     if (current_block() != NULL) Goto(break_block);
   4282     break_block->SetJoinId(stmt->ExitId());
   4283     set_current_block(break_block);
   4284   }
   4285 }
   4286 
   4287 
   4288 void HOptimizedGraphBuilder::VisitExpressionStatement(
   4289     ExpressionStatement* stmt) {
   4290   DCHECK(!HasStackOverflow());
   4291   DCHECK(current_block() != NULL);
   4292   DCHECK(current_block()->HasPredecessor());
   4293   VisitForEffect(stmt->expression());
   4294 }
   4295 
   4296 
   4297 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
   4298   DCHECK(!HasStackOverflow());
   4299   DCHECK(current_block() != NULL);
   4300   DCHECK(current_block()->HasPredecessor());
   4301 }
   4302 
   4303 
   4304 void HOptimizedGraphBuilder::VisitSloppyBlockFunctionStatement(
   4305     SloppyBlockFunctionStatement* stmt) {
   4306   Visit(stmt->statement());
   4307 }
   4308 
   4309 
   4310 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
   4311   DCHECK(!HasStackOverflow());
   4312   DCHECK(current_block() != NULL);
   4313   DCHECK(current_block()->HasPredecessor());
   4314   if (stmt->condition()->ToBooleanIsTrue()) {
   4315     Add<HSimulate>(stmt->ThenId());
   4316     Visit(stmt->then_statement());
   4317   } else if (stmt->condition()->ToBooleanIsFalse()) {
   4318     Add<HSimulate>(stmt->ElseId());
   4319     Visit(stmt->else_statement());
   4320   } else {
   4321     HBasicBlock* cond_true = graph()->CreateBasicBlock();
   4322     HBasicBlock* cond_false = graph()->CreateBasicBlock();
   4323     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
   4324 
   4325     // Technically, we should be able to handle the case when one side of
   4326     // the test is not connected, but this can trip up liveness analysis
   4327     // if we did not fully connect the test context based on some optimistic
   4328     // assumption. If such an assumption was violated, we would end up with
   4329     // an environment with optimized-out values. So we should always
   4330     // conservatively connect the test context.
   4331     CHECK(cond_true->HasPredecessor());
   4332     CHECK(cond_false->HasPredecessor());
   4333 
   4334     cond_true->SetJoinId(stmt->ThenId());
   4335     set_current_block(cond_true);
   4336     CHECK_BAILOUT(Visit(stmt->then_statement()));
   4337     cond_true = current_block();
   4338 
   4339     cond_false->SetJoinId(stmt->ElseId());
   4340     set_current_block(cond_false);
   4341     CHECK_BAILOUT(Visit(stmt->else_statement()));
   4342     cond_false = current_block();
   4343 
   4344     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
   4345     set_current_block(join);
   4346   }
   4347 }
   4348 
   4349 
   4350 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
   4351     BreakableStatement* stmt,
   4352     BreakType type,
   4353     Scope** scope,
   4354     int* drop_extra) {
   4355   *drop_extra = 0;
   4356   BreakAndContinueScope* current = this;
   4357   while (current != NULL && current->info()->target() != stmt) {
   4358     *drop_extra += current->info()->drop_extra();
   4359     current = current->next();
   4360   }
   4361   DCHECK(current != NULL);  // Always found (unless stack is malformed).
   4362   *scope = current->info()->scope();
   4363 
   4364   if (type == BREAK) {
   4365     *drop_extra += current->info()->drop_extra();
   4366   }
   4367 
   4368   HBasicBlock* block = NULL;
   4369   switch (type) {
   4370     case BREAK:
   4371       block = current->info()->break_block();
   4372       if (block == NULL) {
   4373         block = current->owner()->graph()->CreateBasicBlock();
   4374         current->info()->set_break_block(block);
   4375       }
   4376       break;
   4377 
   4378     case CONTINUE:
   4379       block = current->info()->continue_block();
   4380       if (block == NULL) {
   4381         block = current->owner()->graph()->CreateBasicBlock();
   4382         current->info()->set_continue_block(block);
   4383       }
   4384       break;
   4385   }
   4386 
   4387   return block;
   4388 }
   4389 
   4390 
   4391 void HOptimizedGraphBuilder::VisitContinueStatement(
   4392     ContinueStatement* stmt) {
   4393   DCHECK(!HasStackOverflow());
   4394   DCHECK(current_block() != NULL);
   4395   DCHECK(current_block()->HasPredecessor());
   4396 
   4397   if (function_state()->IsInsideDoExpressionScope()) {
   4398     return Bailout(kDoExpressionUnmodelable);
   4399   }
   4400 
   4401   Scope* outer_scope = NULL;
   4402   Scope* inner_scope = scope();
   4403   int drop_extra = 0;
   4404   HBasicBlock* continue_block = break_scope()->Get(
   4405       stmt->target(), BreakAndContinueScope::CONTINUE,
   4406       &outer_scope, &drop_extra);
   4407   HValue* context = environment()->context();
   4408   Drop(drop_extra);
   4409   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4410   if (context_pop_count > 0) {
   4411     while (context_pop_count-- > 0) {
   4412       HInstruction* context_instruction = Add<HLoadNamedField>(
   4413           context, nullptr,
   4414           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4415       context = context_instruction;
   4416     }
   4417     environment()->BindContext(context);
   4418   }
   4419 
   4420   Goto(continue_block);
   4421   set_current_block(NULL);
   4422 }
   4423 
   4424 
   4425 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
   4426   DCHECK(!HasStackOverflow());
   4427   DCHECK(current_block() != NULL);
   4428   DCHECK(current_block()->HasPredecessor());
   4429 
   4430   if (function_state()->IsInsideDoExpressionScope()) {
   4431     return Bailout(kDoExpressionUnmodelable);
   4432   }
   4433 
   4434   Scope* outer_scope = NULL;
   4435   Scope* inner_scope = scope();
   4436   int drop_extra = 0;
   4437   HBasicBlock* break_block = break_scope()->Get(
   4438       stmt->target(), BreakAndContinueScope::BREAK,
   4439       &outer_scope, &drop_extra);
   4440   HValue* context = environment()->context();
   4441   Drop(drop_extra);
   4442   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4443   if (context_pop_count > 0) {
   4444     while (context_pop_count-- > 0) {
   4445       HInstruction* context_instruction = Add<HLoadNamedField>(
   4446           context, nullptr,
   4447           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4448       context = context_instruction;
   4449     }
   4450     environment()->BindContext(context);
   4451   }
   4452   Goto(break_block);
   4453   set_current_block(NULL);
   4454 }
   4455 
   4456 
   4457 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
   4458   DCHECK(!HasStackOverflow());
   4459   DCHECK(current_block() != NULL);
   4460   DCHECK(current_block()->HasPredecessor());
   4461   FunctionState* state = function_state();
   4462   AstContext* context = call_context();
   4463   if (context == NULL) {
   4464     // Not an inlined return, so an actual one.
   4465     CHECK_ALIVE(VisitForValue(stmt->expression()));
   4466     HValue* result = environment()->Pop();
   4467     Add<HReturn>(result);
   4468   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   4469     // Return from an inlined construct call. In a test context the return value
   4470     // will always evaluate to true, in a value context the return value needs
   4471     // to be a JSObject.
   4472     if (context->IsTest()) {
   4473       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4474       context->ReturnValue(graph()->GetConstantTrue());
   4475     } else if (context->IsEffect()) {
   4476       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4477       Goto(function_return(), state);
   4478     } else {
   4479       DCHECK(context->IsValue());
   4480       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4481       HValue* return_value = Pop();
   4482       HValue* receiver = environment()->arguments_environment()->Lookup(0);
   4483       HHasInstanceTypeAndBranch* typecheck =
   4484           New<HHasInstanceTypeAndBranch>(return_value,
   4485                                          FIRST_JS_RECEIVER_TYPE,
   4486                                          LAST_JS_RECEIVER_TYPE);
   4487       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
   4488       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
   4489       typecheck->SetSuccessorAt(0, if_spec_object);
   4490       typecheck->SetSuccessorAt(1, not_spec_object);
   4491       FinishCurrentBlock(typecheck);
   4492       AddLeaveInlined(if_spec_object, return_value, state);
   4493       AddLeaveInlined(not_spec_object, receiver, state);
   4494     }
   4495   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   4496     // Return from an inlined setter call. The returned value is never used, the
   4497     // value of an assignment is always the value of the RHS of the assignment.
   4498     CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4499     if (context->IsTest()) {
   4500       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4501       context->ReturnValue(rhs);
   4502     } else if (context->IsEffect()) {
   4503       Goto(function_return(), state);
   4504     } else {
   4505       DCHECK(context->IsValue());
   4506       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4507       AddLeaveInlined(rhs, state);
   4508     }
   4509   } else {
   4510     // Return from a normal inlined function. Visit the subexpression in the
   4511     // expression context of the call.
   4512     if (context->IsTest()) {
   4513       TestContext* test = TestContext::cast(context);
   4514       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
   4515     } else if (context->IsEffect()) {
   4516       // Visit in value context and ignore the result. This is needed to keep
   4517       // environment in sync with full-codegen since some visitors (e.g.
   4518       // VisitCountOperation) use the operand stack differently depending on
   4519       // context.
   4520       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4521       Pop();
   4522       Goto(function_return(), state);
   4523     } else {
   4524       DCHECK(context->IsValue());
   4525       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4526       AddLeaveInlined(Pop(), state);
   4527     }
   4528   }
   4529   set_current_block(NULL);
   4530 }
   4531 
   4532 
   4533 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
   4534   DCHECK(!HasStackOverflow());
   4535   DCHECK(current_block() != NULL);
   4536   DCHECK(current_block()->HasPredecessor());
   4537   return Bailout(kWithStatement);
   4538 }
   4539 
   4540 
   4541 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
   4542   DCHECK(!HasStackOverflow());
   4543   DCHECK(current_block() != NULL);
   4544   DCHECK(current_block()->HasPredecessor());
   4545 
   4546   ZoneList<CaseClause*>* clauses = stmt->cases();
   4547   int clause_count = clauses->length();
   4548   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
   4549 
   4550   CHECK_ALIVE(VisitForValue(stmt->tag()));
   4551   Add<HSimulate>(stmt->EntryId());
   4552   HValue* tag_value = Top();
   4553   AstType* tag_type = bounds_.get(stmt->tag()).lower;
   4554 
   4555   // 1. Build all the tests, with dangling true branches
   4556   BailoutId default_id = BailoutId::None();
   4557   for (int i = 0; i < clause_count; ++i) {
   4558     CaseClause* clause = clauses->at(i);
   4559     if (clause->is_default()) {
   4560       body_blocks.Add(NULL, zone());
   4561       if (default_id.IsNone()) default_id = clause->EntryId();
   4562       continue;
   4563     }
   4564 
   4565     // Generate a compare and branch.
   4566     CHECK_BAILOUT(VisitForValue(clause->label()));
   4567     if (current_block() == NULL) return Bailout(kUnsupportedSwitchStatement);
   4568     HValue* label_value = Pop();
   4569 
   4570     AstType* label_type = bounds_.get(clause->label()).lower;
   4571     AstType* combined_type = clause->compare_type();
   4572     HControlInstruction* compare = BuildCompareInstruction(
   4573         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
   4574         combined_type,
   4575         ScriptPositionToSourcePosition(stmt->tag()->position()),
   4576         ScriptPositionToSourcePosition(clause->label()->position()),
   4577         PUSH_BEFORE_SIMULATE, clause->id());
   4578 
   4579     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
   4580     HBasicBlock* body_block = graph()->CreateBasicBlock();
   4581     body_blocks.Add(body_block, zone());
   4582     compare->SetSuccessorAt(0, body_block);
   4583     compare->SetSuccessorAt(1, next_test_block);
   4584     FinishCurrentBlock(compare);
   4585 
   4586     set_current_block(body_block);
   4587     Drop(1);  // tag_value
   4588 
   4589     set_current_block(next_test_block);
   4590   }
   4591 
   4592   // Save the current block to use for the default or to join with the
   4593   // exit.
   4594   HBasicBlock* last_block = current_block();
   4595   Drop(1);  // tag_value
   4596 
   4597   // 2. Loop over the clauses and the linked list of tests in lockstep,
   4598   // translating the clause bodies.
   4599   HBasicBlock* fall_through_block = NULL;
   4600 
   4601   BreakAndContinueInfo break_info(stmt, scope());
   4602   { BreakAndContinueScope push(&break_info, this);
   4603     for (int i = 0; i < clause_count; ++i) {
   4604       CaseClause* clause = clauses->at(i);
   4605 
   4606       // Identify the block where normal (non-fall-through) control flow
   4607       // goes to.
   4608       HBasicBlock* normal_block = NULL;
   4609       if (clause->is_default()) {
   4610         if (last_block == NULL) continue;
   4611         normal_block = last_block;
   4612         last_block = NULL;  // Cleared to indicate we've handled it.
   4613       } else {
   4614         normal_block = body_blocks[i];
   4615       }
   4616 
   4617       if (fall_through_block == NULL) {
   4618         set_current_block(normal_block);
   4619       } else {
   4620         HBasicBlock* join = CreateJoin(fall_through_block,
   4621                                        normal_block,
   4622                                        clause->EntryId());
   4623         set_current_block(join);
   4624       }
   4625 
   4626       CHECK_BAILOUT(VisitStatements(clause->statements()));
   4627       fall_through_block = current_block();
   4628     }
   4629   }
   4630 
   4631   // Create an up-to-3-way join.  Use the break block if it exists since
   4632   // it's already a join block.
   4633   HBasicBlock* break_block = break_info.break_block();
   4634   if (break_block == NULL) {
   4635     set_current_block(CreateJoin(fall_through_block,
   4636                                  last_block,
   4637                                  stmt->ExitId()));
   4638   } else {
   4639     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
   4640     if (last_block != NULL) Goto(last_block, break_block);
   4641     break_block->SetJoinId(stmt->ExitId());
   4642     set_current_block(break_block);
   4643   }
   4644 }
   4645 
   4646 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
   4647                                            BailoutId stack_check_id,
   4648                                            HBasicBlock* loop_entry) {
   4649   Add<HSimulate>(stack_check_id);
   4650   HStackCheck* stack_check =
   4651       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
   4652   DCHECK(loop_entry->IsLoopHeader());
   4653   loop_entry->loop_information()->set_stack_check(stack_check);
   4654   CHECK_BAILOUT(Visit(stmt->body()));
   4655 }
   4656 
   4657 
   4658 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   4659   DCHECK(!HasStackOverflow());
   4660   DCHECK(current_block() != NULL);
   4661   DCHECK(current_block()->HasPredecessor());
   4662   DCHECK(current_block() != NULL);
   4663   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4664 
   4665   BreakAndContinueInfo break_info(stmt, scope());
   4666   {
   4667     BreakAndContinueScope push(&break_info, this);
   4668     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   4669   }
   4670   HBasicBlock* body_exit = JoinContinue(
   4671       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
   4672   HBasicBlock* loop_successor = NULL;
   4673   if (body_exit != NULL) {
   4674     set_current_block(body_exit);
   4675     loop_successor = graph()->CreateBasicBlock();
   4676     if (stmt->cond()->ToBooleanIsFalse()) {
   4677       loop_entry->loop_information()->stack_check()->Eliminate();
   4678       Goto(loop_successor);
   4679       body_exit = NULL;
   4680     } else {
   4681       // The block for a true condition, the actual predecessor block of the
   4682       // back edge.
   4683       body_exit = graph()->CreateBasicBlock();
   4684       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
   4685     }
   4686     if (body_exit != NULL && body_exit->HasPredecessor()) {
   4687       body_exit->SetJoinId(stmt->BackEdgeId());
   4688     } else {
   4689       body_exit = NULL;
   4690     }
   4691     if (loop_successor->HasPredecessor()) {
   4692       loop_successor->SetJoinId(stmt->ExitId());
   4693     } else {
   4694       loop_successor = NULL;
   4695     }
   4696   }
   4697   HBasicBlock* loop_exit = CreateLoop(stmt,
   4698                                       loop_entry,
   4699                                       body_exit,
   4700                                       loop_successor,
   4701                                       break_info.break_block());
   4702   set_current_block(loop_exit);
   4703 }
   4704 
   4705 
   4706 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
   4707   DCHECK(!HasStackOverflow());
   4708   DCHECK(current_block() != NULL);
   4709   DCHECK(current_block()->HasPredecessor());
   4710   DCHECK(current_block() != NULL);
   4711   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4712 
   4713   // If the condition is constant true, do not generate a branch.
   4714   HBasicBlock* loop_successor = NULL;
   4715   HBasicBlock* body_entry = graph()->CreateBasicBlock();
   4716   loop_successor = graph()->CreateBasicBlock();
   4717   CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   4718   if (body_entry->HasPredecessor()) {
   4719     body_entry->SetJoinId(stmt->BodyId());
   4720     set_current_block(body_entry);
   4721   }
   4722   if (loop_successor->HasPredecessor()) {
   4723     loop_successor->SetJoinId(stmt->ExitId());
   4724   } else {
   4725     loop_successor = NULL;
   4726   }
   4727 
   4728   BreakAndContinueInfo break_info(stmt, scope());
   4729   if (current_block() != NULL) {
   4730     BreakAndContinueScope push(&break_info, this);
   4731     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   4732   }
   4733   HBasicBlock* body_exit = JoinContinue(
   4734       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
   4735   HBasicBlock* loop_exit = CreateLoop(stmt,
   4736                                       loop_entry,
   4737                                       body_exit,
   4738                                       loop_successor,
   4739                                       break_info.break_block());
   4740   set_current_block(loop_exit);
   4741 }
   4742 
   4743 
   4744 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
   4745   DCHECK(!HasStackOverflow());
   4746   DCHECK(current_block() != NULL);
   4747   DCHECK(current_block()->HasPredecessor());
   4748   if (stmt->init() != NULL) {
   4749     CHECK_ALIVE(Visit(stmt->init()));
   4750   }
   4751   DCHECK(current_block() != NULL);
   4752   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4753 
   4754   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
   4755   HBasicBlock* body_entry = graph()->CreateBasicBlock();
   4756   if (stmt->cond() != NULL) {
   4757     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   4758     if (body_entry->HasPredecessor()) {
   4759       body_entry->SetJoinId(stmt->BodyId());
   4760       set_current_block(body_entry);
   4761     }
   4762     if (loop_successor->HasPredecessor()) {
   4763       loop_successor->SetJoinId(stmt->ExitId());
   4764     } else {
   4765       loop_successor = NULL;
   4766     }
   4767   } else {
   4768     // Create dummy control flow so that variable liveness analysis
   4769     // produces teh correct result.
   4770     HControlInstruction* branch = New<HBranch>(graph()->GetConstantTrue());
   4771     branch->SetSuccessorAt(0, body_entry);
   4772     branch->SetSuccessorAt(1, loop_successor);
   4773     FinishCurrentBlock(branch);
   4774     set_current_block(body_entry);
   4775   }
   4776 
   4777   BreakAndContinueInfo break_info(stmt, scope());
   4778   if (current_block() != NULL) {
   4779     BreakAndContinueScope push(&break_info, this);
   4780     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   4781   }
   4782   HBasicBlock* body_exit = JoinContinue(
   4783       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
   4784 
   4785   if (stmt->next() != NULL && body_exit != NULL) {
   4786     set_current_block(body_exit);
   4787     CHECK_BAILOUT(Visit(stmt->next()));
   4788     body_exit = current_block();
   4789   }
   4790 
   4791   HBasicBlock* loop_exit = CreateLoop(stmt,
   4792                                       loop_entry,
   4793                                       body_exit,
   4794                                       loop_successor,
   4795                                       break_info.break_block());
   4796   set_current_block(loop_exit);
   4797 }
   4798 
   4799 
   4800 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   4801   DCHECK(!HasStackOverflow());
   4802   DCHECK(current_block() != NULL);
   4803   DCHECK(current_block()->HasPredecessor());
   4804 
   4805   if (!stmt->each()->IsVariableProxy() ||
   4806       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
   4807     return Bailout(kForInStatementWithNonLocalEachVariable);
   4808   }
   4809 
   4810   Variable* each_var = stmt->each()->AsVariableProxy()->var();
   4811 
   4812   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
   4813   HValue* enumerable = Top();  // Leave enumerable at the top.
   4814 
   4815   IfBuilder if_undefined_or_null(this);
   4816   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
   4817       enumerable, graph()->GetConstantUndefined());
   4818   if_undefined_or_null.Or();
   4819   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
   4820       enumerable, graph()->GetConstantNull());
   4821   if_undefined_or_null.ThenDeopt(DeoptimizeReason::kUndefinedOrNullInForIn);
   4822   if_undefined_or_null.End();
   4823   BuildForInBody(stmt, each_var, enumerable);
   4824 }
   4825 
   4826 
   4827 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
   4828                                             Variable* each_var,
   4829                                             HValue* enumerable) {
   4830   Handle<Map> meta_map = isolate()->factory()->meta_map();
   4831   bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
   4832   BuildCheckHeapObject(enumerable);
   4833   Add<HCheckInstanceType>(enumerable, HCheckInstanceType::IS_JS_RECEIVER);
   4834   Add<HSimulate>(stmt->ToObjectId());
   4835   if (fast) {
   4836     HForInPrepareMap* map = Add<HForInPrepareMap>(enumerable);
   4837     Push(map);
   4838     Add<HSimulate>(stmt->EnumId());
   4839     Drop(1);
   4840     Add<HCheckMaps>(map, meta_map);
   4841 
   4842     HForInCacheArray* array = Add<HForInCacheArray>(
   4843         enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
   4844     HValue* enum_length = BuildEnumLength(map);
   4845 
   4846     HForInCacheArray* index_cache = Add<HForInCacheArray>(
   4847         enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
   4848     array->set_index_cache(index_cache);
   4849 
   4850     Push(map);
   4851     Push(array);
   4852     Push(enum_length);
   4853     Add<HSimulate>(stmt->PrepareId());
   4854   } else {
   4855     Runtime::FunctionId function_id = Runtime::kForInEnumerate;
   4856     Add<HPushArguments>(enumerable);
   4857     HCallRuntime* array =
   4858         Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
   4859     Push(array);
   4860     Add<HSimulate>(stmt->EnumId());
   4861     Drop(1);
   4862 
   4863     IfBuilder if_fast(this);
   4864     if_fast.If<HCompareMap>(array, meta_map);
   4865     if_fast.Then();
   4866     {
   4867       HValue* cache_map = array;
   4868       HForInCacheArray* cache = Add<HForInCacheArray>(
   4869           enumerable, cache_map, DescriptorArray::kEnumCacheBridgeCacheIndex);
   4870       HValue* enum_length = BuildEnumLength(cache_map);
   4871       Push(cache_map);
   4872       Push(cache);
   4873       Push(enum_length);
   4874       Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
   4875     }
   4876     if_fast.Else();
   4877     {
   4878       Push(graph()->GetConstant1());
   4879       Push(array);
   4880       Push(AddLoadFixedArrayLength(array));
   4881       Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
   4882     }
   4883   }
   4884 
   4885   Push(graph()->GetConstant0());
   4886 
   4887   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4888 
   4889   // Reload the values to ensure we have up-to-date values inside of the loop.
   4890   // This is relevant especially for OSR where the values don't come from the
   4891   // computation above, but from the OSR entry block.
   4892   HValue* index = environment()->ExpressionStackAt(0);
   4893   HValue* limit = environment()->ExpressionStackAt(1);
   4894   HValue* array = environment()->ExpressionStackAt(2);
   4895   HValue* type = environment()->ExpressionStackAt(3);
   4896   enumerable = environment()->ExpressionStackAt(4);
   4897 
   4898   // Check that we still have more keys.
   4899   HCompareNumericAndBranch* compare_index =
   4900       New<HCompareNumericAndBranch>(index, limit, Token::LT);
   4901   compare_index->set_observed_input_representation(
   4902       Representation::Smi(), Representation::Smi());
   4903 
   4904   HBasicBlock* loop_body = graph()->CreateBasicBlock();
   4905   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
   4906 
   4907   compare_index->SetSuccessorAt(0, loop_body);
   4908   compare_index->SetSuccessorAt(1, loop_successor);
   4909   FinishCurrentBlock(compare_index);
   4910 
   4911   set_current_block(loop_successor);
   4912   Drop(5);
   4913 
   4914   set_current_block(loop_body);
   4915 
   4916   // Compute the next enumerated value.
   4917   HValue* key = Add<HLoadKeyed>(array, index, index, nullptr, FAST_ELEMENTS);
   4918 
   4919   HBasicBlock* continue_block = nullptr;
   4920   if (fast) {
   4921     // Check if expected map still matches that of the enumerable.
   4922     Add<HCheckMapValue>(enumerable, type);
   4923     Add<HSimulate>(stmt->FilterId());
   4924   } else {
   4925     // We need the continue block here to be able to skip over invalidated keys.
   4926     continue_block = graph()->CreateBasicBlock();
   4927 
   4928     // We cannot use the IfBuilder here, since we need to be able to jump
   4929     // over the loop body in case of undefined result from %ForInFilter,
   4930     // and the poor soul that is the IfBuilder get's really confused about
   4931     // such "advanced control flow requirements".
   4932     HBasicBlock* if_fast = graph()->CreateBasicBlock();
   4933     HBasicBlock* if_slow = graph()->CreateBasicBlock();
   4934     HBasicBlock* if_slow_pass = graph()->CreateBasicBlock();
   4935     HBasicBlock* if_slow_skip = graph()->CreateBasicBlock();
   4936     HBasicBlock* if_join = graph()->CreateBasicBlock();
   4937 
   4938     // Check if expected map still matches that of the enumerable.
   4939     HValue* enumerable_map =
   4940         Add<HLoadNamedField>(enumerable, nullptr, HObjectAccess::ForMap());
   4941     FinishCurrentBlock(
   4942         New<HCompareObjectEqAndBranch>(enumerable_map, type, if_fast, if_slow));
   4943     set_current_block(if_fast);
   4944     {
   4945       // The enum cache for enumerable is still valid, no need to check key.
   4946       Push(key);
   4947       Goto(if_join);
   4948     }
   4949     set_current_block(if_slow);
   4950     {
   4951       Callable callable = CodeFactory::ForInFilter(isolate());
   4952       HValue* values[] = {key, enumerable};
   4953       HConstant* stub_value = Add<HConstant>(callable.code());
   4954       Push(Add<HCallWithDescriptor>(stub_value, 0, callable.descriptor(),
   4955                                     ArrayVector(values)));
   4956       Add<HSimulate>(stmt->FilterId());
   4957       FinishCurrentBlock(New<HCompareObjectEqAndBranch>(
   4958           Top(), graph()->GetConstantUndefined(), if_slow_skip, if_slow_pass));
   4959     }
   4960     set_current_block(if_slow_pass);
   4961     { Goto(if_join); }
   4962     set_current_block(if_slow_skip);
   4963     {
   4964       // The key is no longer valid for enumerable, skip it.
   4965       Drop(1);
   4966       Goto(continue_block);
   4967     }
   4968     if_join->SetJoinId(stmt->FilterId());
   4969     set_current_block(if_join);
   4970     key = Pop();
   4971   }
   4972 
   4973   Bind(each_var, key);
   4974   Add<HSimulate>(stmt->AssignmentId());
   4975 
   4976   BreakAndContinueInfo break_info(stmt, scope(), 5);
   4977   break_info.set_continue_block(continue_block);
   4978   {
   4979     BreakAndContinueScope push(&break_info, this);
   4980     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   4981   }
   4982 
   4983   HBasicBlock* body_exit = JoinContinue(
   4984       stmt, stmt->IncrementId(), current_block(), break_info.continue_block());
   4985 
   4986   if (body_exit != NULL) {
   4987     set_current_block(body_exit);
   4988 
   4989     HValue* current_index = Pop();
   4990     HValue* increment =
   4991         AddUncasted<HAdd>(current_index, graph()->GetConstant1());
   4992     increment->ClearFlag(HValue::kCanOverflow);
   4993     Push(increment);
   4994     body_exit = current_block();
   4995   }
   4996 
   4997   HBasicBlock* loop_exit = CreateLoop(stmt,
   4998                                       loop_entry,
   4999                                       body_exit,
   5000                                       loop_successor,
   5001                                       break_info.break_block());
   5002 
   5003   set_current_block(loop_exit);
   5004 }
   5005 
   5006 
   5007 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
   5008   DCHECK(!HasStackOverflow());
   5009   DCHECK(current_block() != NULL);
   5010   DCHECK(current_block()->HasPredecessor());
   5011   return Bailout(kForOfStatement);
   5012 }
   5013 
   5014 
   5015 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
   5016   DCHECK(!HasStackOverflow());
   5017   DCHECK(current_block() != NULL);
   5018   DCHECK(current_block()->HasPredecessor());
   5019   return Bailout(kTryCatchStatement);
   5020 }
   5021 
   5022 
   5023 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
   5024     TryFinallyStatement* stmt) {
   5025   DCHECK(!HasStackOverflow());
   5026   DCHECK(current_block() != NULL);
   5027   DCHECK(current_block()->HasPredecessor());
   5028   return Bailout(kTryFinallyStatement);
   5029 }
   5030 
   5031 
   5032 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   5033   DCHECK(!HasStackOverflow());
   5034   DCHECK(current_block() != NULL);
   5035   DCHECK(current_block()->HasPredecessor());
   5036   return Bailout(kDebuggerStatement);
   5037 }
   5038 
   5039 
   5040 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
   5041   UNREACHABLE();
   5042 }
   5043 
   5044 
   5045 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   5046   DCHECK(!HasStackOverflow());
   5047   DCHECK(current_block() != NULL);
   5048   DCHECK(current_block()->HasPredecessor());
   5049   Handle<SharedFunctionInfo> shared_info = Compiler::GetSharedFunctionInfo(
   5050       expr, current_info()->script(), top_info());
   5051   // We also have a stack overflow if the recursive compilation did.
   5052   if (HasStackOverflow()) return;
   5053   // Use the fast case closure allocation code that allocates in new
   5054   // space for nested functions that don't need pretenuring.
   5055   HConstant* shared_info_value = Add<HConstant>(shared_info);
   5056   HInstruction* instr;
   5057   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
   5058   HValue* vector_value = Add<HConstant>(vector);
   5059   int index = FeedbackVector::GetIndex(expr->LiteralFeedbackSlot());
   5060   HValue* index_value = Add<HConstant>(index);
   5061   if (!expr->pretenure()) {
   5062     Callable callable = CodeFactory::FastNewClosure(isolate());
   5063     HValue* values[] = {shared_info_value, vector_value, index_value};
   5064     HConstant* stub_value = Add<HConstant>(callable.code());
   5065     instr = New<HCallWithDescriptor>(stub_value, 0, callable.descriptor(),
   5066                                      ArrayVector(values));
   5067   } else {
   5068     Add<HPushArguments>(shared_info_value);
   5069     Add<HPushArguments>(vector_value);
   5070     Add<HPushArguments>(index_value);
   5071     Runtime::FunctionId function_id =
   5072         expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
   5073     instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 3);
   5074   }
   5075   return ast_context()->ReturnInstruction(instr, expr->id());
   5076 }
   5077 
   5078 
   5079 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
   5080   DCHECK(!HasStackOverflow());
   5081   DCHECK(current_block() != NULL);
   5082   DCHECK(current_block()->HasPredecessor());
   5083   return Bailout(kClassLiteral);
   5084 }
   5085 
   5086 
   5087 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
   5088     NativeFunctionLiteral* expr) {
   5089   DCHECK(!HasStackOverflow());
   5090   DCHECK(current_block() != NULL);
   5091   DCHECK(current_block()->HasPredecessor());
   5092   return Bailout(kNativeFunctionLiteral);
   5093 }
   5094 
   5095 
   5096 void HOptimizedGraphBuilder::VisitDoExpression(DoExpression* expr) {
   5097   DoExpressionScope scope(this);
   5098   DCHECK(!HasStackOverflow());
   5099   DCHECK(current_block() != NULL);
   5100   DCHECK(current_block()->HasPredecessor());
   5101   CHECK_ALIVE(VisitBlock(expr->block()));
   5102   Visit(expr->result());
   5103 }
   5104 
   5105 
   5106 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
   5107   DCHECK(!HasStackOverflow());
   5108   DCHECK(current_block() != NULL);
   5109   DCHECK(current_block()->HasPredecessor());
   5110   HBasicBlock* cond_true = graph()->CreateBasicBlock();
   5111   HBasicBlock* cond_false = graph()->CreateBasicBlock();
   5112   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
   5113 
   5114   // Visit the true and false subexpressions in the same AST context as the
   5115   // whole expression.
   5116   if (cond_true->HasPredecessor()) {
   5117     cond_true->SetJoinId(expr->ThenId());
   5118     set_current_block(cond_true);
   5119     CHECK_BAILOUT(Visit(expr->then_expression()));
   5120     cond_true = current_block();
   5121   } else {
   5122     cond_true = NULL;
   5123   }
   5124 
   5125   if (cond_false->HasPredecessor()) {
   5126     cond_false->SetJoinId(expr->ElseId());
   5127     set_current_block(cond_false);
   5128     CHECK_BAILOUT(Visit(expr->else_expression()));
   5129     cond_false = current_block();
   5130   } else {
   5131     cond_false = NULL;
   5132   }
   5133 
   5134   if (!ast_context()->IsTest()) {
   5135     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
   5136     set_current_block(join);
   5137     if (join != NULL && !ast_context()->IsEffect()) {
   5138       return ast_context()->ReturnValue(Pop());
   5139     }
   5140   }
   5141 }
   5142 
   5143 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess(
   5144     Variable* var, LookupIterator* it, PropertyAccessType access_type) {
   5145   if (var->is_this()) return false;
   5146   return CanInlineGlobalPropertyAccess(it, access_type);
   5147 }
   5148 
   5149 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess(
   5150     LookupIterator* it, PropertyAccessType access_type) {
   5151   if (!current_info()->has_global_object()) {
   5152     return false;
   5153   }
   5154 
   5155   switch (it->state()) {
   5156     case LookupIterator::ACCESSOR:
   5157     case LookupIterator::ACCESS_CHECK:
   5158     case LookupIterator::INTERCEPTOR:
   5159     case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5160     case LookupIterator::NOT_FOUND:
   5161       return false;
   5162     case LookupIterator::DATA:
   5163       if (access_type == STORE && it->IsReadOnly()) return false;
   5164       if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return false;
   5165       return true;
   5166     case LookupIterator::JSPROXY:
   5167     case LookupIterator::TRANSITION:
   5168       UNREACHABLE();
   5169   }
   5170   UNREACHABLE();
   5171   return false;
   5172 }
   5173 
   5174 
   5175 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
   5176   DCHECK(var->IsContextSlot());
   5177   HValue* context = environment()->context();
   5178   int length = scope()->ContextChainLength(var->scope());
   5179   while (length-- > 0) {
   5180     context = Add<HLoadNamedField>(
   5181         context, nullptr,
   5182         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   5183   }
   5184   return context;
   5185 }
   5186 
   5187 void HOptimizedGraphBuilder::InlineGlobalPropertyLoad(LookupIterator* it,
   5188                                                       BailoutId ast_id) {
   5189   Handle<PropertyCell> cell = it->GetPropertyCell();
   5190   top_info()->dependencies()->AssumePropertyCell(cell);
   5191   auto cell_type = it->property_details().cell_type();
   5192   if (cell_type == PropertyCellType::kConstant ||
   5193       cell_type == PropertyCellType::kUndefined) {
   5194     Handle<Object> constant_object(cell->value(), isolate());
   5195     if (constant_object->IsConsString()) {
   5196       constant_object = String::Flatten(Handle<String>::cast(constant_object));
   5197     }
   5198     HConstant* constant = New<HConstant>(constant_object);
   5199     return ast_context()->ReturnInstruction(constant, ast_id);
   5200   } else {
   5201     auto access = HObjectAccess::ForPropertyCellValue();
   5202     UniqueSet<Map>* field_maps = nullptr;
   5203     if (cell_type == PropertyCellType::kConstantType) {
   5204       switch (cell->GetConstantType()) {
   5205         case PropertyCellConstantType::kSmi:
   5206           access = access.WithRepresentation(Representation::Smi());
   5207           break;
   5208         case PropertyCellConstantType::kStableMap: {
   5209           // Check that the map really is stable. The heap object could
   5210           // have mutated without the cell updating state. In that case,
   5211           // make no promises about the loaded value except that it's a
   5212           // heap object.
   5213           access = access.WithRepresentation(Representation::HeapObject());
   5214           Handle<Map> map(HeapObject::cast(cell->value())->map());
   5215           if (map->is_stable()) {
   5216             field_maps = new (zone())
   5217                 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
   5218           }
   5219           break;
   5220         }
   5221       }
   5222     }
   5223     HConstant* cell_constant = Add<HConstant>(cell);
   5224     HLoadNamedField* instr;
   5225     if (field_maps == nullptr) {
   5226       instr = New<HLoadNamedField>(cell_constant, nullptr, access);
   5227     } else {
   5228       instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps,
   5229                                    HType::HeapObject());
   5230     }
   5231     instr->ClearDependsOnFlag(kInobjectFields);
   5232     instr->SetDependsOnFlag(kGlobalVars);
   5233     return ast_context()->ReturnInstruction(instr, ast_id);
   5234   }
   5235 }
   5236 
   5237 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
   5238   DCHECK(!HasStackOverflow());
   5239   DCHECK(current_block() != NULL);
   5240   DCHECK(current_block()->HasPredecessor());
   5241   Variable* variable = expr->var();
   5242   switch (variable->location()) {
   5243     case VariableLocation::UNALLOCATED: {
   5244       if (IsLexicalVariableMode(variable->mode())) {
   5245         // TODO(rossberg): should this be an DCHECK?
   5246         return Bailout(kReferenceToGlobalLexicalVariable);
   5247       }
   5248       // Handle known global constants like 'undefined' specially to avoid a
   5249       // load from a global cell for them.
   5250       Handle<Object> constant_value =
   5251           isolate()->factory()->GlobalConstantFor(variable->name());
   5252       if (!constant_value.is_null()) {
   5253         HConstant* instr = New<HConstant>(constant_value);
   5254         return ast_context()->ReturnInstruction(instr, expr->id());
   5255       }
   5256 
   5257       Handle<JSGlobalObject> global(current_info()->global_object());
   5258 
   5259       // Lookup in script contexts.
   5260       {
   5261         Handle<ScriptContextTable> script_contexts(
   5262             global->native_context()->script_context_table());
   5263         ScriptContextTable::LookupResult lookup;
   5264         if (ScriptContextTable::Lookup(script_contexts, variable->name(),
   5265                                        &lookup)) {
   5266           Handle<Context> script_context = ScriptContextTable::GetContext(
   5267               script_contexts, lookup.context_index);
   5268           Handle<Object> current_value =
   5269               FixedArray::get(*script_context, lookup.slot_index, isolate());
   5270 
   5271           // If the values is not the hole, it will stay initialized,
   5272           // so no need to generate a check.
   5273           if (current_value->IsTheHole(isolate())) {
   5274             return Bailout(kReferenceToUninitializedVariable);
   5275           }
   5276           HInstruction* result = New<HLoadNamedField>(
   5277               Add<HConstant>(script_context), nullptr,
   5278               HObjectAccess::ForContextSlot(lookup.slot_index));
   5279           return ast_context()->ReturnInstruction(result, expr->id());
   5280         }
   5281       }
   5282 
   5283       LookupIterator it(global, variable->name(), LookupIterator::OWN);
   5284       it.TryLookupCachedProperty();
   5285       if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) {
   5286         InlineGlobalPropertyLoad(&it, expr->id());
   5287         return;
   5288       } else {
   5289         Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
   5290         FeedbackSlot slot = expr->VariableFeedbackSlot();
   5291         DCHECK(vector->IsLoadGlobalIC(slot));
   5292 
   5293         HValue* vector_value = Add<HConstant>(vector);
   5294         HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
   5295         Callable callable = CodeFactory::LoadGlobalICInOptimizedCode(
   5296             isolate(), ast_context()->typeof_mode());
   5297         HValue* stub = Add<HConstant>(callable.code());
   5298         HValue* name = Add<HConstant>(variable->name());
   5299         HValue* values[] = {name, slot_value, vector_value};
   5300         HCallWithDescriptor* instr = New<HCallWithDescriptor>(
   5301             Code::LOAD_GLOBAL_IC, stub, 0, callable.descriptor(),
   5302             ArrayVector(values));
   5303         return ast_context()->ReturnInstruction(instr, expr->id());
   5304       }
   5305     }
   5306 
   5307     case VariableLocation::PARAMETER:
   5308     case VariableLocation::LOCAL: {
   5309       HValue* value = LookupAndMakeLive(variable);
   5310       if (value == graph()->GetConstantHole()) {
   5311         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
   5312                variable->mode() != VAR);
   5313         return Bailout(kReferenceToUninitializedVariable);
   5314       }
   5315       return ast_context()->ReturnValue(value);
   5316     }
   5317 
   5318     case VariableLocation::CONTEXT: {
   5319       HValue* context = BuildContextChainWalk(variable);
   5320       HLoadContextSlot::Mode mode;
   5321       switch (variable->mode()) {
   5322         case LET:
   5323         case CONST:
   5324           mode = HLoadContextSlot::kCheckDeoptimize;
   5325           break;
   5326         default:
   5327           mode = HLoadContextSlot::kNoCheck;
   5328           break;
   5329       }
   5330       HLoadContextSlot* instr =
   5331           new(zone()) HLoadContextSlot(context, variable->index(), mode);
   5332       return ast_context()->ReturnInstruction(instr, expr->id());
   5333     }
   5334 
   5335     case VariableLocation::LOOKUP:
   5336       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
   5337 
   5338     case VariableLocation::MODULE:
   5339       UNREACHABLE();
   5340   }
   5341 }
   5342 
   5343 
   5344 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
   5345   DCHECK(!HasStackOverflow());
   5346   DCHECK(current_block() != NULL);
   5347   DCHECK(current_block()->HasPredecessor());
   5348   HConstant* instr = New<HConstant>(expr->value());
   5349   return ast_context()->ReturnInstruction(instr, expr->id());
   5350 }
   5351 
   5352 
   5353 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   5354   DCHECK(!HasStackOverflow());
   5355   DCHECK(current_block() != NULL);
   5356   DCHECK(current_block()->HasPredecessor());
   5357   Callable callable = CodeFactory::FastCloneRegExp(isolate());
   5358   int index = FeedbackVector::GetIndex(expr->literal_slot());
   5359   HValue* values[] = {AddThisFunction(), Add<HConstant>(index),
   5360                       Add<HConstant>(expr->pattern()),
   5361                       Add<HConstant>(expr->flags())};
   5362   HConstant* stub_value = Add<HConstant>(callable.code());
   5363   HInstruction* instr = New<HCallWithDescriptor>(
   5364       stub_value, 0, callable.descriptor(), ArrayVector(values));
   5365   return ast_context()->ReturnInstruction(instr, expr->id());
   5366 }
   5367 
   5368 
   5369 static bool CanInlinePropertyAccess(Handle<Map> map) {
   5370   if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
   5371   if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
   5372   return map->IsJSObjectMap() && !map->is_dictionary_map() &&
   5373          !map->has_named_interceptor() &&
   5374          // TODO(verwaest): Whitelist contexts to which we have access.
   5375          !map->is_access_check_needed();
   5376 }
   5377 
   5378 
   5379 // Determines whether the given array or object literal boilerplate satisfies
   5380 // all limits to be considered for fast deep-copying and computes the total
   5381 // size of all objects that are part of the graph.
   5382 static bool IsFastLiteral(Handle<JSObject> boilerplate,
   5383                           int max_depth,
   5384                           int* max_properties) {
   5385   if (boilerplate->map()->is_deprecated() &&
   5386       !JSObject::TryMigrateInstance(boilerplate)) {
   5387     return false;
   5388   }
   5389 
   5390   DCHECK(max_depth >= 0 && *max_properties >= 0);
   5391   if (max_depth == 0) return false;
   5392 
   5393   Isolate* isolate = boilerplate->GetIsolate();
   5394   Handle<FixedArrayBase> elements(boilerplate->elements());
   5395   if (elements->length() > 0 &&
   5396       elements->map() != isolate->heap()->fixed_cow_array_map()) {
   5397     if (boilerplate->HasFastSmiOrObjectElements()) {
   5398       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   5399       int length = elements->length();
   5400       for (int i = 0; i < length; i++) {
   5401         if ((*max_properties)-- == 0) return false;
   5402         Handle<Object> value(fast_elements->get(i), isolate);
   5403         if (value->IsJSObject()) {
   5404           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5405           if (!IsFastLiteral(value_object,
   5406                              max_depth - 1,
   5407                              max_properties)) {
   5408             return false;
   5409           }
   5410         }
   5411       }
   5412     } else if (boilerplate->HasFastDoubleElements()) {
   5413       if (elements->Size() > kMaxRegularHeapObjectSize) return false;
   5414     } else {
   5415       return false;
   5416     }
   5417   }
   5418 
   5419   Handle<FixedArray> properties(boilerplate->properties());
   5420   if (properties->length() > 0) {
   5421     return false;
   5422   } else {
   5423     Handle<DescriptorArray> descriptors(
   5424         boilerplate->map()->instance_descriptors());
   5425     int limit = boilerplate->map()->NumberOfOwnDescriptors();
   5426     for (int i = 0; i < limit; i++) {
   5427       PropertyDetails details = descriptors->GetDetails(i);
   5428       if (details.location() != kField) continue;
   5429       DCHECK_EQ(kData, details.kind());
   5430       if ((*max_properties)-- == 0) return false;
   5431       FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
   5432       if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
   5433       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
   5434                            isolate);
   5435       if (value->IsJSObject()) {
   5436         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5437         if (!IsFastLiteral(value_object,
   5438                            max_depth - 1,
   5439                            max_properties)) {
   5440           return false;
   5441         }
   5442       }
   5443     }
   5444   }
   5445   return true;
   5446 }
   5447 
   5448 
   5449 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   5450   DCHECK(!HasStackOverflow());
   5451   DCHECK(current_block() != NULL);
   5452   DCHECK(current_block()->HasPredecessor());
   5453 
   5454   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
   5455   HInstruction* literal;
   5456 
   5457   // Check whether to use fast or slow deep-copying for boilerplate.
   5458   int max_properties = kMaxFastLiteralProperties;
   5459   Handle<Object> literals_cell(
   5460       closure->feedback_vector()->Get(expr->literal_slot()), isolate());
   5461   Handle<AllocationSite> site;
   5462   Handle<JSObject> boilerplate;
   5463   if (!literals_cell->IsUndefined(isolate())) {
   5464     // Retrieve the boilerplate
   5465     site = Handle<AllocationSite>::cast(literals_cell);
   5466     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
   5467                                    isolate());
   5468   }
   5469 
   5470   if (!boilerplate.is_null() &&
   5471       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
   5472     AllocationSiteUsageContext site_context(isolate(), site, false);
   5473     site_context.EnterNewScope();
   5474     literal = BuildFastLiteral(boilerplate, &site_context);
   5475     site_context.ExitScope(site, boilerplate);
   5476   } else {
   5477     NoObservableSideEffectsScope no_effects(this);
   5478     Handle<BoilerplateDescription> constant_properties =
   5479         expr->GetOrBuildConstantProperties(isolate());
   5480     int literal_index = FeedbackVector::GetIndex(expr->literal_slot());
   5481     int flags = expr->ComputeFlags(true);
   5482 
   5483     Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
   5484                         Add<HConstant>(constant_properties),
   5485                         Add<HConstant>(flags));
   5486 
   5487     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
   5488     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
   5489   }
   5490 
   5491   // The object is expected in the bailout environment during computation
   5492   // of the property values and is the value of the entire expression.
   5493   Push(literal);
   5494   for (int i = 0; i < expr->properties()->length(); i++) {
   5495     ObjectLiteral::Property* property = expr->properties()->at(i);
   5496     if (property->is_computed_name()) return Bailout(kComputedPropertyName);
   5497     if (property->IsCompileTimeValue()) continue;
   5498 
   5499     Literal* key = property->key()->AsLiteral();
   5500     Expression* value = property->value();
   5501 
   5502     switch (property->kind()) {
   5503       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   5504         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
   5505         // Fall through.
   5506       case ObjectLiteral::Property::COMPUTED:
   5507         // It is safe to use [[Put]] here because the boilerplate already
   5508         // contains computed properties with an uninitialized value.
   5509         if (key->IsStringLiteral()) {
   5510           DCHECK(key->IsPropertyName());
   5511           if (property->emit_store()) {
   5512             CHECK_ALIVE(VisitForValue(value));
   5513             HValue* value = Pop();
   5514 
   5515             Handle<Map> map = property->GetReceiverType();
   5516             Handle<String> name = key->AsPropertyName();
   5517             HValue* store;
   5518             FeedbackSlot slot = property->GetSlot();
   5519             if (map.is_null()) {
   5520               // If we don't know the monomorphic type, do a generic store.
   5521               CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
   5522                                                     name, value));
   5523             } else {
   5524               PropertyAccessInfo info(this, STORE, map, name);
   5525               if (info.CanAccessMonomorphic()) {
   5526                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
   5527                 DCHECK(!info.IsAccessorConstant());
   5528                 info.MarkAsInitializingStore();
   5529                 store = BuildMonomorphicAccess(
   5530                     &info, literal, checked_literal, value,
   5531                     BailoutId::None(), BailoutId::None());
   5532                 DCHECK_NOT_NULL(store);
   5533               } else {
   5534                 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
   5535                                                       literal, name, value));
   5536               }
   5537             }
   5538             if (store->IsInstruction()) {
   5539               AddInstruction(HInstruction::cast(store));
   5540             }
   5541             DCHECK(store->HasObservableSideEffects());
   5542             Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
   5543 
   5544             // Add [[HomeObject]] to function literals.
   5545             if (FunctionLiteral::NeedsHomeObject(property->value())) {
   5546               Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
   5547               HInstruction* store_home = BuildNamedGeneric(
   5548                   STORE, NULL, property->GetSlot(1), value, sym, literal);
   5549               AddInstruction(store_home);
   5550               DCHECK(store_home->HasObservableSideEffects());
   5551               Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
   5552             }
   5553           } else {
   5554             CHECK_ALIVE(VisitForEffect(value));
   5555           }
   5556           break;
   5557         }
   5558         // Fall through.
   5559       case ObjectLiteral::Property::PROTOTYPE:
   5560       case ObjectLiteral::Property::SETTER:
   5561       case ObjectLiteral::Property::GETTER:
   5562         return Bailout(kObjectLiteralWithComplexProperty);
   5563       default: UNREACHABLE();
   5564     }
   5565   }
   5566 
   5567   return ast_context()->ReturnValue(Pop());
   5568 }
   5569 
   5570 
   5571 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   5572   DCHECK(!HasStackOverflow());
   5573   DCHECK(current_block() != NULL);
   5574   DCHECK(current_block()->HasPredecessor());
   5575   ZoneList<Expression*>* subexprs = expr->values();
   5576   int length = subexprs->length();
   5577   HInstruction* literal;
   5578 
   5579   Handle<AllocationSite> site;
   5580   Handle<FeedbackVector> vector(environment()->closure()->feedback_vector(),
   5581                                 isolate());
   5582   Handle<Object> literals_cell(vector->Get(expr->literal_slot()), isolate());
   5583   Handle<JSObject> boilerplate_object;
   5584   if (!literals_cell->IsUndefined(isolate())) {
   5585     DCHECK(literals_cell->IsAllocationSite());
   5586     site = Handle<AllocationSite>::cast(literals_cell);
   5587     boilerplate_object = Handle<JSObject>(
   5588         JSObject::cast(site->transition_info()), isolate());
   5589   }
   5590 
   5591   // Check whether to use fast or slow deep-copying for boilerplate.
   5592   int max_properties = kMaxFastLiteralProperties;
   5593   if (!boilerplate_object.is_null() &&
   5594       IsFastLiteral(boilerplate_object, kMaxFastLiteralDepth,
   5595                     &max_properties)) {
   5596     DCHECK(site->SitePointsToLiteral());
   5597     AllocationSiteUsageContext site_context(isolate(), site, false);
   5598     site_context.EnterNewScope();
   5599     literal = BuildFastLiteral(boilerplate_object, &site_context);
   5600     site_context.ExitScope(site, boilerplate_object);
   5601   } else {
   5602     NoObservableSideEffectsScope no_effects(this);
   5603     Handle<ConstantElementsPair> constants =
   5604         expr->GetOrBuildConstantElements(isolate());
   5605     int literal_index = FeedbackVector::GetIndex(expr->literal_slot());
   5606     int flags = expr->ComputeFlags(true);
   5607 
   5608     Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
   5609                         Add<HConstant>(constants), Add<HConstant>(flags));
   5610 
   5611     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
   5612     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
   5613 
   5614     // Register to deopt if the boilerplate ElementsKind changes.
   5615     if (!site.is_null()) {
   5616       top_info()->dependencies()->AssumeTransitionStable(site);
   5617     }
   5618   }
   5619 
   5620   // The array is expected in the bailout environment during computation
   5621   // of the property values and is the value of the entire expression.
   5622   Push(literal);
   5623 
   5624   HInstruction* elements = NULL;
   5625 
   5626   for (int i = 0; i < length; i++) {
   5627     Expression* subexpr = subexprs->at(i);
   5628     DCHECK(!subexpr->IsSpread());
   5629 
   5630     // If the subexpression is a literal or a simple materialized literal it
   5631     // is already set in the cloned array.
   5632     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
   5633 
   5634     CHECK_ALIVE(VisitForValue(subexpr));
   5635     HValue* value = Pop();
   5636     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
   5637 
   5638     elements = AddLoadElements(literal);
   5639 
   5640     HValue* key = Add<HConstant>(i);
   5641 
   5642     if (!boilerplate_object.is_null()) {
   5643       ElementsKind boilerplate_elements_kind =
   5644           boilerplate_object->GetElementsKind();
   5645       switch (boilerplate_elements_kind) {
   5646         case FAST_SMI_ELEMENTS:
   5647         case FAST_HOLEY_SMI_ELEMENTS:
   5648         case FAST_ELEMENTS:
   5649         case FAST_HOLEY_ELEMENTS:
   5650         case FAST_DOUBLE_ELEMENTS:
   5651         case FAST_HOLEY_DOUBLE_ELEMENTS: {
   5652           Add<HStoreKeyed>(elements, key, value, nullptr,
   5653                            boilerplate_elements_kind);
   5654           break;
   5655         }
   5656         default:
   5657           UNREACHABLE();
   5658           break;
   5659       }
   5660     } else {
   5661       HInstruction* instr = BuildKeyedGeneric(
   5662           STORE, expr, expr->LiteralFeedbackSlot(), literal, key, value);
   5663       AddInstruction(instr);
   5664     }
   5665 
   5666     Add<HSimulate>(expr->GetIdForElement(i));
   5667   }
   5668 
   5669   return ast_context()->ReturnValue(Pop());
   5670 }
   5671 
   5672 
   5673 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
   5674                                                 Handle<Map> map) {
   5675   BuildCheckHeapObject(object);
   5676   return Add<HCheckMaps>(object, map);
   5677 }
   5678 
   5679 
   5680 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
   5681     PropertyAccessInfo* info,
   5682     HValue* checked_object) {
   5683   // Check if this is a load of an immutable or constant property.
   5684   if (checked_object->ActualValue()->IsConstant()) {
   5685     Handle<Object> object(
   5686         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
   5687 
   5688     if (object->IsJSObject()) {
   5689       LookupIterator it(object, info->name(),
   5690                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   5691       if (it.IsFound()) {
   5692         bool is_reaonly_non_configurable =
   5693             it.IsReadOnly() && !it.IsConfigurable();
   5694         if (is_reaonly_non_configurable ||
   5695             (FLAG_track_constant_fields && info->IsDataConstantField())) {
   5696           Handle<Object> value = JSReceiver::GetDataProperty(&it);
   5697           if (!is_reaonly_non_configurable) {
   5698             DCHECK(!it.is_dictionary_holder());
   5699             // Add dependency on the map that introduced the field.
   5700             Handle<Map> field_owner_map = it.GetFieldOwnerMap();
   5701             top_info()->dependencies()->AssumeFieldOwner(field_owner_map);
   5702           }
   5703           return New<HConstant>(value);
   5704         }
   5705       }
   5706     }
   5707   }
   5708 
   5709   HObjectAccess access = info->access();
   5710   if (access.representation().IsDouble() &&
   5711       (!FLAG_unbox_double_fields || !access.IsInobject())) {
   5712     // Load the heap number.
   5713     checked_object = Add<HLoadNamedField>(
   5714         checked_object, nullptr,
   5715         access.WithRepresentation(Representation::Tagged()));
   5716     // Load the double value from it.
   5717     access = HObjectAccess::ForHeapNumberValue();
   5718   }
   5719 
   5720   SmallMapList* map_list = info->field_maps();
   5721   if (map_list->length() == 0) {
   5722     return New<HLoadNamedField>(checked_object, checked_object, access);
   5723   }
   5724 
   5725   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
   5726   for (int i = 0; i < map_list->length(); ++i) {
   5727     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
   5728   }
   5729   return New<HLoadNamedField>(
   5730       checked_object, checked_object, access, maps, info->field_type());
   5731 }
   5732 
   5733 HValue* HOptimizedGraphBuilder::BuildStoreNamedField(PropertyAccessInfo* info,
   5734                                                      HValue* checked_object,
   5735                                                      HValue* value) {
   5736   bool transition_to_field = info->IsTransition();
   5737   // TODO(verwaest): Move this logic into PropertyAccessInfo.
   5738   HObjectAccess field_access = info->access();
   5739 
   5740   bool store_to_constant_field = FLAG_track_constant_fields &&
   5741                                  info->StoreMode() != INITIALIZING_STORE &&
   5742                                  info->IsDataConstantField();
   5743 
   5744   HStoreNamedField *instr;
   5745   if (field_access.representation().IsDouble() &&
   5746       (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
   5747     HObjectAccess heap_number_access =
   5748         field_access.WithRepresentation(Representation::Tagged());
   5749     if (transition_to_field) {
   5750       // The store requires a mutable HeapNumber to be allocated.
   5751       NoObservableSideEffectsScope no_side_effects(this);
   5752       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
   5753 
   5754       // TODO(hpayer): Allocation site pretenuring support.
   5755       HInstruction* heap_number =
   5756           Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
   5757                          MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
   5758       AddStoreMapConstant(
   5759           heap_number, isolate()->factory()->mutable_heap_number_map());
   5760       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
   5761                             value);
   5762       instr = New<HStoreNamedField>(checked_object->ActualValue(),
   5763                                     heap_number_access,
   5764                                     heap_number);
   5765     } else {
   5766       // Already holds a HeapNumber; load the box and write its value field.
   5767       HInstruction* heap_number =
   5768           Add<HLoadNamedField>(checked_object, nullptr, heap_number_access);
   5769 
   5770       if (store_to_constant_field) {
   5771         // If the field is constant check that the value we are going to store
   5772         // matches current value.
   5773         HInstruction* current_value = Add<HLoadNamedField>(
   5774             heap_number, nullptr, HObjectAccess::ForHeapNumberValue());
   5775         IfBuilder value_checker(this);
   5776         value_checker.IfNot<HCompareNumericAndBranch>(current_value, value,
   5777                                                       Token::EQ);
   5778         value_checker.ThenDeopt(DeoptimizeReason::kValueMismatch);
   5779         value_checker.End();
   5780         return nullptr;
   5781 
   5782       } else {
   5783         instr = New<HStoreNamedField>(heap_number,
   5784                                       HObjectAccess::ForHeapNumberValue(),
   5785                                       value, STORE_TO_INITIALIZED_ENTRY);
   5786       }
   5787     }
   5788   } else {
   5789     if (store_to_constant_field) {
   5790       // If the field is constant check that the value we are going to store
   5791       // matches current value.
   5792       HInstruction* current_value = Add<HLoadNamedField>(
   5793           checked_object->ActualValue(), checked_object, field_access);
   5794 
   5795       IfBuilder value_checker(this);
   5796       if (field_access.representation().IsDouble()) {
   5797         value_checker.IfNot<HCompareNumericAndBranch>(current_value, value,
   5798                                                       Token::EQ);
   5799       } else {
   5800         value_checker.IfNot<HCompareObjectEqAndBranch>(current_value, value);
   5801       }
   5802       value_checker.ThenDeopt(DeoptimizeReason::kValueMismatch);
   5803       value_checker.End();
   5804       return nullptr;
   5805 
   5806     } else {
   5807       if (field_access.representation().IsHeapObject()) {
   5808         BuildCheckHeapObject(value);
   5809       }
   5810 
   5811       if (!info->field_maps()->is_empty()) {
   5812         DCHECK(field_access.representation().IsHeapObject());
   5813         value = Add<HCheckMaps>(value, info->field_maps());
   5814       }
   5815 
   5816       // This is a normal store.
   5817       instr = New<HStoreNamedField>(checked_object->ActualValue(), field_access,
   5818                                     value, info->StoreMode());
   5819     }
   5820   }
   5821 
   5822   if (transition_to_field) {
   5823     Handle<Map> transition(info->transition());
   5824     DCHECK(!transition->is_deprecated());
   5825     instr->SetTransition(Add<HConstant>(transition));
   5826   }
   5827   return instr;
   5828 }
   5829 
   5830 Handle<FieldType>
   5831 HOptimizedGraphBuilder::PropertyAccessInfo::GetFieldTypeFromMap(
   5832     Handle<Map> map) const {
   5833   DCHECK(IsFound());
   5834   DCHECK(number_ < map->NumberOfOwnDescriptors());
   5835   return handle(map->instance_descriptors()->GetFieldType(number_), isolate());
   5836 }
   5837 
   5838 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
   5839     PropertyAccessInfo* info) {
   5840   if (!CanInlinePropertyAccess(map_)) return false;
   5841 
   5842   // Currently only handle AstType::Number as a polymorphic case.
   5843   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   5844   // instruction.
   5845   if (IsNumberType()) return false;
   5846 
   5847   // Values are only compatible for monomorphic load if they all behave the same
   5848   // regarding value wrappers.
   5849   if (IsValueWrapped() != info->IsValueWrapped()) return false;
   5850 
   5851   if (!LookupDescriptor()) return false;
   5852 
   5853   if (!IsFound()) {
   5854     return (!info->IsFound() || info->has_holder()) &&
   5855            map()->prototype() == info->map()->prototype();
   5856   }
   5857 
   5858   // Mismatch if the other access info found the property in the prototype
   5859   // chain.
   5860   if (info->has_holder()) return false;
   5861 
   5862   if (IsAccessorConstant()) {
   5863     return accessor_.is_identical_to(info->accessor_) &&
   5864         api_holder_.is_identical_to(info->api_holder_);
   5865   }
   5866 
   5867   if (IsDataConstant()) {
   5868     return constant_.is_identical_to(info->constant_);
   5869   }
   5870 
   5871   DCHECK(IsData());
   5872   if (!info->IsData()) return false;
   5873 
   5874   Representation r = access_.representation();
   5875   if (IsLoad()) {
   5876     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
   5877   } else {
   5878     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
   5879   }
   5880   if (info->access_.offset() != access_.offset()) return false;
   5881   if (info->access_.IsInobject() != access_.IsInobject()) return false;
   5882   if (IsLoad()) {
   5883     if (field_maps_.is_empty()) {
   5884       info->field_maps_.Clear();
   5885     } else if (!info->field_maps_.is_empty()) {
   5886       for (int i = 0; i < field_maps_.length(); ++i) {
   5887         info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
   5888       }
   5889       info->field_maps_.Sort();
   5890     }
   5891   } else {
   5892     // We can only merge stores that agree on their field maps. The comparison
   5893     // below is safe, since we keep the field maps sorted.
   5894     if (field_maps_.length() != info->field_maps_.length()) return false;
   5895     for (int i = 0; i < field_maps_.length(); ++i) {
   5896       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
   5897         return false;
   5898       }
   5899     }
   5900   }
   5901   info->GeneralizeRepresentation(r);
   5902   info->field_type_ = info->field_type_.Combine(field_type_);
   5903   return true;
   5904 }
   5905 
   5906 
   5907 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
   5908   if (!map_->IsJSObjectMap()) return true;
   5909   LookupDescriptor(*map_, *name_);
   5910   return LoadResult(map_);
   5911 }
   5912 
   5913 
   5914 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
   5915   if (!IsLoad() && IsProperty() && IsReadOnly()) {
   5916     return false;
   5917   }
   5918 
   5919   if (IsData()) {
   5920     // Construct the object field access.
   5921     int index = GetLocalFieldIndexFromMap(map);
   5922     access_ = HObjectAccess::ForField(map, index, representation(), name_);
   5923 
   5924     // Load field map for heap objects.
   5925     return LoadFieldMaps(map);
   5926   } else if (IsAccessorConstant()) {
   5927     Handle<Object> accessors = GetAccessorsFromMap(map);
   5928     if (!accessors->IsAccessorPair()) return false;
   5929     Object* raw_accessor =
   5930         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
   5931                  : Handle<AccessorPair>::cast(accessors)->setter();
   5932     if (!raw_accessor->IsJSFunction() &&
   5933         !raw_accessor->IsFunctionTemplateInfo())
   5934       return false;
   5935     Handle<Object> accessor = handle(HeapObject::cast(raw_accessor));
   5936     CallOptimization call_optimization(accessor);
   5937     if (call_optimization.is_simple_api_call()) {
   5938       CallOptimization::HolderLookup holder_lookup;
   5939       api_holder_ =
   5940           call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
   5941     }
   5942     accessor_ = accessor;
   5943   } else if (IsDataConstant()) {
   5944     constant_ = GetConstantFromMap(map);
   5945   }
   5946 
   5947   return true;
   5948 }
   5949 
   5950 
   5951 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
   5952     Handle<Map> map) {
   5953   // Clear any previously collected field maps/type.
   5954   field_maps_.Clear();
   5955   field_type_ = HType::Tagged();
   5956 
   5957   // Figure out the field type from the accessor map.
   5958   Handle<FieldType> field_type = GetFieldTypeFromMap(map);
   5959 
   5960   // Collect the (stable) maps from the field type.
   5961   if (field_type->IsClass()) {
   5962     DCHECK(access_.representation().IsHeapObject());
   5963     Handle<Map> field_map = field_type->AsClass();
   5964     if (field_map->is_stable()) {
   5965       field_maps_.Add(field_map, zone());
   5966     }
   5967   }
   5968 
   5969   if (field_maps_.is_empty()) {
   5970     // Store is not safe if the field map was cleared.
   5971     return IsLoad() || !field_type->IsNone();
   5972   }
   5973 
   5974   // Determine field HType from field type.
   5975   field_type_ = HType::FromFieldType(field_type, zone());
   5976   DCHECK(field_type_.IsHeapObject());
   5977 
   5978   // Add dependency on the map that introduced the field.
   5979   top_info()->dependencies()->AssumeFieldOwner(GetFieldOwnerFromMap(map));
   5980   return true;
   5981 }
   5982 
   5983 
   5984 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
   5985   Handle<Map> map = this->map();
   5986   if (name_->IsPrivate()) {
   5987     NotFound();
   5988     return !map->has_hidden_prototype();
   5989   }
   5990 
   5991   while (map->prototype()->IsJSObject()) {
   5992     holder_ = handle(JSObject::cast(map->prototype()));
   5993     if (holder_->map()->is_deprecated()) {
   5994       JSObject::TryMigrateInstance(holder_);
   5995     }
   5996     map = Handle<Map>(holder_->map());
   5997     if (!CanInlinePropertyAccess(map)) {
   5998       NotFound();
   5999       return false;
   6000     }
   6001     LookupDescriptor(*map, *name_);
   6002     if (IsFound()) return LoadResult(map);
   6003   }
   6004 
   6005   NotFound();
   6006   return !map->prototype()->IsJSReceiver();
   6007 }
   6008 
   6009 
   6010 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
   6011   InstanceType instance_type = map_->instance_type();
   6012   return instance_type == JS_TYPED_ARRAY_TYPE && name_->IsString() &&
   6013          IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name_));
   6014 }
   6015 
   6016 
   6017 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
   6018   if (!CanInlinePropertyAccess(map_)) return false;
   6019   if (IsJSObjectFieldAccessor()) return IsLoad();
   6020   if (map_->IsJSFunctionMap() && map_->is_constructor() &&
   6021       !map_->has_non_instance_prototype() &&
   6022       name_.is_identical_to(isolate()->factory()->prototype_string())) {
   6023     return IsLoad();
   6024   }
   6025   if (!LookupDescriptor()) return false;
   6026   if (IsFound()) return IsLoad() || !IsReadOnly();
   6027   if (IsIntegerIndexedExotic()) return false;
   6028   if (!LookupInPrototypes()) return false;
   6029   if (IsLoad()) return true;
   6030 
   6031   if (IsAccessorConstant()) return true;
   6032   LookupTransition(*map_, *name_, NONE);
   6033   if (IsTransitionToData() && map_->unused_property_fields() > 0) {
   6034     // Construct the object field access.
   6035     int descriptor = transition()->LastAdded();
   6036     int index =
   6037         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
   6038         map_->GetInObjectProperties();
   6039     PropertyDetails details =
   6040         transition()->instance_descriptors()->GetDetails(descriptor);
   6041     Representation representation = details.representation();
   6042     access_ = HObjectAccess::ForField(map_, index, representation, name_);
   6043 
   6044     // Load field map for heap objects.
   6045     return LoadFieldMaps(transition());
   6046   }
   6047   return false;
   6048 }
   6049 
   6050 
   6051 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
   6052     SmallMapList* maps) {
   6053   DCHECK(map_.is_identical_to(maps->first()));
   6054   if (!CanAccessMonomorphic()) return false;
   6055   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6056   if (maps->length() > kMaxLoadPolymorphism) return false;
   6057   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6058   if (GetJSObjectFieldAccess(&access)) {
   6059     for (int i = 1; i < maps->length(); ++i) {
   6060       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
   6061       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
   6062       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
   6063       if (!access.Equals(test_access)) return false;
   6064     }
   6065     return true;
   6066   }
   6067 
   6068   // Currently only handle numbers as a polymorphic case.
   6069   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   6070   // instruction.
   6071   if (IsNumberType()) return false;
   6072 
   6073   // Multiple maps cannot transition to the same target map.
   6074   DCHECK(!IsLoad() || !IsTransition());
   6075   if (IsTransition() && maps->length() > 1) return false;
   6076 
   6077   for (int i = 1; i < maps->length(); ++i) {
   6078     PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
   6079     if (!test_info.IsCompatible(this)) return false;
   6080   }
   6081 
   6082   return true;
   6083 }
   6084 
   6085 
   6086 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
   6087   Handle<JSFunction> ctor;
   6088   if (Map::GetConstructorFunction(
   6089           map_, handle(current_info()->closure()->context()->native_context()))
   6090           .ToHandle(&ctor)) {
   6091     return handle(ctor->initial_map());
   6092   }
   6093   return map_;
   6094 }
   6095 
   6096 
   6097 static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
   6098   return !map->IsJSObjectMap() &&
   6099          is_sloppy(target->shared()->language_mode()) &&
   6100          !target->shared()->native();
   6101 }
   6102 
   6103 
   6104 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
   6105     Handle<JSFunction> target) const {
   6106   return NeedsWrapping(map_, target);
   6107 }
   6108 
   6109 
   6110 HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
   6111     PropertyAccessInfo* info, HValue* object, HValue* checked_object,
   6112     HValue* value, BailoutId ast_id, BailoutId return_id,
   6113     bool can_inline_accessor) {
   6114   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6115   if (info->GetJSObjectFieldAccess(&access)) {
   6116     DCHECK(info->IsLoad());
   6117     return New<HLoadNamedField>(object, checked_object, access);
   6118   }
   6119 
   6120   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
   6121       info->map()->IsJSFunctionMap() && info->map()->is_constructor()) {
   6122     DCHECK(!info->map()->has_non_instance_prototype());
   6123     return New<HLoadFunctionPrototype>(checked_object);
   6124   }
   6125 
   6126   HValue* checked_holder = checked_object;
   6127   if (info->has_holder()) {
   6128     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
   6129     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
   6130   }
   6131 
   6132   if (!info->IsFound()) {
   6133     DCHECK(info->IsLoad());
   6134     return graph()->GetConstantUndefined();
   6135   }
   6136 
   6137   if (info->IsData()) {
   6138     if (info->IsLoad()) {
   6139       return BuildLoadNamedField(info, checked_holder);
   6140     } else {
   6141       return BuildStoreNamedField(info, checked_object, value);
   6142     }
   6143   }
   6144 
   6145   if (info->IsTransition()) {
   6146     DCHECK(!info->IsLoad());
   6147     return BuildStoreNamedField(info, checked_object, value);
   6148   }
   6149 
   6150   if (info->IsAccessorConstant()) {
   6151     MaybeHandle<Name> maybe_name =
   6152         FunctionTemplateInfo::TryGetCachedPropertyName(isolate(),
   6153                                                        info->accessor());
   6154     if (!maybe_name.is_null()) {
   6155       Handle<Name> name = maybe_name.ToHandleChecked();
   6156       PropertyAccessInfo cache_info(this, LOAD, info->map(), name);
   6157       // Load new target.
   6158       if (cache_info.CanAccessMonomorphic()) {
   6159         return BuildLoadNamedField(&cache_info, checked_object);
   6160       }
   6161     }
   6162 
   6163     Push(checked_object);
   6164     int argument_count = 1;
   6165     if (!info->IsLoad()) {
   6166       argument_count = 2;
   6167       Push(value);
   6168     }
   6169 
   6170     if (info->accessor()->IsJSFunction() &&
   6171         info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) {
   6172       HValue* function = Add<HConstant>(info->accessor());
   6173       PushArgumentsFromEnvironment(argument_count);
   6174       return NewCallFunction(function, argument_count, TailCallMode::kDisallow,
   6175                              ConvertReceiverMode::kNotNullOrUndefined,
   6176                              TailCallMode::kDisallow);
   6177     } else if (FLAG_inline_accessors && can_inline_accessor) {
   6178       bool success = info->IsLoad()
   6179           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
   6180           : TryInlineSetter(
   6181               info->accessor(), info->map(), ast_id, return_id, value);
   6182       if (success || HasStackOverflow()) return NULL;
   6183     }
   6184 
   6185     PushArgumentsFromEnvironment(argument_count);
   6186     if (!info->accessor()->IsJSFunction()) {
   6187       Bailout(kInliningBailedOut);
   6188       return nullptr;
   6189     }
   6190     return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()),
   6191                                    argument_count, TailCallMode::kDisallow,
   6192                                    TailCallMode::kDisallow);
   6193   }
   6194 
   6195   DCHECK(info->IsDataConstant());
   6196   if (info->IsLoad()) {
   6197     return New<HConstant>(info->constant());
   6198   } else {
   6199     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
   6200   }
   6201 }
   6202 
   6203 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
   6204     PropertyAccessType access_type, Expression* expr, FeedbackSlot slot,
   6205     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
   6206     SmallMapList* maps, Handle<Name> name) {
   6207   // Something did not match; must use a polymorphic load.
   6208   int count = 0;
   6209   HBasicBlock* join = NULL;
   6210   HBasicBlock* number_block = NULL;
   6211   bool handled_string = false;
   6212 
   6213   bool handle_smi = false;
   6214   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6215   int i;
   6216   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
   6217     PropertyAccessInfo info(this, access_type, maps->at(i), name);
   6218     if (info.IsStringType()) {
   6219       if (handled_string) continue;
   6220       handled_string = true;
   6221     }
   6222     if (info.CanAccessMonomorphic()) {
   6223       count++;
   6224       if (info.IsNumberType()) {
   6225         handle_smi = true;
   6226         break;
   6227       }
   6228     }
   6229   }
   6230 
   6231   if (i < maps->length()) {
   6232     count = -1;
   6233     maps->Clear();
   6234   } else {
   6235     count = 0;
   6236   }
   6237   HControlInstruction* smi_check = NULL;
   6238   handled_string = false;
   6239 
   6240   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
   6241     PropertyAccessInfo info(this, access_type, maps->at(i), name);
   6242     if (info.IsStringType()) {
   6243       if (handled_string) continue;
   6244       handled_string = true;
   6245     }
   6246     if (!info.CanAccessMonomorphic()) continue;
   6247 
   6248     if (count == 0) {
   6249       join = graph()->CreateBasicBlock();
   6250       if (handle_smi) {
   6251         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   6252         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   6253         number_block = graph()->CreateBasicBlock();
   6254         smi_check = New<HIsSmiAndBranch>(
   6255             object, empty_smi_block, not_smi_block);
   6256         FinishCurrentBlock(smi_check);
   6257         GotoNoSimulate(empty_smi_block, number_block);
   6258         set_current_block(not_smi_block);
   6259       } else {
   6260         BuildCheckHeapObject(object);
   6261       }
   6262     }
   6263     ++count;
   6264     HBasicBlock* if_true = graph()->CreateBasicBlock();
   6265     HBasicBlock* if_false = graph()->CreateBasicBlock();
   6266     HUnaryControlInstruction* compare;
   6267 
   6268     HValue* dependency;
   6269     if (info.IsNumberType()) {
   6270       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   6271       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
   6272       dependency = smi_check;
   6273     } else if (info.IsStringType()) {
   6274       compare = New<HIsStringAndBranch>(object, if_true, if_false);
   6275       dependency = compare;
   6276     } else {
   6277       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
   6278       dependency = compare;
   6279     }
   6280     FinishCurrentBlock(compare);
   6281 
   6282     if (info.IsNumberType()) {
   6283       GotoNoSimulate(if_true, number_block);
   6284       if_true = number_block;
   6285     }
   6286 
   6287     set_current_block(if_true);
   6288 
   6289     HValue* access =
   6290         BuildMonomorphicAccess(&info, object, dependency, value, ast_id,
   6291                                return_id, FLAG_polymorphic_inlining);
   6292 
   6293     HValue* result = NULL;
   6294     switch (access_type) {
   6295       case LOAD:
   6296         result = access;
   6297         break;
   6298       case STORE:
   6299         result = value;
   6300         break;
   6301     }
   6302 
   6303     if (access == NULL) {
   6304       if (HasStackOverflow()) return;
   6305     } else {
   6306       if (access->IsInstruction()) {
   6307         HInstruction* instr = HInstruction::cast(access);
   6308         if (!instr->IsLinked()) AddInstruction(instr);
   6309       }
   6310       if (!ast_context()->IsEffect()) Push(result);
   6311     }
   6312 
   6313     if (current_block() != NULL) Goto(join);
   6314     set_current_block(if_false);
   6315   }
   6316 
   6317   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   6318   // know about and do not want to handle ones we've never seen.  Otherwise
   6319   // use a generic IC.
   6320   if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
   6321     FinishExitWithHardDeoptimization(
   6322         DeoptimizeReason::kUnknownMapInPolymorphicAccess);
   6323   } else {
   6324     HInstruction* instr =
   6325         BuildNamedGeneric(access_type, expr, slot, object, name, value);
   6326     AddInstruction(instr);
   6327     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
   6328 
   6329     if (join != NULL) {
   6330       Goto(join);
   6331     } else {
   6332       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6333       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6334       return;
   6335     }
   6336   }
   6337 
   6338   DCHECK(join != NULL);
   6339   if (join->HasPredecessor()) {
   6340     join->SetJoinId(ast_id);
   6341     set_current_block(join);
   6342     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6343   } else {
   6344     set_current_block(NULL);
   6345   }
   6346 }
   6347 
   6348 static bool ComputeReceiverTypes(Expression* expr, HValue* receiver,
   6349                                  SmallMapList** t,
   6350                                  HOptimizedGraphBuilder* builder) {
   6351   Zone* zone = builder->zone();
   6352   SmallMapList* maps = expr->GetReceiverTypes();
   6353   *t = maps;
   6354   bool monomorphic = expr->IsMonomorphic();
   6355   if (maps != nullptr && receiver->HasMonomorphicJSObjectType()) {
   6356     if (maps->length() > 0) {
   6357       Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
   6358       maps->FilterForPossibleTransitions(root_map);
   6359       monomorphic = maps->length() == 1;
   6360     } else {
   6361       // No type feedback, see if we can infer the type. This is safely
   6362       // possible if the receiver had a known map at some point, and no
   6363       // map-changing stores have happened to it since.
   6364       Handle<Map> candidate_map = receiver->GetMonomorphicJSObjectMap();
   6365       for (HInstruction* current = builder->current_block()->last();
   6366            current != nullptr; current = current->previous()) {
   6367         if (current->IsBlockEntry()) break;
   6368         if (current->CheckChangesFlag(kMaps)) {
   6369           // Only allow map changes that store the candidate map. We don't
   6370           // need to care which object the map is being written into.
   6371           if (!current->IsStoreNamedField()) break;
   6372           HStoreNamedField* map_change = HStoreNamedField::cast(current);
   6373           if (!map_change->value()->IsConstant()) break;
   6374           HConstant* map_constant = HConstant::cast(map_change->value());
   6375           if (!map_constant->representation().IsTagged()) break;
   6376           Handle<Object> map = map_constant->handle(builder->isolate());
   6377           if (!map.is_identical_to(candidate_map)) break;
   6378         }
   6379         if (current == receiver) {
   6380           // We made it all the way back to the receiver without encountering
   6381           // a map change! So we can assume that the receiver still has the
   6382           // candidate_map we know about.
   6383           maps->Add(candidate_map, zone);
   6384           monomorphic = true;
   6385           break;
   6386         }
   6387       }
   6388     }
   6389   }
   6390   return monomorphic && CanInlinePropertyAccess(maps->first());
   6391 }
   6392 
   6393 
   6394 static bool AreStringTypes(SmallMapList* maps) {
   6395   for (int i = 0; i < maps->length(); i++) {
   6396     if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
   6397   }
   6398   return true;
   6399 }
   6400 
   6401 void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
   6402                                         FeedbackSlot slot, BailoutId ast_id,
   6403                                         BailoutId return_id,
   6404                                         bool is_uninitialized) {
   6405   if (!prop->key()->IsPropertyName()) {
   6406     // Keyed store.
   6407     HValue* value = Pop();
   6408     HValue* key = Pop();
   6409     HValue* object = Pop();
   6410     bool has_side_effects = false;
   6411     HValue* result =
   6412         HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
   6413                                  return_id, STORE, &has_side_effects);
   6414     if (has_side_effects) {
   6415       if (!ast_context()->IsEffect()) Push(value);
   6416       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6417       if (!ast_context()->IsEffect()) Drop(1);
   6418     }
   6419     if (result == NULL) return;
   6420     return ast_context()->ReturnValue(value);
   6421   }
   6422 
   6423   // Named store.
   6424   HValue* value = Pop();
   6425   HValue* object = Pop();
   6426 
   6427   Literal* key = prop->key()->AsLiteral();
   6428   Handle<String> name = Handle<String>::cast(key->value());
   6429   DCHECK(!name.is_null());
   6430 
   6431   HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, slot,
   6432                                     object, name, value, is_uninitialized);
   6433   if (access == NULL) return;
   6434 
   6435   if (!ast_context()->IsEffect()) Push(value);
   6436   if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
   6437   if (access->HasObservableSideEffects()) {
   6438     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6439   }
   6440   if (!ast_context()->IsEffect()) Drop(1);
   6441   return ast_context()->ReturnValue(value);
   6442 }
   6443 
   6444 
   6445 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
   6446   Property* prop = expr->target()->AsProperty();
   6447   DCHECK(prop != NULL);
   6448   CHECK_ALIVE(VisitForValue(prop->obj()));
   6449   if (!prop->key()->IsPropertyName()) {
   6450     CHECK_ALIVE(VisitForValue(prop->key()));
   6451   }
   6452   CHECK_ALIVE(VisitForValue(expr->value()));
   6453   BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
   6454              expr->AssignmentId(), expr->IsUninitialized());
   6455 }
   6456 
   6457 HInstruction* HOptimizedGraphBuilder::InlineGlobalPropertyStore(
   6458     LookupIterator* it, HValue* value, BailoutId ast_id) {
   6459   Handle<PropertyCell> cell = it->GetPropertyCell();
   6460   top_info()->dependencies()->AssumePropertyCell(cell);
   6461   auto cell_type = it->property_details().cell_type();
   6462   if (cell_type == PropertyCellType::kConstant ||
   6463       cell_type == PropertyCellType::kUndefined) {
   6464     Handle<Object> constant(cell->value(), isolate());
   6465     if (value->IsConstant()) {
   6466       HConstant* c_value = HConstant::cast(value);
   6467       if (!constant.is_identical_to(c_value->handle(isolate()))) {
   6468         Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment,
   6469                          Deoptimizer::EAGER);
   6470       }
   6471     } else {
   6472       HValue* c_constant = Add<HConstant>(constant);
   6473       IfBuilder builder(this);
   6474       if (constant->IsNumber()) {
   6475         builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
   6476       } else {
   6477         builder.If<HCompareObjectEqAndBranch>(value, c_constant);
   6478       }
   6479       builder.Then();
   6480       builder.Else();
   6481       Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment,
   6482                        Deoptimizer::EAGER);
   6483       builder.End();
   6484     }
   6485   }
   6486   HConstant* cell_constant = Add<HConstant>(cell);
   6487   auto access = HObjectAccess::ForPropertyCellValue();
   6488   if (cell_type == PropertyCellType::kConstantType) {
   6489     switch (cell->GetConstantType()) {
   6490       case PropertyCellConstantType::kSmi:
   6491         access = access.WithRepresentation(Representation::Smi());
   6492         break;
   6493       case PropertyCellConstantType::kStableMap: {
   6494         // First check that the previous value of the {cell} still has the
   6495         // map that we are about to check the new {value} for. If not, then
   6496         // the stable map assumption was invalidated and we cannot continue
   6497         // with the optimized code.
   6498         Handle<HeapObject> cell_value(HeapObject::cast(cell->value()));
   6499         Handle<Map> cell_value_map(cell_value->map());
   6500         if (!cell_value_map->is_stable()) {
   6501           Bailout(kUnstableConstantTypeHeapObject);
   6502           return nullptr;
   6503         }
   6504         top_info()->dependencies()->AssumeMapStable(cell_value_map);
   6505         // Now check that the new {value} is a HeapObject with the same map
   6506         Add<HCheckHeapObject>(value);
   6507         value = Add<HCheckMaps>(value, cell_value_map);
   6508         access = access.WithRepresentation(Representation::HeapObject());
   6509         break;
   6510       }
   6511     }
   6512   }
   6513   HInstruction* instr = New<HStoreNamedField>(cell_constant, access, value);
   6514   instr->ClearChangesFlag(kInobjectFields);
   6515   instr->SetChangesFlag(kGlobalVars);
   6516   return instr;
   6517 }
   6518 
   6519 // Because not every expression has a position and there is not common
   6520 // superclass of Assignment and CountOperation, we cannot just pass the
   6521 // owning expression instead of position and ast_id separately.
   6522 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
   6523                                                             HValue* value,
   6524                                                             FeedbackSlot slot,
   6525                                                             BailoutId ast_id) {
   6526   Handle<JSGlobalObject> global(current_info()->global_object());
   6527 
   6528   // Lookup in script contexts.
   6529   {
   6530     Handle<ScriptContextTable> script_contexts(
   6531         global->native_context()->script_context_table());
   6532     ScriptContextTable::LookupResult lookup;
   6533     if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
   6534       if (lookup.mode == CONST) {
   6535         return Bailout(kNonInitializerAssignmentToConst);
   6536       }
   6537       Handle<Context> script_context =
   6538           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
   6539 
   6540       Handle<Object> current_value =
   6541           FixedArray::get(*script_context, lookup.slot_index, isolate());
   6542 
   6543       // If the values is not the hole, it will stay initialized,
   6544       // so no need to generate a check.
   6545       if (current_value->IsTheHole(isolate())) {
   6546         return Bailout(kReferenceToUninitializedVariable);
   6547       }
   6548 
   6549       HStoreNamedField* instr = Add<HStoreNamedField>(
   6550           Add<HConstant>(script_context),
   6551           HObjectAccess::ForContextSlot(lookup.slot_index), value);
   6552       USE(instr);
   6553       DCHECK(instr->HasObservableSideEffects());
   6554       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6555       return;
   6556     }
   6557   }
   6558 
   6559   LookupIterator it(global, var->name(), LookupIterator::OWN);
   6560   if (CanInlineGlobalPropertyAccess(var, &it, STORE)) {
   6561     HInstruction* instr = InlineGlobalPropertyStore(&it, value, ast_id);
   6562     if (!instr) return;
   6563     AddInstruction(instr);
   6564     if (instr->HasObservableSideEffects()) {
   6565       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6566     }
   6567   } else {
   6568     HValue* global_object = Add<HLoadNamedField>(
   6569         BuildGetNativeContext(), nullptr,
   6570         HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
   6571     Handle<FeedbackVector> vector =
   6572         handle(current_feedback_vector(), isolate());
   6573     HValue* name = Add<HConstant>(var->name());
   6574     HValue* vector_value = Add<HConstant>(vector);
   6575     HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
   6576     DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode());
   6577     Callable callable = CodeFactory::StoreICInOptimizedCode(
   6578         isolate(), function_language_mode());
   6579     HValue* stub = Add<HConstant>(callable.code());
   6580     HValue* values[] = {global_object, name, value, slot_value, vector_value};
   6581     HCallWithDescriptor* instr = Add<HCallWithDescriptor>(
   6582         Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values));
   6583     USE(instr);
   6584     DCHECK(instr->HasObservableSideEffects());
   6585     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6586   }
   6587 }
   6588 
   6589 
   6590 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
   6591   Expression* target = expr->target();
   6592   VariableProxy* proxy = target->AsVariableProxy();
   6593   Property* prop = target->AsProperty();
   6594   DCHECK(proxy == NULL || prop == NULL);
   6595 
   6596   // We have a second position recorded in the FullCodeGenerator to have
   6597   // type feedback for the binary operation.
   6598   BinaryOperation* operation = expr->binary_operation();
   6599 
   6600   if (proxy != NULL) {
   6601     Variable* var = proxy->var();
   6602     if (var->mode() == LET)  {
   6603       return Bailout(kUnsupportedLetCompoundAssignment);
   6604     }
   6605 
   6606     CHECK_ALIVE(VisitForValue(operation));
   6607 
   6608     switch (var->location()) {
   6609       case VariableLocation::UNALLOCATED:
   6610         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
   6611                                        expr->AssignmentId());
   6612         break;
   6613 
   6614       case VariableLocation::PARAMETER:
   6615       case VariableLocation::LOCAL:
   6616         if (var->mode() == CONST) {
   6617           return Bailout(kNonInitializerAssignmentToConst);
   6618         }
   6619         BindIfLive(var, Top());
   6620         break;
   6621 
   6622       case VariableLocation::CONTEXT: {
   6623         // Bail out if we try to mutate a parameter value in a function
   6624         // using the arguments object.  We do not (yet) correctly handle the
   6625         // arguments property of the function.
   6626         if (current_info()->scope()->arguments() != NULL) {
   6627           // Parameters will be allocated to context slots.  We have no
   6628           // direct way to detect that the variable is a parameter so we do
   6629           // a linear search of the parameter variables.
   6630           int count = current_info()->scope()->num_parameters();
   6631           for (int i = 0; i < count; ++i) {
   6632             if (var == current_info()->scope()->parameter(i)) {
   6633               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
   6634             }
   6635           }
   6636         }
   6637 
   6638         HStoreContextSlot::Mode mode;
   6639 
   6640         switch (var->mode()) {
   6641           case LET:
   6642             mode = HStoreContextSlot::kCheckDeoptimize;
   6643             break;
   6644           case CONST:
   6645             if (var->throw_on_const_assignment(function_language_mode())) {
   6646               return Bailout(kNonInitializerAssignmentToConst);
   6647             } else {
   6648               return ast_context()->ReturnValue(Pop());
   6649             }
   6650           default:
   6651             mode = HStoreContextSlot::kNoCheck;
   6652         }
   6653 
   6654         HValue* context = BuildContextChainWalk(var);
   6655         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   6656             context, var->index(), mode, Top());
   6657         if (instr->HasObservableSideEffects()) {
   6658           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   6659         }
   6660         break;
   6661       }
   6662 
   6663       case VariableLocation::LOOKUP:
   6664         return Bailout(kCompoundAssignmentToLookupSlot);
   6665 
   6666       case VariableLocation::MODULE:
   6667         UNREACHABLE();
   6668     }
   6669     return ast_context()->ReturnValue(Pop());
   6670 
   6671   } else if (prop != NULL) {
   6672     CHECK_ALIVE(VisitForValue(prop->obj()));
   6673     HValue* object = Top();
   6674     HValue* key = NULL;
   6675     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   6676       CHECK_ALIVE(VisitForValue(prop->key()));
   6677       key = Top();
   6678     }
   6679 
   6680     CHECK_ALIVE(PushLoad(prop, object, key));
   6681 
   6682     CHECK_ALIVE(VisitForValue(expr->value()));
   6683     HValue* right = Pop();
   6684     HValue* left = Pop();
   6685 
   6686     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
   6687 
   6688     BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
   6689                expr->AssignmentId(), expr->IsUninitialized());
   6690   } else {
   6691     return Bailout(kInvalidLhsInCompoundAssignment);
   6692   }
   6693 }
   6694 
   6695 
   6696 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
   6697   DCHECK(!HasStackOverflow());
   6698   DCHECK(current_block() != NULL);
   6699   DCHECK(current_block()->HasPredecessor());
   6700 
   6701   VariableProxy* proxy = expr->target()->AsVariableProxy();
   6702   Property* prop = expr->target()->AsProperty();
   6703   DCHECK(proxy == NULL || prop == NULL);
   6704 
   6705   if (expr->is_compound()) {
   6706     HandleCompoundAssignment(expr);
   6707     return;
   6708   }
   6709 
   6710   if (prop != NULL) {
   6711     HandlePropertyAssignment(expr);
   6712   } else if (proxy != NULL) {
   6713     Variable* var = proxy->var();
   6714 
   6715     if (var->mode() == CONST) {
   6716       if (expr->op() != Token::INIT) {
   6717         if (var->throw_on_const_assignment(function_language_mode())) {
   6718           return Bailout(kNonInitializerAssignmentToConst);
   6719         } else {
   6720           CHECK_ALIVE(VisitForValue(expr->value()));
   6721           return ast_context()->ReturnValue(Pop());
   6722         }
   6723       }
   6724     }
   6725 
   6726     // Handle the assignment.
   6727     switch (var->location()) {
   6728       case VariableLocation::UNALLOCATED:
   6729         CHECK_ALIVE(VisitForValue(expr->value()));
   6730         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
   6731                                        expr->AssignmentId());
   6732         return ast_context()->ReturnValue(Pop());
   6733 
   6734       case VariableLocation::PARAMETER:
   6735       case VariableLocation::LOCAL: {
   6736         // Perform an initialization check for let declared variables
   6737         // or parameters.
   6738         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
   6739           HValue* env_value = environment()->Lookup(var);
   6740           if (env_value == graph()->GetConstantHole()) {
   6741             return Bailout(kAssignmentToLetVariableBeforeInitialization);
   6742           }
   6743         }
   6744         // We do not allow the arguments object to occur in a context where it
   6745         // may escape, but assignments to stack-allocated locals are
   6746         // permitted.
   6747         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
   6748         HValue* value = Pop();
   6749         BindIfLive(var, value);
   6750         return ast_context()->ReturnValue(value);
   6751       }
   6752 
   6753       case VariableLocation::CONTEXT: {
   6754         // Bail out if we try to mutate a parameter value in a function using
   6755         // the arguments object.  We do not (yet) correctly handle the
   6756         // arguments property of the function.
   6757         if (current_info()->scope()->arguments() != NULL) {
   6758           // Parameters will rewrite to context slots.  We have no direct way
   6759           // to detect that the variable is a parameter.
   6760           int count = current_info()->scope()->num_parameters();
   6761           for (int i = 0; i < count; ++i) {
   6762             if (var == current_info()->scope()->parameter(i)) {
   6763               return Bailout(kAssignmentToParameterInArgumentsObject);
   6764             }
   6765           }
   6766         }
   6767 
   6768         CHECK_ALIVE(VisitForValue(expr->value()));
   6769         HStoreContextSlot::Mode mode;
   6770         if (expr->op() == Token::ASSIGN) {
   6771           switch (var->mode()) {
   6772             case LET:
   6773               mode = HStoreContextSlot::kCheckDeoptimize;
   6774               break;
   6775             case CONST:
   6776               // If we reached this point, the only possibility
   6777               // is a sloppy assignment to a function name.
   6778               DCHECK(function_language_mode() == SLOPPY &&
   6779                      !var->throw_on_const_assignment(SLOPPY));
   6780               return ast_context()->ReturnValue(Pop());
   6781             default:
   6782               mode = HStoreContextSlot::kNoCheck;
   6783           }
   6784         } else {
   6785           DCHECK_EQ(Token::INIT, expr->op());
   6786           mode = HStoreContextSlot::kNoCheck;
   6787         }
   6788 
   6789         HValue* context = BuildContextChainWalk(var);
   6790         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   6791             context, var->index(), mode, Top());
   6792         if (instr->HasObservableSideEffects()) {
   6793           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   6794         }
   6795         return ast_context()->ReturnValue(Pop());
   6796       }
   6797 
   6798       case VariableLocation::LOOKUP:
   6799         return Bailout(kAssignmentToLOOKUPVariable);
   6800 
   6801       case VariableLocation::MODULE:
   6802         UNREACHABLE();
   6803     }
   6804   } else {
   6805     return Bailout(kInvalidLeftHandSideInAssignment);
   6806   }
   6807 }
   6808 
   6809 
   6810 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
   6811   // Generators are not optimized, so we should never get here.
   6812   UNREACHABLE();
   6813 }
   6814 
   6815 
   6816 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
   6817   DCHECK(!HasStackOverflow());
   6818   DCHECK(current_block() != NULL);
   6819   DCHECK(current_block()->HasPredecessor());
   6820   if (!ast_context()->IsEffect()) {
   6821     // The parser turns invalid left-hand sides in assignments into throw
   6822     // statements, which may not be in effect contexts. We might still try
   6823     // to optimize such functions; bail out now if we do.
   6824     return Bailout(kInvalidLeftHandSideInAssignment);
   6825   }
   6826   CHECK_ALIVE(VisitForValue(expr->exception()));
   6827 
   6828   HValue* value = environment()->Pop();
   6829   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   6830   Add<HPushArguments>(value);
   6831   Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1);
   6832   Add<HSimulate>(expr->id());
   6833 
   6834   // If the throw definitely exits the function, we can finish with a dummy
   6835   // control flow at this point.  This is not the case if the throw is inside
   6836   // an inlined function which may be replaced.
   6837   if (call_context() == NULL) {
   6838     FinishExitCurrentBlock(New<HAbnormalExit>());
   6839   }
   6840 }
   6841 
   6842 
   6843 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
   6844   if (string->IsConstant()) {
   6845     HConstant* c_string = HConstant::cast(string);
   6846     if (c_string->HasStringValue()) {
   6847       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
   6848     }
   6849   }
   6850   return Add<HLoadNamedField>(
   6851       Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
   6852       HObjectAccess::ForMapInstanceType());
   6853 }
   6854 
   6855 
   6856 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
   6857   return AddInstruction(BuildLoadStringLength(string));
   6858 }
   6859 
   6860 
   6861 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* string) {
   6862   if (string->IsConstant()) {
   6863     HConstant* c_string = HConstant::cast(string);
   6864     if (c_string->HasStringValue()) {
   6865       return New<HConstant>(c_string->StringValue()->length());
   6866     }
   6867   }
   6868   return New<HLoadNamedField>(string, nullptr,
   6869                               HObjectAccess::ForStringLength());
   6870 }
   6871 
   6872 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
   6873     PropertyAccessType access_type, Expression* expr, FeedbackSlot slot,
   6874     HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
   6875   if (is_uninitialized) {
   6876     Add<HDeoptimize>(
   6877         DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess,
   6878         Deoptimizer::SOFT);
   6879   }
   6880   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
   6881 
   6882   HValue* key = Add<HConstant>(name);
   6883   HValue* vector_value = Add<HConstant>(vector);
   6884   HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
   6885 
   6886   if (access_type == LOAD) {
   6887     HValue* values[] = {object, key, slot_value, vector_value};
   6888     if (!expr->AsProperty()->key()->IsPropertyName()) {
   6889       DCHECK(vector->IsKeyedLoadIC(slot));
   6890       // It's possible that a keyed load of a constant string was converted
   6891       // to a named load. Here, at the last minute, we need to make sure to
   6892       // use a generic Keyed Load if we are using the type vector, because
   6893       // it has to share information with full code.
   6894       Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
   6895       HValue* stub = Add<HConstant>(callable.code());
   6896       HCallWithDescriptor* result =
   6897           New<HCallWithDescriptor>(Code::KEYED_LOAD_IC, stub, 0,
   6898                                    callable.descriptor(), ArrayVector(values));
   6899       return result;
   6900     }
   6901     DCHECK(vector->IsLoadIC(slot));
   6902     Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
   6903     HValue* stub = Add<HConstant>(callable.code());
   6904     HCallWithDescriptor* result = New<HCallWithDescriptor>(
   6905         Code::LOAD_IC, stub, 0, callable.descriptor(), ArrayVector(values));
   6906     return result;
   6907 
   6908   } else {
   6909     HValue* values[] = {object, key, value, slot_value, vector_value};
   6910     if (vector->IsKeyedStoreIC(slot)) {
   6911       // It's possible that a keyed store of a constant string was converted
   6912       // to a named store. Here, at the last minute, we need to make sure to
   6913       // use a generic Keyed Store if we are using the type vector, because
   6914       // it has to share information with full code.
   6915       DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode());
   6916       Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
   6917           isolate(), function_language_mode());
   6918       HValue* stub = Add<HConstant>(callable.code());
   6919       HCallWithDescriptor* result =
   6920           New<HCallWithDescriptor>(Code::KEYED_STORE_IC, stub, 0,
   6921                                    callable.descriptor(), ArrayVector(values));
   6922       return result;
   6923     }
   6924     HCallWithDescriptor* result;
   6925     if (vector->IsStoreOwnIC(slot)) {
   6926       Callable callable = CodeFactory::StoreOwnICInOptimizedCode(isolate());
   6927       HValue* stub = Add<HConstant>(callable.code());
   6928       result = New<HCallWithDescriptor>(
   6929           Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values));
   6930     } else {
   6931       DCHECK(vector->IsStoreIC(slot));
   6932       DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode());
   6933       Callable callable = CodeFactory::StoreICInOptimizedCode(
   6934           isolate(), function_language_mode());
   6935       HValue* stub = Add<HConstant>(callable.code());
   6936       result = New<HCallWithDescriptor>(
   6937           Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values));
   6938     }
   6939     return result;
   6940   }
   6941 }
   6942 
   6943 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
   6944     PropertyAccessType access_type, Expression* expr, FeedbackSlot slot,
   6945     HValue* object, HValue* key, HValue* value) {
   6946   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
   6947   HValue* vector_value = Add<HConstant>(vector);
   6948   HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
   6949 
   6950   if (access_type == LOAD) {
   6951     HValue* values[] = {object, key, slot_value, vector_value};
   6952 
   6953     Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
   6954     HValue* stub = Add<HConstant>(callable.code());
   6955     HCallWithDescriptor* result =
   6956         New<HCallWithDescriptor>(Code::KEYED_LOAD_IC, stub, 0,
   6957                                  callable.descriptor(), ArrayVector(values));
   6958     return result;
   6959   } else {
   6960     HValue* values[] = {object, key, value, slot_value, vector_value};
   6961 
   6962     Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
   6963         isolate(), function_language_mode());
   6964     HValue* stub = Add<HConstant>(callable.code());
   6965     HCallWithDescriptor* result =
   6966         New<HCallWithDescriptor>(Code::KEYED_STORE_IC, stub, 0,
   6967                                  callable.descriptor(), ArrayVector(values));
   6968     return result;
   6969   }
   6970 }
   6971 
   6972 
   6973 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
   6974   // Loads from a "stock" fast holey double arrays can elide the hole check.
   6975   // Loads from a "stock" fast holey array can convert the hole to undefined
   6976   // with impunity.
   6977   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   6978   bool holey_double_elements =
   6979       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS);
   6980   bool holey_elements =
   6981       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS);
   6982   if ((holey_double_elements || holey_elements) &&
   6983       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
   6984     load_mode =
   6985         holey_double_elements ? ALLOW_RETURN_HOLE : CONVERT_HOLE_TO_UNDEFINED;
   6986 
   6987     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
   6988     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
   6989     BuildCheckPrototypeMaps(prototype, object_prototype);
   6990     graph()->MarkDependsOnEmptyArrayProtoElements();
   6991   }
   6992   return load_mode;
   6993 }
   6994 
   6995 
   6996 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
   6997     HValue* object,
   6998     HValue* key,
   6999     HValue* val,
   7000     HValue* dependency,
   7001     Handle<Map> map,
   7002     PropertyAccessType access_type,
   7003     KeyedAccessStoreMode store_mode) {
   7004   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
   7005 
   7006   if (access_type == STORE && map->prototype()->IsJSObject()) {
   7007     // monomorphic stores need a prototype chain check because shape
   7008     // changes could allow callbacks on elements in the chain that
   7009     // aren't compatible with monomorphic keyed stores.
   7010     PrototypeIterator iter(map);
   7011     JSObject* holder = NULL;
   7012     while (!iter.IsAtEnd()) {
   7013       // JSProxies can't occur here because we wouldn't have installed a
   7014       // non-generic IC if there were any.
   7015       holder = *PrototypeIterator::GetCurrent<JSObject>(iter);
   7016       iter.Advance();
   7017     }
   7018     DCHECK(holder && holder->IsJSObject());
   7019 
   7020     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
   7021                             Handle<JSObject>(holder));
   7022   }
   7023 
   7024   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   7025   return BuildUncheckedMonomorphicElementAccess(
   7026       checked_object, key, val,
   7027       map->instance_type() == JS_ARRAY_TYPE,
   7028       map->elements_kind(), access_type,
   7029       load_mode, store_mode);
   7030 }
   7031 
   7032 
   7033 static bool CanInlineElementAccess(Handle<Map> map) {
   7034   return map->IsJSObjectMap() &&
   7035          (map->has_fast_elements() || map->has_fixed_typed_array_elements()) &&
   7036          !map->has_indexed_interceptor() && !map->is_access_check_needed();
   7037 }
   7038 
   7039 
   7040 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
   7041     HValue* object,
   7042     HValue* key,
   7043     HValue* val,
   7044     SmallMapList* maps) {
   7045   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
   7046   // double), always use the "worst case" code without a transition.  This is
   7047   // much faster than transitioning the elements to the worst case, trading a
   7048   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
   7049   bool has_double_maps = false;
   7050   bool has_smi_or_object_maps = false;
   7051   bool has_js_array_access = false;
   7052   bool has_non_js_array_access = false;
   7053   bool has_seen_holey_elements = false;
   7054   Handle<Map> most_general_consolidated_map;
   7055   for (int i = 0; i < maps->length(); ++i) {
   7056     Handle<Map> map = maps->at(i);
   7057     if (!CanInlineElementAccess(map)) return NULL;
   7058     // Don't allow mixing of JSArrays with JSObjects.
   7059     if (map->instance_type() == JS_ARRAY_TYPE) {
   7060       if (has_non_js_array_access) return NULL;
   7061       has_js_array_access = true;
   7062     } else if (has_js_array_access) {
   7063       return NULL;
   7064     } else {
   7065       has_non_js_array_access = true;
   7066     }
   7067     // Don't allow mixed, incompatible elements kinds.
   7068     if (map->has_fast_double_elements()) {
   7069       if (has_smi_or_object_maps) return NULL;
   7070       has_double_maps = true;
   7071     } else if (map->has_fast_smi_or_object_elements()) {
   7072       if (has_double_maps) return NULL;
   7073       has_smi_or_object_maps = true;
   7074     } else {
   7075       return NULL;
   7076     }
   7077     // Remember if we've ever seen holey elements.
   7078     if (IsHoleyElementsKind(map->elements_kind())) {
   7079       has_seen_holey_elements = true;
   7080     }
   7081     // Remember the most general elements kind, the code for its load will
   7082     // properly handle all of the more specific cases.
   7083     if ((i == 0) || IsMoreGeneralElementsKindTransition(
   7084             most_general_consolidated_map->elements_kind(),
   7085             map->elements_kind())) {
   7086       most_general_consolidated_map = map;
   7087     }
   7088   }
   7089   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
   7090 
   7091   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
   7092   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
   7093   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
   7094   ElementsKind consolidated_elements_kind = has_seen_holey_elements
   7095       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
   7096       : most_general_consolidated_map->elements_kind();
   7097   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   7098   if (has_seen_holey_elements) {
   7099     // Make sure that all of the maps we are handling have the initial array
   7100     // prototype.
   7101     bool saw_non_array_prototype = false;
   7102     for (int i = 0; i < maps->length(); ++i) {
   7103       Handle<Map> map = maps->at(i);
   7104       if (map->prototype() != *isolate()->initial_array_prototype()) {
   7105         // We can't guarantee that loading the hole is safe. The prototype may
   7106         // have an element at this position.
   7107         saw_non_array_prototype = true;
   7108         break;
   7109       }
   7110     }
   7111 
   7112     if (!saw_non_array_prototype) {
   7113       Handle<Map> holey_map = handle(
   7114           isolate()->get_initial_js_array_map(consolidated_elements_kind));
   7115       load_mode = BuildKeyedHoleMode(holey_map);
   7116       if (load_mode != NEVER_RETURN_HOLE) {
   7117         for (int i = 0; i < maps->length(); ++i) {
   7118           Handle<Map> map = maps->at(i);
   7119           // The prototype check was already done for the holey map in
   7120           // BuildKeyedHoleMode.
   7121           if (!map.is_identical_to(holey_map)) {
   7122             Handle<JSObject> prototype(JSObject::cast(map->prototype()),
   7123                                        isolate());
   7124             Handle<JSObject> object_prototype =
   7125                 isolate()->initial_object_prototype();
   7126             BuildCheckPrototypeMaps(prototype, object_prototype);
   7127           }
   7128         }
   7129       }
   7130     }
   7131   }
   7132   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
   7133       checked_object, key, val,
   7134       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
   7135       consolidated_elements_kind, LOAD, load_mode, STANDARD_STORE);
   7136   return instr;
   7137 }
   7138 
   7139 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
   7140     Expression* expr, FeedbackSlot slot, HValue* object, HValue* key,
   7141     HValue* val, SmallMapList* maps, PropertyAccessType access_type,
   7142     KeyedAccessStoreMode store_mode, bool* has_side_effects) {
   7143   *has_side_effects = false;
   7144   BuildCheckHeapObject(object);
   7145 
   7146   if (access_type == LOAD) {
   7147     HInstruction* consolidated_load =
   7148         TryBuildConsolidatedElementLoad(object, key, val, maps);
   7149     if (consolidated_load != NULL) {
   7150       *has_side_effects |= consolidated_load->HasObservableSideEffects();
   7151       return consolidated_load;
   7152     }
   7153   }
   7154 
   7155   // Elements_kind transition support.
   7156   MapHandleList transition_target(maps->length());
   7157   // Collect possible transition targets.
   7158   MapHandleList possible_transitioned_maps(maps->length());
   7159   for (int i = 0; i < maps->length(); ++i) {
   7160     Handle<Map> map = maps->at(i);
   7161     // Loads from strings or loads with a mix of string and non-string maps
   7162     // shouldn't be handled polymorphically.
   7163     DCHECK(access_type != LOAD || !map->IsStringMap());
   7164     ElementsKind elements_kind = map->elements_kind();
   7165     if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
   7166         elements_kind != GetInitialFastElementsKind()) {
   7167       possible_transitioned_maps.Add(map);
   7168     }
   7169     if (IsSloppyArgumentsElements(elements_kind)) {
   7170       HInstruction* result =
   7171           BuildKeyedGeneric(access_type, expr, slot, object, key, val);
   7172       *has_side_effects = result->HasObservableSideEffects();
   7173       return AddInstruction(result);
   7174     }
   7175   }
   7176   // Get transition target for each map (NULL == no transition).
   7177   for (int i = 0; i < maps->length(); ++i) {
   7178     Handle<Map> map = maps->at(i);
   7179     Map* transitioned_map =
   7180         map->FindElementsKindTransitionedMap(&possible_transitioned_maps);
   7181     if (transitioned_map != nullptr) {
   7182       transition_target.Add(handle(transitioned_map));
   7183     } else {
   7184       transition_target.Add(Handle<Map>());
   7185     }
   7186   }
   7187 
   7188   MapHandleList untransitionable_maps(maps->length());
   7189   HTransitionElementsKind* transition = NULL;
   7190   for (int i = 0; i < maps->length(); ++i) {
   7191     Handle<Map> map = maps->at(i);
   7192     DCHECK(map->IsMap());
   7193     if (!transition_target.at(i).is_null()) {
   7194       DCHECK(Map::IsValidElementsTransition(
   7195           map->elements_kind(),
   7196           transition_target.at(i)->elements_kind()));
   7197       transition = Add<HTransitionElementsKind>(object, map,
   7198                                                 transition_target.at(i));
   7199     } else {
   7200       untransitionable_maps.Add(map);
   7201     }
   7202   }
   7203 
   7204   // If only one map is left after transitioning, handle this case
   7205   // monomorphically.
   7206   DCHECK(untransitionable_maps.length() >= 1);
   7207   if (untransitionable_maps.length() == 1) {
   7208     Handle<Map> untransitionable_map = untransitionable_maps[0];
   7209     HInstruction* instr = NULL;
   7210     if (!CanInlineElementAccess(untransitionable_map)) {
   7211       instr = AddInstruction(
   7212           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
   7213     } else {
   7214       instr = BuildMonomorphicElementAccess(
   7215           object, key, val, transition, untransitionable_map, access_type,
   7216           store_mode);
   7217     }
   7218     *has_side_effects |= instr->HasObservableSideEffects();
   7219     return access_type == STORE ? val : instr;
   7220   }
   7221 
   7222   HBasicBlock* join = graph()->CreateBasicBlock();
   7223 
   7224   for (int i = 0; i < untransitionable_maps.length(); ++i) {
   7225     Handle<Map> map = untransitionable_maps[i];
   7226     ElementsKind elements_kind = map->elements_kind();
   7227     HBasicBlock* this_map = graph()->CreateBasicBlock();
   7228     HBasicBlock* other_map = graph()->CreateBasicBlock();
   7229     HCompareMap* mapcompare =
   7230         New<HCompareMap>(object, map, this_map, other_map);
   7231     FinishCurrentBlock(mapcompare);
   7232 
   7233     set_current_block(this_map);
   7234     HInstruction* access = NULL;
   7235     if (!CanInlineElementAccess(map)) {
   7236       access = AddInstruction(
   7237           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
   7238     } else {
   7239       DCHECK(IsFastElementsKind(elements_kind) ||
   7240              IsFixedTypedArrayElementsKind(elements_kind));
   7241       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   7242       // Happily, mapcompare is a checked object.
   7243       access = BuildUncheckedMonomorphicElementAccess(
   7244           mapcompare, key, val,
   7245           map->instance_type() == JS_ARRAY_TYPE,
   7246           elements_kind, access_type,
   7247           load_mode,
   7248           store_mode);
   7249     }
   7250     *has_side_effects |= access->HasObservableSideEffects();
   7251     // The caller will use has_side_effects and add a correct Simulate.
   7252     access->SetFlag(HValue::kHasNoObservableSideEffects);
   7253     if (access_type == LOAD) {
   7254       Push(access);
   7255     }
   7256     NoObservableSideEffectsScope scope(this);
   7257     GotoNoSimulate(join);
   7258     set_current_block(other_map);
   7259   }
   7260 
   7261   // Ensure that we visited at least one map above that goes to join. This is
   7262   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
   7263   // rather than joining the join block. If this becomes an issue, insert a
   7264   // generic access in the case length() == 0.
   7265   DCHECK(join->predecessors()->length() > 0);
   7266   // Deopt if none of the cases matched.
   7267   NoObservableSideEffectsScope scope(this);
   7268   FinishExitWithHardDeoptimization(
   7269       DeoptimizeReason::kUnknownMapInPolymorphicElementAccess);
   7270   set_current_block(join);
   7271   return access_type == STORE ? val : Pop();
   7272 }
   7273 
   7274 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
   7275     HValue* obj, HValue* key, HValue* val, Expression* expr, FeedbackSlot slot,
   7276     BailoutId ast_id, BailoutId return_id, PropertyAccessType access_type,
   7277     bool* has_side_effects) {
   7278   // A keyed name access with type feedback may contain the name.
   7279   Handle<FeedbackVector> vector = handle(current_feedback_vector(), isolate());
   7280   HValue* expected_key = key;
   7281   if (!key->ActualValue()->IsConstant()) {
   7282     Name* name = nullptr;
   7283     if (access_type == LOAD) {
   7284       KeyedLoadICNexus nexus(vector, slot);
   7285       name = nexus.FindFirstName();
   7286     } else {
   7287       KeyedStoreICNexus nexus(vector, slot);
   7288       name = nexus.FindFirstName();
   7289     }
   7290     if (name != nullptr) {
   7291       Handle<Name> handle_name(name);
   7292       expected_key = Add<HConstant>(handle_name);
   7293       // We need a check against the key.
   7294       bool in_new_space = isolate()->heap()->InNewSpace(*handle_name);
   7295       Unique<Name> unique_name = Unique<Name>::CreateUninitialized(handle_name);
   7296       Add<HCheckValue>(key, unique_name, in_new_space);
   7297     }
   7298   }
   7299   if (expected_key->ActualValue()->IsConstant()) {
   7300     Handle<Object> constant =
   7301         HConstant::cast(expected_key->ActualValue())->handle(isolate());
   7302     uint32_t array_index;
   7303     if ((constant->IsString() &&
   7304          !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) ||
   7305         constant->IsSymbol()) {
   7306       if (!constant->IsUniqueName()) {
   7307         constant = isolate()->factory()->InternalizeString(
   7308             Handle<String>::cast(constant));
   7309       }
   7310       HValue* access =
   7311           BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
   7312                            Handle<Name>::cast(constant), val, false);
   7313       if (access == NULL || access->IsPhi() ||
   7314           HInstruction::cast(access)->IsLinked()) {
   7315         *has_side_effects = false;
   7316       } else {
   7317         HInstruction* instr = HInstruction::cast(access);
   7318         AddInstruction(instr);
   7319         *has_side_effects = instr->HasObservableSideEffects();
   7320       }
   7321       return access;
   7322     }
   7323   }
   7324 
   7325   DCHECK(!expr->IsPropertyName());
   7326   HInstruction* instr = NULL;
   7327 
   7328   SmallMapList* maps;
   7329   bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, this);
   7330 
   7331   bool force_generic = false;
   7332   if (expr->GetKeyType() == PROPERTY) {
   7333     // Non-Generic accesses assume that elements are being accessed, and will
   7334     // deopt for non-index keys, which the IC knows will occur.
   7335     // TODO(jkummerow): Consider adding proper support for property accesses.
   7336     force_generic = true;
   7337     monomorphic = false;
   7338   } else if (access_type == STORE &&
   7339              (monomorphic || (maps != NULL && !maps->is_empty()))) {
   7340     // Stores can't be mono/polymorphic if their prototype chain has dictionary
   7341     // elements. However a receiver map that has dictionary elements itself
   7342     // should be left to normal mono/poly behavior (the other maps may benefit
   7343     // from highly optimized stores).
   7344     for (int i = 0; i < maps->length(); i++) {
   7345       Handle<Map> current_map = maps->at(i);
   7346       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
   7347         force_generic = true;
   7348         monomorphic = false;
   7349         break;
   7350       }
   7351     }
   7352   } else if (access_type == LOAD && !monomorphic &&
   7353              (maps != NULL && !maps->is_empty())) {
   7354     // Polymorphic loads have to go generic if any of the maps are strings.
   7355     // If some, but not all of the maps are strings, we should go generic
   7356     // because polymorphic access wants to key on ElementsKind and isn't
   7357     // compatible with strings.
   7358     for (int i = 0; i < maps->length(); i++) {
   7359       Handle<Map> current_map = maps->at(i);
   7360       if (current_map->IsStringMap()) {
   7361         force_generic = true;
   7362         break;
   7363       }
   7364     }
   7365   }
   7366 
   7367   if (monomorphic) {
   7368     Handle<Map> map = maps->first();
   7369     if (!CanInlineElementAccess(map)) {
   7370       instr = AddInstruction(
   7371           BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
   7372     } else {
   7373       BuildCheckHeapObject(obj);
   7374       instr = BuildMonomorphicElementAccess(
   7375           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
   7376     }
   7377   } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
   7378     return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
   7379                                           access_type, expr->GetStoreMode(),
   7380                                           has_side_effects);
   7381   } else {
   7382     if (access_type == STORE) {
   7383       if (expr->IsAssignment() &&
   7384           expr->AsAssignment()->HasNoTypeInformation()) {
   7385         Add<HDeoptimize>(
   7386             DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess,
   7387             Deoptimizer::SOFT);
   7388       }
   7389     } else {
   7390       if (expr->AsProperty()->HasNoTypeInformation()) {
   7391         Add<HDeoptimize>(
   7392             DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess,
   7393             Deoptimizer::SOFT);
   7394       }
   7395     }
   7396     instr = AddInstruction(
   7397         BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
   7398   }
   7399   *has_side_effects = instr->HasObservableSideEffects();
   7400   return instr;
   7401 }
   7402 
   7403 
   7404 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
   7405   // Outermost function already has arguments on the stack.
   7406   if (function_state()->outer() == NULL) return;
   7407 
   7408   if (function_state()->arguments_pushed()) return;
   7409 
   7410   // Push arguments when entering inlined function.
   7411   HEnterInlined* entry = function_state()->entry();
   7412   entry->set_arguments_pushed();
   7413 
   7414   HArgumentsObject* arguments = entry->arguments_object();
   7415   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
   7416 
   7417   HInstruction* insert_after = entry;
   7418   for (int i = 0; i < arguments_values->length(); i++) {
   7419     HValue* argument = arguments_values->at(i);
   7420     HInstruction* push_argument = New<HPushArguments>(argument);
   7421     push_argument->InsertAfter(insert_after);
   7422     insert_after = push_argument;
   7423   }
   7424 
   7425   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
   7426   arguments_elements->ClearFlag(HValue::kUseGVN);
   7427   arguments_elements->InsertAfter(insert_after);
   7428   function_state()->set_arguments_elements(arguments_elements);
   7429 }
   7430 
   7431 bool HOptimizedGraphBuilder::IsAnyParameterContextAllocated() {
   7432   int count = current_info()->scope()->num_parameters();
   7433   for (int i = 0; i < count; ++i) {
   7434     if (current_info()->scope()->parameter(i)->location() ==
   7435         VariableLocation::CONTEXT) {
   7436       return true;
   7437     }
   7438   }
   7439   return false;
   7440 }
   7441 
   7442 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
   7443   VariableProxy* proxy = expr->obj()->AsVariableProxy();
   7444   if (proxy == NULL) return false;
   7445   if (!proxy->var()->IsStackAllocated()) return false;
   7446   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
   7447     return false;
   7448   }
   7449 
   7450   HInstruction* result = NULL;
   7451   if (expr->key()->IsPropertyName()) {
   7452     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7453     if (!String::Equals(name, isolate()->factory()->length_string())) {
   7454       return false;
   7455     }
   7456 
   7457     // Make sure we visit the arguments object so that the liveness analysis
   7458     // still records the access.
   7459     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
   7460     Drop(1);
   7461 
   7462     if (function_state()->outer() == NULL) {
   7463       HInstruction* elements = Add<HArgumentsElements>(false);
   7464       result = New<HArgumentsLength>(elements);
   7465     } else {
   7466       // Number of arguments without receiver.
   7467       int argument_count = environment()->
   7468           arguments_environment()->parameter_count() - 1;
   7469       result = New<HConstant>(argument_count);
   7470     }
   7471   } else {
   7472     // We need to take into account the KEYED_LOAD_IC feedback to guard the
   7473     // HBoundsCheck instructions below.
   7474     if (!expr->IsMonomorphic() && !expr->IsUninitialized()) return false;
   7475     if (IsAnyParameterContextAllocated()) return false;
   7476     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
   7477     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
   7478     HValue* key = Pop();
   7479     Drop(1);  // Arguments object.
   7480     if (function_state()->outer() == NULL) {
   7481       HInstruction* elements = Add<HArgumentsElements>(false);
   7482       HInstruction* length = Add<HArgumentsLength>(elements);
   7483       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7484       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7485     } else {
   7486       EnsureArgumentsArePushedForAccess();
   7487 
   7488       // Number of arguments without receiver.
   7489       HInstruction* elements = function_state()->arguments_elements();
   7490       int argument_count = environment()->
   7491           arguments_environment()->parameter_count() - 1;
   7492       HInstruction* length = Add<HConstant>(argument_count);
   7493       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7494       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7495     }
   7496   }
   7497   ast_context()->ReturnInstruction(result, expr->id());
   7498   return true;
   7499 }
   7500 
   7501 HValue* HOptimizedGraphBuilder::BuildNamedAccess(
   7502     PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
   7503     Expression* expr, FeedbackSlot slot, HValue* object, Handle<Name> name,
   7504     HValue* value, bool is_uninitialized) {
   7505   SmallMapList* maps;
   7506   ComputeReceiverTypes(expr, object, &maps, this);
   7507   DCHECK(maps != NULL);
   7508 
   7509   // Check for special case: Access via a single map to the global proxy
   7510   // can also be handled monomorphically.
   7511   if (maps->length() > 0) {
   7512     Handle<Object> map_constructor =
   7513         handle(maps->first()->GetConstructor(), isolate());
   7514     if (map_constructor->IsJSFunction()) {
   7515       Handle<Context> map_context =
   7516           handle(Handle<JSFunction>::cast(map_constructor)->context());
   7517       Handle<Context> current_context(current_info()->context());
   7518       bool is_same_context_global_proxy_access =
   7519           maps->length() == 1 &&  // >1 map => fallback to polymorphic
   7520           maps->first()->IsJSGlobalProxyMap() &&
   7521           (*map_context == *current_context);
   7522       if (is_same_context_global_proxy_access) {
   7523         Handle<JSGlobalObject> global_object(current_info()->global_object());
   7524         LookupIterator it(global_object, name, LookupIterator::OWN);
   7525         if (CanInlineGlobalPropertyAccess(&it, access)) {
   7526           BuildCheckHeapObject(object);
   7527           Add<HCheckMaps>(object, maps);
   7528           if (access == LOAD) {
   7529             InlineGlobalPropertyLoad(&it, expr->id());
   7530             return nullptr;
   7531           } else {
   7532             return InlineGlobalPropertyStore(&it, value, expr->id());
   7533           }
   7534         }
   7535       }
   7536     }
   7537 
   7538     PropertyAccessInfo info(this, access, maps->first(), name);
   7539     if (!info.CanAccessAsMonomorphic(maps)) {
   7540       HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
   7541                                         object, value, maps, name);
   7542       return NULL;
   7543     }
   7544 
   7545     HValue* checked_object;
   7546     // AstType::Number() is only supported by polymorphic load/call handling.
   7547     DCHECK(!info.IsNumberType());
   7548     BuildCheckHeapObject(object);
   7549     if (AreStringTypes(maps)) {
   7550       checked_object =
   7551           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
   7552     } else {
   7553       checked_object = Add<HCheckMaps>(object, maps);
   7554     }
   7555     return BuildMonomorphicAccess(
   7556         &info, object, checked_object, value, ast_id, return_id);
   7557   }
   7558 
   7559   return BuildNamedGeneric(access, expr, slot, object, name, value,
   7560                            is_uninitialized);
   7561 }
   7562 
   7563 
   7564 void HOptimizedGraphBuilder::PushLoad(Property* expr,
   7565                                       HValue* object,
   7566                                       HValue* key) {
   7567   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   7568   Push(object);
   7569   if (key != NULL) Push(key);
   7570   BuildLoad(expr, expr->LoadId());
   7571 }
   7572 
   7573 
   7574 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
   7575                                        BailoutId ast_id) {
   7576   HInstruction* instr = NULL;
   7577   if (expr->IsStringAccess() && expr->GetKeyType() == ELEMENT) {
   7578     HValue* index = Pop();
   7579     HValue* string = Pop();
   7580     HInstruction* char_code = BuildStringCharCodeAt(string, index);
   7581     AddInstruction(char_code);
   7582     if (char_code->IsConstant()) {
   7583       HConstant* c_code = HConstant::cast(char_code);
   7584       if (c_code->HasNumberValue() && std::isnan(c_code->DoubleValue())) {
   7585         Add<HDeoptimize>(DeoptimizeReason::kOutOfBounds, Deoptimizer::EAGER);
   7586       }
   7587     }
   7588     instr = NewUncasted<HStringCharFromCode>(char_code);
   7589 
   7590   } else if (expr->key()->IsPropertyName()) {
   7591     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7592     HValue* object = Pop();
   7593 
   7594     HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
   7595                                      expr->PropertyFeedbackSlot(), object, name,
   7596                                      NULL, expr->IsUninitialized());
   7597     if (value == NULL) return;
   7598     if (value->IsPhi()) return ast_context()->ReturnValue(value);
   7599     instr = HInstruction::cast(value);
   7600     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
   7601 
   7602   } else {
   7603     HValue* key = Pop();
   7604     HValue* obj = Pop();
   7605 
   7606     bool has_side_effects = false;
   7607     HValue* load = HandleKeyedElementAccess(
   7608         obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
   7609         expr->LoadId(), LOAD, &has_side_effects);
   7610     if (has_side_effects) {
   7611       if (ast_context()->IsEffect()) {
   7612         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7613       } else {
   7614         Push(load);
   7615         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7616         Drop(1);
   7617       }
   7618     }
   7619     if (load == NULL) return;
   7620     return ast_context()->ReturnValue(load);
   7621   }
   7622   return ast_context()->ReturnInstruction(instr, ast_id);
   7623 }
   7624 
   7625 
   7626 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
   7627   DCHECK(!HasStackOverflow());
   7628   DCHECK(current_block() != NULL);
   7629   DCHECK(current_block()->HasPredecessor());
   7630 
   7631   if (TryArgumentsAccess(expr)) return;
   7632 
   7633   CHECK_ALIVE(VisitForValue(expr->obj()));
   7634   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
   7635     CHECK_ALIVE(VisitForValue(expr->key()));
   7636   }
   7637 
   7638   BuildLoad(expr, expr->id());
   7639 }
   7640 
   7641 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
   7642                                                    bool ensure_no_elements) {
   7643   HCheckMaps* check = Add<HCheckMaps>(
   7644       Add<HConstant>(constant), handle(constant->map()));
   7645   check->ClearDependsOnFlag(kElementsKind);
   7646   if (ensure_no_elements) {
   7647     // TODO(ishell): remove this once we support NO_ELEMENTS elements kind.
   7648     HValue* elements = AddLoadElements(check, nullptr);
   7649     HValue* empty_elements =
   7650         Add<HConstant>(isolate()->factory()->empty_fixed_array());
   7651     IfBuilder if_empty(this);
   7652     if_empty.IfNot<HCompareObjectEqAndBranch>(elements, empty_elements);
   7653     if_empty.ThenDeopt(DeoptimizeReason::kWrongMap);
   7654     if_empty.End();
   7655   }
   7656   return check;
   7657 }
   7658 
   7659 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
   7660                                                      Handle<JSObject> holder,
   7661                                                      bool ensure_no_elements) {
   7662   PrototypeIterator iter(isolate(), prototype, kStartAtReceiver);
   7663   while (holder.is_null() ||
   7664          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
   7665     BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter),
   7666                           ensure_no_elements);
   7667     iter.Advance();
   7668     if (iter.IsAtEnd()) {
   7669       return NULL;
   7670     }
   7671   }
   7672   return BuildConstantMapCheck(holder);
   7673 }
   7674 
   7675 
   7676 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
   7677                                                    Handle<Map> receiver_map) {
   7678   if (!holder.is_null()) {
   7679     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   7680     BuildCheckPrototypeMaps(prototype, holder);
   7681   }
   7682 }
   7683 
   7684 void HOptimizedGraphBuilder::BuildEnsureCallable(HValue* object) {
   7685   NoObservableSideEffectsScope scope(this);
   7686   const Runtime::Function* throw_called_non_callable =
   7687       Runtime::FunctionForId(Runtime::kThrowCalledNonCallable);
   7688 
   7689   IfBuilder is_not_function(this);
   7690   HValue* smi_check = is_not_function.If<HIsSmiAndBranch>(object);
   7691   is_not_function.Or();
   7692   HValue* map = AddLoadMap(object, smi_check);
   7693   HValue* bit_field =
   7694       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
   7695   HValue* bit_field_masked = AddUncasted<HBitwise>(
   7696       Token::BIT_AND, bit_field, Add<HConstant>(1 << Map::kIsCallable));
   7697   is_not_function.IfNot<HCompareNumericAndBranch>(
   7698       bit_field_masked, Add<HConstant>(1 << Map::kIsCallable), Token::EQ);
   7699   is_not_function.Then();
   7700   {
   7701     Add<HPushArguments>(object);
   7702     Add<HCallRuntime>(throw_called_non_callable, 1);
   7703   }
   7704   is_not_function.End();
   7705 }
   7706 
   7707 HInstruction* HOptimizedGraphBuilder::NewCallFunction(
   7708     HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode,
   7709     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) {
   7710   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
   7711     BuildEnsureCallable(function);
   7712   } else {
   7713     DCHECK_EQ(TailCallMode::kDisallow, tail_call_mode);
   7714   }
   7715   HValue* arity = Add<HConstant>(argument_count - 1);
   7716 
   7717   HValue* op_vals[] = {function, arity};
   7718 
   7719   Callable callable =
   7720       CodeFactory::Call(isolate(), convert_mode, tail_call_mode);
   7721   HConstant* stub = Add<HConstant>(callable.code());
   7722 
   7723   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
   7724                                   ArrayVector(op_vals),
   7725                                   syntactic_tail_call_mode);
   7726 }
   7727 
   7728 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC(
   7729     HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode,
   7730     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode,
   7731     FeedbackSlot slot) {
   7732   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
   7733     BuildEnsureCallable(function);
   7734   } else {
   7735     DCHECK_EQ(TailCallMode::kDisallow, tail_call_mode);
   7736   }
   7737   int arity = argument_count - 1;
   7738   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
   7739   HValue* arity_val = Add<HConstant>(arity);
   7740   HValue* index_val = Add<HConstant>(vector->GetIndex(slot));
   7741   HValue* vector_val = Add<HConstant>(vector);
   7742 
   7743   HValue* op_vals[] = {function, arity_val, index_val, vector_val};
   7744   Callable callable =
   7745       CodeFactory::CallIC(isolate(), convert_mode, tail_call_mode);
   7746   HConstant* stub = Add<HConstant>(callable.code());
   7747 
   7748   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
   7749                                   ArrayVector(op_vals),
   7750                                   syntactic_tail_call_mode);
   7751 }
   7752 
   7753 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction(
   7754     Handle<JSFunction> function, int argument_count,
   7755     TailCallMode syntactic_tail_call_mode, TailCallMode tail_call_mode) {
   7756   HValue* target = Add<HConstant>(function);
   7757   return New<HInvokeFunction>(target, function, argument_count,
   7758                               syntactic_tail_call_mode, tail_call_mode);
   7759 }
   7760 
   7761 
   7762 class FunctionSorter {
   7763  public:
   7764   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
   7765       : index_(index), ticks_(ticks), size_(size) {}
   7766 
   7767   int index() const { return index_; }
   7768   int ticks() const { return ticks_; }
   7769   int size() const { return size_; }
   7770 
   7771  private:
   7772   int index_;
   7773   int ticks_;
   7774   int size_;
   7775 };
   7776 
   7777 
   7778 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
   7779   int diff = lhs.ticks() - rhs.ticks();
   7780   if (diff != 0) return diff > 0;
   7781   return lhs.size() < rhs.size();
   7782 }
   7783 
   7784 
   7785 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
   7786                                                         HValue* receiver,
   7787                                                         SmallMapList* maps,
   7788                                                         Handle<String> name) {
   7789   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
   7790   FunctionSorter order[kMaxCallPolymorphism];
   7791 
   7792   bool handle_smi = false;
   7793   bool handled_string = false;
   7794   int ordered_functions = 0;
   7795 
   7796   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   7797   TailCallMode tail_call_mode =
   7798       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   7799 
   7800   int i;
   7801   for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
   7802        ++i) {
   7803     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
   7804     if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
   7805         info.constant()->IsJSFunction()) {
   7806       if (info.IsStringType()) {
   7807         if (handled_string) continue;
   7808         handled_string = true;
   7809       }
   7810       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   7811       if (info.IsNumberType()) {
   7812         handle_smi = true;
   7813       }
   7814       expr->set_target(target);
   7815       order[ordered_functions++] = FunctionSorter(
   7816           i, target->shared()->profiler_ticks(), InliningAstSize(target));
   7817     }
   7818   }
   7819 
   7820   std::sort(order, order + ordered_functions);
   7821 
   7822   if (i < maps->length()) {
   7823     maps->Clear();
   7824     ordered_functions = -1;
   7825   }
   7826 
   7827   HBasicBlock* number_block = NULL;
   7828   HBasicBlock* join = NULL;
   7829   handled_string = false;
   7830   int count = 0;
   7831 
   7832   for (int fn = 0; fn < ordered_functions; ++fn) {
   7833     int i = order[fn].index();
   7834     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
   7835     if (info.IsStringType()) {
   7836       if (handled_string) continue;
   7837       handled_string = true;
   7838     }
   7839     // Reloads the target.
   7840     info.CanAccessMonomorphic();
   7841     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   7842 
   7843     expr->set_target(target);
   7844     if (count == 0) {
   7845       // Only needed once.
   7846       join = graph()->CreateBasicBlock();
   7847       if (handle_smi) {
   7848         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   7849         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   7850         number_block = graph()->CreateBasicBlock();
   7851         FinishCurrentBlock(New<HIsSmiAndBranch>(
   7852                 receiver, empty_smi_block, not_smi_block));
   7853         GotoNoSimulate(empty_smi_block, number_block);
   7854         set_current_block(not_smi_block);
   7855       } else {
   7856         BuildCheckHeapObject(receiver);
   7857       }
   7858     }
   7859     ++count;
   7860     HBasicBlock* if_true = graph()->CreateBasicBlock();
   7861     HBasicBlock* if_false = graph()->CreateBasicBlock();
   7862     HUnaryControlInstruction* compare;
   7863 
   7864     Handle<Map> map = info.map();
   7865     if (info.IsNumberType()) {
   7866       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   7867       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
   7868     } else if (info.IsStringType()) {
   7869       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
   7870     } else {
   7871       compare = New<HCompareMap>(receiver, map, if_true, if_false);
   7872     }
   7873     FinishCurrentBlock(compare);
   7874 
   7875     if (info.IsNumberType()) {
   7876       GotoNoSimulate(if_true, number_block);
   7877       if_true = number_block;
   7878     }
   7879 
   7880     set_current_block(if_true);
   7881 
   7882     AddCheckPrototypeMaps(info.holder(), map);
   7883 
   7884     HValue* function = Add<HConstant>(expr->target());
   7885     environment()->SetExpressionStackAt(0, function);
   7886     Push(receiver);
   7887     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   7888     bool needs_wrapping = info.NeedsWrappingFor(target);
   7889     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
   7890     if (FLAG_trace_inlining && try_inline) {
   7891       Handle<JSFunction> caller = current_info()->closure();
   7892       std::unique_ptr<char[]> caller_name =
   7893           caller->shared()->DebugName()->ToCString();
   7894       PrintF("Trying to inline the polymorphic call to %s from %s\n",
   7895              name->ToCString().get(),
   7896              caller_name.get());
   7897     }
   7898     if (try_inline && TryInlineCall(expr)) {
   7899       // Trying to inline will signal that we should bailout from the
   7900       // entire compilation by setting stack overflow on the visitor.
   7901       if (HasStackOverflow()) return;
   7902     } else {
   7903       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
   7904       // use the regular call builtin for method calls to wrap the receiver.
   7905       // TODO(verwaest): Support creation of value wrappers directly in
   7906       // HWrapReceiver.
   7907       HInstruction* call =
   7908           needs_wrapping
   7909               ? NewCallFunction(
   7910                     function, argument_count, syntactic_tail_call_mode,
   7911                     ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode)
   7912               : NewCallConstantFunction(target, argument_count,
   7913                                         syntactic_tail_call_mode,
   7914                                         tail_call_mode);
   7915       PushArgumentsFromEnvironment(argument_count);
   7916       AddInstruction(call);
   7917       Drop(1);  // Drop the function.
   7918       if (!ast_context()->IsEffect()) Push(call);
   7919     }
   7920 
   7921     if (current_block() != NULL) Goto(join);
   7922     set_current_block(if_false);
   7923   }
   7924 
   7925   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   7926   // know about and do not want to handle ones we've never seen.  Otherwise
   7927   // use a generic IC.
   7928   if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
   7929     FinishExitWithHardDeoptimization(
   7930         DeoptimizeReason::kUnknownMapInPolymorphicCall);
   7931   } else {
   7932     Property* prop = expr->expression()->AsProperty();
   7933     HInstruction* function =
   7934         BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
   7935                           name, NULL, prop->IsUninitialized());
   7936     AddInstruction(function);
   7937     Push(function);
   7938     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
   7939 
   7940     environment()->SetExpressionStackAt(1, function);
   7941     environment()->SetExpressionStackAt(0, receiver);
   7942     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   7943 
   7944     HInstruction* call = NewCallFunction(
   7945         function, argument_count, syntactic_tail_call_mode,
   7946         ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode);
   7947 
   7948     PushArgumentsFromEnvironment(argument_count);
   7949 
   7950     Drop(1);  // Function.
   7951 
   7952     if (join != NULL) {
   7953       AddInstruction(call);
   7954       if (!ast_context()->IsEffect()) Push(call);
   7955       Goto(join);
   7956     } else {
   7957       return ast_context()->ReturnInstruction(call, expr->id());
   7958     }
   7959   }
   7960 
   7961   // We assume that control flow is always live after an expression.  So
   7962   // even without predecessors to the join block, we set it as the exit
   7963   // block and continue by adding instructions there.
   7964   DCHECK(join != NULL);
   7965   if (join->HasPredecessor()) {
   7966     set_current_block(join);
   7967     join->SetJoinId(expr->id());
   7968     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
   7969   } else {
   7970     set_current_block(NULL);
   7971   }
   7972 }
   7973 
   7974 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
   7975                                          Handle<JSFunction> caller,
   7976                                          const char* reason,
   7977                                          TailCallMode tail_call_mode) {
   7978   if (FLAG_trace_inlining) {
   7979     std::unique_ptr<char[]> target_name =
   7980         target->shared()->DebugName()->ToCString();
   7981     std::unique_ptr<char[]> caller_name =
   7982         caller->shared()->DebugName()->ToCString();
   7983     if (reason == NULL) {
   7984       const char* call_mode =
   7985           tail_call_mode == TailCallMode::kAllow ? "tail called" : "called";
   7986       PrintF("Inlined %s %s from %s.\n", target_name.get(), call_mode,
   7987              caller_name.get());
   7988     } else {
   7989       PrintF("Did not inline %s called from %s (%s).\n",
   7990              target_name.get(), caller_name.get(), reason);
   7991     }
   7992   }
   7993 }
   7994 
   7995 
   7996 static const int kNotInlinable = 1000000000;
   7997 
   7998 
   7999 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
   8000   if (!FLAG_use_inlining) return kNotInlinable;
   8001 
   8002   // Precondition: call is monomorphic and we have found a target with the
   8003   // appropriate arity.
   8004   Handle<JSFunction> caller = current_info()->closure();
   8005   Handle<SharedFunctionInfo> target_shared(target->shared());
   8006 
   8007   // Always inline functions that force inlining.
   8008   if (target_shared->force_inline()) {
   8009     return 0;
   8010   }
   8011   if (!target->shared()->IsUserJavaScript()) {
   8012     return kNotInlinable;
   8013   }
   8014 
   8015   if (target_shared->IsApiFunction()) {
   8016     TraceInline(target, caller, "target is api function");
   8017     return kNotInlinable;
   8018   }
   8019 
   8020   // Do a quick check on source code length to avoid parsing large
   8021   // inlining candidates.
   8022   if (target_shared->SourceSize() >
   8023       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
   8024     TraceInline(target, caller, "target text too big");
   8025     return kNotInlinable;
   8026   }
   8027 
   8028   // Target must be inlineable.
   8029   BailoutReason noopt_reason = target_shared->disable_optimization_reason();
   8030   if (!target_shared->IsInlineable() && noopt_reason != kHydrogenFilter) {
   8031     TraceInline(target, caller, "target not inlineable");
   8032     return kNotInlinable;
   8033   }
   8034   if (noopt_reason != kNoReason && noopt_reason != kHydrogenFilter) {
   8035     TraceInline(target, caller, "target contains unsupported syntax [early]");
   8036     return kNotInlinable;
   8037   }
   8038 
   8039   int nodes_added = target_shared->ast_node_count();
   8040   return nodes_added;
   8041 }
   8042 
   8043 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
   8044                                        int arguments_count,
   8045                                        HValue* implicit_return_value,
   8046                                        BailoutId ast_id, BailoutId return_id,
   8047                                        InliningKind inlining_kind,
   8048                                        TailCallMode syntactic_tail_call_mode) {
   8049   if (target->context()->native_context() !=
   8050       top_info()->closure()->context()->native_context()) {
   8051     return false;
   8052   }
   8053   int nodes_added = InliningAstSize(target);
   8054   if (nodes_added == kNotInlinable) return false;
   8055 
   8056   Handle<JSFunction> caller = current_info()->closure();
   8057   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   8058     TraceInline(target, caller, "target AST is too large [early]");
   8059     return false;
   8060   }
   8061 
   8062   // Don't inline deeper than the maximum number of inlining levels.
   8063   HEnvironment* env = environment();
   8064   int current_level = 1;
   8065   while (env->outer() != NULL) {
   8066     if (current_level == FLAG_max_inlining_levels) {
   8067       TraceInline(target, caller, "inline depth limit reached");
   8068       return false;
   8069     }
   8070     if (env->outer()->frame_type() == JS_FUNCTION) {
   8071       current_level++;
   8072     }
   8073     env = env->outer();
   8074   }
   8075 
   8076   // Don't inline recursive functions.
   8077   for (FunctionState* state = function_state();
   8078        state != NULL;
   8079        state = state->outer()) {
   8080     if (*state->compilation_info()->closure() == *target) {
   8081       TraceInline(target, caller, "target is recursive");
   8082       return false;
   8083     }
   8084   }
   8085 
   8086   // We don't want to add more than a certain number of nodes from inlining.
   8087   // Always inline small methods (<= 10 nodes).
   8088   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
   8089                            kUnlimitedMaxInlinedNodesCumulative)) {
   8090     TraceInline(target, caller, "cumulative AST node limit reached");
   8091     return false;
   8092   }
   8093 
   8094   // Parse and allocate variables.
   8095   // Use the same AstValueFactory for creating strings in the sub-compilation
   8096   // step, but don't transfer ownership to target_info.
   8097   Handle<SharedFunctionInfo> target_shared(target->shared());
   8098   ParseInfo parse_info(target_shared, top_info()->parse_info()->zone_shared());
   8099   parse_info.set_ast_value_factory(
   8100       top_info()->parse_info()->ast_value_factory());
   8101   parse_info.set_ast_value_factory_owned(false);
   8102 
   8103   CompilationInfo target_info(parse_info.zone(), &parse_info, target);
   8104 
   8105   if (inlining_kind != CONSTRUCT_CALL_RETURN &&
   8106       IsClassConstructor(target_shared->kind())) {
   8107     TraceInline(target, caller, "target is classConstructor");
   8108     return false;
   8109   }
   8110 
   8111   if (target_shared->HasDebugInfo()) {
   8112     TraceInline(target, caller, "target is being debugged");
   8113     return false;
   8114   }
   8115   if (!Compiler::ParseAndAnalyze(target_info.parse_info())) {
   8116     if (target_info.isolate()->has_pending_exception()) {
   8117       // Parse or scope error, never optimize this function.
   8118       SetStackOverflow();
   8119       target_shared->DisableOptimization(kParseScopeError);
   8120     }
   8121     TraceInline(target, caller, "parse failure");
   8122     return false;
   8123   }
   8124   if (target_shared->must_use_ignition_turbo()) {
   8125     TraceInline(target, caller, "ParseAndAnalyze found incompatibility");
   8126     return false;
   8127   }
   8128 
   8129   if (target_info.scope()->NeedsContext()) {
   8130     TraceInline(target, caller, "target has context-allocated variables");
   8131     return false;
   8132   }
   8133 
   8134   if (target_info.scope()->rest_parameter() != nullptr) {
   8135     TraceInline(target, caller, "target uses rest parameters");
   8136     return false;
   8137   }
   8138 
   8139   FunctionLiteral* function = target_info.literal();
   8140 
   8141   // The following conditions must be checked again after re-parsing, because
   8142   // earlier the information might not have been complete due to lazy parsing.
   8143   nodes_added = function->ast_node_count();
   8144   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   8145     TraceInline(target, caller, "target AST is too large [late]");
   8146     return false;
   8147   }
   8148   if (function->dont_optimize()) {
   8149     TraceInline(target, caller, "target contains unsupported syntax [late]");
   8150     return false;
   8151   }
   8152 
   8153   // If the function uses the arguments object check that inlining of functions
   8154   // with arguments object is enabled and the arguments-variable is
   8155   // stack allocated.
   8156   if (function->scope()->arguments() != NULL) {
   8157     if (!FLAG_inline_arguments) {
   8158       TraceInline(target, caller, "target uses arguments object");
   8159       return false;
   8160     }
   8161   }
   8162 
   8163   // Unsupported variable references present.
   8164   if (function->scope()->this_function_var() != nullptr ||
   8165       function->scope()->new_target_var() != nullptr) {
   8166     TraceInline(target, caller, "target uses new target or this function");
   8167     return false;
   8168   }
   8169 
   8170   // All declarations must be inlineable.
   8171   Declaration::List* decls = target_info.scope()->declarations();
   8172   for (Declaration* decl : *decls) {
   8173     if (decl->IsFunctionDeclaration() ||
   8174         !decl->proxy()->var()->IsStackAllocated()) {
   8175       TraceInline(target, caller, "target has non-trivial declaration");
   8176       return false;
   8177     }
   8178   }
   8179 
   8180   // Generate the deoptimization data for the unoptimized version of
   8181   // the target function if we don't already have it.
   8182   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
   8183     TraceInline(target, caller, "could not generate deoptimization info");
   8184     return false;
   8185   }
   8186 
   8187   // Remember that we inlined this function. This needs to be called right
   8188   // after the EnsureDeoptimizationSupport call so that the code flusher
   8189   // does not remove the code with the deoptimization support.
   8190   int inlining_id = top_info()->AddInlinedFunction(target_info.shared_info(),
   8191                                                    source_position());
   8192 
   8193   // ----------------------------------------------------------------
   8194   // After this point, we've made a decision to inline this function (so
   8195   // TryInline should always return true).
   8196 
   8197   // If target was lazily compiled, it's literals array may not yet be set up.
   8198   JSFunction::EnsureLiterals(target);
   8199 
   8200   // Type-check the inlined function.
   8201   DCHECK(target_shared->has_deoptimization_support());
   8202   AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
   8203            target_info.scope(), target_info.osr_ast_id(), target_info.literal(),
   8204            &bounds_)
   8205       .Run();
   8206 
   8207   // Save the pending call context. Set up new one for the inlined function.
   8208   // The function state is new-allocated because we need to delete it
   8209   // in two different places.
   8210   FunctionState* target_state = new FunctionState(
   8211       this, &target_info, inlining_kind, inlining_id,
   8212       function_state()->ComputeTailCallMode(syntactic_tail_call_mode));
   8213 
   8214   HConstant* undefined = graph()->GetConstantUndefined();
   8215 
   8216   HEnvironment* inner_env = environment()->CopyForInlining(
   8217       target, arguments_count, function, undefined,
   8218       function_state()->inlining_kind(), syntactic_tail_call_mode);
   8219 
   8220   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
   8221   inner_env->BindContext(context);
   8222 
   8223   // Create a dematerialized arguments object for the function, also copy the
   8224   // current arguments values to use them for materialization.
   8225   HEnvironment* arguments_env = inner_env->arguments_environment();
   8226   int parameter_count = arguments_env->parameter_count();
   8227   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
   8228   for (int i = 0; i < parameter_count; i++) {
   8229     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
   8230   }
   8231 
   8232   // If the function uses arguments object then bind bind one.
   8233   if (function->scope()->arguments() != NULL) {
   8234     DCHECK(function->scope()->arguments()->IsStackAllocated());
   8235     inner_env->Bind(function->scope()->arguments(), arguments_object);
   8236   }
   8237 
   8238   // Capture the state before invoking the inlined function for deopt in the
   8239   // inlined function. This simulate has no bailout-id since it's not directly
   8240   // reachable for deopt, and is only used to capture the state. If the simulate
   8241   // becomes reachable by merging, the ast id of the simulate merged into it is
   8242   // adopted.
   8243   Add<HSimulate>(BailoutId::None());
   8244 
   8245   current_block()->UpdateEnvironment(inner_env);
   8246   Scope* saved_scope = scope();
   8247   set_scope(target_info.scope());
   8248   HEnterInlined* enter_inlined = Add<HEnterInlined>(
   8249       return_id, target, context, arguments_count, function,
   8250       function_state()->inlining_kind(), function->scope()->arguments(),
   8251       arguments_object, syntactic_tail_call_mode);
   8252   if (is_tracking_positions()) {
   8253     enter_inlined->set_inlining_id(inlining_id);
   8254   }
   8255 
   8256   function_state()->set_entry(enter_inlined);
   8257 
   8258   VisitDeclarations(target_info.scope()->declarations());
   8259   VisitStatements(function->body());
   8260   set_scope(saved_scope);
   8261   if (HasStackOverflow()) {
   8262     // Bail out if the inline function did, as we cannot residualize a call
   8263     // instead, but do not disable optimization for the outer function.
   8264     TraceInline(target, caller, "inline graph construction failed");
   8265     target_shared->DisableOptimization(kInliningBailedOut);
   8266     current_info()->RetryOptimization(kInliningBailedOut);
   8267     delete target_state;
   8268     return true;
   8269   }
   8270 
   8271   // Update inlined nodes count.
   8272   inlined_count_ += nodes_added;
   8273 
   8274   Handle<Code> unoptimized_code(target_shared->code());
   8275   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   8276   Handle<TypeFeedbackInfo> type_info(
   8277       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   8278   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
   8279 
   8280   TraceInline(target, caller, NULL, syntactic_tail_call_mode);
   8281 
   8282   if (current_block() != NULL) {
   8283     FunctionState* state = function_state();
   8284     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   8285       // Falling off the end of an inlined construct call. In a test context the
   8286       // return value will always evaluate to true, in a value context the
   8287       // return value is the newly allocated receiver.
   8288       if (call_context()->IsTest()) {
   8289         inlined_test_context()->ReturnValue(graph()->GetConstantTrue());
   8290       } else if (call_context()->IsEffect()) {
   8291         Goto(function_return(), state);
   8292       } else {
   8293         DCHECK(call_context()->IsValue());
   8294         AddLeaveInlined(implicit_return_value, state);
   8295       }
   8296     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   8297       // Falling off the end of an inlined setter call. The returned value is
   8298       // never used, the value of an assignment is always the value of the RHS
   8299       // of the assignment.
   8300       if (call_context()->IsTest()) {
   8301         inlined_test_context()->ReturnValue(implicit_return_value);
   8302       } else if (call_context()->IsEffect()) {
   8303         Goto(function_return(), state);
   8304       } else {
   8305         DCHECK(call_context()->IsValue());
   8306         AddLeaveInlined(implicit_return_value, state);
   8307       }
   8308     } else {
   8309       // Falling off the end of a normal inlined function. This basically means
   8310       // returning undefined.
   8311       if (call_context()->IsTest()) {
   8312         inlined_test_context()->ReturnValue(graph()->GetConstantFalse());
   8313       } else if (call_context()->IsEffect()) {
   8314         Goto(function_return(), state);
   8315       } else {
   8316         DCHECK(call_context()->IsValue());
   8317         AddLeaveInlined(undefined, state);
   8318       }
   8319     }
   8320   }
   8321 
   8322   // Fix up the function exits.
   8323   if (inlined_test_context() != NULL) {
   8324     HBasicBlock* if_true = inlined_test_context()->if_true();
   8325     HBasicBlock* if_false = inlined_test_context()->if_false();
   8326 
   8327     HEnterInlined* entry = function_state()->entry();
   8328 
   8329     // Pop the return test context from the expression context stack.
   8330     DCHECK(ast_context() == inlined_test_context());
   8331     ClearInlinedTestContext();
   8332     delete target_state;
   8333 
   8334     // Forward to the real test context.
   8335     if (if_true->HasPredecessor()) {
   8336       entry->RegisterReturnTarget(if_true, zone());
   8337       if_true->SetJoinId(ast_id);
   8338       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
   8339       Goto(if_true, true_target, function_state());
   8340     }
   8341     if (if_false->HasPredecessor()) {
   8342       entry->RegisterReturnTarget(if_false, zone());
   8343       if_false->SetJoinId(ast_id);
   8344       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
   8345       Goto(if_false, false_target, function_state());
   8346     }
   8347     set_current_block(NULL);
   8348     return true;
   8349 
   8350   } else if (function_return()->HasPredecessor()) {
   8351     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
   8352     function_return()->SetJoinId(ast_id);
   8353     set_current_block(function_return());
   8354   } else {
   8355     set_current_block(NULL);
   8356   }
   8357   delete target_state;
   8358   return true;
   8359 }
   8360 
   8361 
   8362 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
   8363   return TryInline(expr->target(), expr->arguments()->length(), NULL,
   8364                    expr->id(), expr->ReturnId(), NORMAL_RETURN,
   8365                    expr->tail_call_mode());
   8366 }
   8367 
   8368 
   8369 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
   8370                                                 HValue* implicit_return_value) {
   8371   return TryInline(expr->target(), expr->arguments()->length(),
   8372                    implicit_return_value, expr->id(), expr->ReturnId(),
   8373                    CONSTRUCT_CALL_RETURN, TailCallMode::kDisallow);
   8374 }
   8375 
   8376 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter,
   8377                                              Handle<Map> receiver_map,
   8378                                              BailoutId ast_id,
   8379                                              BailoutId return_id) {
   8380   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
   8381   if (getter->IsJSFunction()) {
   8382     Handle<JSFunction> getter_function = Handle<JSFunction>::cast(getter);
   8383     return TryInlineBuiltinGetterCall(getter_function, receiver_map, ast_id) ||
   8384            TryInline(getter_function, 0, NULL, ast_id, return_id,
   8385                      GETTER_CALL_RETURN, TailCallMode::kDisallow);
   8386   }
   8387   return false;
   8388 }
   8389 
   8390 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
   8391                                              Handle<Map> receiver_map,
   8392                                              BailoutId id,
   8393                                              BailoutId assignment_id,
   8394                                              HValue* implicit_return_value) {
   8395   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
   8396   return setter->IsJSFunction() &&
   8397          TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value,
   8398                    id, assignment_id, SETTER_CALL_RETURN,
   8399                    TailCallMode::kDisallow);
   8400 }
   8401 
   8402 
   8403 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
   8404                                                    Call* expr,
   8405                                                    int arguments_count) {
   8406   return TryInline(function, arguments_count, NULL, expr->id(),
   8407                    expr->ReturnId(), NORMAL_RETURN, expr->tail_call_mode());
   8408 }
   8409 
   8410 
   8411 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
   8412   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
   8413   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
   8414   // We intentionally ignore expr->tail_call_mode() here because builtins
   8415   // we inline here do not observe if they were tail called or not.
   8416   switch (id) {
   8417     case kMathCos:
   8418     case kMathExp:
   8419     case kMathRound:
   8420     case kMathFround:
   8421     case kMathFloor:
   8422     case kMathAbs:
   8423     case kMathSin:
   8424     case kMathSqrt:
   8425     case kMathLog:
   8426     case kMathClz32:
   8427       if (expr->arguments()->length() == 1) {
   8428         HValue* argument = Pop();
   8429         Drop(2);  // Receiver and function.
   8430         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8431         ast_context()->ReturnInstruction(op, expr->id());
   8432         return true;
   8433       }
   8434       break;
   8435     case kMathImul:
   8436       if (expr->arguments()->length() == 2) {
   8437         HValue* right = Pop();
   8438         HValue* left = Pop();
   8439         Drop(2);  // Receiver and function.
   8440         HInstruction* op =
   8441             HMul::NewImul(isolate(), zone(), context(), left, right);
   8442         ast_context()->ReturnInstruction(op, expr->id());
   8443         return true;
   8444       }
   8445       break;
   8446     default:
   8447       // Not supported for inlining yet.
   8448       break;
   8449   }
   8450   return false;
   8451 }
   8452 
   8453 
   8454 // static
   8455 bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
   8456     Handle<Map> jsarray_map) {
   8457   DCHECK(!jsarray_map->is_dictionary_map());
   8458   Isolate* isolate = jsarray_map->GetIsolate();
   8459   Handle<Name> length_string = isolate->factory()->length_string();
   8460   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
   8461   int number =
   8462       descriptors->SearchWithCache(isolate, *length_string, *jsarray_map);
   8463   DCHECK_NE(DescriptorArray::kNotFound, number);
   8464   return descriptors->GetDetails(number).IsReadOnly();
   8465 }
   8466 
   8467 
   8468 // static
   8469 bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
   8470     Handle<Map> receiver_map) {
   8471   return !receiver_map.is_null() && receiver_map->prototype()->IsJSObject() &&
   8472          receiver_map->instance_type() == JS_ARRAY_TYPE &&
   8473          IsFastElementsKind(receiver_map->elements_kind()) &&
   8474          !receiver_map->is_dictionary_map() && receiver_map->is_extensible() &&
   8475          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
   8476          !IsReadOnlyLengthDescriptor(receiver_map);
   8477 }
   8478 
   8479 bool HOptimizedGraphBuilder::TryInlineBuiltinGetterCall(
   8480     Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id) {
   8481   if (!function->shared()->HasBuiltinFunctionId()) return false;
   8482   BuiltinFunctionId id = function->shared()->builtin_function_id();
   8483 
   8484   // Try to inline getter calls like DataView.prototype.byteLength/byteOffset
   8485   // as operations in the calling function.
   8486   switch (id) {
   8487     case kDataViewBuffer: {
   8488       if (!receiver_map->IsJSDataViewMap()) return false;
   8489       HObjectAccess access = HObjectAccess::ForMapAndOffset(
   8490           receiver_map, JSDataView::kBufferOffset);
   8491       HValue* object = Pop();  // receiver
   8492       HInstruction* result = New<HLoadNamedField>(object, object, access);
   8493       ast_context()->ReturnInstruction(result, ast_id);
   8494       return true;
   8495     }
   8496     case kDataViewByteLength:
   8497     case kDataViewByteOffset: {
   8498       if (!receiver_map->IsJSDataViewMap()) return false;
   8499       int offset = (id == kDataViewByteLength) ? JSDataView::kByteLengthOffset
   8500                                                : JSDataView::kByteOffsetOffset;
   8501       HObjectAccess access =
   8502           HObjectAccess::ForMapAndOffset(receiver_map, offset);
   8503       HValue* object = Pop();  // receiver
   8504       HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
   8505       HInstruction* result =
   8506           New<HLoadNamedField>(object, checked_object, access);
   8507       ast_context()->ReturnInstruction(result, ast_id);
   8508       return true;
   8509     }
   8510     case kTypedArrayByteLength:
   8511     case kTypedArrayByteOffset:
   8512     case kTypedArrayLength: {
   8513       if (!receiver_map->IsJSTypedArrayMap()) return false;
   8514       int offset = (id == kTypedArrayLength)
   8515                        ? JSTypedArray::kLengthOffset
   8516                        : (id == kTypedArrayByteLength)
   8517                              ? JSTypedArray::kByteLengthOffset
   8518                              : JSTypedArray::kByteOffsetOffset;
   8519       HObjectAccess access =
   8520           HObjectAccess::ForMapAndOffset(receiver_map, offset);
   8521       HValue* object = Pop();  // receiver
   8522       HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
   8523       HInstruction* result =
   8524           New<HLoadNamedField>(object, checked_object, access);
   8525       ast_context()->ReturnInstruction(result, ast_id);
   8526       return true;
   8527     }
   8528     default:
   8529       return false;
   8530   }
   8531 }
   8532 
   8533 // static
   8534 bool HOptimizedGraphBuilder::NoElementsInPrototypeChain(
   8535     Handle<Map> receiver_map) {
   8536   // TODO(ishell): remove this once we support NO_ELEMENTS elements kind.
   8537   PrototypeIterator iter(receiver_map);
   8538   Handle<Object> empty_fixed_array =
   8539       iter.isolate()->factory()->empty_fixed_array();
   8540   while (true) {
   8541     Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
   8542     if (current->elements() != *empty_fixed_array) return false;
   8543     iter.Advance();
   8544     if (iter.IsAtEnd()) {
   8545       return true;
   8546     }
   8547   }
   8548 }
   8549 
   8550 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
   8551     Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id,
   8552     int args_count_no_receiver) {
   8553   if (!function->shared()->HasBuiltinFunctionId()) return false;
   8554   BuiltinFunctionId id = function->shared()->builtin_function_id();
   8555   int argument_count = args_count_no_receiver + 1;  // Plus receiver.
   8556 
   8557   if (receiver_map.is_null()) {
   8558     HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
   8559     if (receiver->IsConstant() &&
   8560         HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
   8561       receiver_map =
   8562           handle(Handle<HeapObject>::cast(
   8563                      HConstant::cast(receiver)->handle(isolate()))->map());
   8564     }
   8565   }
   8566   // Try to inline calls like Math.* as operations in the calling function.
   8567   switch (id) {
   8568     case kObjectHasOwnProperty: {
   8569       // It's not safe to look through the phi for elements if we're compiling
   8570       // for osr.
   8571       if (top_info()->is_osr()) return false;
   8572       if (argument_count != 2) return false;
   8573       HValue* key = Top();
   8574       if (!key->IsLoadKeyed()) return false;
   8575       HValue* elements = HLoadKeyed::cast(key)->elements();
   8576       if (!elements->IsPhi() || elements->OperandCount() != 1) return false;
   8577       if (!elements->OperandAt(0)->IsForInCacheArray()) return false;
   8578       HForInCacheArray* cache = HForInCacheArray::cast(elements->OperandAt(0));
   8579       HValue* receiver = environment()->ExpressionStackAt(1);
   8580       if (!receiver->IsPhi() || receiver->OperandCount() != 1) return false;
   8581       if (cache->enumerable() != receiver->OperandAt(0)) return false;
   8582       Drop(3);  // key, receiver, function
   8583       Add<HCheckMapValue>(receiver, cache->map());
   8584       ast_context()->ReturnValue(graph()->GetConstantTrue());
   8585       return true;
   8586     }
   8587     case kStringCharCodeAt:
   8588     case kStringCharAt:
   8589       if (argument_count == 2) {
   8590         HValue* index = Pop();
   8591         HValue* string = Pop();
   8592         Drop(1);  // Function.
   8593         HInstruction* char_code =
   8594             BuildStringCharCodeAt(string, index);
   8595         if (id == kStringCharCodeAt) {
   8596           ast_context()->ReturnInstruction(char_code, ast_id);
   8597           return true;
   8598         }
   8599         AddInstruction(char_code);
   8600         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   8601         ast_context()->ReturnInstruction(result, ast_id);
   8602         return true;
   8603       }
   8604       break;
   8605     case kStringFromCharCode:
   8606       if (argument_count == 2) {
   8607         HValue* argument = Pop();
   8608         Drop(2);  // Receiver and function.
   8609         argument = AddUncasted<HForceRepresentation>(
   8610             argument, Representation::Integer32());
   8611         argument->SetFlag(HValue::kTruncatingToInt32);
   8612         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
   8613         ast_context()->ReturnInstruction(result, ast_id);
   8614         return true;
   8615       }
   8616       break;
   8617     case kMathCos:
   8618     case kMathExp:
   8619     case kMathRound:
   8620     case kMathFround:
   8621     case kMathFloor:
   8622     case kMathAbs:
   8623     case kMathSin:
   8624     case kMathSqrt:
   8625     case kMathLog:
   8626     case kMathClz32:
   8627       if (argument_count == 2) {
   8628         HValue* argument = Pop();
   8629         Drop(2);  // Receiver and function.
   8630         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8631         ast_context()->ReturnInstruction(op, ast_id);
   8632         return true;
   8633       }
   8634       break;
   8635     case kMathPow:
   8636       if (argument_count == 3) {
   8637         HValue* right = Pop();
   8638         HValue* left = Pop();
   8639         Drop(2);  // Receiver and function.
   8640         HInstruction* result = NULL;
   8641         // Use sqrt() if exponent is 0.5 or -0.5.
   8642         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
   8643           double exponent = HConstant::cast(right)->DoubleValue();
   8644           if (exponent == 0.5) {
   8645             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
   8646           } else if (exponent == -0.5) {
   8647             HValue* one = graph()->GetConstant1();
   8648             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
   8649                 left, kMathPowHalf);
   8650             // MathPowHalf doesn't have side effects so there's no need for
   8651             // an environment simulation here.
   8652             DCHECK(!sqrt->HasObservableSideEffects());
   8653             result = NewUncasted<HDiv>(one, sqrt);
   8654           } else if (exponent == 2.0) {
   8655             result = NewUncasted<HMul>(left, left);
   8656           }
   8657         }
   8658 
   8659         if (result == NULL) {
   8660           result = NewUncasted<HPower>(left, right);
   8661         }
   8662         ast_context()->ReturnInstruction(result, ast_id);
   8663         return true;
   8664       }
   8665       break;
   8666     case kMathMax:
   8667     case kMathMin:
   8668       if (argument_count == 3) {
   8669         HValue* right = Pop();
   8670         HValue* left = Pop();
   8671         Drop(2);  // Receiver and function.
   8672         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
   8673                                                      : HMathMinMax::kMathMax;
   8674         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
   8675         ast_context()->ReturnInstruction(result, ast_id);
   8676         return true;
   8677       }
   8678       break;
   8679     case kMathImul:
   8680       if (argument_count == 3) {
   8681         HValue* right = Pop();
   8682         HValue* left = Pop();
   8683         Drop(2);  // Receiver and function.
   8684         HInstruction* result =
   8685             HMul::NewImul(isolate(), zone(), context(), left, right);
   8686         ast_context()->ReturnInstruction(result, ast_id);
   8687         return true;
   8688       }
   8689       break;
   8690     case kArrayPop: {
   8691       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8692       ElementsKind elements_kind = receiver_map->elements_kind();
   8693 
   8694       Drop(args_count_no_receiver);
   8695       HValue* result;
   8696       HValue* reduced_length;
   8697       HValue* receiver = Pop();
   8698 
   8699       HValue* checked_object = AddCheckMap(receiver, receiver_map);
   8700       HValue* length =
   8701           Add<HLoadNamedField>(checked_object, nullptr,
   8702                                HObjectAccess::ForArrayLength(elements_kind));
   8703 
   8704       Drop(1);  // Function.
   8705 
   8706       { NoObservableSideEffectsScope scope(this);
   8707         IfBuilder length_checker(this);
   8708 
   8709         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
   8710             length, graph()->GetConstant0(), Token::EQ);
   8711         length_checker.Then();
   8712 
   8713         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8714 
   8715         length_checker.Else();
   8716         HValue* elements = AddLoadElements(checked_object);
   8717         // Ensure that we aren't popping from a copy-on-write array.
   8718         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8719           elements = BuildCopyElementsOnWrite(checked_object, elements,
   8720                                               elements_kind, length);
   8721         }
   8722         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
   8723         result = AddElementAccess(elements, reduced_length, nullptr,
   8724                                   bounds_check, nullptr, elements_kind, LOAD);
   8725         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   8726                            ? graph()->GetConstantHole()
   8727                            : Add<HConstant>(HConstant::kHoleNaN);
   8728         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8729           elements_kind = FAST_HOLEY_ELEMENTS;
   8730         }
   8731         AddElementAccess(elements, reduced_length, hole, bounds_check, nullptr,
   8732                          elements_kind, STORE);
   8733         Add<HStoreNamedField>(
   8734             checked_object, HObjectAccess::ForArrayLength(elements_kind),
   8735             reduced_length, STORE_TO_INITIALIZED_ENTRY);
   8736 
   8737         if (!ast_context()->IsEffect()) Push(result);
   8738 
   8739         length_checker.End();
   8740       }
   8741       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   8742       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8743       if (!ast_context()->IsEffect()) Drop(1);
   8744 
   8745       ast_context()->ReturnValue(result);
   8746       return true;
   8747     }
   8748     case kArrayPush: {
   8749       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8750       ElementsKind elements_kind = receiver_map->elements_kind();
   8751 
   8752       // If there may be elements accessors in the prototype chain, the fast
   8753       // inlined version can't be used.
   8754       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8755       // If there currently can be no elements accessors on the prototype chain,
   8756       // it doesn't mean that there won't be any later. Install a full prototype
   8757       // chain check to trap element accessors being installed on the prototype
   8758       // chain, which would cause elements to go to dictionary mode and result
   8759       // in a map change.
   8760       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   8761       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
   8762 
   8763       // Protect against adding elements to the Array prototype, which needs to
   8764       // route through appropriate bottlenecks.
   8765       if (isolate()->IsFastArrayConstructorPrototypeChainIntact() &&
   8766           !prototype->IsJSArray()) {
   8767         return false;
   8768       }
   8769 
   8770       const int argc = args_count_no_receiver;
   8771       if (argc != 1) return false;
   8772 
   8773       HValue* value_to_push = Pop();
   8774       HValue* array = Pop();
   8775       Drop(1);  // Drop function.
   8776 
   8777       HInstruction* new_size = NULL;
   8778       HValue* length = NULL;
   8779 
   8780       {
   8781         NoObservableSideEffectsScope scope(this);
   8782 
   8783         length = Add<HLoadNamedField>(
   8784             array, nullptr, HObjectAccess::ForArrayLength(elements_kind));
   8785 
   8786         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
   8787 
   8788         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
   8789         HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
   8790         BuildUncheckedMonomorphicElementAccess(
   8791             checked_array, length, value_to_push, is_array, elements_kind,
   8792             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
   8793 
   8794         if (!ast_context()->IsEffect()) Push(new_size);
   8795         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8796         if (!ast_context()->IsEffect()) Drop(1);
   8797       }
   8798 
   8799       ast_context()->ReturnValue(new_size);
   8800       return true;
   8801     }
   8802     case kArrayShift: {
   8803       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8804       if (!NoElementsInPrototypeChain(receiver_map)) return false;
   8805       ElementsKind kind = receiver_map->elements_kind();
   8806 
   8807       // If there may be elements accessors in the prototype chain, the fast
   8808       // inlined version can't be used.
   8809       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8810 
   8811       // If there currently can be no elements accessors on the prototype chain,
   8812       // it doesn't mean that there won't be any later. Install a full prototype
   8813       // chain check to trap element accessors being installed on the prototype
   8814       // chain, which would cause elements to go to dictionary mode and result
   8815       // in a map change.
   8816       BuildCheckPrototypeMaps(
   8817           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   8818           Handle<JSObject>::null(), true);
   8819 
   8820       // Threshold for fast inlined Array.shift().
   8821       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
   8822 
   8823       Drop(args_count_no_receiver);
   8824       HValue* result;
   8825       HValue* receiver = Pop();
   8826       HValue* checked_object = AddCheckMap(receiver, receiver_map);
   8827       HValue* length = Add<HLoadNamedField>(
   8828           receiver, checked_object, HObjectAccess::ForArrayLength(kind));
   8829 
   8830       Drop(1);  // Function.
   8831       {
   8832         NoObservableSideEffectsScope scope(this);
   8833 
   8834         IfBuilder if_lengthiszero(this);
   8835         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
   8836             length, graph()->GetConstant0(), Token::EQ);
   8837         if_lengthiszero.Then();
   8838         {
   8839           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8840         }
   8841         if_lengthiszero.Else();
   8842         {
   8843           HValue* elements = AddLoadElements(receiver);
   8844 
   8845           // Check if we can use the fast inlined Array.shift().
   8846           IfBuilder if_inline(this);
   8847           if_inline.If<HCompareNumericAndBranch>(
   8848               length, inline_threshold, Token::LTE);
   8849           if (IsFastSmiOrObjectElementsKind(kind)) {
   8850             // We cannot handle copy-on-write backing stores here.
   8851             if_inline.AndIf<HCompareMap>(
   8852                 elements, isolate()->factory()->fixed_array_map());
   8853           }
   8854           if_inline.Then();
   8855           {
   8856             // Remember the result.
   8857             if (!ast_context()->IsEffect()) {
   8858               Push(AddElementAccess(elements, graph()->GetConstant0(), nullptr,
   8859                                     lengthiszero, nullptr, kind, LOAD));
   8860             }
   8861 
   8862             // Compute the new length.
   8863             HValue* new_length = AddUncasted<HSub>(
   8864                 length, graph()->GetConstant1());
   8865             new_length->ClearFlag(HValue::kCanOverflow);
   8866 
   8867             // Copy the remaining elements.
   8868             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   8869             {
   8870               HValue* new_key = loop.BeginBody(
   8871                   graph()->GetConstant0(), new_length, Token::LT);
   8872               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
   8873               key->ClearFlag(HValue::kCanOverflow);
   8874               ElementsKind copy_kind =
   8875                   kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
   8876               HValue* element =
   8877                   AddUncasted<HLoadKeyed>(elements, key, lengthiszero, nullptr,
   8878                                           copy_kind, ALLOW_RETURN_HOLE);
   8879               HStoreKeyed* store = Add<HStoreKeyed>(elements, new_key, element,
   8880                                                     nullptr, copy_kind);
   8881               store->SetFlag(HValue::kTruncatingToNumber);
   8882             }
   8883             loop.EndBody();
   8884 
   8885             // Put a hole at the end.
   8886             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
   8887                                ? graph()->GetConstantHole()
   8888                                : Add<HConstant>(HConstant::kHoleNaN);
   8889             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
   8890             Add<HStoreKeyed>(elements, new_length, hole, nullptr, kind,
   8891                              INITIALIZING_STORE);
   8892 
   8893             // Remember new length.
   8894             Add<HStoreNamedField>(
   8895                 receiver, HObjectAccess::ForArrayLength(kind),
   8896                 new_length, STORE_TO_INITIALIZED_ENTRY);
   8897           }
   8898           if_inline.Else();
   8899           {
   8900             Add<HPushArguments>(receiver);
   8901             result = AddInstruction(NewCallConstantFunction(
   8902                 function, 1, TailCallMode::kDisallow, TailCallMode::kDisallow));
   8903             if (!ast_context()->IsEffect()) Push(result);
   8904           }
   8905           if_inline.End();
   8906         }
   8907         if_lengthiszero.End();
   8908       }
   8909       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   8910       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8911       if (!ast_context()->IsEffect()) Drop(1);
   8912       ast_context()->ReturnValue(result);
   8913       return true;
   8914     }
   8915     case kArrayIndexOf:
   8916     case kArrayLastIndexOf: {
   8917       if (receiver_map.is_null()) return false;
   8918       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
   8919       if (!receiver_map->prototype()->IsJSObject()) return false;
   8920       ElementsKind kind = receiver_map->elements_kind();
   8921       if (!IsFastElementsKind(kind)) return false;
   8922       if (argument_count != 2) return false;
   8923       if (!receiver_map->is_extensible()) return false;
   8924 
   8925       // If there may be elements accessors in the prototype chain, the fast
   8926       // inlined version can't be used.
   8927       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8928 
   8929       // If there currently can be no elements accessors on the prototype chain,
   8930       // it doesn't mean that there won't be any later. Install a full prototype
   8931       // chain check to trap element accessors being installed on the prototype
   8932       // chain, which would cause elements to go to dictionary mode and result
   8933       // in a map change.
   8934       BuildCheckPrototypeMaps(
   8935           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   8936           Handle<JSObject>::null());
   8937 
   8938       HValue* search_element = Pop();
   8939       HValue* receiver = Pop();
   8940       Drop(1);  // Drop function.
   8941 
   8942       ArrayIndexOfMode mode = (id == kArrayIndexOf)
   8943           ? kFirstIndexOf : kLastIndexOf;
   8944       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
   8945 
   8946       if (!ast_context()->IsEffect()) Push(index);
   8947       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8948       if (!ast_context()->IsEffect()) Drop(1);
   8949       ast_context()->ReturnValue(index);
   8950       return true;
   8951     }
   8952     default:
   8953       // Not yet supported for inlining.
   8954       break;
   8955   }
   8956   return false;
   8957 }
   8958 
   8959 
   8960 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
   8961                                                       HValue* receiver) {
   8962   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   8963   Handle<JSFunction> function = expr->target();
   8964   int argc = expr->arguments()->length();
   8965   SmallMapList receiver_maps;
   8966   return TryInlineApiCall(function, receiver, &receiver_maps, argc, expr->id(),
   8967                           kCallApiFunction, expr->tail_call_mode());
   8968 }
   8969 
   8970 
   8971 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
   8972     Call* expr,
   8973     HValue* receiver,
   8974     SmallMapList* receiver_maps) {
   8975   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   8976   Handle<JSFunction> function = expr->target();
   8977   int argc = expr->arguments()->length();
   8978   return TryInlineApiCall(function, receiver, receiver_maps, argc, expr->id(),
   8979                           kCallApiMethod, expr->tail_call_mode());
   8980 }
   8981 
   8982 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function,
   8983                                                 Handle<Map> receiver_map,
   8984                                                 BailoutId ast_id) {
   8985   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   8986   SmallMapList receiver_maps(1, zone());
   8987   receiver_maps.Add(receiver_map, zone());
   8988   return TryInlineApiCall(function,
   8989                           NULL,  // Receiver is on expression stack.
   8990                           &receiver_maps, 0, ast_id, kCallApiGetter,
   8991                           TailCallMode::kDisallow);
   8992 }
   8993 
   8994 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function,
   8995                                                 Handle<Map> receiver_map,
   8996                                                 BailoutId ast_id) {
   8997   SmallMapList receiver_maps(1, zone());
   8998   receiver_maps.Add(receiver_map, zone());
   8999   return TryInlineApiCall(function,
   9000                           NULL,  // Receiver is on expression stack.
   9001                           &receiver_maps, 1, ast_id, kCallApiSetter,
   9002                           TailCallMode::kDisallow);
   9003 }
   9004 
   9005 bool HOptimizedGraphBuilder::TryInlineApiCall(
   9006     Handle<Object> function, HValue* receiver, SmallMapList* receiver_maps,
   9007     int argc, BailoutId ast_id, ApiCallType call_type,
   9008     TailCallMode syntactic_tail_call_mode) {
   9009   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   9010   if (function->IsJSFunction() &&
   9011       Handle<JSFunction>::cast(function)->context()->native_context() !=
   9012           top_info()->closure()->context()->native_context()) {
   9013     return false;
   9014   }
   9015   if (argc > CallApiCallbackStub::kArgMax) {
   9016     return false;
   9017   }
   9018 
   9019   CallOptimization optimization(function);
   9020   if (!optimization.is_simple_api_call()) return false;
   9021   Handle<Map> holder_map;
   9022   for (int i = 0; i < receiver_maps->length(); ++i) {
   9023     auto map = receiver_maps->at(i);
   9024     // Don't inline calls to receivers requiring accesschecks.
   9025     if (map->is_access_check_needed()) return false;
   9026   }
   9027   if (call_type == kCallApiFunction) {
   9028     // Cannot embed a direct reference to the global proxy map
   9029     // as it maybe dropped on deserialization.
   9030     CHECK(!isolate()->serializer_enabled());
   9031     DCHECK(function->IsJSFunction());
   9032     DCHECK_EQ(0, receiver_maps->length());
   9033     receiver_maps->Add(
   9034         handle(Handle<JSFunction>::cast(function)->global_proxy()->map()),
   9035         zone());
   9036   }
   9037   CallOptimization::HolderLookup holder_lookup =
   9038       CallOptimization::kHolderNotFound;
   9039   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
   9040       receiver_maps->first(), &holder_lookup);
   9041   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
   9042 
   9043   if (FLAG_trace_inlining) {
   9044     PrintF("Inlining api function ");
   9045     function->ShortPrint();
   9046     PrintF("\n");
   9047   }
   9048 
   9049   bool is_function = false;
   9050   bool is_store = false;
   9051   switch (call_type) {
   9052     case kCallApiFunction:
   9053     case kCallApiMethod:
   9054       // Need to check that none of the receiver maps could have changed.
   9055       Add<HCheckMaps>(receiver, receiver_maps);
   9056       // Need to ensure the chain between receiver and api_holder is intact.
   9057       if (holder_lookup == CallOptimization::kHolderFound) {
   9058         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
   9059       } else {
   9060         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
   9061       }
   9062       // Includes receiver.
   9063       PushArgumentsFromEnvironment(argc + 1);
   9064       is_function = true;
   9065       break;
   9066     case kCallApiGetter:
   9067       // Receiver and prototype chain cannot have changed.
   9068       DCHECK_EQ(0, argc);
   9069       DCHECK_NULL(receiver);
   9070       // Receiver is on expression stack.
   9071       receiver = Pop();
   9072       Add<HPushArguments>(receiver);
   9073       break;
   9074     case kCallApiSetter:
   9075       {
   9076         is_store = true;
   9077         // Receiver and prototype chain cannot have changed.
   9078         DCHECK_EQ(1, argc);
   9079         DCHECK_NULL(receiver);
   9080         // Receiver and value are on expression stack.
   9081         HValue* value = Pop();
   9082         receiver = Pop();
   9083         Add<HPushArguments>(receiver, value);
   9084         break;
   9085      }
   9086   }
   9087 
   9088   HValue* holder = NULL;
   9089   switch (holder_lookup) {
   9090     case CallOptimization::kHolderFound:
   9091       holder = Add<HConstant>(api_holder);
   9092       break;
   9093     case CallOptimization::kHolderIsReceiver:
   9094       holder = receiver;
   9095       break;
   9096     case CallOptimization::kHolderNotFound:
   9097       UNREACHABLE();
   9098       break;
   9099   }
   9100   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   9101   Handle<Object> call_data_obj(api_call_info->data(), isolate());
   9102   bool call_data_undefined = call_data_obj->IsUndefined(isolate());
   9103   HValue* call_data = Add<HConstant>(call_data_obj);
   9104   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
   9105   ExternalReference ref = ExternalReference(&fun,
   9106                                             ExternalReference::DIRECT_API_CALL,
   9107                                             isolate());
   9108   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
   9109 
   9110   HValue* op_vals[] = {Add<HConstant>(function), call_data, holder,
   9111                        api_function_address};
   9112 
   9113   HInstruction* call = nullptr;
   9114   CHECK(argc <= CallApiCallbackStub::kArgMax);
   9115   if (!is_function) {
   9116     CallApiCallbackStub stub(isolate(), is_store, call_data_undefined,
   9117                              !optimization.is_constant_call());
   9118     Handle<Code> code = stub.GetCode();
   9119     HConstant* code_value = Add<HConstant>(code);
   9120     call = New<HCallWithDescriptor>(
   9121         code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
   9122         Vector<HValue*>(op_vals, arraysize(op_vals)), syntactic_tail_call_mode);
   9123   } else {
   9124     CallApiCallbackStub stub(isolate(), argc, call_data_undefined, false);
   9125     Handle<Code> code = stub.GetCode();
   9126     HConstant* code_value = Add<HConstant>(code);
   9127     call = New<HCallWithDescriptor>(
   9128         code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
   9129         Vector<HValue*>(op_vals, arraysize(op_vals)), syntactic_tail_call_mode);
   9130     Drop(1);  // Drop function.
   9131   }
   9132 
   9133   ast_context()->ReturnInstruction(call, ast_id);
   9134   return true;
   9135 }
   9136 
   9137 
   9138 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
   9139                                                 int arguments_count) {
   9140   Handle<JSFunction> known_function;
   9141   int args_count_no_receiver = arguments_count - 1;
   9142   if (function->IsConstant() &&
   9143       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9144     known_function =
   9145         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
   9146     if (TryInlineBuiltinMethodCall(known_function, Handle<Map>(), expr->id(),
   9147                                    args_count_no_receiver)) {
   9148       if (FLAG_trace_inlining) {
   9149         PrintF("Inlining builtin ");
   9150         known_function->ShortPrint();
   9151         PrintF("\n");
   9152       }
   9153       return;
   9154     }
   9155 
   9156     if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
   9157       return;
   9158     }
   9159   }
   9160 
   9161   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   9162   TailCallMode tail_call_mode =
   9163       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   9164 
   9165   PushArgumentsFromEnvironment(arguments_count);
   9166   HInvokeFunction* call =
   9167       New<HInvokeFunction>(function, known_function, arguments_count,
   9168                            syntactic_tail_call_mode, tail_call_mode);
   9169   Drop(1);  // Function
   9170   ast_context()->ReturnInstruction(call, expr->id());
   9171 }
   9172 
   9173 
   9174 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
   9175   DCHECK(expr->expression()->IsProperty());
   9176 
   9177   if (!expr->IsMonomorphic()) {
   9178     return false;
   9179   }
   9180   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9181   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
   9182       !expr->target()->shared()->HasBuiltinFunctionId()) {
   9183     return false;
   9184   }
   9185 
   9186   switch (expr->target()->shared()->builtin_function_id()) {
   9187     case kFunctionCall: {
   9188       if (expr->arguments()->length() == 0) return false;
   9189       BuildFunctionCall(expr);
   9190       return true;
   9191     }
   9192     case kFunctionApply: {
   9193       // For .apply, only the pattern f.apply(receiver, arguments)
   9194       // is supported.
   9195       if (!CanBeFunctionApplyArguments(expr)) return false;
   9196 
   9197       BuildFunctionApply(expr);
   9198       return true;
   9199     }
   9200     default: { return false; }
   9201   }
   9202   UNREACHABLE();
   9203 }
   9204 
   9205 
   9206 // f.apply(...)
   9207 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
   9208   ZoneList<Expression*>* args = expr->arguments();
   9209   CHECK_ALIVE(VisitForValue(args->at(0)));
   9210   HValue* receiver = Pop();  // receiver
   9211   HValue* function = Pop();  // f
   9212   Drop(1);  // apply
   9213 
   9214   // Make sure the arguments object is live.
   9215   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
   9216   LookupAndMakeLive(arg_two->var());
   9217 
   9218   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9219   HValue* checked_function = AddCheckMap(function, function_map);
   9220 
   9221   if (function_state()->outer() == NULL) {
   9222     TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   9223     TailCallMode tail_call_mode =
   9224         function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   9225 
   9226     HInstruction* elements = Add<HArgumentsElements>(false);
   9227     HInstruction* length = Add<HArgumentsLength>(elements);
   9228     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
   9229     HInstruction* result = New<HApplyArguments>(
   9230         function, wrapped_receiver, length, elements, tail_call_mode);
   9231     ast_context()->ReturnInstruction(result, expr->id());
   9232   } else {
   9233     // We are inside inlined function and we know exactly what is inside
   9234     // arguments object. But we need to be able to materialize at deopt.
   9235     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
   9236               function_state()->entry()->arguments_object()->arguments_count());
   9237     HArgumentsObject* args = function_state()->entry()->arguments_object();
   9238     const ZoneList<HValue*>* arguments_values = args->arguments_values();
   9239     int arguments_count = arguments_values->length();
   9240     Push(function);
   9241     Push(BuildWrapReceiver(receiver, checked_function));
   9242     for (int i = 1; i < arguments_count; i++) {
   9243       Push(arguments_values->at(i));
   9244     }
   9245     HandleIndirectCall(expr, function, arguments_count);
   9246   }
   9247 }
   9248 
   9249 
   9250 // f.call(...)
   9251 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
   9252   HValue* function = Top();  // f
   9253   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9254   HValue* checked_function = AddCheckMap(function, function_map);
   9255 
   9256   // f and call are on the stack in the unoptimized code
   9257   // during evaluation of the arguments.
   9258   CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9259 
   9260   int args_length = expr->arguments()->length();
   9261   int receiver_index = args_length - 1;
   9262   // Patch the receiver.
   9263   HValue* receiver = BuildWrapReceiver(
   9264       environment()->ExpressionStackAt(receiver_index), checked_function);
   9265   environment()->SetExpressionStackAt(receiver_index, receiver);
   9266 
   9267   // Call must not be on the stack from now on.
   9268   int call_index = args_length + 1;
   9269   environment()->RemoveExpressionStackAt(call_index);
   9270 
   9271   HandleIndirectCall(expr, function, args_length);
   9272 }
   9273 
   9274 
   9275 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
   9276                                                     Handle<JSFunction> target) {
   9277   SharedFunctionInfo* shared = target->shared();
   9278   if (is_sloppy(shared->language_mode()) && !shared->native()) {
   9279     // Cannot embed a direct reference to the global proxy
   9280     // as is it dropped on deserialization.
   9281     CHECK(!isolate()->serializer_enabled());
   9282     Handle<JSObject> global_proxy(target->context()->global_proxy());
   9283     return Add<HConstant>(global_proxy);
   9284   }
   9285   return graph()->GetConstantUndefined();
   9286 }
   9287 
   9288 
   9289 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
   9290                                                   HValue* search_element,
   9291                                                   ElementsKind kind,
   9292                                                   ArrayIndexOfMode mode) {
   9293   DCHECK(IsFastElementsKind(kind));
   9294 
   9295   NoObservableSideEffectsScope no_effects(this);
   9296 
   9297   HValue* elements = AddLoadElements(receiver);
   9298   HValue* length = AddLoadArrayLength(receiver, kind);
   9299 
   9300   HValue* initial;
   9301   HValue* terminating;
   9302   Token::Value token;
   9303   LoopBuilder::Direction direction;
   9304   if (mode == kFirstIndexOf) {
   9305     initial = graph()->GetConstant0();
   9306     terminating = length;
   9307     token = Token::LT;
   9308     direction = LoopBuilder::kPostIncrement;
   9309   } else {
   9310     DCHECK_EQ(kLastIndexOf, mode);
   9311     initial = length;
   9312     terminating = graph()->GetConstant0();
   9313     token = Token::GT;
   9314     direction = LoopBuilder::kPreDecrement;
   9315   }
   9316 
   9317   Push(graph()->GetConstantMinus1());
   9318   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
   9319     // Make sure that we can actually compare numbers correctly below, see
   9320     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
   9321     search_element = AddUncasted<HForceRepresentation>(
   9322         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
   9323                                                     : Representation::Double());
   9324 
   9325     LoopBuilder loop(this, context(), direction);
   9326     {
   9327       HValue* index = loop.BeginBody(initial, terminating, token);
   9328       HValue* element = AddUncasted<HLoadKeyed>(
   9329           elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9330       IfBuilder if_issame(this);
   9331       if_issame.If<HCompareNumericAndBranch>(element, search_element,
   9332                                              Token::EQ_STRICT);
   9333       if_issame.Then();
   9334       {
   9335         Drop(1);
   9336         Push(index);
   9337         loop.Break();
   9338       }
   9339       if_issame.End();
   9340     }
   9341     loop.EndBody();
   9342   } else {
   9343     IfBuilder if_isstring(this);
   9344     if_isstring.If<HIsStringAndBranch>(search_element);
   9345     if_isstring.Then();
   9346     {
   9347       LoopBuilder loop(this, context(), direction);
   9348       {
   9349         HValue* index = loop.BeginBody(initial, terminating, token);
   9350         HValue* element = AddUncasted<HLoadKeyed>(
   9351             elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9352         IfBuilder if_issame(this);
   9353         if_issame.If<HIsStringAndBranch>(element);
   9354         if_issame.AndIf<HStringCompareAndBranch>(
   9355             element, search_element, Token::EQ_STRICT);
   9356         if_issame.Then();
   9357         {
   9358           Drop(1);
   9359           Push(index);
   9360           loop.Break();
   9361         }
   9362         if_issame.End();
   9363       }
   9364       loop.EndBody();
   9365     }
   9366     if_isstring.Else();
   9367     {
   9368       IfBuilder if_isnumber(this);
   9369       if_isnumber.If<HIsSmiAndBranch>(search_element);
   9370       if_isnumber.OrIf<HCompareMap>(
   9371           search_element, isolate()->factory()->heap_number_map());
   9372       if_isnumber.Then();
   9373       {
   9374         HValue* search_number =
   9375             AddUncasted<HForceRepresentation>(search_element,
   9376                                               Representation::Double());
   9377         LoopBuilder loop(this, context(), direction);
   9378         {
   9379           HValue* index = loop.BeginBody(initial, terminating, token);
   9380           HValue* element = AddUncasted<HLoadKeyed>(
   9381               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9382 
   9383           IfBuilder if_element_isnumber(this);
   9384           if_element_isnumber.If<HIsSmiAndBranch>(element);
   9385           if_element_isnumber.OrIf<HCompareMap>(
   9386               element, isolate()->factory()->heap_number_map());
   9387           if_element_isnumber.Then();
   9388           {
   9389             HValue* number =
   9390                 AddUncasted<HForceRepresentation>(element,
   9391                                                   Representation::Double());
   9392             IfBuilder if_issame(this);
   9393             if_issame.If<HCompareNumericAndBranch>(
   9394                 number, search_number, Token::EQ_STRICT);
   9395             if_issame.Then();
   9396             {
   9397               Drop(1);
   9398               Push(index);
   9399               loop.Break();
   9400             }
   9401             if_issame.End();
   9402           }
   9403           if_element_isnumber.End();
   9404         }
   9405         loop.EndBody();
   9406       }
   9407       if_isnumber.Else();
   9408       {
   9409         LoopBuilder loop(this, context(), direction);
   9410         {
   9411           HValue* index = loop.BeginBody(initial, terminating, token);
   9412           HValue* element = AddUncasted<HLoadKeyed>(
   9413               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9414           IfBuilder if_issame(this);
   9415           if_issame.If<HCompareObjectEqAndBranch>(
   9416               element, search_element);
   9417           if_issame.Then();
   9418           {
   9419             Drop(1);
   9420             Push(index);
   9421             loop.Break();
   9422           }
   9423           if_issame.End();
   9424         }
   9425         loop.EndBody();
   9426       }
   9427       if_isnumber.End();
   9428     }
   9429     if_isstring.End();
   9430   }
   9431 
   9432   return Pop();
   9433 }
   9434 
   9435 template <class T>
   9436 bool HOptimizedGraphBuilder::TryHandleArrayCall(T* expr, HValue* function) {
   9437   if (!array_function().is_identical_to(expr->target())) {
   9438     return false;
   9439   }
   9440 
   9441   Handle<AllocationSite> site = expr->allocation_site();
   9442   if (site.is_null()) return false;
   9443 
   9444   Add<HCheckValue>(function, array_function());
   9445 
   9446   int arguments_count = expr->arguments()->length();
   9447   if (TryInlineArrayCall(expr, arguments_count, site)) return true;
   9448 
   9449   HInstruction* call = PreProcessCall(New<HCallNewArray>(
   9450       function, arguments_count + 1, site->GetElementsKind(), site));
   9451   if (expr->IsCall()) Drop(1);
   9452   ast_context()->ReturnInstruction(call, expr->id());
   9453 
   9454   return true;
   9455 }
   9456 
   9457 
   9458 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
   9459   ZoneList<Expression*>* args = expr->arguments();
   9460   if (args->length() != 2) return false;
   9461   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
   9462   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
   9463   HValue* arg_two_value = environment()->Lookup(arg_two->var());
   9464   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
   9465   DCHECK_NOT_NULL(current_info()->scope()->arguments());
   9466   return true;
   9467 }
   9468 
   9469 
   9470 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
   9471   DCHECK(!HasStackOverflow());
   9472   DCHECK(current_block() != NULL);
   9473   DCHECK(current_block()->HasPredecessor());
   9474   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   9475   Expression* callee = expr->expression();
   9476   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   9477   HInstruction* call = NULL;
   9478 
   9479   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   9480   TailCallMode tail_call_mode =
   9481       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   9482 
   9483   Property* prop = callee->AsProperty();
   9484   if (prop != NULL) {
   9485     CHECK_ALIVE(VisitForValue(prop->obj()));
   9486     HValue* receiver = Top();
   9487 
   9488     SmallMapList* maps;
   9489     ComputeReceiverTypes(expr, receiver, &maps, this);
   9490 
   9491     if (prop->key()->IsPropertyName() && maps->length() > 0) {
   9492       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
   9493       PropertyAccessInfo info(this, LOAD, maps->first(), name);
   9494       if (!info.CanAccessAsMonomorphic(maps)) {
   9495         HandlePolymorphicCallNamed(expr, receiver, maps, name);
   9496         return;
   9497       }
   9498     }
   9499     HValue* key = NULL;
   9500     if (!prop->key()->IsPropertyName()) {
   9501       CHECK_ALIVE(VisitForValue(prop->key()));
   9502       key = Pop();
   9503     }
   9504 
   9505     CHECK_ALIVE(PushLoad(prop, receiver, key));
   9506     HValue* function = Pop();
   9507 
   9508     if (function->IsConstant() &&
   9509         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9510       // Push the function under the receiver.
   9511       environment()->SetExpressionStackAt(0, function);
   9512       Push(receiver);
   9513 
   9514       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
   9515           HConstant::cast(function)->handle(isolate()));
   9516       expr->set_target(known_function);
   9517 
   9518       if (TryIndirectCall(expr)) return;
   9519       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9520 
   9521       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
   9522       if (TryInlineBuiltinMethodCall(known_function, map, expr->id(),
   9523                                      expr->arguments()->length())) {
   9524         if (FLAG_trace_inlining) {
   9525           PrintF("Inlining builtin ");
   9526           known_function->ShortPrint();
   9527           PrintF("\n");
   9528         }
   9529         return;
   9530       }
   9531       if (TryInlineApiMethodCall(expr, receiver, maps)) return;
   9532 
   9533       // Wrap the receiver if necessary.
   9534       if (NeedsWrapping(maps->first(), known_function)) {
   9535         // Since HWrapReceiver currently cannot actually wrap numbers and
   9536         // strings, use the regular call builtin for method calls to wrap
   9537         // the receiver.
   9538         // TODO(verwaest): Support creation of value wrappers directly in
   9539         // HWrapReceiver.
   9540         call = NewCallFunction(
   9541             function, argument_count, syntactic_tail_call_mode,
   9542             ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode);
   9543       } else if (TryInlineCall(expr)) {
   9544         return;
   9545       } else {
   9546         call =
   9547             NewCallConstantFunction(known_function, argument_count,
   9548                                     syntactic_tail_call_mode, tail_call_mode);
   9549       }
   9550 
   9551     } else {
   9552       ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
   9553       if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
   9554         // We have to use EAGER deoptimization here because Deoptimizer::SOFT
   9555         // gets ignored by the always-opt flag, which leads to incorrect code.
   9556         Add<HDeoptimize>(
   9557             DeoptimizeReason::kInsufficientTypeFeedbackForCallWithArguments,
   9558             Deoptimizer::EAGER);
   9559         arguments_flag = ARGUMENTS_FAKED;
   9560       }
   9561 
   9562       // Push the function under the receiver.
   9563       environment()->SetExpressionStackAt(0, function);
   9564       Push(receiver);
   9565 
   9566       CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
   9567       call = NewCallFunction(function, argument_count, syntactic_tail_call_mode,
   9568                              ConvertReceiverMode::kNotNullOrUndefined,
   9569                              tail_call_mode);
   9570     }
   9571     PushArgumentsFromEnvironment(argument_count);
   9572 
   9573   } else {
   9574     if (expr->is_possibly_eval()) {
   9575       return Bailout(kPossibleDirectCallToEval);
   9576     }
   9577 
   9578     // The function is on the stack in the unoptimized code during
   9579     // evaluation of the arguments.
   9580     CHECK_ALIVE(VisitForValue(expr->expression()));
   9581     HValue* function = Top();
   9582     if (function->IsConstant() &&
   9583         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9584       Handle<Object> constant = HConstant::cast(function)->handle(isolate());
   9585       Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
   9586       expr->SetKnownGlobalTarget(target);
   9587     }
   9588 
   9589     // Placeholder for the receiver.
   9590     Push(graph()->GetConstantUndefined());
   9591     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9592 
   9593     if (expr->IsMonomorphic() &&
   9594         !IsClassConstructor(expr->target()->shared()->kind())) {
   9595       Add<HCheckValue>(function, expr->target());
   9596 
   9597       // Patch the global object on the stack by the expected receiver.
   9598       HValue* receiver = ImplicitReceiverFor(function, expr->target());
   9599       const int receiver_index = argument_count - 1;
   9600       environment()->SetExpressionStackAt(receiver_index, receiver);
   9601 
   9602       if (TryInlineBuiltinFunctionCall(expr)) {
   9603         if (FLAG_trace_inlining) {
   9604           PrintF("Inlining builtin ");
   9605           expr->target()->ShortPrint();
   9606           PrintF("\n");
   9607         }
   9608         return;
   9609       }
   9610       if (TryInlineApiFunctionCall(expr, receiver)) return;
   9611       if (TryHandleArrayCall(expr, function)) return;
   9612       if (TryInlineCall(expr)) return;
   9613 
   9614       PushArgumentsFromEnvironment(argument_count);
   9615       call = NewCallConstantFunction(expr->target(), argument_count,
   9616                                      syntactic_tail_call_mode, tail_call_mode);
   9617     } else {
   9618       PushArgumentsFromEnvironment(argument_count);
   9619       if (expr->is_uninitialized()) {
   9620         // We've never seen this call before, so let's have Crankshaft learn
   9621         // through the type vector.
   9622         call = NewCallFunctionViaIC(function, argument_count,
   9623                                     syntactic_tail_call_mode,
   9624                                     ConvertReceiverMode::kNullOrUndefined,
   9625                                     tail_call_mode, expr->CallFeedbackICSlot());
   9626       } else {
   9627         call = NewCallFunction(
   9628             function, argument_count, syntactic_tail_call_mode,
   9629             ConvertReceiverMode::kNullOrUndefined, tail_call_mode);
   9630       }
   9631     }
   9632   }
   9633 
   9634   Drop(1);  // Drop the function.
   9635   return ast_context()->ReturnInstruction(call, expr->id());
   9636 }
   9637 
   9638 bool HOptimizedGraphBuilder::TryInlineArrayCall(Expression* expression,
   9639                                                 int argument_count,
   9640                                                 Handle<AllocationSite> site) {
   9641   Handle<JSFunction> caller = current_info()->closure();
   9642   Handle<JSFunction> target = array_function();
   9643 
   9644   if (!site->CanInlineCall()) {
   9645     TraceInline(target, caller, "AllocationSite requested no inlining.");
   9646     return false;
   9647   }
   9648 
   9649   if (argument_count > 1) {
   9650     TraceInline(target, caller, "Too many arguments to inline.");
   9651     return false;
   9652   }
   9653 
   9654   int array_length = 0;
   9655   // Do not inline if the constant length argument is not a smi or outside the
   9656   // valid range for unrolled loop initialization.
   9657   if (argument_count == 1) {
   9658     HValue* argument = Top();
   9659     if (!argument->IsConstant()) {
   9660       TraceInline(target, caller,
   9661                   "Dont inline [new] Array(n) where n isn't constant.");
   9662       return false;
   9663     }
   9664 
   9665     HConstant* constant_argument = HConstant::cast(argument);
   9666     if (!constant_argument->HasSmiValue()) {
   9667       TraceInline(target, caller,
   9668                   "Constant length outside of valid inlining range.");
   9669       return false;
   9670     }
   9671     array_length = constant_argument->Integer32Value();
   9672     if (array_length < 0 || array_length > kElementLoopUnrollThreshold) {
   9673       TraceInline(target, caller,
   9674                   "Constant length outside of valid inlining range.");
   9675       return false;
   9676     }
   9677   }
   9678 
   9679   TraceInline(target, caller, NULL);
   9680 
   9681   NoObservableSideEffectsScope no_effects(this);
   9682 
   9683   // Register on the site for deoptimization if the transition feedback changes.
   9684   top_info()->dependencies()->AssumeTransitionStable(site);
   9685 
   9686   // Build the array.
   9687   ElementsKind kind = site->GetElementsKind();
   9688   HValue* capacity;
   9689   HValue* length;
   9690   if (array_length == 0) {
   9691     STATIC_ASSERT(0 < JSArray::kPreallocatedArrayElements);
   9692     const int initial_capacity = JSArray::kPreallocatedArrayElements;
   9693     capacity = Add<HConstant>(initial_capacity);
   9694     length = graph()->GetConstant0();
   9695   } else {
   9696     length = Top();
   9697     capacity = length;
   9698     kind = GetHoleyElementsKind(kind);
   9699   }
   9700 
   9701   // These HForceRepresentations are because we store these as fields in the
   9702   // objects we construct, and an int32-to-smi HChange could deopt. Accept
   9703   // the deopt possibility now, before allocation occurs.
   9704   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   9705   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
   9706 
   9707   // Generate size calculation code here in order to make it dominate
   9708   // the JSArray allocation.
   9709   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
   9710 
   9711   // Bail out for large objects.
   9712   HValue* max_size = Add<HConstant>(kMaxRegularHeapObjectSize);
   9713   Add<HBoundsCheck>(elements_size, max_size);
   9714 
   9715   // Allocate (dealing with failure appropriately).
   9716   AllocationSiteMode mode = DONT_TRACK_ALLOCATION_SITE;
   9717   HAllocate* new_object = AllocateJSArrayObject(mode);
   9718 
   9719   // Fill in the fields: map, properties, length.
   9720   Handle<Map> map_constant(isolate()->get_initial_js_array_map(kind));
   9721   HValue* map = Add<HConstant>(map_constant);
   9722 
   9723   BuildJSArrayHeader(new_object, map,
   9724                      nullptr,  // set elements to empty fixed array
   9725                      mode, kind, nullptr, length);
   9726 
   9727   // Allocate and initialize the elements.
   9728   HAllocate* elements = BuildAllocateElements(kind, elements_size);
   9729   BuildInitializeElementsHeader(elements, kind, capacity);
   9730   BuildFillElementsWithHole(elements, kind, graph()->GetConstant0(), capacity);
   9731 
   9732   // Set the elements.
   9733   Add<HStoreNamedField>(new_object, HObjectAccess::ForElementsPointer(),
   9734                         elements);
   9735 
   9736   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
   9737   Drop(args_to_drop);
   9738   ast_context()->ReturnValue(new_object);
   9739   return true;
   9740 }
   9741 
   9742 
   9743 // Checks whether allocation using the given constructor can be inlined.
   9744 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
   9745   return constructor->has_initial_map() &&
   9746          !IsDerivedConstructor(constructor->shared()->kind()) &&
   9747          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
   9748          constructor->initial_map()->instance_size() <
   9749              HAllocate::kMaxInlineSize;
   9750 }
   9751 
   9752 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
   9753   DCHECK(!HasStackOverflow());
   9754   DCHECK(current_block() != NULL);
   9755   DCHECK(current_block()->HasPredecessor());
   9756   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   9757   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
   9758   Factory* factory = isolate()->factory();
   9759 
   9760   // The constructor function is on the stack in the unoptimized code
   9761   // during evaluation of the arguments.
   9762   CHECK_ALIVE(VisitForValue(expr->expression()));
   9763   HValue* function = Top();
   9764   CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9765 
   9766   if (function->IsConstant() &&
   9767       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9768     Handle<Object> constant = HConstant::cast(function)->handle(isolate());
   9769     expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
   9770   }
   9771 
   9772   if (FLAG_inline_construct &&
   9773       expr->IsMonomorphic() &&
   9774       IsAllocationInlineable(expr->target())) {
   9775     Handle<JSFunction> constructor = expr->target();
   9776     DCHECK(
   9777         constructor->shared()->construct_stub() ==
   9778             isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric) ||
   9779         constructor->shared()->construct_stub() ==
   9780             isolate()->builtins()->builtin(Builtins::kJSConstructStubApi));
   9781     HValue* check = Add<HCheckValue>(function, constructor);
   9782 
   9783     // Force completion of inobject slack tracking before generating
   9784     // allocation code to finalize instance size.
   9785     constructor->CompleteInobjectSlackTrackingIfActive();
   9786 
   9787     // Calculate instance size from initial map of constructor.
   9788     DCHECK(constructor->has_initial_map());
   9789     Handle<Map> initial_map(constructor->initial_map());
   9790     int instance_size = initial_map->instance_size();
   9791 
   9792     // Allocate an instance of the implicit receiver object.
   9793     HValue* size_in_bytes = Add<HConstant>(instance_size);
   9794     HAllocationMode allocation_mode;
   9795     HAllocate* receiver = BuildAllocate(
   9796         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
   9797     receiver->set_known_initial_map(initial_map);
   9798 
   9799     // Initialize map and fields of the newly allocated object.
   9800     { NoObservableSideEffectsScope no_effects(this);
   9801       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
   9802       Add<HStoreNamedField>(receiver,
   9803           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
   9804           Add<HConstant>(initial_map));
   9805       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
   9806       Add<HStoreNamedField>(receiver,
   9807           HObjectAccess::ForMapAndOffset(initial_map,
   9808                                          JSObject::kPropertiesOffset),
   9809           empty_fixed_array);
   9810       Add<HStoreNamedField>(receiver,
   9811           HObjectAccess::ForMapAndOffset(initial_map,
   9812                                          JSObject::kElementsOffset),
   9813           empty_fixed_array);
   9814       BuildInitializeInobjectProperties(receiver, initial_map);
   9815     }
   9816 
   9817     // Replace the constructor function with a newly allocated receiver using
   9818     // the index of the receiver from the top of the expression stack.
   9819     const int receiver_index = argument_count - 1;
   9820     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
   9821     environment()->SetExpressionStackAt(receiver_index, receiver);
   9822 
   9823     if (TryInlineConstruct(expr, receiver)) {
   9824       // Inlining worked, add a dependency on the initial map to make sure that
   9825       // this code is deoptimized whenever the initial map of the constructor
   9826       // changes.
   9827       top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
   9828       return;
   9829     }
   9830 
   9831     // TODO(mstarzinger): For now we remove the previous HAllocate and all
   9832     // corresponding instructions and instead add HPushArguments for the
   9833     // arguments in case inlining failed.  What we actually should do is for
   9834     // inlining to try to build a subgraph without mutating the parent graph.
   9835     HInstruction* instr = current_block()->last();
   9836     do {
   9837       HInstruction* prev_instr = instr->previous();
   9838       instr->DeleteAndReplaceWith(NULL);
   9839       instr = prev_instr;
   9840     } while (instr != check);
   9841     environment()->SetExpressionStackAt(receiver_index, function);
   9842   } else {
   9843     // The constructor function is both an operand to the instruction and an
   9844     // argument to the construct call.
   9845     if (TryHandleArrayCall(expr, function)) return;
   9846   }
   9847 
   9848   HValue* arity = Add<HConstant>(argument_count - 1);
   9849   HValue* op_vals[] = {function, function, arity};
   9850   Callable callable = CodeFactory::Construct(isolate());
   9851   HConstant* stub = Add<HConstant>(callable.code());
   9852   PushArgumentsFromEnvironment(argument_count);
   9853   HInstruction* construct = New<HCallWithDescriptor>(
   9854       stub, argument_count, callable.descriptor(), ArrayVector(op_vals));
   9855   return ast_context()->ReturnInstruction(construct, expr->id());
   9856 }
   9857 
   9858 
   9859 void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
   9860     HValue* receiver, Handle<Map> initial_map) {
   9861   if (initial_map->GetInObjectProperties() != 0) {
   9862     HConstant* undefined = graph()->GetConstantUndefined();
   9863     for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
   9864       int property_offset = initial_map->GetInObjectPropertyOffset(i);
   9865       Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
   9866                                           initial_map, property_offset),
   9867                             undefined);
   9868     }
   9869   }
   9870 }
   9871 
   9872 
   9873 HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
   9874   // We HForceRepresentation here to avoid allocations during an *-to-tagged
   9875   // HChange that could cause GC while the array buffer object is not fully
   9876   // initialized.
   9877   HObjectAccess byte_length_access(HObjectAccess::ForJSArrayBufferByteLength());
   9878   byte_length = AddUncasted<HForceRepresentation>(
   9879       byte_length, byte_length_access.representation());
   9880   HAllocate* result =
   9881       BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
   9882                     HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());
   9883 
   9884   HValue* native_context = BuildGetNativeContext();
   9885   Add<HStoreNamedField>(
   9886       result, HObjectAccess::ForMap(),
   9887       Add<HLoadNamedField>(
   9888           native_context, nullptr,
   9889           HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));
   9890 
   9891   HConstant* empty_fixed_array =
   9892       Add<HConstant>(isolate()->factory()->empty_fixed_array());
   9893   Add<HStoreNamedField>(
   9894       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
   9895       empty_fixed_array);
   9896   Add<HStoreNamedField>(
   9897       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
   9898       empty_fixed_array);
   9899   Add<HStoreNamedField>(
   9900       result, HObjectAccess::ForJSArrayBufferBackingStore().WithRepresentation(
   9901                   Representation::Smi()),
   9902       graph()->GetConstant0());
   9903   Add<HStoreNamedField>(result, byte_length_access, byte_length);
   9904   Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
   9905                         graph()->GetConstant0());
   9906   Add<HStoreNamedField>(
   9907       result, HObjectAccess::ForJSArrayBufferBitField(),
   9908       Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
   9909                      (1 << JSArrayBuffer::IsNeuterable::kShift)));
   9910 
   9911   for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
   9912     Add<HStoreNamedField>(
   9913         result,
   9914         HObjectAccess::ForObservableJSObjectOffset(
   9915             JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
   9916         graph()->GetConstant0());
   9917   }
   9918 
   9919   return result;
   9920 }
   9921 
   9922 
   9923 template <class ViewClass>
   9924 void HGraphBuilder::BuildArrayBufferViewInitialization(
   9925     HValue* obj,
   9926     HValue* buffer,
   9927     HValue* byte_offset,
   9928     HValue* byte_length) {
   9929 
   9930   for (int offset = ViewClass::kSize;
   9931        offset < ViewClass::kSizeWithInternalFields;
   9932        offset += kPointerSize) {
   9933     Add<HStoreNamedField>(obj,
   9934         HObjectAccess::ForObservableJSObjectOffset(offset),
   9935         graph()->GetConstant0());
   9936   }
   9937 
   9938   Add<HStoreNamedField>(
   9939       obj,
   9940       HObjectAccess::ForJSArrayBufferViewByteOffset(),
   9941       byte_offset);
   9942   Add<HStoreNamedField>(
   9943       obj,
   9944       HObjectAccess::ForJSArrayBufferViewByteLength(),
   9945       byte_length);
   9946   Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
   9947                         buffer);
   9948 }
   9949 
   9950 
   9951 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
   9952     ExternalArrayType array_type,
   9953     bool is_zero_byte_offset,
   9954     HValue* buffer, HValue* byte_offset, HValue* length) {
   9955   Handle<Map> external_array_map(
   9956       isolate()->heap()->MapForFixedTypedArray(array_type));
   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   HValue* elements = Add<HAllocate>(
   9962       Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
   9963       NOT_TENURED, external_array_map->instance_type(),
   9964       graph()->GetConstant0());
   9965 
   9966   AddStoreMapConstant(elements, external_array_map);
   9967   Add<HStoreNamedField>(elements,
   9968       HObjectAccess::ForFixedArrayLength(), length);
   9969 
   9970   HValue* backing_store = Add<HLoadNamedField>(
   9971       buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());
   9972 
   9973   HValue* typed_array_start;
   9974   if (is_zero_byte_offset) {
   9975     typed_array_start = backing_store;
   9976   } else {
   9977     HInstruction* external_pointer =
   9978         AddUncasted<HAdd>(backing_store, byte_offset);
   9979     // Arguments are checked prior to call to TypedArrayInitialize,
   9980     // including byte_offset.
   9981     external_pointer->ClearFlag(HValue::kCanOverflow);
   9982     typed_array_start = external_pointer;
   9983   }
   9984 
   9985   Add<HStoreNamedField>(elements,
   9986                         HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
   9987                         graph()->GetConstant0());
   9988   Add<HStoreNamedField>(elements,
   9989                         HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
   9990                         typed_array_start);
   9991 
   9992   return elements;
   9993 }
   9994 
   9995 
   9996 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
   9997     ExternalArrayType array_type, size_t element_size,
   9998     ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length,
   9999     bool initialize) {
   10000   STATIC_ASSERT(
   10001       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
   10002   HValue* total_size;
   10003 
   10004   // if fixed array's elements are not aligned to object's alignment,
   10005   // we need to align the whole array to object alignment.
   10006   if (element_size % kObjectAlignment != 0) {
   10007     total_size = BuildObjectSizeAlignment(
   10008         byte_length, FixedTypedArrayBase::kHeaderSize);
   10009   } else {
   10010     total_size = AddUncasted<HAdd>(byte_length,
   10011         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
   10012     total_size->ClearFlag(HValue::kCanOverflow);
   10013   }
   10014 
   10015   // The HForceRepresentation is to prevent possible deopt on int-smi
   10016   // conversion after allocation but before the new object fields are set.
   10017   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   10018   Handle<Map> fixed_typed_array_map(
   10019       isolate()->heap()->MapForFixedTypedArray(array_type));
   10020   HAllocate* elements = Add<HAllocate>(
   10021       total_size, HType::HeapObject(), NOT_TENURED,
   10022       fixed_typed_array_map->instance_type(), graph()->GetConstant0());
   10023 
   10024 #ifndef V8_HOST_ARCH_64_BIT
   10025   if (array_type == kExternalFloat64Array) {
   10026     elements->MakeDoubleAligned();
   10027   }
   10028 #endif
   10029 
   10030   AddStoreMapConstant(elements, fixed_typed_array_map);
   10031 
   10032   Add<HStoreNamedField>(elements,
   10033       HObjectAccess::ForFixedArrayLength(),
   10034       length);
   10035   Add<HStoreNamedField>(
   10036       elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
   10037 
   10038   Add<HStoreNamedField>(
   10039       elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
   10040       Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));
   10041 
   10042   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
   10043 
   10044   if (initialize) {
   10045     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
   10046 
   10047     HValue* backing_store = AddUncasted<HAdd>(
   10048         Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
   10049         elements, AddOfExternalAndTagged);
   10050 
   10051     HValue* key = builder.BeginBody(
   10052         Add<HConstant>(static_cast<int32_t>(0)),
   10053         length, Token::LT);
   10054     Add<HStoreKeyed>(backing_store, key, filler, elements, fixed_elements_kind);
   10055 
   10056     builder.EndBody();
   10057   }
   10058   return elements;
   10059 }
   10060 
   10061 
   10062 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
   10063     CallRuntime* expr) {
   10064   ZoneList<Expression*>* arguments = expr->arguments();
   10065 
   10066   static const int kObjectArg = 0;
   10067   static const int kArrayIdArg = 1;
   10068   static const int kBufferArg = 2;
   10069   static const int kByteOffsetArg = 3;
   10070   static const int kByteLengthArg = 4;
   10071   static const int kInitializeArg = 5;
   10072   static const int kArgsLength = 6;
   10073   DCHECK(arguments->length() == kArgsLength);
   10074 
   10075 
   10076   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
   10077   HValue* obj = Pop();
   10078 
   10079   if (!arguments->at(kArrayIdArg)->IsLiteral()) {
   10080     // This should never happen in real use, but can happen when fuzzing.
   10081     // Just bail out.
   10082     Bailout(kNeedSmiLiteral);
   10083     return;
   10084   }
   10085   Handle<Object> value =
   10086       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
   10087   if (!value->IsSmi()) {
   10088     // This should never happen in real use, but can happen when fuzzing.
   10089     // Just bail out.
   10090     Bailout(kNeedSmiLiteral);
   10091     return;
   10092   }
   10093   int array_id = Smi::cast(*value)->value();
   10094 
   10095   HValue* buffer;
   10096   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
   10097     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
   10098     buffer = Pop();
   10099   } else {
   10100     buffer = NULL;
   10101   }
   10102 
   10103   HValue* byte_offset;
   10104   bool is_zero_byte_offset;
   10105 
   10106   if (arguments->at(kByteOffsetArg)->IsLiteral() &&
   10107       Smi::kZero ==
   10108           *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
   10109     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
   10110     is_zero_byte_offset = true;
   10111   } else {
   10112     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
   10113     byte_offset = Pop();
   10114     is_zero_byte_offset = false;
   10115     DCHECK(buffer != NULL);
   10116   }
   10117 
   10118   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
   10119   HValue* byte_length = Pop();
   10120 
   10121   CHECK(arguments->at(kInitializeArg)->IsLiteral());
   10122   bool initialize = static_cast<Literal*>(arguments->at(kInitializeArg))
   10123                         ->value()
   10124                         ->BooleanValue();
   10125 
   10126   NoObservableSideEffectsScope scope(this);
   10127   IfBuilder byte_offset_smi(this);
   10128 
   10129   if (!is_zero_byte_offset) {
   10130     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
   10131     byte_offset_smi.Then();
   10132   }
   10133 
   10134   ExternalArrayType array_type =
   10135       kExternalInt8Array;  // Bogus initialization.
   10136   size_t element_size = 1;  // Bogus initialization.
   10137   ElementsKind fixed_elements_kind =  // Bogus initialization.
   10138       INT8_ELEMENTS;
   10139   Runtime::ArrayIdToTypeAndSize(array_id,
   10140       &array_type,
   10141       &fixed_elements_kind,
   10142       &element_size);
   10143 
   10144 
   10145   { //  byte_offset is Smi.
   10146     HValue* allocated_buffer = buffer;
   10147     if (buffer == NULL) {
   10148       allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
   10149     }
   10150     BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
   10151                                                      byte_offset, byte_length);
   10152 
   10153 
   10154     HInstruction* length = AddUncasted<HDiv>(byte_length,
   10155         Add<HConstant>(static_cast<int32_t>(element_size)));
   10156     // Callers (in typedarray.js) ensure that length <= %_MaxSmi().
   10157     length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   10158 
   10159     Add<HStoreNamedField>(obj,
   10160         HObjectAccess::ForJSTypedArrayLength(),
   10161         length);
   10162 
   10163     HValue* elements;
   10164     if (buffer != NULL) {
   10165       elements = BuildAllocateExternalElements(
   10166           array_type, is_zero_byte_offset, buffer, byte_offset, length);
   10167     } else {
   10168       DCHECK(is_zero_byte_offset);
   10169       elements = BuildAllocateFixedTypedArray(array_type, element_size,
   10170                                               fixed_elements_kind, byte_length,
   10171                                               length, initialize);
   10172     }
   10173     Add<HStoreNamedField>(
   10174         obj, HObjectAccess::ForElementsPointer(), elements);
   10175   }
   10176 
   10177   if (!is_zero_byte_offset) {
   10178     byte_offset_smi.Else();
   10179     { //  byte_offset is not Smi.
   10180       Push(obj);
   10181       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
   10182       Push(buffer);
   10183       Push(byte_offset);
   10184       Push(byte_length);
   10185       CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
   10186       PushArgumentsFromEnvironment(kArgsLength);
   10187       Add<HCallRuntime>(expr->function(), kArgsLength);
   10188     }
   10189   }
   10190   byte_offset_smi.End();
   10191 }
   10192 
   10193 
   10194 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
   10195   DCHECK(expr->arguments()->length() == 0);
   10196   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
   10197   return ast_context()->ReturnInstruction(max_smi, expr->id());
   10198 }
   10199 
   10200 
   10201 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
   10202     CallRuntime* expr) {
   10203   DCHECK(expr->arguments()->length() == 0);
   10204   HConstant* result = New<HConstant>(static_cast<int32_t>(
   10205         FLAG_typed_array_max_size_in_heap));
   10206   return ast_context()->ReturnInstruction(result, expr->id());
   10207 }
   10208 
   10209 
   10210 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
   10211     CallRuntime* expr) {
   10212   DCHECK(expr->arguments()->length() == 1);
   10213   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10214   HValue* buffer = Pop();
   10215   HInstruction* result = New<HLoadNamedField>(
   10216       buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
   10217   return ast_context()->ReturnInstruction(result, expr->id());
   10218 }
   10219 
   10220 
   10221 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
   10222     CallRuntime* expr) {
   10223   NoObservableSideEffectsScope scope(this);
   10224   DCHECK(expr->arguments()->length() == 1);
   10225   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10226   HValue* view = Pop();
   10227 
   10228   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10229       view, nullptr,
   10230       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset)));
   10231 }
   10232 
   10233 
   10234 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
   10235     CallRuntime* expr) {
   10236   NoObservableSideEffectsScope scope(this);
   10237   DCHECK(expr->arguments()->length() == 1);
   10238   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10239   HValue* view = Pop();
   10240 
   10241   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10242       view, nullptr,
   10243       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
   10244 }
   10245 
   10246 
   10247 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
   10248     CallRuntime* expr) {
   10249   NoObservableSideEffectsScope scope(this);
   10250   DCHECK(expr->arguments()->length() == 1);
   10251   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10252   HValue* view = Pop();
   10253 
   10254   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10255       view, nullptr,
   10256       FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset)));
   10257 }
   10258 
   10259 
   10260 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
   10261   DCHECK(!HasStackOverflow());
   10262   DCHECK(current_block() != NULL);
   10263   DCHECK(current_block()->HasPredecessor());
   10264   if (expr->is_jsruntime()) {
   10265     // Crankshaft always specializes to the native context, so we can just grab
   10266     // the constant function from the current native context and embed that into
   10267     // the code object.
   10268     Handle<JSFunction> known_function(
   10269         JSFunction::cast(
   10270             current_info()->native_context()->get(expr->context_index())),
   10271         isolate());
   10272 
   10273     // The callee and the receiver both have to be pushed onto the operand stack
   10274     // before arguments are being evaluated.
   10275     HConstant* function = Add<HConstant>(known_function);
   10276     HValue* receiver = ImplicitReceiverFor(function, known_function);
   10277     Push(function);
   10278     Push(receiver);
   10279 
   10280     int argument_count = expr->arguments()->length() + 1;  // Count receiver.
   10281     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   10282     PushArgumentsFromEnvironment(argument_count);
   10283     HInstruction* call = NewCallConstantFunction(known_function, argument_count,
   10284                                                  TailCallMode::kDisallow,
   10285                                                  TailCallMode::kDisallow);
   10286     Drop(1);  // Function
   10287     return ast_context()->ReturnInstruction(call, expr->id());
   10288   }
   10289 
   10290   const Runtime::Function* function = expr->function();
   10291   DCHECK(function != NULL);
   10292   switch (function->function_id) {
   10293 #define CALL_INTRINSIC_GENERATOR(Name) \
   10294   case Runtime::kInline##Name:         \
   10295     return Generate##Name(expr);
   10296 
   10297     FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
   10298 #undef CALL_INTRINSIC_GENERATOR
   10299     default: {
   10300       int argument_count = expr->arguments()->length();
   10301       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   10302       PushArgumentsFromEnvironment(argument_count);
   10303       HCallRuntime* call = New<HCallRuntime>(function, argument_count);
   10304       return ast_context()->ReturnInstruction(call, expr->id());
   10305     }
   10306   }
   10307 }
   10308 
   10309 
   10310 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
   10311   DCHECK(!HasStackOverflow());
   10312   DCHECK(current_block() != NULL);
   10313   DCHECK(current_block()->HasPredecessor());
   10314   switch (expr->op()) {
   10315     case Token::DELETE: return VisitDelete(expr);
   10316     case Token::VOID: return VisitVoid(expr);
   10317     case Token::TYPEOF: return VisitTypeof(expr);
   10318     case Token::NOT: return VisitNot(expr);
   10319     default: UNREACHABLE();
   10320   }
   10321 }
   10322 
   10323 
   10324 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
   10325   Property* prop = expr->expression()->AsProperty();
   10326   VariableProxy* proxy = expr->expression()->AsVariableProxy();
   10327   if (prop != NULL) {
   10328     CHECK_ALIVE(VisitForValue(prop->obj()));
   10329     CHECK_ALIVE(VisitForValue(prop->key()));
   10330     HValue* key = Pop();
   10331     HValue* obj = Pop();
   10332     Add<HPushArguments>(obj, key);
   10333     HInstruction* instr = New<HCallRuntime>(
   10334         Runtime::FunctionForId(is_strict(function_language_mode())
   10335                                    ? Runtime::kDeleteProperty_Strict
   10336                                    : Runtime::kDeleteProperty_Sloppy),
   10337         2);
   10338     return ast_context()->ReturnInstruction(instr, expr->id());
   10339   } else if (proxy != NULL) {
   10340     Variable* var = proxy->var();
   10341     if (var->IsUnallocated()) {
   10342       Bailout(kDeleteWithGlobalVariable);
   10343     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
   10344       // Result of deleting non-global variables is false.  'this' is not really
   10345       // a variable, though we implement it as one.  The subexpression does not
   10346       // have side effects.
   10347       HValue* value = var->is_this() ? graph()->GetConstantTrue()
   10348                                      : graph()->GetConstantFalse();
   10349       return ast_context()->ReturnValue(value);
   10350     } else {
   10351       Bailout(kDeleteWithNonGlobalVariable);
   10352     }
   10353   } else {
   10354     // Result of deleting non-property, non-variable reference is true.
   10355     // Evaluate the subexpression for side effects.
   10356     CHECK_ALIVE(VisitForEffect(expr->expression()));
   10357     return ast_context()->ReturnValue(graph()->GetConstantTrue());
   10358   }
   10359 }
   10360 
   10361 
   10362 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
   10363   CHECK_ALIVE(VisitForEffect(expr->expression()));
   10364   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   10365 }
   10366 
   10367 
   10368 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
   10369   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
   10370   HValue* value = Pop();
   10371   HInstruction* instr = New<HTypeof>(value);
   10372   return ast_context()->ReturnInstruction(instr, expr->id());
   10373 }
   10374 
   10375 
   10376 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
   10377   if (ast_context()->IsTest()) {
   10378     TestContext* context = TestContext::cast(ast_context());
   10379     VisitForControl(expr->expression(),
   10380                     context->if_false(),
   10381                     context->if_true());
   10382     return;
   10383   }
   10384 
   10385   if (ast_context()->IsEffect()) {
   10386     VisitForEffect(expr->expression());
   10387     return;
   10388   }
   10389 
   10390   DCHECK(ast_context()->IsValue());
   10391   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
   10392   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
   10393   CHECK_BAILOUT(VisitForControl(expr->expression(),
   10394                                 materialize_false,
   10395                                 materialize_true));
   10396 
   10397   if (materialize_false->HasPredecessor()) {
   10398     materialize_false->SetJoinId(expr->MaterializeFalseId());
   10399     set_current_block(materialize_false);
   10400     Push(graph()->GetConstantFalse());
   10401   } else {
   10402     materialize_false = NULL;
   10403   }
   10404 
   10405   if (materialize_true->HasPredecessor()) {
   10406     materialize_true->SetJoinId(expr->MaterializeTrueId());
   10407     set_current_block(materialize_true);
   10408     Push(graph()->GetConstantTrue());
   10409   } else {
   10410     materialize_true = NULL;
   10411   }
   10412 
   10413   HBasicBlock* join =
   10414     CreateJoin(materialize_false, materialize_true, expr->id());
   10415   set_current_block(join);
   10416   if (join != NULL) return ast_context()->ReturnValue(Pop());
   10417 }
   10418 
   10419 static Representation RepresentationFor(AstType* type) {
   10420   DisallowHeapAllocation no_allocation;
   10421   if (type->Is(AstType::None())) return Representation::None();
   10422   if (type->Is(AstType::SignedSmall())) return Representation::Smi();
   10423   if (type->Is(AstType::Signed32())) return Representation::Integer32();
   10424   if (type->Is(AstType::Number())) return Representation::Double();
   10425   return Representation::Tagged();
   10426 }
   10427 
   10428 HInstruction* HOptimizedGraphBuilder::BuildIncrement(CountOperation* expr) {
   10429   // The input to the count operation is on top of the expression stack.
   10430   Representation rep = RepresentationFor(expr->type());
   10431   if (rep.IsNone() || rep.IsTagged()) {
   10432     rep = Representation::Smi();
   10433   }
   10434 
   10435   // We need an explicit HValue representing ToNumber(input).  The
   10436   // actual HChange instruction we need is (sometimes) added in a later
   10437   // phase, so it is not available now to be used as an input to HAdd and
   10438   // as the return value.
   10439   HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
   10440   if (!rep.IsDouble()) {
   10441     number_input->SetFlag(HInstruction::kFlexibleRepresentation);
   10442     number_input->SetFlag(HInstruction::kCannotBeTagged);
   10443   }
   10444   Push(number_input);
   10445 
   10446   // The addition has no side effects, so we do not need
   10447   // to simulate the expression stack after this instruction.
   10448   // Any later failures deopt to the load of the input or earlier.
   10449   HConstant* delta = (expr->op() == Token::INC)
   10450       ? graph()->GetConstant1()
   10451       : graph()->GetConstantMinus1();
   10452   HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
   10453   if (instr->IsAdd()) {
   10454     HAdd* add = HAdd::cast(instr);
   10455     add->set_observed_input_representation(1, rep);
   10456     add->set_observed_input_representation(2, Representation::Smi());
   10457   }
   10458   instr->ClearAllSideEffects();
   10459   instr->SetFlag(HInstruction::kCannotBeTagged);
   10460   return instr;
   10461 }
   10462 
   10463 void HOptimizedGraphBuilder::BuildStoreForEffect(
   10464     Expression* expr, Property* prop, FeedbackSlot slot, BailoutId ast_id,
   10465     BailoutId return_id, HValue* object, HValue* key, HValue* value) {
   10466   EffectContext for_effect(this);
   10467   Push(object);
   10468   if (key != NULL) Push(key);
   10469   Push(value);
   10470   BuildStore(expr, prop, slot, ast_id, return_id);
   10471 }
   10472 
   10473 
   10474 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
   10475   DCHECK(!HasStackOverflow());
   10476   DCHECK(current_block() != NULL);
   10477   DCHECK(current_block()->HasPredecessor());
   10478   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   10479   Expression* target = expr->expression();
   10480   VariableProxy* proxy = target->AsVariableProxy();
   10481   Property* prop = target->AsProperty();
   10482   if (proxy == NULL && prop == NULL) {
   10483     return Bailout(kInvalidLhsInCountOperation);
   10484   }
   10485 
   10486   // Match the full code generator stack by simulating an extra stack
   10487   // element for postfix operations in a non-effect context.  The return
   10488   // value is ToNumber(input).
   10489   bool returns_original_input =
   10490       expr->is_postfix() && !ast_context()->IsEffect();
   10491   HValue* input = NULL;  // ToNumber(original_input).
   10492   HValue* after = NULL;  // The result after incrementing or decrementing.
   10493 
   10494   if (proxy != NULL) {
   10495     Variable* var = proxy->var();
   10496     if (var->mode() == CONST) {
   10497       return Bailout(kNonInitializerAssignmentToConst);
   10498     }
   10499     // Argument of the count operation is a variable, not a property.
   10500     DCHECK(prop == NULL);
   10501     CHECK_ALIVE(VisitForValue(target));
   10502 
   10503     after = BuildIncrement(expr);
   10504     input = returns_original_input ? Top() : Pop();
   10505     Push(after);
   10506 
   10507     switch (var->location()) {
   10508       case VariableLocation::UNALLOCATED:
   10509         HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
   10510                                        expr->AssignmentId());
   10511         break;
   10512 
   10513       case VariableLocation::PARAMETER:
   10514       case VariableLocation::LOCAL:
   10515         BindIfLive(var, after);
   10516         break;
   10517 
   10518       case VariableLocation::CONTEXT: {
   10519         HValue* context = BuildContextChainWalk(var);
   10520         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
   10521             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
   10522         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
   10523                                                           mode, after);
   10524         if (instr->HasObservableSideEffects()) {
   10525           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   10526         }
   10527         break;
   10528       }
   10529 
   10530       case VariableLocation::LOOKUP:
   10531         return Bailout(kLookupVariableInCountOperation);
   10532 
   10533       case VariableLocation::MODULE:
   10534         UNREACHABLE();
   10535     }
   10536 
   10537     Drop(returns_original_input ? 2 : 1);
   10538     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
   10539   }
   10540 
   10541   // Argument of the count operation is a property.
   10542   DCHECK(prop != NULL);
   10543   if (returns_original_input) Push(graph()->GetConstantUndefined());
   10544 
   10545   CHECK_ALIVE(VisitForValue(prop->obj()));
   10546   HValue* object = Top();
   10547 
   10548   HValue* key = NULL;
   10549   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   10550     CHECK_ALIVE(VisitForValue(prop->key()));
   10551     key = Top();
   10552   }
   10553 
   10554   CHECK_ALIVE(PushLoad(prop, object, key));
   10555 
   10556   after = BuildIncrement(expr);
   10557 
   10558   if (returns_original_input) {
   10559     input = Pop();
   10560     // Drop object and key to push it again in the effect context below.
   10561     Drop(key == NULL ? 1 : 2);
   10562     environment()->SetExpressionStackAt(0, input);
   10563     CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
   10564                                     expr->AssignmentId(), object, key, after));
   10565     return ast_context()->ReturnValue(Pop());
   10566   }
   10567 
   10568   environment()->SetExpressionStackAt(0, after);
   10569   return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
   10570                     expr->AssignmentId());
   10571 }
   10572 
   10573 
   10574 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
   10575     HValue* string,
   10576     HValue* index) {
   10577   if (string->IsConstant() && index->IsConstant()) {
   10578     HConstant* c_string = HConstant::cast(string);
   10579     HConstant* c_index = HConstant::cast(index);
   10580     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
   10581       int32_t i = c_index->NumberValueAsInteger32();
   10582       Handle<String> s = c_string->StringValue();
   10583       if (i < 0 || i >= s->length()) {
   10584         return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
   10585       }
   10586       return New<HConstant>(s->Get(i));
   10587     }
   10588   }
   10589   string = BuildCheckString(string);
   10590   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
   10591   return New<HStringCharCodeAt>(string, index);
   10592 }
   10593 
   10594 
   10595 // Checks if the given shift amounts have following forms:
   10596 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
   10597 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
   10598                                              HValue* const32_minus_sa) {
   10599   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
   10600     const HConstant* c1 = HConstant::cast(sa);
   10601     const HConstant* c2 = HConstant::cast(const32_minus_sa);
   10602     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
   10603         (c1->Integer32Value() + c2->Integer32Value() == 32);
   10604   }
   10605   if (!const32_minus_sa->IsSub()) return false;
   10606   HSub* sub = HSub::cast(const32_minus_sa);
   10607   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
   10608 }
   10609 
   10610 
   10611 // Checks if the left and the right are shift instructions with the oposite
   10612 // directions that can be replaced by one rotate right instruction or not.
   10613 // Returns the operand and the shift amount for the rotate instruction in the
   10614 // former case.
   10615 bool HGraphBuilder::MatchRotateRight(HValue* left,
   10616                                      HValue* right,
   10617                                      HValue** operand,
   10618                                      HValue** shift_amount) {
   10619   HShl* shl;
   10620   HShr* shr;
   10621   if (left->IsShl() && right->IsShr()) {
   10622     shl = HShl::cast(left);
   10623     shr = HShr::cast(right);
   10624   } else if (left->IsShr() && right->IsShl()) {
   10625     shl = HShl::cast(right);
   10626     shr = HShr::cast(left);
   10627   } else {
   10628     return false;
   10629   }
   10630   if (shl->left() != shr->left()) return false;
   10631 
   10632   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
   10633       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
   10634     return false;
   10635   }
   10636   *operand = shr->left();
   10637   *shift_amount = shr->right();
   10638   return true;
   10639 }
   10640 
   10641 
   10642 bool CanBeZero(HValue* right) {
   10643   if (right->IsConstant()) {
   10644     HConstant* right_const = HConstant::cast(right);
   10645     if (right_const->HasInteger32Value() &&
   10646        (right_const->Integer32Value() & 0x1f) != 0) {
   10647       return false;
   10648     }
   10649   }
   10650   return true;
   10651 }
   10652 
   10653 HValue* HGraphBuilder::EnforceNumberType(HValue* number, AstType* expected) {
   10654   if (expected->Is(AstType::SignedSmall())) {
   10655     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
   10656   }
   10657   if (expected->Is(AstType::Signed32())) {
   10658     return AddUncasted<HForceRepresentation>(number,
   10659                                              Representation::Integer32());
   10660   }
   10661   return number;
   10662 }
   10663 
   10664 HValue* HGraphBuilder::TruncateToNumber(HValue* value, AstType** expected) {
   10665   if (value->IsConstant()) {
   10666     HConstant* constant = HConstant::cast(value);
   10667     Maybe<HConstant*> number =
   10668         constant->CopyToTruncatedNumber(isolate(), zone());
   10669     if (number.IsJust()) {
   10670       *expected = AstType::Number();
   10671       return AddInstruction(number.FromJust());
   10672     }
   10673   }
   10674 
   10675   // We put temporary values on the stack, which don't correspond to anything
   10676   // in baseline code. Since nothing is observable we avoid recording those
   10677   // pushes with a NoObservableSideEffectsScope.
   10678   NoObservableSideEffectsScope no_effects(this);
   10679 
   10680   AstType* expected_type = *expected;
   10681 
   10682   // Separate the number type from the rest.
   10683   AstType* expected_obj =
   10684       AstType::Intersect(expected_type, AstType::NonNumber(), zone());
   10685   AstType* expected_number =
   10686       AstType::Intersect(expected_type, AstType::Number(), zone());
   10687 
   10688   // We expect to get a number.
   10689   // (We need to check first, since AstType::None->Is(AstType::Any()) == true.
   10690   if (expected_obj->Is(AstType::None())) {
   10691     DCHECK(!expected_number->Is(AstType::None()));
   10692     return value;
   10693   }
   10694 
   10695   if (expected_obj->Is(AstType::Undefined())) {
   10696     // This is already done by HChange.
   10697     *expected = AstType::Union(expected_number, AstType::Number(), zone());
   10698     return value;
   10699   }
   10700 
   10701   return value;
   10702 }
   10703 
   10704 
   10705 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
   10706     BinaryOperation* expr,
   10707     HValue* left,
   10708     HValue* right,
   10709     PushBeforeSimulateBehavior push_sim_result) {
   10710   AstType* left_type = bounds_.get(expr->left()).lower;
   10711   AstType* right_type = bounds_.get(expr->right()).lower;
   10712   AstType* result_type = bounds_.get(expr).lower;
   10713   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
   10714   Handle<AllocationSite> allocation_site = expr->allocation_site();
   10715 
   10716   HAllocationMode allocation_mode;
   10717   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
   10718     allocation_mode = HAllocationMode(allocation_site);
   10719   }
   10720   HValue* result = HGraphBuilder::BuildBinaryOperation(
   10721       expr->op(), left, right, left_type, right_type, result_type,
   10722       fixed_right_arg, allocation_mode, expr->id());
   10723   // Add a simulate after instructions with observable side effects, and
   10724   // after phis, which are the result of BuildBinaryOperation when we
   10725   // inlined some complex subgraph.
   10726   if (result->HasObservableSideEffects() || result->IsPhi()) {
   10727     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   10728       Push(result);
   10729       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10730       Drop(1);
   10731     } else {
   10732       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10733     }
   10734   }
   10735   return result;
   10736 }
   10737 
   10738 HValue* HGraphBuilder::BuildBinaryOperation(
   10739     Token::Value op, HValue* left, HValue* right, AstType* left_type,
   10740     AstType* right_type, AstType* result_type, Maybe<int> fixed_right_arg,
   10741     HAllocationMode allocation_mode, BailoutId opt_id) {
   10742   bool maybe_string_add = false;
   10743   if (op == Token::ADD) {
   10744     // If we are adding constant string with something for which we don't have
   10745     // a feedback yet, assume that it's also going to be a string and don't
   10746     // generate deopt instructions.
   10747     if (!left_type->IsInhabited() && right->IsConstant() &&
   10748         HConstant::cast(right)->HasStringValue()) {
   10749       left_type = AstType::String();
   10750     }
   10751 
   10752     if (!right_type->IsInhabited() && left->IsConstant() &&
   10753         HConstant::cast(left)->HasStringValue()) {
   10754       right_type = AstType::String();
   10755     }
   10756 
   10757     maybe_string_add = (left_type->Maybe(AstType::String()) ||
   10758                         left_type->Maybe(AstType::Receiver()) ||
   10759                         right_type->Maybe(AstType::String()) ||
   10760                         right_type->Maybe(AstType::Receiver()));
   10761   }
   10762 
   10763   Representation left_rep = RepresentationFor(left_type);
   10764   Representation right_rep = RepresentationFor(right_type);
   10765 
   10766   if (!left_type->IsInhabited()) {
   10767     Add<HDeoptimize>(
   10768         DeoptimizeReason::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
   10769         Deoptimizer::SOFT);
   10770     left_type = AstType::Any();
   10771     left_rep = RepresentationFor(left_type);
   10772     maybe_string_add = op == Token::ADD;
   10773   }
   10774 
   10775   if (!right_type->IsInhabited()) {
   10776     Add<HDeoptimize>(
   10777         DeoptimizeReason::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
   10778         Deoptimizer::SOFT);
   10779     right_type = AstType::Any();
   10780     right_rep = RepresentationFor(right_type);
   10781     maybe_string_add = op == Token::ADD;
   10782   }
   10783 
   10784   if (!maybe_string_add) {
   10785     left = TruncateToNumber(left, &left_type);
   10786     right = TruncateToNumber(right, &right_type);
   10787   }
   10788 
   10789   // Special case for string addition here.
   10790   if (op == Token::ADD &&
   10791       (left_type->Is(AstType::String()) || right_type->Is(AstType::String()))) {
   10792     // Validate type feedback for left argument.
   10793     if (left_type->Is(AstType::String())) {
   10794       left = BuildCheckString(left);
   10795     }
   10796 
   10797     // Validate type feedback for right argument.
   10798     if (right_type->Is(AstType::String())) {
   10799       right = BuildCheckString(right);
   10800     }
   10801 
   10802     // Convert left argument as necessary.
   10803     if (left_type->Is(AstType::Number())) {
   10804       DCHECK(right_type->Is(AstType::String()));
   10805       left = BuildNumberToString(left, left_type);
   10806     } else if (!left_type->Is(AstType::String())) {
   10807       DCHECK(right_type->Is(AstType::String()));
   10808       return AddUncasted<HStringAdd>(
   10809           left, right, allocation_mode.GetPretenureMode(),
   10810           STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
   10811     }
   10812 
   10813     // Convert right argument as necessary.
   10814     if (right_type->Is(AstType::Number())) {
   10815       DCHECK(left_type->Is(AstType::String()));
   10816       right = BuildNumberToString(right, right_type);
   10817     } else if (!right_type->Is(AstType::String())) {
   10818       DCHECK(left_type->Is(AstType::String()));
   10819       return AddUncasted<HStringAdd>(
   10820           left, right, allocation_mode.GetPretenureMode(),
   10821           STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
   10822     }
   10823 
   10824     // Fast paths for empty constant strings.
   10825     Handle<String> left_string =
   10826         left->IsConstant() && HConstant::cast(left)->HasStringValue()
   10827             ? HConstant::cast(left)->StringValue()
   10828             : Handle<String>();
   10829     Handle<String> right_string =
   10830         right->IsConstant() && HConstant::cast(right)->HasStringValue()
   10831             ? HConstant::cast(right)->StringValue()
   10832             : Handle<String>();
   10833     if (!left_string.is_null() && left_string->length() == 0) return right;
   10834     if (!right_string.is_null() && right_string->length() == 0) return left;
   10835     if (!left_string.is_null() && !right_string.is_null()) {
   10836       return AddUncasted<HStringAdd>(
   10837           left, right, allocation_mode.GetPretenureMode(),
   10838           STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
   10839     }
   10840 
   10841     // Register the dependent code with the allocation site.
   10842     if (!allocation_mode.feedback_site().is_null()) {
   10843       DCHECK(!graph()->info()->IsStub());
   10844       Handle<AllocationSite> site(allocation_mode.feedback_site());
   10845       top_info()->dependencies()->AssumeTenuringDecision(site);
   10846     }
   10847 
   10848     // Inline the string addition into the stub when creating allocation
   10849     // mementos to gather allocation site feedback, or if we can statically
   10850     // infer that we're going to create a cons string.
   10851     if ((graph()->info()->IsStub() &&
   10852          allocation_mode.CreateAllocationMementos()) ||
   10853         (left->IsConstant() &&
   10854          HConstant::cast(left)->HasStringValue() &&
   10855          HConstant::cast(left)->StringValue()->length() + 1 >=
   10856            ConsString::kMinLength) ||
   10857         (right->IsConstant() &&
   10858          HConstant::cast(right)->HasStringValue() &&
   10859          HConstant::cast(right)->StringValue()->length() + 1 >=
   10860            ConsString::kMinLength)) {
   10861       return BuildStringAdd(left, right, allocation_mode);
   10862     }
   10863 
   10864     // Fallback to using the string add stub.
   10865     return AddUncasted<HStringAdd>(
   10866         left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE,
   10867         allocation_mode.feedback_site());
   10868   }
   10869 
   10870   // Special case for +x here.
   10871   if (op == Token::MUL) {
   10872     if (left->EqualsInteger32Constant(1)) {
   10873       return BuildToNumber(right);
   10874     }
   10875     if (right->EqualsInteger32Constant(1)) {
   10876       return BuildToNumber(left);
   10877     }
   10878   }
   10879 
   10880   if (graph()->info()->IsStub()) {
   10881     left = EnforceNumberType(left, left_type);
   10882     right = EnforceNumberType(right, right_type);
   10883   }
   10884 
   10885   Representation result_rep = RepresentationFor(result_type);
   10886 
   10887   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
   10888                           (right_rep.IsTagged() && !right_rep.IsSmi());
   10889 
   10890   HInstruction* instr = NULL;
   10891   // Only the stub is allowed to call into the runtime, since otherwise we would
   10892   // inline several instructions (including the two pushes) for every tagged
   10893   // operation in optimized code, which is more expensive, than a stub call.
   10894   if (graph()->info()->IsStub() && is_non_primitive) {
   10895     HValue* values[] = {left, right};
   10896 #define GET_STUB(Name)                                                       \
   10897   do {                                                                       \
   10898     Callable callable = CodeFactory::Name(isolate());                        \
   10899     HValue* stub = Add<HConstant>(callable.code());                          \
   10900     instr = AddUncasted<HCallWithDescriptor>(stub, 0, callable.descriptor(), \
   10901                                              ArrayVector(values));           \
   10902   } while (false)
   10903 
   10904     switch (op) {
   10905       default:
   10906         UNREACHABLE();
   10907       case Token::ADD:
   10908         GET_STUB(Add);
   10909         break;
   10910       case Token::SUB:
   10911         GET_STUB(Subtract);
   10912         break;
   10913       case Token::MUL:
   10914         GET_STUB(Multiply);
   10915         break;
   10916       case Token::DIV:
   10917         GET_STUB(Divide);
   10918         break;
   10919       case Token::MOD:
   10920         GET_STUB(Modulus);
   10921         break;
   10922       case Token::BIT_OR:
   10923         GET_STUB(BitwiseOr);
   10924         break;
   10925       case Token::BIT_AND:
   10926         GET_STUB(BitwiseAnd);
   10927         break;
   10928       case Token::BIT_XOR:
   10929         GET_STUB(BitwiseXor);
   10930         break;
   10931       case Token::SAR:
   10932         GET_STUB(ShiftRight);
   10933         break;
   10934       case Token::SHR:
   10935         GET_STUB(ShiftRightLogical);
   10936         break;
   10937       case Token::SHL:
   10938         GET_STUB(ShiftLeft);
   10939         break;
   10940     }
   10941 #undef GET_STUB
   10942   } else {
   10943     switch (op) {
   10944       case Token::ADD:
   10945         instr = AddUncasted<HAdd>(left, right);
   10946         break;
   10947       case Token::SUB:
   10948         instr = AddUncasted<HSub>(left, right);
   10949         break;
   10950       case Token::MUL:
   10951         instr = AddUncasted<HMul>(left, right);
   10952         break;
   10953       case Token::MOD: {
   10954         if (fixed_right_arg.IsJust() &&
   10955             !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
   10956           HConstant* fixed_right =
   10957               Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
   10958           IfBuilder if_same(this);
   10959           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
   10960           if_same.Then();
   10961           if_same.ElseDeopt(DeoptimizeReason::kUnexpectedRHSOfBinaryOperation);
   10962           right = fixed_right;
   10963         }
   10964         instr = AddUncasted<HMod>(left, right);
   10965         break;
   10966       }
   10967       case Token::DIV:
   10968         instr = AddUncasted<HDiv>(left, right);
   10969         break;
   10970       case Token::BIT_XOR:
   10971       case Token::BIT_AND:
   10972         instr = AddUncasted<HBitwise>(op, left, right);
   10973         break;
   10974       case Token::BIT_OR: {
   10975         HValue *operand, *shift_amount;
   10976         if (left_type->Is(AstType::Signed32()) &&
   10977             right_type->Is(AstType::Signed32()) &&
   10978             MatchRotateRight(left, right, &operand, &shift_amount)) {
   10979           instr = AddUncasted<HRor>(operand, shift_amount);
   10980         } else {
   10981           instr = AddUncasted<HBitwise>(op, left, right);
   10982         }
   10983         break;
   10984       }
   10985       case Token::SAR:
   10986         instr = AddUncasted<HSar>(left, right);
   10987         break;
   10988       case Token::SHR:
   10989         instr = AddUncasted<HShr>(left, right);
   10990         if (instr->IsShr() && CanBeZero(right)) {
   10991           graph()->RecordUint32Instruction(instr);
   10992         }
   10993         break;
   10994       case Token::SHL:
   10995         instr = AddUncasted<HShl>(left, right);
   10996         break;
   10997       default:
   10998         UNREACHABLE();
   10999     }
   11000   }
   11001 
   11002   if (instr->IsBinaryOperation()) {
   11003     HBinaryOperation* binop = HBinaryOperation::cast(instr);
   11004     binop->set_observed_input_representation(1, left_rep);
   11005     binop->set_observed_input_representation(2, right_rep);
   11006     binop->initialize_output_representation(result_rep);
   11007     if (graph()->info()->IsStub()) {
   11008       // Stub should not call into stub.
   11009       instr->SetFlag(HValue::kCannotBeTagged);
   11010       // And should truncate on HForceRepresentation already.
   11011       if (left->IsForceRepresentation()) {
   11012         left->CopyFlag(HValue::kTruncatingToSmi, instr);
   11013         left->CopyFlag(HValue::kTruncatingToInt32, instr);
   11014       }
   11015       if (right->IsForceRepresentation()) {
   11016         right->CopyFlag(HValue::kTruncatingToSmi, instr);
   11017         right->CopyFlag(HValue::kTruncatingToInt32, instr);
   11018       }
   11019     }
   11020   }
   11021   return instr;
   11022 }
   11023 
   11024 
   11025 // Check for the form (%_ClassOf(foo) === 'BarClass').
   11026 static bool IsClassOfTest(CompareOperation* expr) {
   11027   if (expr->op() != Token::EQ_STRICT) return false;
   11028   CallRuntime* call = expr->left()->AsCallRuntime();
   11029   if (call == NULL) return false;
   11030   Literal* literal = expr->right()->AsLiteral();
   11031   if (literal == NULL) return false;
   11032   if (!literal->value()->IsString()) return false;
   11033   if (call->is_jsruntime()) return false;
   11034   if (call->function()->function_id != Runtime::kInlineClassOf) return false;
   11035   DCHECK_EQ(call->arguments()->length(), 1);
   11036   return true;
   11037 }
   11038 
   11039 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
   11040   DCHECK(!HasStackOverflow());
   11041   DCHECK(current_block() != NULL);
   11042   DCHECK(current_block()->HasPredecessor());
   11043   switch (expr->op()) {
   11044     case Token::COMMA:
   11045       return VisitComma(expr);
   11046     case Token::OR:
   11047     case Token::AND:
   11048       return VisitLogicalExpression(expr);
   11049     default:
   11050       return VisitArithmeticExpression(expr);
   11051   }
   11052 }
   11053 
   11054 
   11055 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
   11056   CHECK_ALIVE(VisitForEffect(expr->left()));
   11057   // Visit the right subexpression in the same AST context as the entire
   11058   // expression.
   11059   Visit(expr->right());
   11060 }
   11061 
   11062 
   11063 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
   11064   bool is_logical_and = expr->op() == Token::AND;
   11065   if (ast_context()->IsTest()) {
   11066     TestContext* context = TestContext::cast(ast_context());
   11067     // Translate left subexpression.
   11068     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   11069     if (is_logical_and) {
   11070       CHECK_BAILOUT(VisitForControl(expr->left(),
   11071                                     eval_right,
   11072                                     context->if_false()));
   11073     } else {
   11074       CHECK_BAILOUT(VisitForControl(expr->left(),
   11075                                     context->if_true(),
   11076                                     eval_right));
   11077     }
   11078 
   11079     // Translate right subexpression by visiting it in the same AST
   11080     // context as the entire expression.
   11081     CHECK(eval_right->HasPredecessor());
   11082     eval_right->SetJoinId(expr->RightId());
   11083     set_current_block(eval_right);
   11084     Visit(expr->right());
   11085   } else if (ast_context()->IsValue()) {
   11086     CHECK_ALIVE(VisitForValue(expr->left()));
   11087     DCHECK(current_block() != NULL);
   11088     HValue* left_value = Top();
   11089 
   11090     // Short-circuit left values that always evaluate to the same boolean value.
   11091     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
   11092       // l (evals true)  && r -> r
   11093       // l (evals true)  || r -> l
   11094       // l (evals false) && r -> l
   11095       // l (evals false) || r -> r
   11096       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
   11097         Drop(1);
   11098         CHECK_ALIVE(VisitForValue(expr->right()));
   11099       }
   11100       return ast_context()->ReturnValue(Pop());
   11101     }
   11102 
   11103     // We need an extra block to maintain edge-split form.
   11104     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   11105     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   11106     ToBooleanHints expected(expr->left()->to_boolean_types());
   11107     HBranch* test = is_logical_and
   11108         ? New<HBranch>(left_value, expected, eval_right, empty_block)
   11109         : New<HBranch>(left_value, expected, empty_block, eval_right);
   11110     FinishCurrentBlock(test);
   11111 
   11112     set_current_block(eval_right);
   11113     Drop(1);  // Value of the left subexpression.
   11114     CHECK_BAILOUT(VisitForValue(expr->right()));
   11115 
   11116     HBasicBlock* join_block =
   11117       CreateJoin(empty_block, current_block(), expr->id());
   11118     set_current_block(join_block);
   11119     return ast_context()->ReturnValue(Pop());
   11120 
   11121   } else {
   11122     DCHECK(ast_context()->IsEffect());
   11123     // In an effect context, we don't need the value of the left subexpression,
   11124     // only its control flow and side effects.  We need an extra block to
   11125     // maintain edge-split form.
   11126     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   11127     HBasicBlock* right_block = graph()->CreateBasicBlock();
   11128     if (is_logical_and) {
   11129       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
   11130     } else {
   11131       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
   11132     }
   11133 
   11134     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
   11135     // actually two empty blocks (one here and one inserted by
   11136     // TestContext::BuildBranch, and that they both have an HSimulate though the
   11137     // second one is not a merge node, and that we really have no good AST ID to
   11138     // put on that first HSimulate.
   11139 
   11140     // Technically, we should be able to handle the case when one side of
   11141     // the test is not connected, but this can trip up liveness analysis
   11142     // if we did not fully connect the test context based on some optimistic
   11143     // assumption. If such an assumption was violated, we would end up with
   11144     // an environment with optimized-out values. So we should always
   11145     // conservatively connect the test context.
   11146 
   11147     CHECK(right_block->HasPredecessor());
   11148     CHECK(empty_block->HasPredecessor());
   11149 
   11150     empty_block->SetJoinId(expr->id());
   11151 
   11152     right_block->SetJoinId(expr->RightId());
   11153     set_current_block(right_block);
   11154     CHECK_BAILOUT(VisitForEffect(expr->right()));
   11155     right_block = current_block();
   11156 
   11157     HBasicBlock* join_block =
   11158       CreateJoin(empty_block, right_block, expr->id());
   11159     set_current_block(join_block);
   11160     // We did not materialize any value in the predecessor environments,
   11161     // so there is no need to handle it here.
   11162   }
   11163 }
   11164 
   11165 
   11166 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
   11167   CHECK_ALIVE(VisitForValue(expr->left()));
   11168   CHECK_ALIVE(VisitForValue(expr->right()));
   11169   SetSourcePosition(expr->position());
   11170   HValue* right = Pop();
   11171   HValue* left = Pop();
   11172   HValue* result =
   11173       BuildBinaryOperation(expr, left, right,
   11174           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   11175                                     : PUSH_BEFORE_SIMULATE);
   11176   return ast_context()->ReturnValue(result);
   11177 }
   11178 
   11179 
   11180 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
   11181                                                         Expression* sub_expr,
   11182                                                         Handle<String> check) {
   11183   CHECK_ALIVE(VisitForTypeOf(sub_expr));
   11184   SetSourcePosition(expr->position());
   11185   HValue* value = Pop();
   11186   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
   11187   return ast_context()->ReturnControl(instr, expr->id());
   11188 }
   11189 
   11190 namespace {
   11191 
   11192 bool IsLiteralCompareStrict(Isolate* isolate, HValue* left, Token::Value op,
   11193                             HValue* right) {
   11194   return op == Token::EQ_STRICT &&
   11195          ((left->IsConstant() &&
   11196            !HConstant::cast(left)->handle(isolate)->IsNumber() &&
   11197            !HConstant::cast(left)->handle(isolate)->IsString()) ||
   11198           (right->IsConstant() &&
   11199            !HConstant::cast(right)->handle(isolate)->IsNumber() &&
   11200            !HConstant::cast(right)->handle(isolate)->IsString()));
   11201 }
   11202 
   11203 }  // namespace
   11204 
   11205 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   11206   DCHECK(!HasStackOverflow());
   11207   DCHECK(current_block() != NULL);
   11208   DCHECK(current_block()->HasPredecessor());
   11209 
   11210   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   11211 
   11212   // Check for a few fast cases. The AST visiting behavior must be in sync
   11213   // with the full codegen: We don't push both left and right values onto
   11214   // the expression stack when one side is a special-case literal.
   11215   Expression* sub_expr = NULL;
   11216   Handle<String> check;
   11217   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
   11218     return HandleLiteralCompareTypeof(expr, sub_expr, check);
   11219   }
   11220   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
   11221     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
   11222   }
   11223   if (expr->IsLiteralCompareNull(&sub_expr)) {
   11224     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
   11225   }
   11226 
   11227   if (IsClassOfTest(expr)) {
   11228     CallRuntime* call = expr->left()->AsCallRuntime();
   11229     DCHECK(call->arguments()->length() == 1);
   11230     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11231     HValue* value = Pop();
   11232     Literal* literal = expr->right()->AsLiteral();
   11233     Handle<String> rhs = Handle<String>::cast(literal->value());
   11234     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
   11235     return ast_context()->ReturnControl(instr, expr->id());
   11236   }
   11237 
   11238   AstType* left_type = bounds_.get(expr->left()).lower;
   11239   AstType* right_type = bounds_.get(expr->right()).lower;
   11240   AstType* combined_type = expr->combined_type();
   11241 
   11242   CHECK_ALIVE(VisitForValue(expr->left()));
   11243   CHECK_ALIVE(VisitForValue(expr->right()));
   11244 
   11245   HValue* right = Pop();
   11246   HValue* left = Pop();
   11247   Token::Value op = expr->op();
   11248 
   11249   if (IsLiteralCompareStrict(isolate(), left, op, right)) {
   11250     HCompareObjectEqAndBranch* result =
   11251         New<HCompareObjectEqAndBranch>(left, right);
   11252     return ast_context()->ReturnControl(result, expr->id());
   11253   }
   11254 
   11255   if (op == Token::INSTANCEOF) {
   11256     // Check to see if the rhs of the instanceof is a known function.
   11257     if (right->IsConstant() &&
   11258         HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
   11259       Handle<JSFunction> function =
   11260           Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
   11261       // Make sure that the {function} already has a meaningful initial map
   11262       // (i.e. we constructed at least one instance using the constructor
   11263       // {function}), and has an instance as .prototype.
   11264       if (function->has_initial_map() &&
   11265           !function->map()->has_non_instance_prototype()) {
   11266         // Lookup @@hasInstance on the {function}.
   11267         Handle<Map> function_map(function->map(), isolate());
   11268         PropertyAccessInfo has_instance(
   11269             this, LOAD, function_map,
   11270             isolate()->factory()->has_instance_symbol());
   11271         // Check if we are using the Function.prototype[@@hasInstance].
   11272         if (has_instance.CanAccessMonomorphic() &&
   11273             has_instance.IsDataConstant() &&
   11274             has_instance.constant().is_identical_to(
   11275                 isolate()->function_has_instance())) {
   11276           // Add appropriate receiver map check and prototype chain
   11277           // checks to guard the @@hasInstance lookup chain.
   11278           AddCheckMap(right, function_map);
   11279           if (has_instance.has_holder()) {
   11280             Handle<JSObject> prototype(
   11281                 JSObject::cast(has_instance.map()->prototype()), isolate());
   11282             BuildCheckPrototypeMaps(prototype, has_instance.holder());
   11283           }
   11284           // Perform the prototype chain walk.
   11285           Handle<Map> initial_map(function->initial_map(), isolate());
   11286           top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
   11287           HInstruction* prototype =
   11288               Add<HConstant>(handle(initial_map->prototype(), isolate()));
   11289           HHasInPrototypeChainAndBranch* result =
   11290               New<HHasInPrototypeChainAndBranch>(left, prototype);
   11291           return ast_context()->ReturnControl(result, expr->id());
   11292         }
   11293       }
   11294     }
   11295 
   11296     Callable callable = CodeFactory::InstanceOf(isolate());
   11297     HValue* stub = Add<HConstant>(callable.code());
   11298     HValue* values[] = {left, right};
   11299     HCallWithDescriptor* result = New<HCallWithDescriptor>(
   11300         stub, 0, callable.descriptor(), ArrayVector(values));
   11301     result->set_type(HType::Boolean());
   11302     return ast_context()->ReturnInstruction(result, expr->id());
   11303 
   11304   } else if (op == Token::IN) {
   11305     Callable callable = CodeFactory::HasProperty(isolate());
   11306     HValue* stub = Add<HConstant>(callable.code());
   11307     HValue* values[] = {left, right};
   11308     HInstruction* result =
   11309         New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
   11310                                  Vector<HValue*>(values, arraysize(values)));
   11311     return ast_context()->ReturnInstruction(result, expr->id());
   11312   }
   11313 
   11314   PushBeforeSimulateBehavior push_behavior =
   11315     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   11316                               : PUSH_BEFORE_SIMULATE;
   11317   HControlInstruction* compare = BuildCompareInstruction(
   11318       op, left, right, left_type, right_type, combined_type,
   11319       ScriptPositionToSourcePosition(expr->left()->position()),
   11320       ScriptPositionToSourcePosition(expr->right()->position()),
   11321       push_behavior, expr->id());
   11322   if (compare == NULL) return;  // Bailed out.
   11323   return ast_context()->ReturnControl(compare, expr->id());
   11324 }
   11325 
   11326 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
   11327     Token::Value op, HValue* left, HValue* right, AstType* left_type,
   11328     AstType* right_type, AstType* combined_type, SourcePosition left_position,
   11329     SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
   11330     BailoutId bailout_id) {
   11331   // Cases handled below depend on collected type feedback. They should
   11332   // soft deoptimize when there is no type feedback.
   11333   if (!combined_type->IsInhabited()) {
   11334     Add<HDeoptimize>(
   11335         DeoptimizeReason::
   11336             kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
   11337         Deoptimizer::SOFT);
   11338     combined_type = left_type = right_type = AstType::Any();
   11339   }
   11340 
   11341   Representation left_rep = RepresentationFor(left_type);
   11342   Representation right_rep = RepresentationFor(right_type);
   11343   Representation combined_rep = RepresentationFor(combined_type);
   11344 
   11345   if (combined_type->Is(AstType::Receiver())) {
   11346     if (Token::IsEqualityOp(op)) {
   11347       // HCompareObjectEqAndBranch can only deal with object, so
   11348       // exclude numbers.
   11349       if ((left->IsConstant() &&
   11350            HConstant::cast(left)->HasNumberValue()) ||
   11351           (right->IsConstant() &&
   11352            HConstant::cast(right)->HasNumberValue())) {
   11353         Add<HDeoptimize>(
   11354             DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant,
   11355             Deoptimizer::SOFT);
   11356         // The caller expects a branch instruction, so make it happy.
   11357         return New<HBranch>(graph()->GetConstantTrue());
   11358       }
   11359       if (op == Token::EQ) {
   11360         // For abstract equality we need to check both sides are receivers.
   11361         if (combined_type->IsClass()) {
   11362           Handle<Map> map = combined_type->AsClass()->Map();
   11363           AddCheckMap(left, map);
   11364           AddCheckMap(right, map);
   11365         } else {
   11366           BuildCheckHeapObject(left);
   11367           Add<HCheckInstanceType>(left, HCheckInstanceType::IS_JS_RECEIVER);
   11368           BuildCheckHeapObject(right);
   11369           Add<HCheckInstanceType>(right, HCheckInstanceType::IS_JS_RECEIVER);
   11370         }
   11371       } else {
   11372         // For strict equality we only need to check one side.
   11373         HValue* operand_to_check =
   11374             left->block()->block_id() < right->block()->block_id() ? left
   11375                                                                    : right;
   11376         if (combined_type->IsClass()) {
   11377           Handle<Map> map = combined_type->AsClass()->Map();
   11378           AddCheckMap(operand_to_check, map);
   11379         } else {
   11380           BuildCheckHeapObject(operand_to_check);
   11381           Add<HCheckInstanceType>(operand_to_check,
   11382                                   HCheckInstanceType::IS_JS_RECEIVER);
   11383         }
   11384       }
   11385       HCompareObjectEqAndBranch* result =
   11386           New<HCompareObjectEqAndBranch>(left, right);
   11387       return result;
   11388     } else {
   11389       if (combined_type->IsClass()) {
   11390         // TODO(bmeurer): This is an optimized version of an x < y, x > y,
   11391         // x <= y or x >= y, where both x and y are spec objects with the
   11392         // same map. The CompareIC collects this map for us. So if we know
   11393         // that there's no @@toPrimitive on the map (including the prototype
   11394         // chain), and both valueOf and toString are the default initial
   11395         // implementations (on the %ObjectPrototype%), then we can reduce
   11396         // the comparison to map checks on x and y, because the comparison
   11397         // will turn into a comparison of "[object CLASS]" to itself (the
   11398         // default outcome of toString, since valueOf returns a spec object).
   11399         // This is pretty much adhoc, so in TurboFan we could do a lot better
   11400         // and inline the interesting parts of ToPrimitive (actually we could
   11401         // even do that in Crankshaft but we don't want to waste too much
   11402         // time on this now).
   11403         DCHECK(Token::IsOrderedRelationalCompareOp(op));
   11404         Handle<Map> map = combined_type->AsClass()->Map();
   11405         PropertyAccessInfo value_of(this, LOAD, map,
   11406                                     isolate()->factory()->valueOf_string());
   11407         PropertyAccessInfo to_primitive(
   11408             this, LOAD, map, isolate()->factory()->to_primitive_symbol());
   11409         PropertyAccessInfo to_string(this, LOAD, map,
   11410                                      isolate()->factory()->toString_string());
   11411         PropertyAccessInfo to_string_tag(
   11412             this, LOAD, map, isolate()->factory()->to_string_tag_symbol());
   11413         if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() &&
   11414             to_string_tag.CanAccessMonomorphic() &&
   11415             (!to_string_tag.IsFound() || to_string_tag.IsData() ||
   11416              to_string_tag.IsDataConstant()) &&
   11417             value_of.CanAccessMonomorphic() && value_of.IsDataConstant() &&
   11418             value_of.constant().is_identical_to(isolate()->object_value_of()) &&
   11419             to_string.CanAccessMonomorphic() && to_string.IsDataConstant() &&
   11420             to_string.constant().is_identical_to(
   11421                 isolate()->object_to_string())) {
   11422           // We depend on the prototype chain to stay the same, because we
   11423           // also need to deoptimize when someone installs @@toPrimitive
   11424           // or @@toStringTag somewhere in the prototype chain.
   11425           Handle<Object> prototype(map->prototype(), isolate());
   11426           if (prototype->IsJSObject()) {
   11427             BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype),
   11428                                     Handle<JSObject>::null());
   11429           }
   11430           AddCheckMap(left, map);
   11431           AddCheckMap(right, map);
   11432           // The caller expects a branch instruction, so make it happy.
   11433           return New<HBranch>(
   11434               graph()->GetConstantBool(op == Token::LTE || op == Token::GTE));
   11435         }
   11436       }
   11437       Bailout(kUnsupportedNonPrimitiveCompare);
   11438       return NULL;
   11439     }
   11440   } else if (combined_type->Is(AstType::InternalizedString()) &&
   11441              Token::IsEqualityOp(op)) {
   11442     // If we have a constant argument, it should be consistent with the type
   11443     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
   11444     if ((left->IsConstant() &&
   11445          !HConstant::cast(left)->HasInternalizedStringValue()) ||
   11446         (right->IsConstant() &&
   11447          !HConstant::cast(right)->HasInternalizedStringValue())) {
   11448       Add<HDeoptimize>(
   11449           DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant,
   11450           Deoptimizer::SOFT);
   11451       // The caller expects a branch instruction, so make it happy.
   11452       return New<HBranch>(graph()->GetConstantTrue());
   11453     }
   11454     BuildCheckHeapObject(left);
   11455     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11456     BuildCheckHeapObject(right);
   11457     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11458     HCompareObjectEqAndBranch* result =
   11459         New<HCompareObjectEqAndBranch>(left, right);
   11460     return result;
   11461   } else if (combined_type->Is(AstType::String())) {
   11462     BuildCheckHeapObject(left);
   11463     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
   11464     BuildCheckHeapObject(right);
   11465     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
   11466     HStringCompareAndBranch* result =
   11467         New<HStringCompareAndBranch>(left, right, op);
   11468     return result;
   11469   } else if (combined_type->Is(AstType::Boolean())) {
   11470     AddCheckMap(left, isolate()->factory()->boolean_map());
   11471     AddCheckMap(right, isolate()->factory()->boolean_map());
   11472     if (Token::IsEqualityOp(op)) {
   11473       HCompareObjectEqAndBranch* result =
   11474           New<HCompareObjectEqAndBranch>(left, right);
   11475       return result;
   11476     }
   11477     left = Add<HLoadNamedField>(
   11478         left, nullptr,
   11479         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11480     right = Add<HLoadNamedField>(
   11481         right, nullptr,
   11482         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11483     HCompareNumericAndBranch* result =
   11484         New<HCompareNumericAndBranch>(left, right, op);
   11485     return result;
   11486   } else {
   11487     if (op == Token::EQ) {
   11488       if (left->IsConstant() &&
   11489           HConstant::cast(left)->GetInstanceType() == ODDBALL_TYPE &&
   11490           HConstant::cast(left)->IsUndetectable()) {
   11491         return New<HIsUndetectableAndBranch>(right);
   11492       }
   11493 
   11494       if (right->IsConstant() &&
   11495           HConstant::cast(right)->GetInstanceType() == ODDBALL_TYPE &&
   11496           HConstant::cast(right)->IsUndetectable()) {
   11497         return New<HIsUndetectableAndBranch>(left);
   11498       }
   11499     }
   11500 
   11501     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
   11502       HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
   11503       result->set_observed_input_representation(1, left_rep);
   11504       result->set_observed_input_representation(2, right_rep);
   11505       if (result->HasObservableSideEffects()) {
   11506         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   11507           Push(result);
   11508           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11509           Drop(1);
   11510         } else {
   11511           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11512         }
   11513       }
   11514       // TODO(jkummerow): Can we make this more efficient?
   11515       HBranch* branch = New<HBranch>(result);
   11516       return branch;
   11517     } else {
   11518       HCompareNumericAndBranch* result =
   11519           New<HCompareNumericAndBranch>(left, right, op);
   11520       result->set_observed_input_representation(left_rep, right_rep);
   11521       return result;
   11522     }
   11523   }
   11524 }
   11525 
   11526 
   11527 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
   11528                                                      Expression* sub_expr,
   11529                                                      NilValue nil) {
   11530   DCHECK(!HasStackOverflow());
   11531   DCHECK(current_block() != NULL);
   11532   DCHECK(current_block()->HasPredecessor());
   11533   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
   11534   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   11535   CHECK_ALIVE(VisitForValue(sub_expr));
   11536   HValue* value = Pop();
   11537   HControlInstruction* instr;
   11538   if (expr->op() == Token::EQ_STRICT) {
   11539     HConstant* nil_constant = nil == kNullValue
   11540         ? graph()->GetConstantNull()
   11541         : graph()->GetConstantUndefined();
   11542     instr = New<HCompareObjectEqAndBranch>(value, nil_constant);
   11543   } else {
   11544     DCHECK_EQ(Token::EQ, expr->op());
   11545     instr = New<HIsUndetectableAndBranch>(value);
   11546   }
   11547   return ast_context()->ReturnControl(instr, expr->id());
   11548 }
   11549 
   11550 
   11551 void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
   11552 
   11553 
   11554 void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
   11555   UNREACHABLE();
   11556 }
   11557 
   11558 void HOptimizedGraphBuilder::VisitGetIterator(GetIterator* expr) {
   11559   UNREACHABLE();
   11560 }
   11561 
   11562 HValue* HOptimizedGraphBuilder::AddThisFunction() {
   11563   return AddInstruction(BuildThisFunction());
   11564 }
   11565 
   11566 
   11567 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
   11568   // If we share optimized code between different closures, the
   11569   // this-function is not a constant, except inside an inlined body.
   11570   if (function_state()->outer() != NULL) {
   11571       return New<HConstant>(
   11572           function_state()->compilation_info()->closure());
   11573   } else {
   11574       return New<HThisFunction>();
   11575   }
   11576 }
   11577 
   11578 
   11579 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
   11580     Handle<JSObject> boilerplate_object,
   11581     AllocationSiteUsageContext* site_context) {
   11582   NoObservableSideEffectsScope no_effects(this);
   11583   Handle<Map> initial_map(boilerplate_object->map());
   11584   InstanceType instance_type = initial_map->instance_type();
   11585   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
   11586 
   11587   HType type = instance_type == JS_ARRAY_TYPE
   11588       ? HType::JSArray() : HType::JSObject();
   11589   HValue* object_size_constant = Add<HConstant>(initial_map->instance_size());
   11590 
   11591   PretenureFlag pretenure_flag = NOT_TENURED;
   11592   Handle<AllocationSite> top_site(*site_context->top(), isolate());
   11593   if (FLAG_allocation_site_pretenuring) {
   11594     pretenure_flag = top_site->GetPretenureMode();
   11595   }
   11596 
   11597   Handle<AllocationSite> current_site(*site_context->current(), isolate());
   11598   if (*top_site == *current_site) {
   11599     // We install a dependency for pretenuring only on the outermost literal.
   11600     top_info()->dependencies()->AssumeTenuringDecision(top_site);
   11601   }
   11602   top_info()->dependencies()->AssumeTransitionStable(current_site);
   11603 
   11604   HInstruction* object =
   11605       Add<HAllocate>(object_size_constant, type, pretenure_flag, instance_type,
   11606                      graph()->GetConstant0(), top_site);
   11607 
   11608   // If allocation folding reaches kMaxRegularHeapObjectSize the
   11609   // elements array may not get folded into the object. Hence, we set the
   11610   // elements pointer to empty fixed array and let store elimination remove
   11611   // this store in the folding case.
   11612   HConstant* empty_fixed_array = Add<HConstant>(
   11613       isolate()->factory()->empty_fixed_array());
   11614   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11615       empty_fixed_array);
   11616 
   11617   BuildEmitObjectHeader(boilerplate_object, object);
   11618 
   11619   // Similarly to the elements pointer, there is no guarantee that all
   11620   // property allocations can get folded, so pre-initialize all in-object
   11621   // properties to a safe value.
   11622   BuildInitializeInobjectProperties(object, initial_map);
   11623 
   11624   Handle<FixedArrayBase> elements(boilerplate_object->elements());
   11625   int elements_size = (elements->length() > 0 &&
   11626       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
   11627           elements->Size() : 0;
   11628 
   11629   if (pretenure_flag == TENURED &&
   11630       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
   11631       isolate()->heap()->InNewSpace(*elements)) {
   11632     // If we would like to pretenure a fixed cow array, we must ensure that the
   11633     // array is already in old space, otherwise we'll create too many old-to-
   11634     // new-space pointers (overflowing the store buffer).
   11635     elements = Handle<FixedArrayBase>(
   11636         isolate()->factory()->CopyAndTenureFixedCOWArray(
   11637             Handle<FixedArray>::cast(elements)));
   11638     boilerplate_object->set_elements(*elements);
   11639   }
   11640 
   11641   HInstruction* object_elements = NULL;
   11642   if (elements_size > 0) {
   11643     HValue* object_elements_size = Add<HConstant>(elements_size);
   11644     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
   11645         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
   11646     object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
   11647                                      pretenure_flag, instance_type,
   11648                                      graph()->GetConstant0(), top_site);
   11649     BuildEmitElements(boilerplate_object, elements, object_elements,
   11650                       site_context);
   11651     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11652                           object_elements);
   11653   } else {
   11654     Handle<Object> elements_field =
   11655         Handle<Object>(boilerplate_object->elements(), isolate());
   11656     HInstruction* object_elements_cow = Add<HConstant>(elements_field);
   11657     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11658                           object_elements_cow);
   11659   }
   11660 
   11661   // Copy in-object properties.
   11662   if (initial_map->NumberOfFields() != 0 ||
   11663       initial_map->unused_property_fields() > 0) {
   11664     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
   11665                                 pretenure_flag);
   11666   }
   11667   return object;
   11668 }
   11669 
   11670 
   11671 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
   11672     Handle<JSObject> boilerplate_object,
   11673     HInstruction* object) {
   11674   DCHECK(boilerplate_object->properties()->length() == 0);
   11675 
   11676   Handle<Map> boilerplate_object_map(boilerplate_object->map());
   11677   AddStoreMapConstant(object, boilerplate_object_map);
   11678 
   11679   Handle<Object> properties_field =
   11680       Handle<Object>(boilerplate_object->properties(), isolate());
   11681   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
   11682   HInstruction* properties = Add<HConstant>(properties_field);
   11683   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
   11684   Add<HStoreNamedField>(object, access, properties);
   11685 
   11686   if (boilerplate_object->IsJSArray()) {
   11687     Handle<JSArray> boilerplate_array =
   11688         Handle<JSArray>::cast(boilerplate_object);
   11689     Handle<Object> length_field =
   11690         Handle<Object>(boilerplate_array->length(), isolate());
   11691     HInstruction* length = Add<HConstant>(length_field);
   11692 
   11693     DCHECK(boilerplate_array->length()->IsSmi());
   11694     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
   11695         boilerplate_array->GetElementsKind()), length);
   11696   }
   11697 }
   11698 
   11699 
   11700 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
   11701     Handle<JSObject> boilerplate_object,
   11702     HInstruction* object,
   11703     AllocationSiteUsageContext* site_context,
   11704     PretenureFlag pretenure_flag) {
   11705   Handle<Map> boilerplate_map(boilerplate_object->map());
   11706   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
   11707   int limit = boilerplate_map->NumberOfOwnDescriptors();
   11708 
   11709   int copied_fields = 0;
   11710   for (int i = 0; i < limit; i++) {
   11711     PropertyDetails details = descriptors->GetDetails(i);
   11712     if (details.location() != kField) continue;
   11713     DCHECK_EQ(kData, details.kind());
   11714     copied_fields++;
   11715     FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);
   11716 
   11717 
   11718     int property_offset = field_index.offset();
   11719     Handle<Name> name(descriptors->GetKey(i));
   11720 
   11721     // The access for the store depends on the type of the boilerplate.
   11722     HObjectAccess access = boilerplate_object->IsJSArray() ?
   11723         HObjectAccess::ForJSArrayOffset(property_offset) :
   11724         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11725 
   11726     if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
   11727       CHECK(!boilerplate_object->IsJSArray());
   11728       double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
   11729       access = access.WithRepresentation(Representation::Double());
   11730       Add<HStoreNamedField>(object, access, Add<HConstant>(value));
   11731       continue;
   11732     }
   11733     Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
   11734                          isolate());
   11735 
   11736     if (value->IsJSObject()) {
   11737       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11738       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11739       HInstruction* result =
   11740           BuildFastLiteral(value_object, site_context);
   11741       site_context->ExitScope(current_site, value_object);
   11742       Add<HStoreNamedField>(object, access, result);
   11743     } else {
   11744       Representation representation = details.representation();
   11745       HInstruction* value_instruction;
   11746 
   11747       if (representation.IsDouble()) {
   11748         // Allocate a HeapNumber box and store the value into it.
   11749         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
   11750         HInstruction* double_box = Add<HAllocate>(
   11751             heap_number_constant, HType::HeapObject(), pretenure_flag,
   11752             MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
   11753         AddStoreMapConstant(double_box,
   11754             isolate()->factory()->mutable_heap_number_map());
   11755         // Unwrap the mutable heap number from the boilerplate.
   11756         HValue* double_value =
   11757             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
   11758         Add<HStoreNamedField>(
   11759             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
   11760         value_instruction = double_box;
   11761       } else if (representation.IsSmi()) {
   11762         value_instruction = value->IsUninitialized(isolate())
   11763                                 ? graph()->GetConstant0()
   11764                                 : Add<HConstant>(value);
   11765         // Ensure that value is stored as smi.
   11766         access = access.WithRepresentation(representation);
   11767       } else {
   11768         value_instruction = Add<HConstant>(value);
   11769       }
   11770 
   11771       Add<HStoreNamedField>(object, access, value_instruction);
   11772     }
   11773   }
   11774 
   11775   int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
   11776   HInstruction* value_instruction =
   11777       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
   11778   for (int i = copied_fields; i < inobject_properties; i++) {
   11779     DCHECK(boilerplate_object->IsJSObject());
   11780     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
   11781     HObjectAccess access =
   11782         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11783     Add<HStoreNamedField>(object, access, value_instruction);
   11784   }
   11785 }
   11786 
   11787 
   11788 void HOptimizedGraphBuilder::BuildEmitElements(
   11789     Handle<JSObject> boilerplate_object,
   11790     Handle<FixedArrayBase> elements,
   11791     HValue* object_elements,
   11792     AllocationSiteUsageContext* site_context) {
   11793   ElementsKind kind = boilerplate_object->map()->elements_kind();
   11794   int elements_length = elements->length();
   11795   HValue* object_elements_length = Add<HConstant>(elements_length);
   11796   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
   11797 
   11798   // Copy elements backing store content.
   11799   if (elements->IsFixedDoubleArray()) {
   11800     BuildEmitFixedDoubleArray(elements, kind, object_elements);
   11801   } else if (elements->IsFixedArray()) {
   11802     BuildEmitFixedArray(elements, kind, object_elements,
   11803                         site_context);
   11804   } else {
   11805     UNREACHABLE();
   11806   }
   11807 }
   11808 
   11809 
   11810 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
   11811     Handle<FixedArrayBase> elements,
   11812     ElementsKind kind,
   11813     HValue* object_elements) {
   11814   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11815   int elements_length = elements->length();
   11816   for (int i = 0; i < elements_length; i++) {
   11817     HValue* key_constant = Add<HConstant>(i);
   11818     HInstruction* value_instruction =
   11819         Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   11820                         kind, ALLOW_RETURN_HOLE);
   11821     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
   11822                                            value_instruction, nullptr, kind);
   11823     store->SetFlag(HValue::kTruncatingToNumber);
   11824   }
   11825 }
   11826 
   11827 
   11828 void HOptimizedGraphBuilder::BuildEmitFixedArray(
   11829     Handle<FixedArrayBase> elements,
   11830     ElementsKind kind,
   11831     HValue* object_elements,
   11832     AllocationSiteUsageContext* site_context) {
   11833   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11834   int elements_length = elements->length();
   11835   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   11836   for (int i = 0; i < elements_length; i++) {
   11837     Handle<Object> value(fast_elements->get(i), isolate());
   11838     HValue* key_constant = Add<HConstant>(i);
   11839     if (value->IsJSObject()) {
   11840       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11841       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11842       HInstruction* result =
   11843           BuildFastLiteral(value_object, site_context);
   11844       site_context->ExitScope(current_site, value_object);
   11845       Add<HStoreKeyed>(object_elements, key_constant, result, nullptr, kind);
   11846     } else {
   11847       ElementsKind copy_kind =
   11848           kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
   11849       HInstruction* value_instruction =
   11850           Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   11851                           copy_kind, ALLOW_RETURN_HOLE);
   11852       Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
   11853                        nullptr, copy_kind);
   11854     }
   11855   }
   11856 }
   11857 
   11858 
   11859 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   11860   DCHECK(!HasStackOverflow());
   11861   DCHECK(current_block() != NULL);
   11862   DCHECK(current_block()->HasPredecessor());
   11863   HInstruction* instr = BuildThisFunction();
   11864   return ast_context()->ReturnInstruction(instr, expr->id());
   11865 }
   11866 
   11867 
   11868 void HOptimizedGraphBuilder::VisitSuperPropertyReference(
   11869     SuperPropertyReference* expr) {
   11870   DCHECK(!HasStackOverflow());
   11871   DCHECK(current_block() != NULL);
   11872   DCHECK(current_block()->HasPredecessor());
   11873   return Bailout(kSuperReference);
   11874 }
   11875 
   11876 
   11877 void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
   11878   DCHECK(!HasStackOverflow());
   11879   DCHECK(current_block() != NULL);
   11880   DCHECK(current_block()->HasPredecessor());
   11881   return Bailout(kSuperReference);
   11882 }
   11883 
   11884 void HOptimizedGraphBuilder::VisitDeclarations(
   11885     Declaration::List* declarations) {
   11886   DCHECK(globals_.is_empty());
   11887   AstVisitor<HOptimizedGraphBuilder>::VisitDeclarations(declarations);
   11888   if (!globals_.is_empty()) {
   11889     Handle<FixedArray> array =
   11890        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
   11891     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
   11892     int flags = current_info()->GetDeclareGlobalsFlags();
   11893     Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
   11894     Add<HDeclareGlobals>(array, flags, vector);
   11895     globals_.Rewind(0);
   11896   }
   11897 }
   11898 
   11899 
   11900 void HOptimizedGraphBuilder::VisitVariableDeclaration(
   11901     VariableDeclaration* declaration) {
   11902   VariableProxy* proxy = declaration->proxy();
   11903   Variable* variable = proxy->var();
   11904   switch (variable->location()) {
   11905     case VariableLocation::UNALLOCATED: {
   11906       DCHECK(!variable->binding_needs_init());
   11907       globals_.Add(variable->name(), zone());
   11908       FeedbackSlot slot = proxy->VariableFeedbackSlot();
   11909       DCHECK(!slot.IsInvalid());
   11910       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11911       globals_.Add(isolate()->factory()->undefined_value(), zone());
   11912       globals_.Add(isolate()->factory()->undefined_value(), zone());
   11913       return;
   11914     }
   11915     case VariableLocation::PARAMETER:
   11916     case VariableLocation::LOCAL:
   11917       if (variable->binding_needs_init()) {
   11918         HValue* value = graph()->GetConstantHole();
   11919         environment()->Bind(variable, value);
   11920       }
   11921       break;
   11922     case VariableLocation::CONTEXT:
   11923       if (variable->binding_needs_init()) {
   11924         HValue* value = graph()->GetConstantHole();
   11925         HValue* context = environment()->context();
   11926         HStoreContextSlot* store = Add<HStoreContextSlot>(
   11927             context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11928         if (store->HasObservableSideEffects()) {
   11929           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11930         }
   11931       }
   11932       break;
   11933     case VariableLocation::LOOKUP:
   11934       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11935     case VariableLocation::MODULE:
   11936       UNREACHABLE();
   11937   }
   11938 }
   11939 
   11940 
   11941 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
   11942     FunctionDeclaration* declaration) {
   11943   VariableProxy* proxy = declaration->proxy();
   11944   Variable* variable = proxy->var();
   11945   switch (variable->location()) {
   11946     case VariableLocation::UNALLOCATED: {
   11947       globals_.Add(variable->name(), zone());
   11948       FeedbackSlot slot = proxy->VariableFeedbackSlot();
   11949       DCHECK(!slot.IsInvalid());
   11950       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11951 
   11952       // We need the slot where the literals array lives, too.
   11953       slot = declaration->fun()->LiteralFeedbackSlot();
   11954       DCHECK(!slot.IsInvalid());
   11955       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11956 
   11957       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
   11958           declaration->fun(), current_info()->script(), top_info());
   11959       // Check for stack-overflow exception.
   11960       if (function.is_null()) return SetStackOverflow();
   11961       globals_.Add(function, zone());
   11962       return;
   11963     }
   11964     case VariableLocation::PARAMETER:
   11965     case VariableLocation::LOCAL: {
   11966       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11967       HValue* value = Pop();
   11968       BindIfLive(variable, value);
   11969       break;
   11970     }
   11971     case VariableLocation::CONTEXT: {
   11972       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11973       HValue* value = Pop();
   11974       HValue* context = environment()->context();
   11975       HStoreContextSlot* store = Add<HStoreContextSlot>(
   11976           context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11977       if (store->HasObservableSideEffects()) {
   11978         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11979       }
   11980       break;
   11981     }
   11982     case VariableLocation::LOOKUP:
   11983       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11984     case VariableLocation::MODULE:
   11985       UNREACHABLE();
   11986   }
   11987 }
   11988 
   11989 
   11990 void HOptimizedGraphBuilder::VisitRewritableExpression(
   11991     RewritableExpression* node) {
   11992   CHECK_ALIVE(Visit(node->expression()));
   11993 }
   11994 
   11995 
   11996 // Generators for inline runtime functions.
   11997 // Support for types.
   11998 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
   11999   DCHECK(call->arguments()->length() == 1);
   12000   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12001   HValue* value = Pop();
   12002   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
   12003   return ast_context()->ReturnControl(result, call->id());
   12004 }
   12005 
   12006 
   12007 void HOptimizedGraphBuilder::GenerateIsJSReceiver(CallRuntime* call) {
   12008   DCHECK(call->arguments()->length() == 1);
   12009   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12010   HValue* value = Pop();
   12011   HHasInstanceTypeAndBranch* result =
   12012       New<HHasInstanceTypeAndBranch>(value,
   12013                                      FIRST_JS_RECEIVER_TYPE,
   12014                                      LAST_JS_RECEIVER_TYPE);
   12015   return ast_context()->ReturnControl(result, call->id());
   12016 }
   12017 
   12018 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
   12019   DCHECK(call->arguments()->length() == 1);
   12020   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12021   HValue* value = Pop();
   12022   HHasInstanceTypeAndBranch* result =
   12023       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
   12024   return ast_context()->ReturnControl(result, call->id());
   12025 }
   12026 
   12027 
   12028 void HOptimizedGraphBuilder::GenerateIsTypedArray(CallRuntime* call) {
   12029   DCHECK(call->arguments()->length() == 1);
   12030   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12031   HValue* value = Pop();
   12032   HHasInstanceTypeAndBranch* result =
   12033       New<HHasInstanceTypeAndBranch>(value, JS_TYPED_ARRAY_TYPE);
   12034   return ast_context()->ReturnControl(result, call->id());
   12035 }
   12036 
   12037 
   12038 void HOptimizedGraphBuilder::GenerateToInteger(CallRuntime* call) {
   12039   DCHECK_EQ(1, call->arguments()->length());
   12040   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12041   HValue* input = Pop();
   12042   if (input->type().IsSmi()) {
   12043     return ast_context()->ReturnValue(input);
   12044   } else {
   12045     Callable callable = CodeFactory::ToInteger(isolate());
   12046     HValue* stub = Add<HConstant>(callable.code());
   12047     HValue* values[] = {input};
   12048     HInstruction* result = New<HCallWithDescriptor>(
   12049         stub, 0, callable.descriptor(), ArrayVector(values));
   12050     return ast_context()->ReturnInstruction(result, call->id());
   12051   }
   12052 }
   12053 
   12054 
   12055 void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
   12056   DCHECK_EQ(1, call->arguments()->length());
   12057   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12058   HValue* value = Pop();
   12059   HValue* result = BuildToObject(value);
   12060   return ast_context()->ReturnValue(result);
   12061 }
   12062 
   12063 
   12064 void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
   12065   DCHECK_EQ(1, call->arguments()->length());
   12066   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12067   HValue* input = Pop();
   12068   if (input->type().IsString()) {
   12069     return ast_context()->ReturnValue(input);
   12070   } else {
   12071     Callable callable = CodeFactory::ToString(isolate());
   12072     HValue* stub = Add<HConstant>(callable.code());
   12073     HValue* values[] = {input};
   12074     HInstruction* result = New<HCallWithDescriptor>(
   12075         stub, 0, callable.descriptor(), ArrayVector(values));
   12076     return ast_context()->ReturnInstruction(result, call->id());
   12077   }
   12078 }
   12079 
   12080 
   12081 void HOptimizedGraphBuilder::GenerateToLength(CallRuntime* call) {
   12082   DCHECK_EQ(1, call->arguments()->length());
   12083   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12084   Callable callable = CodeFactory::ToLength(isolate());
   12085   HValue* input = Pop();
   12086   HValue* stub = Add<HConstant>(callable.code());
   12087   HValue* values[] = {input};
   12088   HInstruction* result = New<HCallWithDescriptor>(
   12089       stub, 0, callable.descriptor(), ArrayVector(values));
   12090   return ast_context()->ReturnInstruction(result, call->id());
   12091 }
   12092 
   12093 
   12094 void HOptimizedGraphBuilder::GenerateToNumber(CallRuntime* call) {
   12095   DCHECK_EQ(1, call->arguments()->length());
   12096   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12097   Callable callable = CodeFactory::ToNumber(isolate());
   12098   HValue* input = Pop();
   12099   HValue* result = BuildToNumber(input);
   12100   if (result->HasObservableSideEffects()) {
   12101     if (!ast_context()->IsEffect()) Push(result);
   12102     Add<HSimulate>(call->id(), REMOVABLE_SIMULATE);
   12103     if (!ast_context()->IsEffect()) result = Pop();
   12104   }
   12105   return ast_context()->ReturnValue(result);
   12106 }
   12107 
   12108 
   12109 void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
   12110   DCHECK(call->arguments()->length() == 1);
   12111   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12112   HValue* value = Pop();
   12113   HIfContinuation continuation;
   12114   IfBuilder if_proxy(this);
   12115 
   12116   HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
   12117   if_proxy.And();
   12118   HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
   12119   HValue* instance_type =
   12120       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   12121   if_proxy.If<HCompareNumericAndBranch>(
   12122       instance_type, Add<HConstant>(JS_PROXY_TYPE), Token::EQ);
   12123 
   12124   if_proxy.CaptureContinuation(&continuation);
   12125   return ast_context()->ReturnContinuation(&continuation, call->id());
   12126 }
   12127 
   12128 
   12129 void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
   12130   DCHECK(call->arguments()->length() == 1);
   12131   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12132   HValue* object = Pop();
   12133   HIfContinuation continuation(graph()->CreateBasicBlock(),
   12134                                graph()->CreateBasicBlock());
   12135   IfBuilder if_not_smi(this);
   12136   if_not_smi.IfNot<HIsSmiAndBranch>(object);
   12137   if_not_smi.Then();
   12138   {
   12139     NoObservableSideEffectsScope no_effects(this);
   12140 
   12141     IfBuilder if_fast_packed(this);
   12142     HValue* elements_kind = BuildGetElementsKind(object);
   12143     if_fast_packed.If<HCompareNumericAndBranch>(
   12144         elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
   12145     if_fast_packed.Or();
   12146     if_fast_packed.If<HCompareNumericAndBranch>(
   12147         elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
   12148     if_fast_packed.Or();
   12149     if_fast_packed.If<HCompareNumericAndBranch>(
   12150         elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
   12151     if_fast_packed.JoinContinuation(&continuation);
   12152   }
   12153   if_not_smi.JoinContinuation(&continuation);
   12154   return ast_context()->ReturnContinuation(&continuation, call->id());
   12155 }
   12156 
   12157 
   12158 // Fast support for charCodeAt(n).
   12159 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   12160   DCHECK(call->arguments()->length() == 2);
   12161   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12162   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12163   HValue* index = Pop();
   12164   HValue* string = Pop();
   12165   HInstruction* result = BuildStringCharCodeAt(string, index);
   12166   return ast_context()->ReturnInstruction(result, call->id());
   12167 }
   12168 
   12169 
   12170 // Fast support for SubString.
   12171 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   12172   DCHECK_EQ(3, call->arguments()->length());
   12173   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12174   Callable callable = CodeFactory::SubString(isolate());
   12175   HValue* stub = Add<HConstant>(callable.code());
   12176   HValue* to = Pop();
   12177   HValue* from = Pop();
   12178   HValue* string = Pop();
   12179   HValue* values[] = {string, from, to};
   12180   HInstruction* result = New<HCallWithDescriptor>(
   12181       stub, 0, callable.descriptor(), ArrayVector(values));
   12182   result->set_type(HType::String());
   12183   return ast_context()->ReturnInstruction(result, call->id());
   12184 }
   12185 
   12186 
   12187 // Fast support for calls.
   12188 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
   12189   DCHECK_LE(2, call->arguments()->length());
   12190   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12191   CallTrampolineDescriptor descriptor(isolate());
   12192   PushArgumentsFromEnvironment(call->arguments()->length() - 1);
   12193   HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
   12194   HValue* target = Pop();
   12195   HValue* values[] = {target, Add<HConstant>(call->arguments()->length() - 2)};
   12196   HInstruction* result =
   12197       New<HCallWithDescriptor>(trampoline, call->arguments()->length() - 1,
   12198                                descriptor, ArrayVector(values));
   12199   return ast_context()->ReturnInstruction(result, call->id());
   12200 }
   12201 
   12202 
   12203 void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
   12204   DCHECK(call->arguments()->length() == 2);
   12205   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12206   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12207   HValue* index = Pop();
   12208   HValue* object = Pop();
   12209   HInstruction* result = New<HLoadKeyed>(
   12210       object, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
   12211   return ast_context()->ReturnInstruction(result, call->id());
   12212 }
   12213 
   12214 
   12215 void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
   12216   DCHECK(call->arguments()->length() == 3);
   12217   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12218   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12219   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   12220   HValue* value = Pop();
   12221   HValue* index = Pop();
   12222   HValue* object = Pop();
   12223   NoObservableSideEffectsScope no_effects(this);
   12224   Add<HStoreKeyed>(object, index, value, nullptr, FAST_HOLEY_ELEMENTS);
   12225   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12226 }
   12227 
   12228 
   12229 void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
   12230   DCHECK(call->arguments()->length() == 0);
   12231   return ast_context()->ReturnValue(graph()->GetConstantHole());
   12232 }
   12233 
   12234 
   12235 void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
   12236   DCHECK_EQ(2, call->arguments()->length());
   12237   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12238   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12239   HValue* done = Pop();
   12240   HValue* value = Pop();
   12241   HValue* result = BuildCreateIterResultObject(value, done);
   12242   return ast_context()->ReturnValue(result);
   12243 }
   12244 
   12245 
   12246 void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
   12247   DCHECK(call->arguments()->length() == 1);
   12248   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12249   HValue* receiver = Pop();
   12250   HInstruction* result = New<HLoadNamedField>(
   12251       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   12252   return ast_context()->ReturnInstruction(result, call->id());
   12253 }
   12254 
   12255 
   12256 void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) {
   12257   DCHECK(call->arguments()->length() == 1);
   12258   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12259   HValue* object = Pop();
   12260   HInstruction* result = New<HLoadNamedField>(
   12261       object, nullptr, HObjectAccess::ForStringHashField());
   12262   return ast_context()->ReturnInstruction(result, call->id());
   12263 }
   12264 
   12265 
   12266 template <typename CollectionType>
   12267 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
   12268   static const int kCapacity = CollectionType::kMinCapacity;
   12269   static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
   12270   static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
   12271                                        kBucketCount +
   12272                                        (kCapacity * CollectionType::kEntrySize);
   12273   static const int kSizeInBytes =
   12274       FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);
   12275 
   12276   // Allocate the table and add the proper map.
   12277   HValue* table =
   12278       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
   12279                      NOT_TENURED, FIXED_ARRAY_TYPE, graph()->GetConstant0());
   12280   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
   12281 
   12282   // Initialize the FixedArray...
   12283   HValue* length = Add<HConstant>(kFixedArrayLength);
   12284   Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);
   12285 
   12286   // ...and the OrderedHashTable fields.
   12287   Add<HStoreNamedField>(
   12288       table,
   12289       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
   12290       Add<HConstant>(kBucketCount));
   12291   Add<HStoreNamedField>(
   12292       table,
   12293       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
   12294       graph()->GetConstant0());
   12295   Add<HStoreNamedField>(
   12296       table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12297                  CollectionType>(),
   12298       graph()->GetConstant0());
   12299 
   12300   // Fill the buckets with kNotFound.
   12301   HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
   12302   for (int i = 0; i < kBucketCount; ++i) {
   12303     Add<HStoreNamedField>(
   12304         table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
   12305         not_found);
   12306   }
   12307 
   12308   // Fill the data table with undefined.
   12309   HValue* undefined = graph()->GetConstantUndefined();
   12310   for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
   12311     Add<HStoreNamedField>(table,
   12312                           HObjectAccess::ForOrderedHashTableDataTableIndex<
   12313                               CollectionType, kBucketCount>(i),
   12314                           undefined);
   12315   }
   12316 
   12317   return table;
   12318 }
   12319 
   12320 
   12321 void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
   12322   DCHECK(call->arguments()->length() == 1);
   12323   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12324   HValue* receiver = Pop();
   12325 
   12326   NoObservableSideEffectsScope no_effects(this);
   12327   HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
   12328   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12329   return ast_context()->ReturnValue(receiver);
   12330 }
   12331 
   12332 
   12333 void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
   12334   DCHECK(call->arguments()->length() == 1);
   12335   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12336   HValue* receiver = Pop();
   12337 
   12338   NoObservableSideEffectsScope no_effects(this);
   12339   HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
   12340   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12341   return ast_context()->ReturnValue(receiver);
   12342 }
   12343 
   12344 
   12345 template <typename CollectionType>
   12346 void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
   12347   HValue* old_table = Add<HLoadNamedField>(
   12348       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   12349   HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
   12350   Add<HStoreNamedField>(
   12351       old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
   12352       new_table);
   12353   Add<HStoreNamedField>(
   12354       old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12355                      CollectionType>(),
   12356       Add<HConstant>(CollectionType::kClearedTableSentinel));
   12357   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
   12358                         new_table);
   12359 }
   12360 
   12361 
   12362 void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
   12363   DCHECK(call->arguments()->length() == 1);
   12364   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12365   HValue* receiver = Pop();
   12366 
   12367   NoObservableSideEffectsScope no_effects(this);
   12368   BuildOrderedHashTableClear<OrderedHashSet>(receiver);
   12369   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12370 }
   12371 
   12372 
   12373 void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
   12374   DCHECK(call->arguments()->length() == 1);
   12375   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12376   HValue* receiver = Pop();
   12377 
   12378   NoObservableSideEffectsScope no_effects(this);
   12379   BuildOrderedHashTableClear<OrderedHashMap>(receiver);
   12380   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12381 }
   12382 
   12383 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
   12384     CallRuntime* call) {
   12385   Add<HDebugBreak>();
   12386   return ast_context()->ReturnValue(graph()->GetConstant0());
   12387 }
   12388 
   12389 
   12390 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
   12391   DCHECK(call->arguments()->length() == 0);
   12392   HValue* ref =
   12393       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
   12394   HValue* value =
   12395       Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
   12396   return ast_context()->ReturnValue(value);
   12397 }
   12398 
   12399 #undef CHECK_BAILOUT
   12400 #undef CHECK_ALIVE
   12401 
   12402 
   12403 HEnvironment::HEnvironment(HEnvironment* outer,
   12404                            Scope* scope,
   12405                            Handle<JSFunction> closure,
   12406                            Zone* zone)
   12407     : closure_(closure),
   12408       values_(0, zone),
   12409       frame_type_(JS_FUNCTION),
   12410       parameter_count_(0),
   12411       specials_count_(1),
   12412       local_count_(0),
   12413       outer_(outer),
   12414       entry_(NULL),
   12415       pop_count_(0),
   12416       push_count_(0),
   12417       ast_id_(BailoutId::None()),
   12418       zone_(zone) {
   12419   DeclarationScope* declaration_scope = scope->GetDeclarationScope();
   12420   Initialize(declaration_scope->num_parameters() + 1,
   12421              declaration_scope->num_stack_slots(), 0);
   12422 }
   12423 
   12424 
   12425 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
   12426     : values_(0, zone),
   12427       frame_type_(STUB),
   12428       parameter_count_(parameter_count),
   12429       specials_count_(1),
   12430       local_count_(0),
   12431       outer_(NULL),
   12432       entry_(NULL),
   12433       pop_count_(0),
   12434       push_count_(0),
   12435       ast_id_(BailoutId::None()),
   12436       zone_(zone) {
   12437   Initialize(parameter_count, 0, 0);
   12438 }
   12439 
   12440 
   12441 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
   12442     : values_(0, zone),
   12443       frame_type_(JS_FUNCTION),
   12444       parameter_count_(0),
   12445       specials_count_(0),
   12446       local_count_(0),
   12447       outer_(NULL),
   12448       entry_(NULL),
   12449       pop_count_(0),
   12450       push_count_(0),
   12451       ast_id_(other->ast_id()),
   12452       zone_(zone) {
   12453   Initialize(other);
   12454 }
   12455 
   12456 
   12457 HEnvironment::HEnvironment(HEnvironment* outer,
   12458                            Handle<JSFunction> closure,
   12459                            FrameType frame_type,
   12460                            int arguments,
   12461                            Zone* zone)
   12462     : closure_(closure),
   12463       values_(arguments, zone),
   12464       frame_type_(frame_type),
   12465       parameter_count_(arguments),
   12466       specials_count_(0),
   12467       local_count_(0),
   12468       outer_(outer),
   12469       entry_(NULL),
   12470       pop_count_(0),
   12471       push_count_(0),
   12472       ast_id_(BailoutId::None()),
   12473       zone_(zone) {
   12474 }
   12475 
   12476 
   12477 void HEnvironment::Initialize(int parameter_count,
   12478                               int local_count,
   12479                               int stack_height) {
   12480   parameter_count_ = parameter_count;
   12481   local_count_ = local_count;
   12482 
   12483   // Avoid reallocating the temporaries' backing store on the first Push.
   12484   int total = parameter_count + specials_count_ + local_count + stack_height;
   12485   values_.Initialize(total + 4, zone());
   12486   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
   12487 }
   12488 
   12489 
   12490 void HEnvironment::Initialize(const HEnvironment* other) {
   12491   closure_ = other->closure();
   12492   values_.AddAll(other->values_, zone());
   12493   assigned_variables_.Union(other->assigned_variables_, zone());
   12494   frame_type_ = other->frame_type_;
   12495   parameter_count_ = other->parameter_count_;
   12496   local_count_ = other->local_count_;
   12497   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
   12498   entry_ = other->entry_;
   12499   pop_count_ = other->pop_count_;
   12500   push_count_ = other->push_count_;
   12501   specials_count_ = other->specials_count_;
   12502   ast_id_ = other->ast_id_;
   12503 }
   12504 
   12505 
   12506 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
   12507   DCHECK(!block->IsLoopHeader());
   12508   DCHECK(values_.length() == other->values_.length());
   12509 
   12510   int length = values_.length();
   12511   for (int i = 0; i < length; ++i) {
   12512     HValue* value = values_[i];
   12513     if (value != NULL && value->IsPhi() && value->block() == block) {
   12514       // There is already a phi for the i'th value.
   12515       HPhi* phi = HPhi::cast(value);
   12516       // Assert index is correct and that we haven't missed an incoming edge.
   12517       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
   12518       DCHECK(phi->OperandCount() == block->predecessors()->length());
   12519       phi->AddInput(other->values_[i]);
   12520     } else if (values_[i] != other->values_[i]) {
   12521       // There is a fresh value on the incoming edge, a phi is needed.
   12522       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
   12523       HPhi* phi = block->AddNewPhi(i);
   12524       HValue* old_value = values_[i];
   12525       for (int j = 0; j < block->predecessors()->length(); j++) {
   12526         phi->AddInput(old_value);
   12527       }
   12528       phi->AddInput(other->values_[i]);
   12529       this->values_[i] = phi;
   12530     }
   12531   }
   12532 }
   12533 
   12534 
   12535 void HEnvironment::Bind(int index, HValue* value) {
   12536   DCHECK(value != NULL);
   12537   assigned_variables_.Add(index, zone());
   12538   values_[index] = value;
   12539 }
   12540 
   12541 
   12542 bool HEnvironment::HasExpressionAt(int index) const {
   12543   return index >= parameter_count_ + specials_count_ + local_count_;
   12544 }
   12545 
   12546 
   12547 bool HEnvironment::ExpressionStackIsEmpty() const {
   12548   DCHECK(length() >= first_expression_index());
   12549   return length() == first_expression_index();
   12550 }
   12551 
   12552 
   12553 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
   12554   int count = index_from_top + 1;
   12555   int index = values_.length() - count;
   12556   DCHECK(HasExpressionAt(index));
   12557   // The push count must include at least the element in question or else
   12558   // the new value will not be included in this environment's history.
   12559   if (push_count_ < count) {
   12560     // This is the same effect as popping then re-pushing 'count' elements.
   12561     pop_count_ += (count - push_count_);
   12562     push_count_ = count;
   12563   }
   12564   values_[index] = value;
   12565 }
   12566 
   12567 
   12568 HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
   12569   int count = index_from_top + 1;
   12570   int index = values_.length() - count;
   12571   DCHECK(HasExpressionAt(index));
   12572   // Simulate popping 'count' elements and then
   12573   // pushing 'count - 1' elements back.
   12574   pop_count_ += Max(count - push_count_, 0);
   12575   push_count_ = Max(push_count_ - count, 0) + (count - 1);
   12576   return values_.Remove(index);
   12577 }
   12578 
   12579 
   12580 void HEnvironment::Drop(int count) {
   12581   for (int i = 0; i < count; ++i) {
   12582     Pop();
   12583   }
   12584 }
   12585 
   12586 
   12587 void HEnvironment::Print() const {
   12588   OFStream os(stdout);
   12589   os << *this << "\n";
   12590 }
   12591 
   12592 
   12593 HEnvironment* HEnvironment::Copy() const {
   12594   return new(zone()) HEnvironment(this, zone());
   12595 }
   12596 
   12597 
   12598 HEnvironment* HEnvironment::CopyWithoutHistory() const {
   12599   HEnvironment* result = Copy();
   12600   result->ClearHistory();
   12601   return result;
   12602 }
   12603 
   12604 
   12605 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
   12606   HEnvironment* new_env = Copy();
   12607   for (int i = 0; i < values_.length(); ++i) {
   12608     HPhi* phi = loop_header->AddNewPhi(i);
   12609     phi->AddInput(values_[i]);
   12610     new_env->values_[i] = phi;
   12611   }
   12612   new_env->ClearHistory();
   12613   return new_env;
   12614 }
   12615 
   12616 
   12617 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
   12618                                                   Handle<JSFunction> target,
   12619                                                   FrameType frame_type,
   12620                                                   int arguments) const {
   12621   HEnvironment* new_env =
   12622       new(zone()) HEnvironment(outer, target, frame_type,
   12623                                arguments + 1, zone());
   12624   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
   12625     new_env->Push(ExpressionStackAt(arguments - i));
   12626   }
   12627   new_env->ClearHistory();
   12628   return new_env;
   12629 }
   12630 
   12631 void HEnvironment::MarkAsTailCaller() {
   12632   DCHECK_EQ(JS_FUNCTION, frame_type());
   12633   frame_type_ = TAIL_CALLER_FUNCTION;
   12634 }
   12635 
   12636 void HEnvironment::ClearTailCallerMark() {
   12637   DCHECK_EQ(TAIL_CALLER_FUNCTION, frame_type());
   12638   frame_type_ = JS_FUNCTION;
   12639 }
   12640 
   12641 HEnvironment* HEnvironment::CopyForInlining(
   12642     Handle<JSFunction> target, int arguments, FunctionLiteral* function,
   12643     HConstant* undefined, InliningKind inlining_kind,
   12644     TailCallMode syntactic_tail_call_mode) const {
   12645   DCHECK_EQ(JS_FUNCTION, frame_type());
   12646 
   12647   // Outer environment is a copy of this one without the arguments.
   12648   int arity = function->scope()->num_parameters();
   12649 
   12650   HEnvironment* outer = Copy();
   12651   outer->Drop(arguments + 1);  // Including receiver.
   12652   outer->ClearHistory();
   12653 
   12654   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
   12655     DCHECK_EQ(NORMAL_RETURN, inlining_kind);
   12656     outer->MarkAsTailCaller();
   12657   }
   12658 
   12659   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
   12660     // Create artificial constructor stub environment.  The receiver should
   12661     // actually be the constructor function, but we pass the newly allocated
   12662     // object instead, DoComputeConstructStubFrame() relies on that.
   12663     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
   12664   } else if (inlining_kind == GETTER_CALL_RETURN) {
   12665     // We need an additional StackFrame::INTERNAL frame for restoring the
   12666     // correct context.
   12667     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
   12668   } else if (inlining_kind == SETTER_CALL_RETURN) {
   12669     // We need an additional StackFrame::INTERNAL frame for temporarily saving
   12670     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
   12671     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
   12672   }
   12673 
   12674   if (arity != arguments) {
   12675     // Create artificial arguments adaptation environment.
   12676     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
   12677   }
   12678 
   12679   HEnvironment* inner =
   12680       new(zone()) HEnvironment(outer, function->scope(), target, zone());
   12681   // Get the argument values from the original environment.
   12682   for (int i = 0; i <= arity; ++i) {  // Include receiver.
   12683     HValue* push = (i <= arguments) ?
   12684         ExpressionStackAt(arguments - i) : undefined;
   12685     inner->SetValueAt(i, push);
   12686   }
   12687   inner->SetValueAt(arity + 1, context());
   12688   for (int i = arity + 2; i < inner->length(); ++i) {
   12689     inner->SetValueAt(i, undefined);
   12690   }
   12691 
   12692   inner->set_ast_id(BailoutId::FunctionEntry());
   12693   return inner;
   12694 }
   12695 
   12696 
   12697 std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
   12698   for (int i = 0; i < env.length(); i++) {
   12699     if (i == 0) os << "parameters\n";
   12700     if (i == env.parameter_count()) os << "specials\n";
   12701     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
   12702     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
   12703       os << "expressions\n";
   12704     }
   12705     HValue* val = env.values()->at(i);
   12706     os << i << ": ";
   12707     if (val != NULL) {
   12708       os << val;
   12709     } else {
   12710       os << "NULL";
   12711     }
   12712     os << "\n";
   12713   }
   12714   return os << "\n";
   12715 }
   12716 
   12717 
   12718 void HTracer::TraceCompilation(CompilationInfo* info) {
   12719   Tag tag(this, "compilation");
   12720   std::string name;
   12721   if (info->parse_info()) {
   12722     Object* source_name = info->script()->name();
   12723     if (source_name->IsString()) {
   12724       String* str = String::cast(source_name);
   12725       if (str->length() > 0) {
   12726         name.append(str->ToCString().get());
   12727         name.append(":");
   12728       }
   12729     }
   12730   }
   12731   std::unique_ptr<char[]> method_name = info->GetDebugName();
   12732   name.append(method_name.get());
   12733   if (info->IsOptimizing()) {
   12734     PrintStringProperty("name", name.c_str());
   12735     PrintIndent();
   12736     trace_.Add("method \"%s:%d\"\n", method_name.get(),
   12737                info->optimization_id());
   12738   } else {
   12739     PrintStringProperty("name", name.c_str());
   12740     PrintStringProperty("method", "stub");
   12741   }
   12742   PrintLongProperty("date",
   12743                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
   12744 }
   12745 
   12746 
   12747 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
   12748   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
   12749   AllowHandleDereference allow_deref;
   12750   AllowDeferredHandleDereference allow_deferred_deref;
   12751   Trace(name, chunk->graph(), chunk);
   12752 }
   12753 
   12754 
   12755 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
   12756   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
   12757   AllowHandleDereference allow_deref;
   12758   AllowDeferredHandleDereference allow_deferred_deref;
   12759   Trace(name, graph, NULL);
   12760 }
   12761 
   12762 
   12763 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
   12764   Tag tag(this, "cfg");
   12765   PrintStringProperty("name", name);
   12766   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
   12767   for (int i = 0; i < blocks->length(); i++) {
   12768     HBasicBlock* current = blocks->at(i);
   12769     Tag block_tag(this, "block");
   12770     PrintBlockProperty("name", current->block_id());
   12771     PrintIntProperty("from_bci", -1);
   12772     PrintIntProperty("to_bci", -1);
   12773 
   12774     if (!current->predecessors()->is_empty()) {
   12775       PrintIndent();
   12776       trace_.Add("predecessors");
   12777       for (int j = 0; j < current->predecessors()->length(); ++j) {
   12778         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
   12779       }
   12780       trace_.Add("\n");
   12781     } else {
   12782       PrintEmptyProperty("predecessors");
   12783     }
   12784 
   12785     if (current->end()->SuccessorCount() == 0) {
   12786       PrintEmptyProperty("successors");
   12787     } else  {
   12788       PrintIndent();
   12789       trace_.Add("successors");
   12790       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
   12791         trace_.Add(" \"B%d\"", it.Current()->block_id());
   12792       }
   12793       trace_.Add("\n");
   12794     }
   12795 
   12796     PrintEmptyProperty("xhandlers");
   12797 
   12798     {
   12799       PrintIndent();
   12800       trace_.Add("flags");
   12801       if (current->IsLoopSuccessorDominator()) {
   12802         trace_.Add(" \"dom-loop-succ\"");
   12803       }
   12804       if (current->IsUnreachable()) {
   12805         trace_.Add(" \"dead\"");
   12806       }
   12807       if (current->is_osr_entry()) {
   12808         trace_.Add(" \"osr\"");
   12809       }
   12810       trace_.Add("\n");
   12811     }
   12812 
   12813     if (current->dominator() != NULL) {
   12814       PrintBlockProperty("dominator", current->dominator()->block_id());
   12815     }
   12816 
   12817     PrintIntProperty("loop_depth", current->LoopNestingDepth());
   12818 
   12819     if (chunk != NULL) {
   12820       int first_index = current->first_instruction_index();
   12821       int last_index = current->last_instruction_index();
   12822       PrintIntProperty(
   12823           "first_lir_id",
   12824           LifetimePosition::FromInstructionIndex(first_index).Value());
   12825       PrintIntProperty(
   12826           "last_lir_id",
   12827           LifetimePosition::FromInstructionIndex(last_index).Value());
   12828     }
   12829 
   12830     {
   12831       Tag states_tag(this, "states");
   12832       Tag locals_tag(this, "locals");
   12833       int total = current->phis()->length();
   12834       PrintIntProperty("size", current->phis()->length());
   12835       PrintStringProperty("method", "None");
   12836       for (int j = 0; j < total; ++j) {
   12837         HPhi* phi = current->phis()->at(j);
   12838         PrintIndent();
   12839         std::ostringstream os;
   12840         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
   12841         trace_.Add(os.str().c_str());
   12842       }
   12843     }
   12844 
   12845     {
   12846       Tag HIR_tag(this, "HIR");
   12847       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
   12848         HInstruction* instruction = it.Current();
   12849         int uses = instruction->UseCount();
   12850         PrintIndent();
   12851         std::ostringstream os;
   12852         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
   12853         if (instruction->has_position()) {
   12854           const SourcePosition pos = instruction->position();
   12855           os << " pos:";
   12856           if (pos.isInlined()) os << "inlining(" << pos.InliningId() << "),";
   12857           os << pos.ScriptOffset();
   12858         }
   12859         os << " <|@\n";
   12860         trace_.Add(os.str().c_str());
   12861       }
   12862     }
   12863 
   12864 
   12865     if (chunk != NULL) {
   12866       Tag LIR_tag(this, "LIR");
   12867       int first_index = current->first_instruction_index();
   12868       int last_index = current->last_instruction_index();
   12869       if (first_index != -1 && last_index != -1) {
   12870         const ZoneList<LInstruction*>* instructions = chunk->instructions();
   12871         for (int i = first_index; i <= last_index; ++i) {
   12872           LInstruction* linstr = instructions->at(i);
   12873           if (linstr != NULL) {
   12874             PrintIndent();
   12875             trace_.Add("%d ",
   12876                        LifetimePosition::FromInstructionIndex(i).Value());
   12877             linstr->PrintTo(&trace_);
   12878             std::ostringstream os;
   12879             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
   12880             trace_.Add(os.str().c_str());
   12881           }
   12882         }
   12883       }
   12884     }
   12885   }
   12886 }
   12887 
   12888 
   12889 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
   12890   Tag tag(this, "intervals");
   12891   PrintStringProperty("name", name);
   12892 
   12893   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
   12894   for (int i = 0; i < fixed_d->length(); ++i) {
   12895     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
   12896   }
   12897 
   12898   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
   12899   for (int i = 0; i < fixed->length(); ++i) {
   12900     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
   12901   }
   12902 
   12903   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
   12904   for (int i = 0; i < live_ranges->length(); ++i) {
   12905     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
   12906   }
   12907 }
   12908 
   12909 
   12910 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
   12911                              Zone* zone) {
   12912   if (range != NULL && !range->IsEmpty()) {
   12913     PrintIndent();
   12914     trace_.Add("%d %s", range->id(), type);
   12915     if (range->HasRegisterAssigned()) {
   12916       LOperand* op = range->CreateAssignedOperand(zone);
   12917       int assigned_reg = op->index();
   12918       if (op->IsDoubleRegister()) {
   12919         trace_.Add(" \"%s\"",
   12920                    GetRegConfig()->GetDoubleRegisterName(assigned_reg));
   12921       } else {
   12922         DCHECK(op->IsRegister());
   12923         trace_.Add(" \"%s\"",
   12924                    GetRegConfig()->GetGeneralRegisterName(assigned_reg));
   12925       }
   12926     } else if (range->IsSpilled()) {
   12927       LOperand* op = range->TopLevel()->GetSpillOperand();
   12928       if (op->IsDoubleStackSlot()) {
   12929         trace_.Add(" \"double_stack:%d\"", op->index());
   12930       } else {
   12931         DCHECK(op->IsStackSlot());
   12932         trace_.Add(" \"stack:%d\"", op->index());
   12933       }
   12934     }
   12935     int parent_index = -1;
   12936     if (range->IsChild()) {
   12937       parent_index = range->parent()->id();
   12938     } else {
   12939       parent_index = range->id();
   12940     }
   12941     LOperand* op = range->FirstHint();
   12942     int hint_index = -1;
   12943     if (op != NULL && op->IsUnallocated()) {
   12944       hint_index = LUnallocated::cast(op)->virtual_register();
   12945     }
   12946     trace_.Add(" %d %d", parent_index, hint_index);
   12947     UseInterval* cur_interval = range->first_interval();
   12948     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
   12949       trace_.Add(" [%d, %d[",
   12950                  cur_interval->start().Value(),
   12951                  cur_interval->end().Value());
   12952       cur_interval = cur_interval->next();
   12953     }
   12954 
   12955     UsePosition* current_pos = range->first_pos();
   12956     while (current_pos != NULL) {
   12957       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
   12958         trace_.Add(" %d M", current_pos->pos().Value());
   12959       }
   12960       current_pos = current_pos->next();
   12961     }
   12962 
   12963     trace_.Add(" \"\"\n");
   12964   }
   12965 }
   12966 
   12967 
   12968 void HTracer::FlushToFile() {
   12969   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
   12970               false);
   12971   trace_.Reset();
   12972 }
   12973 
   12974 
   12975 void HStatistics::Initialize(CompilationInfo* info) {
   12976   if (!info->has_shared_info()) return;
   12977   source_size_ += info->shared_info()->SourceSize();
   12978 }
   12979 
   12980 
   12981 void HStatistics::Print() {
   12982   PrintF(
   12983       "\n"
   12984       "----------------------------------------"
   12985       "----------------------------------------\n"
   12986       "--- Hydrogen timing results:\n"
   12987       "----------------------------------------"
   12988       "----------------------------------------\n");
   12989   base::TimeDelta sum;
   12990   for (int i = 0; i < times_.length(); ++i) {
   12991     sum += times_[i];
   12992   }
   12993 
   12994   for (int i = 0; i < names_.length(); ++i) {
   12995     PrintF("%33s", names_[i]);
   12996     double ms = times_[i].InMillisecondsF();
   12997     double percent = times_[i].PercentOf(sum);
   12998     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
   12999 
   13000     size_t size = sizes_[i];
   13001     double size_percent = static_cast<double>(size) * 100 / total_size_;
   13002     PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
   13003   }
   13004 
   13005   PrintF(
   13006       "----------------------------------------"
   13007       "----------------------------------------\n");
   13008   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
   13009   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
   13010          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
   13011   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
   13012          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
   13013   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
   13014          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
   13015   PrintF(
   13016       "----------------------------------------"
   13017       "----------------------------------------\n");
   13018   PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
   13019          total.InMillisecondsF(), total_size_);
   13020   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
   13021          total.TimesOf(full_code_gen_));
   13022 
   13023   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
   13024   double normalized_time =  source_size_in_kb > 0
   13025       ? total.InMillisecondsF() / source_size_in_kb
   13026       : 0;
   13027   double normalized_size_in_kb =
   13028       source_size_in_kb > 0
   13029           ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
   13030           : 0;
   13031   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
   13032          "Average per kB source", normalized_time, normalized_size_in_kb);
   13033 }
   13034 
   13035 
   13036 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
   13037                              size_t size) {
   13038   total_size_ += size;
   13039   for (int i = 0; i < names_.length(); ++i) {
   13040     if (strcmp(names_[i], name) == 0) {
   13041       times_[i] += time;
   13042       sizes_[i] += size;
   13043       return;
   13044     }
   13045   }
   13046   names_.Add(name);
   13047   times_.Add(time);
   13048   sizes_.Add(size);
   13049 }
   13050 
   13051 
   13052 HPhase::~HPhase() {
   13053   if (ShouldProduceTraceOutput()) {
   13054     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
   13055   }
   13056 
   13057 #ifdef DEBUG
   13058   graph_->Verify(false);  // No full verify.
   13059 #endif
   13060 }
   13061 
   13062 }  // namespace internal
   13063 }  // namespace v8
   13064