LCOV - code coverage report
Current view: top level - src/crankshaft - hydrogen.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 4364 4969 87.8 %
Date: 2017-04-26 Functions: 377 490 76.9 %

          Line data    Source code
       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           0 : class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder {
      75             :  public:
      76         119 :   explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
      77         119 :       : HOptimizedGraphBuilder(info, true) {
      78         238 :     SetSourcePosition(info->shared_info()->start_position());
      79         119 :   }
      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        6360 :   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        2834 :   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         100 :   DECLARATION_NODE_LIST(DEF_VISIT)
     116             : #undef DEF_VISIT
     117             : };
     118             : 
     119      265576 : HCompilationJob::Status HCompilationJob::PrepareJobImpl() {
     120     3648443 :   if (!isolate()->use_crankshaft() ||
     121      794768 :       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      529075 :   bool should_recompile = !info()->shared_info()->has_deoptimization_support();
     132      264537 :   if (should_recompile || FLAG_hydrogen_stats) {
     133             :     base::ElapsedTimer timer;
     134      217357 :     if (FLAG_hydrogen_stats) {
     135             :       timer.Start();
     136             :     }
     137      217357 :     if (!Compiler::EnsureDeoptimizationSupport(info())) {
     138             :       return FAILED;
     139             :     }
     140      216949 :     if (FLAG_hydrogen_stats) {
     141           0 :       isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
     142             :     }
     143             :   }
     144             :   DCHECK(info()->shared_info()->has_deoptimization_support());
     145             : 
     146             :   // Check the whitelist for Crankshaft.
     147      792388 :   if (!info()->shared_info()->PassesFilter(FLAG_hydrogen_filter)) {
     148          97 :     return AbortOptimization(kHydrogenFilter);
     149             :   }
     150             : 
     151      266466 :   Scope* scope = info()->scope();
     152      264033 :   if (LUnallocated::TooManyParameters(scope->num_parameters())) {
     153             :     // Crankshaft would require too many Lithium operands.
     154           3 :     return AbortOptimization(kTooManyParameters);
     155             :   }
     156             : 
     157      266462 :   if (info()->is_osr() &&
     158             :       LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
     159        2433 :                                                   scope->num_stack_slots())) {
     160             :     // Crankshaft would require too many Lithium operands.
     161           0 :     return AbortOptimization(kTooManyParametersLocals);
     162             :   }
     163             : 
     164      528059 :   if (IsGeneratorFunction(info()->shared_info()->kind())) {
     165             :     // Crankshaft does not support generators.
     166           0 :     return AbortOptimization(kGenerator);
     167             :   }
     168             : 
     169      264030 :   if (FLAG_trace_hydrogen) {
     170           0 :     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      528060 :   if (info()->shared_info()->optimization_disabled()) {
     176             :     return AbortOptimization(
     177        1194 :         info()->shared_info()->disable_optimization_reason());
     178             :   }
     179             : 
     180             :   HOptimizedGraphBuilder* graph_builder =
     181      263429 :       (FLAG_hydrogen_track_positions || isolate()->is_profiling() ||
     182             :        FLAG_trace_ic)
     183         238 :           ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
     184      790180 :           : 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     1053728 :       .Run();
     191             : 
     192      263433 :   graph_ = graph_builder->CreateGraph();
     193             : 
     194      263433 :   if (isolate()->has_pending_exception()) {
     195             :     return FAILED;
     196             :   }
     197             : 
     198      263432 :   if (graph_ == NULL) return FAILED;
     199             : 
     200      259782 :   if (info()->dependencies()->HasAborted()) {
     201             :     // Dependency has changed during graph creation. Let's try again later.
     202           0 :     return RetryOptimization(kBailedOutDueToDependencyChange);
     203             :   }
     204             : 
     205             :   return SUCCEEDED;
     206             : }
     207             : 
     208      259760 : HCompilationJob::Status HCompilationJob::ExecuteJobImpl() {
     209             :   DCHECK(graph_ != NULL);
     210      259760 :   BailoutReason bailout_reason = kNoReason;
     211             : 
     212      259760 :   if (graph_->Optimize(&bailout_reason)) {
     213      259713 :     chunk_ = LChunk::NewChunk(graph_);
     214      259714 :     if (chunk_ != NULL) return SUCCEEDED;
     215          46 :   } else if (bailout_reason != kNoReason) {
     216          46 :     info()->AbortOptimization(bailout_reason);
     217             :   }
     218             : 
     219             :   return FAILED;
     220             : }
     221             : 
     222      255333 : 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      255333 :     Handle<Code> optimized_code = chunk_->Codegen();
     232      255333 :     if (optimized_code.is_null()) {
     233      255333 :       if (info()->bailout_reason() == kNoReason) {
     234          33 :         return AbortOptimization(kCodeGenerationFailed);
     235             :       }
     236             :       return FAILED;
     237             :     }
     238      255300 :     RegisterWeakObjectsInOptimizedCode(optimized_code);
     239             :     info()->SetCode(optimized_code);
     240             :   }
     241             :   // Add to the weak list of optimized code objects.
     242      510600 :   info()->context()->native_context()->AddOptimizedCode(*info()->code());
     243      255300 :   return SUCCEEDED;
     244             : }
     245             : 
     246    23021437 : 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    23021437 :       is_ordered_(false) { }
     269             : 
     270             : 
     271      178417 : Isolate* HBasicBlock::isolate() const {
     272      178417 :   return graph_->isolate();
     273             : }
     274             : 
     275             : 
     276     1971674 : void HBasicBlock::MarkUnreachable() {
     277     1974674 :   is_reachable_ = false;
     278     1971674 : }
     279             : 
     280             : 
     281       61068 : void HBasicBlock::AttachLoopInformation() {
     282             :   DCHECK(!IsLoopHeader());
     283       61068 :   loop_information_ = new(zone()) HLoopInformation(this, zone());
     284       61068 : }
     285             : 
     286             : 
     287           0 : void HBasicBlock::DetachLoopInformation() {
     288             :   DCHECK(IsLoopHeader());
     289         758 :   loop_information_ = NULL;
     290           0 : }
     291             : 
     292             : 
     293      694560 : void HBasicBlock::AddPhi(HPhi* phi) {
     294             :   DCHECK(!IsStartBlock());
     295             :   phis_.Add(phi, zone());
     296      694560 :   phi->SetBlock(this);
     297      694560 : }
     298             : 
     299             : 
     300      378285 : void HBasicBlock::RemovePhi(HPhi* phi) {
     301             :   DCHECK(phi->block() == this);
     302             :   DCHECK(phis_.Contains(phi));
     303      378285 :   phi->Kill();
     304      378285 :   phis_.RemoveElement(phi);
     305      378285 :   phi->SetBlock(NULL);
     306      378285 : }
     307             : 
     308             : 
     309    29461534 : void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
     310             :   DCHECK(!IsStartBlock() || !IsFinished());
     311             :   DCHECK(!instr->IsLinked());
     312             :   DCHECK(!IsFinished());
     313             : 
     314    24859077 :   if (position.IsKnown()) {
     315             :     instr->set_position(position);
     316             :   }
     317    24859077 :   if (first_ == NULL) {
     318             :     DCHECK(last_environment() != NULL);
     319             :     DCHECK(!last_environment()->ast_id().IsNone());
     320     4602458 :     HBlockEntry* entry = new(zone()) HBlockEntry();
     321             :     entry->InitializeAsFirst(this);
     322     4602461 :     if (position.IsKnown()) {
     323             :       entry->set_position(position);
     324             :     } else {
     325             :       DCHECK(!FLAG_hydrogen_track_positions ||
     326             :              !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
     327             :     }
     328     4602461 :     first_ = last_ = entry;
     329             :   }
     330    24859081 :   instr->InsertAfter(last_);
     331    24859065 : }
     332             : 
     333             : 
     334      678608 : HPhi* HBasicBlock::AddNewPhi(int merged_index) {
     335      678608 :   if (graph()->IsInsideNoSideEffectsScope()) {
     336             :     merged_index = HPhi::kInvalidMergedIndex;
     337             :   }
     338      678608 :   HPhi* phi = new(zone()) HPhi(merged_index, zone());
     339      678608 :   AddPhi(phi);
     340      678608 :   return phi;
     341             : }
     342             : 
     343             : 
     344     4955043 : HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
     345    14865130 :                                        RemovableSimulate removable) {
     346             :   DCHECK(HasEnvironment());
     347     4955043 :   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     9910086 :       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     7834492 :   for (int i = 0; i < push_count; ++i) {
     364             :     instr->AddPushedValue(environment->ExpressionStackAt(i));
     365             :   }
     366    10870537 :   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
     367     4955044 :                                       zone());
     368             :        !it.Done();
     369             :        it.Advance()) {
     370             :     int index = it.Current();
     371             :     instr->AddAssignedValue(index, environment->Lookup(index));
     372             :   }
     373             :   environment->ClearHistory();
     374     4955046 :   return instr;
     375             : }
     376             : 
     377             : 
     378     4598903 : void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
     379             :   DCHECK(!IsFinished());
     380     4598903 :   AddInstruction(end, position);
     381     4598903 :   end_ = end;
     382     9825297 :   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
     383     5226394 :     it.Current()->RegisterPredecessor(this);
     384             :   }
     385     4598903 : }
     386             : 
     387             : 
     388     2983096 : void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
     389     6216680 :                        FunctionState* state, bool add_simulate) {
     390     4653698 :   bool drop_extra = state != NULL &&
     391             :       state->inlining_kind() == NORMAL_RETURN;
     392             : 
     393     2983096 :   if (block->IsInlineReturnTarget()) {
     394             :     HEnvironment* env = last_environment();
     395      520993 :     int argument_count = env->arguments_environment()->parameter_count();
     396             :     AddInstruction(new(zone())
     397             :                    HLeaveInlined(state->entry(), argument_count),
     398      520993 :                    position);
     399     1041986 :     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
     400             :   }
     401             : 
     402     2983096 :   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
     403             :   HGoto* instr = new(zone()) HGoto(block);
     404     2983095 :   Finish(instr, position);
     405     2983095 : }
     406             : 
     407             : 
     408       80016 : void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
     409      200040 :                                   SourcePosition position) {
     410             :   HBasicBlock* target = state->function_return();
     411       40008 :   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
     412             : 
     413             :   DCHECK(target->IsInlineReturnTarget());
     414             :   DCHECK(return_value != NULL);
     415             :   HEnvironment* env = last_environment();
     416       40008 :   int argument_count = env->arguments_environment()->parameter_count();
     417             :   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
     418       40008 :                  position);
     419       80016 :   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
     420             :   last_environment()->Push(return_value);
     421       40008 :   AddNewSimulate(BailoutId::None(), position);
     422             :   HGoto* instr = new(zone()) HGoto(target);
     423       40008 :   Finish(instr, position);
     424       40008 : }
     425             : 
     426             : 
     427           0 : void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
     428             :   DCHECK(!HasEnvironment());
     429             :   DCHECK(first() == NULL);
     430             :   UpdateEnvironment(env);
     431           0 : }
     432             : 
     433             : 
     434    15591853 : void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
     435    10432202 :   last_environment_ = env;
     436             :   graph()->update_maximum_environment_size(env->first_expression_index());
     437     5159651 : }
     438             : 
     439             : 
     440       25915 : void HBasicBlock::SetJoinId(BailoutId ast_id) {
     441     1819799 :   int length = predecessors_.length();
     442             :   DCHECK(length > 0);
     443     2522179 :   for (int i = 0; i < length; i++) {
     444     4992528 :     HBasicBlock* predecessor = predecessors_[i];
     445             :     DCHECK(predecessor->end()->IsGoto());
     446     2496264 :     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       25915 : }
     455             : 
     456             : 
     457      364358 : bool HBasicBlock::Dominates(HBasicBlock* other) const {
     458     4982570 :   HBasicBlock* current = other->dominator();
     459     5688725 :   while (current != NULL) {
     460     5334225 :     if (current == this) return true;
     461             :     current = current->dominator();
     462             :   }
     463             :   return false;
     464             : }
     465             : 
     466             : 
     467       30064 : bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
     468       30064 :   if (this == other) return true;
     469       22561 :   return Dominates(other);
     470             : }
     471             : 
     472             : 
     473           0 : int HBasicBlock::LoopNestingDepth() const {
     474           0 :   const HBasicBlock* current = this;
     475           0 :   int result  = (current->IsLoopHeader()) ? 1 : 0;
     476           0 :   while (current->parent_loop_header() != NULL) {
     477             :     current = current->parent_loop_header();
     478           0 :     result++;
     479             :   }
     480           0 :   return result;
     481             : }
     482             : 
     483             : 
     484       89606 : void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
     485             :   DCHECK(IsLoopHeader());
     486             : 
     487             :   SetJoinId(stmt->EntryId());
     488       45182 :   if (predecessors()->length() == 1) {
     489             :     // This is a degenerated loop.
     490             :     DetachLoopInformation();
     491       45182 :     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       44424 :   for (int i = 1; i < predecessors()->length(); ++i) {
     497       88848 :     loop_information()->RegisterBackEdge(predecessors()->at(i));
     498             :   }
     499             : }
     500             : 
     501             : 
     502        3000 : void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
     503             :   DCHECK(IsFinished());
     504        3000 :   HBasicBlock* succ_block = end()->SuccessorAt(succ);
     505             : 
     506             :   DCHECK(succ_block->predecessors()->length() == 1);
     507             :   succ_block->MarkUnreachable();
     508        3000 : }
     509             : 
     510             : 
     511    18824968 : void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
     512     5226397 :   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     4114947 :     HEnvironment* incoming_env = pred->last_environment();
     518      909200 :     if (IsLoopHeader()) {
     519             :       DCHECK_EQ(phis()->length(), incoming_env->length());
     520      924564 :       for (int i = 0; i < phis_.length(); ++i) {
     521     1356861 :         phis_[i]->AddInput(incoming_env->values()->at(i));
     522             :       }
     523             :     } else {
     524      849230 :       last_environment()->AddIncomingEdge(this, pred->last_environment());
     525             :     }
     526     7522944 :   } else if (!HasEnvironment() && !IsFinished()) {
     527             :     DCHECK(!IsLoopHeader());
     528     3205747 :     SetInitialEnvironment(pred->last_environment()->Copy());
     529             :   }
     530             : 
     531             :   predecessors_.Add(pred, zone());
     532     5226391 : }
     533             : 
     534             : 
     535     9843774 : 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    15044168 :   while (index < dominated_blocks_.length() &&
     541     2600197 :          dominated_blocks_[index]->block_id() < block->block_id()) {
     542     2600197 :     ++index;
     543             :   }
     544             :   dominated_blocks_.InsertAt(index, block, zone());
     545     4921886 : }
     546             : 
     547             : 
     548     5864020 : void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
     549     5042293 :   if (dominator_ == NULL) {
     550     4220566 :     dominator_ = other;
     551     4220566 :     other->AddDominatedBlock(this);
     552      821727 :   } else if (other->dominator() != NULL) {
     553     6454651 :     HBasicBlock* first = dominator_;
     554     7826006 :     HBasicBlock* second = other;
     555             : 
     556     5581946 :     while (first != second) {
     557     4760219 :       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      821727 :     if (dominator_ != first) {
     566             :       DCHECK(dominator_->dominated_blocks_.Contains(this));
     567      701326 :       dominator_->dominated_blocks_.RemoveElement(this);
     568      701326 :       dominator_ = first;
     569      701326 :       first->AddDominatedBlock(this);
     570             :     }
     571             :   }
     572     5042291 : }
     573             : 
     574             : 
     575      119754 : 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     2343576 :   HBasicBlock* last = loop_information()->GetLastBackEdge();
     586             :   int outstanding_successors = 1;  // one edge from the pre-header
     587             :   // Header always dominates everything.
     588             :   MarkAsLoopSuccessorDominator();
     589     2179786 :   for (int j = block_id(); j <= last->block_id(); ++j) {
     590     6730697 :     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
     591     2317951 :     for (HPredecessorIterator it(dominator_candidate); !it.Done();
     592             :          it.Advance()) {
     593     1287935 :       HBasicBlock* predecessor = it.Current();
     594             :       // Don't count back edges.
     595     1287935 :       if (predecessor->block_id() < dominator_candidate->block_id()) {
     596     1218920 :         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     2308743 :     if (outstanding_successors == 0 &&
     611     1030016 :         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
     612             :       dominator_candidate->MarkAsLoopSuccessorDominator();
     613             :     }
     614             :     HControlInstruction* end = dominator_candidate->end();
     615     2352714 :     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
     616     1322698 :       HBasicBlock* successor = it.Current();
     617             :       // Only count successors that remain inside the loop and don't loop back
     618             :       // to a loop header.
     619     2576381 :       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     1159043 :         outstanding_successors++;
     625             :       }
     626             :     }
     627             :   }
     628       59877 : }
     629             : 
     630             : 
     631     5572481 : int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
     632    20877016 :   for (int i = 0; i < predecessors_.length(); ++i) {
     633    31315524 :     if (predecessors_[i] == predecessor) return i;
     634             :   }
     635           0 :   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       59970 : void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
     657       59970 :   this->back_edges_.Add(block, block->zone());
     658       59970 :   AddBlock(block);
     659       59970 : }
     660             : 
     661             : 
     662      374479 : HBasicBlock* HLoopInformation::GetLastBackEdge() const {
     663             :   int max_id = -1;
     664             :   HBasicBlock* result = NULL;
     665     1677547 :   for (int i = 0; i < back_edges_.length(); ++i) {
     666     1737424 :     HBasicBlock* cur = back_edges_[i];
     667      434356 :     if (cur->block_id() > max_id) {
     668             :       max_id = cur->block_id();
     669             :       result = cur;
     670             :     }
     671             :   }
     672      374479 :   return result;
     673             : }
     674             : 
     675             : 
     676     1094300 : void HLoopInformation::AddBlock(HBasicBlock* block) {
     677     1966889 :   if (block == loop_header()) return;
     678     1049777 :   if (block->parent_loop_header() == loop_header()) return;
     679      872589 :   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     1891146 :     for (int i = 0; i < block->predecessors()->length(); ++i) {
     685     1034330 :       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      562332 : HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
     825      651268 :                                int32_t value) {
     826      562332 :   if (!pointer->is_set()) {
     827             :     // Can't pass GetInvalidContext() to HConstant::New, because that will
     828             :     // recursively call GetConstant
     829      325634 :     HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
     830      325634 :     constant->InsertAfter(entry_block()->first());
     831             :     pointer->set(constant);
     832      325634 :     return constant;
     833             :   }
     834      236699 :   return ReinsertConstantIfNecessary(pointer->get());
     835             : }
     836             : 
     837             : 
     838           8 : HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
     839     5335887 :   if (!constant->IsLinked()) {
     840             :     // The constant was removed from the graph. Reinsert.
     841             :     constant->ClearFlag(HValue::kIsDead);
     842           8 :     constant->InsertAfter(entry_block()->first());
     843             :   }
     844           0 :   return constant;
     845             : }
     846             : 
     847             : 
     848       34152 : HConstant* HGraph::GetConstant0() {
     849      449675 :   return GetConstant(&constant_0_, 0);
     850             : }
     851             : 
     852             : 
     853         312 : HConstant* HGraph::GetConstant1() {
     854       94501 :   return GetConstant(&constant_1_, 1);
     855             : }
     856             : 
     857             : 
     858           0 : HConstant* HGraph::GetConstantMinus1() {
     859       16963 :   return GetConstant(&constant_minus1_, -1);
     860             : }
     861             : 
     862             : 
     863           2 : HConstant* HGraph::GetConstantBool(bool value) {
     864           2 :   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     3973725 : DEFINE_GET_CONSTANT(Undefined, undefined, undefined_value, undefined,
     883             :                     HType::Undefined(), false, true)
     884      207681 : DEFINE_GET_CONSTANT(True, true, true_value, boolean, HType::Boolean(), true,
     885             :                     false)
     886      188058 : DEFINE_GET_CONSTANT(False, false, false_value, boolean, HType::Boolean(), false,
     887             :                     false)
     888    11161206 : DEFINE_GET_CONSTANT(Hole, the_hole, the_hole_value, the_hole, HType::None(),
     889             :                     false, false)
     890       29433 : DEFINE_GET_CONSTANT(Null, null, null_value, null, HType::Null(), false, true)
     891     1605693 : 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      347292 : DEFINE_IS_CONSTANT(Undefined, undefined)
     901      340064 : DEFINE_IS_CONSTANT(0, 0)
     902      335231 : DEFINE_IS_CONSTANT(1, 1)
     903      331402 : DEFINE_IS_CONSTANT(Minus1, minus1)
     904      331000 : DEFINE_IS_CONSTANT(True, true)
     905      310649 : DEFINE_IS_CONSTANT(False, false)
     906      309718 : DEFINE_IS_CONSTANT(Hole, the_hole)
     907      307304 : DEFINE_IS_CONSTANT(Null, null)
     908             : 
     909             : #undef DEFINE_IS_CONSTANT
     910             : 
     911             : 
     912        1194 : HConstant* HGraph::GetInvalidContext() {
     913        1194 :   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
     914             : }
     915             : 
     916             : 
     917      347292 : bool HGraph::IsStandardConstant(HConstant* constant) {
     918      347292 :   if (IsConstantUndefined(constant)) return true;
     919      340064 :   if (IsConstant0(constant)) return true;
     920      335231 :   if (IsConstant1(constant)) return true;
     921      331402 :   if (IsConstantMinus1(constant)) return true;
     922      331000 :   if (IsConstantTrue(constant)) return true;
     923      310649 :   if (IsConstantFalse(constant)) return true;
     924      309718 :   if (IsConstantHole(constant)) return true;
     925      307304 :   if (IsConstantNull(constant)) return true;
     926      307184 :   return false;
     927             : }
     928             : 
     929             : 
     930           0 : HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
     931             : 
     932             : 
     933       14110 : HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
     934      102983 :     : needs_compare_(true) {
     935      102983 :   Initialize(builder);
     936       14110 : }
     937             : 
     938             : 
     939           0 : HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
     940             :                                     HIfContinuation* continuation)
     941        5174 :     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
     942             :   InitializeDontCreateBlocks(builder);
     943             :   continuation->Continue(&first_true_block_, &first_false_block_);
     944           0 : }
     945             : 
     946             : 
     947           0 : void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
     948             :     HGraphBuilder* builder) {
     949      108157 :   builder_ = builder;
     950      108157 :   finished_ = false;
     951      108157 :   did_then_ = false;
     952      108157 :   did_else_ = false;
     953      108157 :   did_else_if_ = false;
     954      108157 :   did_and_ = false;
     955      108157 :   did_or_ = false;
     956      108157 :   captured_ = false;
     957      108157 :   pending_merge_block_ = false;
     958      108157 :   split_edge_merge_block_ = NULL;
     959      108157 :   merge_at_join_blocks_ = NULL;
     960      108157 :   normal_merge_at_join_block_count_ = 0;
     961      108157 :   deopt_merge_at_join_block_count_ = 0;
     962           0 : }
     963             : 
     964             : 
     965      102983 : void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
     966             :   InitializeDontCreateBlocks(builder);
     967             :   HEnvironment* env = builder->environment();
     968      102983 :   first_true_block_ = builder->CreateBasicBlock(env->Copy());
     969      102983 :   first_false_block_ = builder->CreateBasicBlock(env->Copy());
     970      102983 : }
     971             : 
     972             : 
     973      127968 : HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
     974      177938 :     HControlInstruction* compare) {
     975             :   DCHECK(did_then_ == did_else_);
     976      127968 :   if (did_else_) {
     977             :     // Handle if-then-elseif
     978           0 :     did_else_if_ = true;
     979           0 :     did_else_ = false;
     980           0 :     did_then_ = false;
     981           0 :     did_and_ = false;
     982           0 :     did_or_ = false;
     983           0 :     pending_merge_block_ = false;
     984           0 :     split_edge_merge_block_ = NULL;
     985             :     HEnvironment* env = builder()->environment();
     986           0 :     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
     987           0 :     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
     988             :   }
     989      127968 :   if (split_edge_merge_block_ != NULL) {
     990       24985 :     HEnvironment* env = first_false_block_->last_environment();
     991       49970 :     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
     992       24985 :     if (did_or_) {
     993       16818 :       compare->SetSuccessorAt(0, split_edge);
     994       16818 :       compare->SetSuccessorAt(1, first_false_block_);
     995             :     } else {
     996        8167 :       compare->SetSuccessorAt(0, first_true_block_);
     997        8167 :       compare->SetSuccessorAt(1, split_edge);
     998             :     }
     999       24985 :     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
    1000             :   } else {
    1001      102983 :     compare->SetSuccessorAt(0, first_true_block_);
    1002      102983 :     compare->SetSuccessorAt(1, first_false_block_);
    1003             :   }
    1004      127968 :   builder()->FinishCurrentBlock(compare);
    1005      127968 :   needs_compare_ = false;
    1006      127968 :   return compare;
    1007             : }
    1008             : 
    1009             : 
    1010       84070 : void HGraphBuilder::IfBuilder::Or() {
    1011             :   DCHECK(!needs_compare_);
    1012             :   DCHECK(!did_and_);
    1013       16818 :   did_or_ = true;
    1014       16818 :   HEnvironment* env = first_false_block_->last_environment();
    1015       16818 :   if (split_edge_merge_block_ == NULL) {
    1016       33616 :     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    1017       16808 :     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
    1018       16808 :     first_true_block_ = split_edge_merge_block_;
    1019             :   }
    1020       16818 :   builder()->set_current_block(first_false_block_);
    1021       33636 :   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
    1022       16818 : }
    1023             : 
    1024             : 
    1025       40835 : void HGraphBuilder::IfBuilder::And() {
    1026             :   DCHECK(!needs_compare_);
    1027             :   DCHECK(!did_or_);
    1028        8167 :   did_and_ = true;
    1029        8167 :   HEnvironment* env = first_false_block_->last_environment();
    1030        8167 :   if (split_edge_merge_block_ == NULL) {
    1031       16334 :     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    1032        8167 :     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
    1033        8167 :     first_false_block_ = split_edge_merge_block_;
    1034             :   }
    1035        8167 :   builder()->set_current_block(first_true_block_);
    1036       16334 :   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    1037        8167 : }
    1038             : 
    1039             : 
    1040         843 : void HGraphBuilder::IfBuilder::CaptureContinuation(
    1041         843 :     HIfContinuation* continuation) {
    1042             :   DCHECK(!did_else_if_);
    1043             :   DCHECK(!finished_);
    1044             :   DCHECK(!captured_);
    1045             : 
    1046         843 :   HBasicBlock* true_block = NULL;
    1047         843 :   HBasicBlock* false_block = NULL;
    1048         843 :   Finish(&true_block, &false_block);
    1049             :   DCHECK(true_block != NULL);
    1050             :   DCHECK(false_block != NULL);
    1051         843 :   continuation->Capture(true_block, false_block);
    1052         843 :   captured_ = true;
    1053             :   builder()->set_current_block(NULL);
    1054         843 :   End();
    1055         843 : }
    1056             : 
    1057             : 
    1058       30216 : void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
    1059             :   DCHECK(!did_else_if_);
    1060             :   DCHECK(!finished_);
    1061             :   DCHECK(!captured_);
    1062       12516 :   HBasicBlock* true_block = NULL;
    1063       12516 :   HBasicBlock* false_block = NULL;
    1064       12516 :   Finish(&true_block, &false_block);
    1065       12516 :   merge_at_join_blocks_ = NULL;
    1066       12516 :   if (true_block != NULL && !true_block->IsFinished()) {
    1067             :     DCHECK(continuation->IsTrueReachable());
    1068             :     builder()->GotoNoSimulate(true_block, continuation->true_branch());
    1069             :   }
    1070       12516 :   if (false_block != NULL && !false_block->IsFinished()) {
    1071             :     DCHECK(continuation->IsFalseReachable());
    1072             :     builder()->GotoNoSimulate(false_block, continuation->false_branch());
    1073             :   }
    1074       12516 :   captured_ = true;
    1075       12516 :   End();
    1076       12516 : }
    1077             : 
    1078             : 
    1079      216314 : void HGraphBuilder::IfBuilder::Then() {
    1080             :   DCHECK(!captured_);
    1081             :   DCHECK(!finished_);
    1082      108157 :   did_then_ = true;
    1083      108157 :   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           0 :     HConstant* constant_false = builder()->graph()->GetConstantFalse();
    1089             :     ToBooleanHints boolean_type = ToBooleanHint::kBoolean;
    1090             :     HBranch* branch = builder()->New<HBranch>(
    1091           0 :         constant_false, boolean_type, first_true_block_, first_false_block_);
    1092           0 :     builder()->FinishCurrentBlock(branch);
    1093             :   }
    1094      108157 :   builder()->set_current_block(first_true_block_);
    1095      108157 :   pending_merge_block_ = true;
    1096      108157 : }
    1097             : 
    1098             : 
    1099      122212 : void HGraphBuilder::IfBuilder::Else() {
    1100             :   DCHECK(did_then_);
    1101             :   DCHECK(!captured_);
    1102             :   DCHECK(!finished_);
    1103      108157 :   AddMergeAtJoinBlock(false);
    1104      108157 :   builder()->set_current_block(first_false_block_);
    1105      108157 :   pending_merge_block_ = true;
    1106      108157 :   did_else_ = true;
    1107       14055 : }
    1108             : 
    1109        6964 : void HGraphBuilder::IfBuilder::Deopt(DeoptimizeReason reason) {
    1110             :   DCHECK(did_then_);
    1111        6964 :   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
    1112        6964 :   AddMergeAtJoinBlock(true);
    1113        6964 : }
    1114             : 
    1115             : 
    1116       41157 : void HGraphBuilder::IfBuilder::Return(HValue* value) {
    1117       13719 :   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
    1118             :   builder()->FinishExitCurrentBlock(
    1119       27438 :       builder()->New<HReturn>(value, parameter_count));
    1120       13719 :   AddMergeAtJoinBlock(false);
    1121       13719 : }
    1122             : 
    1123             : 
    1124      683185 : void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
    1125      501114 :   if (!pending_merge_block_) return;
    1126      216314 :   HBasicBlock* block = builder()->current_block();
    1127             :   DCHECK(block == NULL || !block->IsFinished());
    1128      216314 :   MergeAtJoinBlock* record = new (builder()->zone())
    1129      216314 :       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
    1130      216314 :   merge_at_join_blocks_ = record;
    1131      216314 :   if (block != NULL) {
    1132             :     DCHECK(block->end() == NULL);
    1133      194923 :     if (deopt) {
    1134        6964 :       normal_merge_at_join_block_count_++;
    1135             :     } else {
    1136      187959 :       deopt_merge_at_join_block_count_++;
    1137             :     }
    1138             :   }
    1139             :   builder()->set_current_block(NULL);
    1140      216314 :   pending_merge_block_ = false;
    1141             : }
    1142             : 
    1143             : 
    1144      108157 : void HGraphBuilder::IfBuilder::Finish() {
    1145             :   DCHECK(!finished_);
    1146      108157 :   if (!did_then_) {
    1147         853 :     Then();
    1148             :   }
    1149      108157 :   AddMergeAtJoinBlock(false);
    1150      108157 :   if (!did_else_) {
    1151             :     Else();
    1152       13560 :     AddMergeAtJoinBlock(false);
    1153             :   }
    1154      108157 :   finished_ = true;
    1155      108157 : }
    1156             : 
    1157             : 
    1158       13359 : void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
    1159             :                                       HBasicBlock** else_continuation) {
    1160       13359 :   Finish();
    1161             : 
    1162       13359 :   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
    1163       13359 :   if (else_continuation != NULL) {
    1164       13359 :     *else_continuation = else_record->block_;
    1165             :   }
    1166       13359 :   MergeAtJoinBlock* then_record = else_record->next_;
    1167       13359 :   if (then_continuation != NULL) {
    1168       13359 :     *then_continuation = then_record->block_;
    1169             :   }
    1170             :   DCHECK(then_record->next_ == NULL);
    1171       13359 : }
    1172             : 
    1173             : 
    1174           0 : void HGraphBuilder::IfBuilder::EndUnreachable() {
    1175           0 :   if (captured_) return;
    1176           0 :   Finish();
    1177             :   builder()->set_current_block(nullptr);
    1178             : }
    1179             : 
    1180             : 
    1181      445172 : void HGraphBuilder::IfBuilder::End() {
    1182      108157 :   if (captured_) return;
    1183       94798 :   Finish();
    1184             : 
    1185       94798 :   int total_merged_blocks = normal_merge_at_join_block_count_ +
    1186       94798 :     deopt_merge_at_join_block_count_;
    1187             :   DCHECK(total_merged_blocks >= 1);
    1188             :   HBasicBlock* merge_block =
    1189      175537 :       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       94798 :   MergeAtJoinBlock* current = merge_at_join_blocks_;
    1194      351074 :   while (current != NULL) {
    1195      175537 :     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      173366 :       if (total_merged_blocks == 1) {
    1200             :         builder()->set_current_block(current->block_);
    1201             :         return;
    1202             :       }
    1203             :       builder()->GotoNoSimulate(current->block_, merge_block);
    1204             :     }
    1205      161478 :     current = current->next_;
    1206             :   }
    1207             : 
    1208             :   // Merge deopt blocks, padding when necessary.
    1209       80739 :   current = merge_at_join_blocks_;
    1210      322956 :   while (current != NULL) {
    1211      161478 :     if (current->deopt_ && current->block_ != NULL) {
    1212             :       current->block_->FinishExit(
    1213        4342 :           HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
    1214        2171 :           SourcePosition::Unknown());
    1215             :     }
    1216      161478 :     current = current->next_;
    1217             :   }
    1218             :   builder()->set_current_block(merge_block);
    1219             : }
    1220             : 
    1221             : 
    1222           0 : HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
    1223             :   Initialize(builder, NULL, kWhileTrue, NULL);
    1224           0 : }
    1225             : 
    1226             : 
    1227       15546 : HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
    1228             :                                         LoopBuilder::Direction direction) {
    1229             :   Initialize(builder, context, direction, builder->graph()->GetConstant1());
    1230       15546 : }
    1231             : 
    1232             : 
    1233           0 : HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
    1234             :                                         LoopBuilder::Direction direction,
    1235             :                                         HValue* increment_amount) {
    1236             :   Initialize(builder, context, direction, increment_amount);
    1237           0 :   increment_amount_ = increment_amount;
    1238           0 : }
    1239             : 
    1240             : 
    1241           0 : void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
    1242             :                                             HValue* context,
    1243             :                                             Direction direction,
    1244             :                                             HValue* increment_amount) {
    1245       15546 :   builder_ = builder;
    1246       15546 :   context_ = context;
    1247       15546 :   direction_ = direction;
    1248       15546 :   increment_amount_ = increment_amount;
    1249             : 
    1250       15546 :   finished_ = false;
    1251       15546 :   header_block_ = builder->CreateLoopHeaderBlock();
    1252       15546 :   body_block_ = NULL;
    1253       15546 :   exit_block_ = NULL;
    1254       15546 :   exit_trampoline_block_ = NULL;
    1255           0 : }
    1256             : 
    1257             : 
    1258       15546 : HValue* HGraphBuilder::LoopBuilder::BeginBody(
    1259             :     HValue* initial,
    1260             :     HValue* terminating,
    1261          82 :     Token::Value token) {
    1262             :   DCHECK(direction_ != kWhileTrue);
    1263       15628 :   HEnvironment* env = builder_->environment();
    1264       15546 :   phi_ = header_block_->AddNewPhi(env->values()->length());
    1265       15546 :   phi_->AddInput(initial);
    1266             :   env->Push(initial);
    1267       15546 :   builder_->GotoNoSimulate(header_block_);
    1268             : 
    1269       15546 :   HEnvironment* body_env = env->Copy();
    1270       15546 :   HEnvironment* exit_env = env->Copy();
    1271             :   // Remove the phi from the expression stack
    1272       15546 :   body_env->Pop();
    1273       15546 :   exit_env->Pop();
    1274       15546 :   body_block_ = builder_->CreateBasicBlock(body_env);
    1275       15546 :   exit_block_ = builder_->CreateBasicBlock(exit_env);
    1276             : 
    1277       15546 :   builder_->set_current_block(header_block_);
    1278       15546 :   env->Pop();
    1279             :   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
    1280       15546 :           phi_, terminating, token, body_block_, exit_block_));
    1281             : 
    1282       15546 :   builder_->set_current_block(body_block_);
    1283       15546 :   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
    1284          82 :     Isolate* isolate = builder_->isolate();
    1285             :     HValue* one = builder_->graph()->GetConstant1();
    1286          82 :     if (direction_ == kPreIncrement) {
    1287           0 :       increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
    1288             :     } else {
    1289         164 :       increment_ = HSub::New(isolate, zone(), context_, phi_, one);
    1290             :     }
    1291          82 :     increment_->ClearFlag(HValue::kCanOverflow);
    1292          82 :     builder_->AddInstruction(increment_);
    1293          82 :     return increment_;
    1294             :   } else {
    1295       15464 :     return phi_;
    1296             :   }
    1297             : }
    1298             : 
    1299             : 
    1300           0 : void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
    1301             :   DCHECK(direction_ == kWhileTrue);
    1302           0 :   HEnvironment* env = builder_->environment();
    1303           0 :   builder_->GotoNoSimulate(header_block_);
    1304           0 :   builder_->set_current_block(header_block_);
    1305             :   env->Drop(drop_count);
    1306           0 : }
    1307             : 
    1308             : 
    1309         340 : void HGraphBuilder::LoopBuilder::Break() {
    1310         340 :   if (exit_trampoline_block_ == NULL) {
    1311             :     // Its the first time we saw a break.
    1312         340 :     if (direction_ == kWhileTrue) {
    1313           0 :       HEnvironment* env = builder_->environment()->Copy();
    1314           0 :       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
    1315             :     } else {
    1316         340 :       HEnvironment* env = exit_block_->last_environment()->Copy();
    1317         340 :       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
    1318         340 :       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
    1319             :     }
    1320             :   }
    1321             : 
    1322         340 :   builder_->GotoNoSimulate(exit_trampoline_block_);
    1323         340 :   builder_->set_current_block(NULL);
    1324         340 : }
    1325             : 
    1326             : 
    1327       15546 : void HGraphBuilder::LoopBuilder::EndBody() {
    1328             :   DCHECK(!finished_);
    1329             : 
    1330       15546 :   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
    1331       31010 :     Isolate* isolate = builder_->isolate();
    1332       15464 :     if (direction_ == kPostIncrement) {
    1333             :       increment_ =
    1334       29276 :           HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
    1335             :     } else {
    1336             :       increment_ =
    1337        1652 :           HSub::New(isolate, zone(), context_, phi_, increment_amount_);
    1338             :     }
    1339       15464 :     increment_->ClearFlag(HValue::kCanOverflow);
    1340       15464 :     builder_->AddInstruction(increment_);
    1341             :   }
    1342             : 
    1343       15546 :   if (direction_ != kWhileTrue) {
    1344             :     // Push the new increment value on the expression stack to merge into
    1345             :     // the phi.
    1346       15546 :     builder_->environment()->Push(increment_);
    1347             :   }
    1348       15546 :   HBasicBlock* last_block = builder_->current_block();
    1349       31092 :   builder_->GotoNoSimulate(last_block, header_block_);
    1350       31092 :   header_block_->loop_information()->RegisterBackEdge(last_block);
    1351             : 
    1352       15546 :   if (exit_trampoline_block_ != NULL) {
    1353         340 :     builder_->set_current_block(exit_trampoline_block_);
    1354             :   } else {
    1355       15206 :     builder_->set_current_block(exit_block_);
    1356             :   }
    1357       15546 :   finished_ = true;
    1358       15546 : }
    1359             : 
    1360             : 
    1361     1144013 : HGraph* HGraphBuilder::CreateGraph() {
    1362             :   DCHECK(!FLAG_minimal);
    1363      573831 :   graph_ = new (zone()) HGraph(info_, descriptor_);
    1364      286916 :   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
    1365      286916 :   CompilationPhase phase("H_Block building", info_);
    1366      286916 :   set_current_block(graph()->entry_block());
    1367      286916 :   if (!BuildGraph()) return NULL;
    1368      283265 :   graph()->FinalizeUniqueness();
    1369      283265 :   return graph_;
    1370             : }
    1371             : 
    1372             : 
    1373    33732890 : HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
    1374             :   DCHECK(current_block() != NULL);
    1375             :   DCHECK(!FLAG_hydrogen_track_positions || position_.IsKnown() ||
    1376             :          !info_->IsOptimizing());
    1377    16866447 :   current_block()->AddInstruction(instr, source_position());
    1378    16866443 :   if (graph()->IsInsideNoSideEffectsScope()) {
    1379             :     instr->SetFlag(HValue::kHasNoObservableSideEffects);
    1380             :   }
    1381    16866443 :   return instr;
    1382             : }
    1383             : 
    1384             : 
    1385     1218975 : void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
    1386             :   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
    1387             :          position_.IsKnown());
    1388     1218975 :   current_block()->Finish(last, source_position());
    1389     3633442 :   if (last->IsReturn() || last->IsAbnormalExit()) {
    1390             :     set_current_block(NULL);
    1391             :   }
    1392     1218975 : }
    1393             : 
    1394             : 
    1395      354654 : void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
    1396             :   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
    1397             :          position_.IsKnown());
    1398             :   current_block()->FinishExit(instruction, source_position());
    1399      722263 :   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
    1400             :     set_current_block(NULL);
    1401             :   }
    1402      354654 : }
    1403             : 
    1404             : 
    1405       54904 : void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
    1406       54904 :   if (FLAG_native_code_counters && counter->Enabled()) {
    1407           0 :     HValue* reference = Add<HConstant>(ExternalReference(counter));
    1408             :     HValue* old_value =
    1409           0 :         Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
    1410           0 :     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           0 :                           new_value, STORE_TO_INITIALIZED_ENTRY);
    1414             :   }
    1415       54904 : }
    1416             : 
    1417             : 
    1418           0 : void HGraphBuilder::AddSimulate(BailoutId id,
    1419      335797 :                                 RemovableSimulate removable) {
    1420             :   DCHECK(current_block() != NULL);
    1421             :   DCHECK(!graph()->IsInsideNoSideEffectsScope());
    1422      335797 :   current_block()->AddNewSimulate(id, source_position(), removable);
    1423           0 : }
    1424             : 
    1425             : 
    1426     1050384 : HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
    1427     1050384 :   HBasicBlock* b = graph()->CreateBasicBlock();
    1428             :   b->SetInitialEnvironment(env);
    1429     1050383 :   return b;
    1430             : }
    1431             : 
    1432             : 
    1433       61068 : HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
    1434       61068 :   HBasicBlock* header = graph()->CreateBasicBlock();
    1435       61068 :   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
    1436             :   header->SetInitialEnvironment(entry_env);
    1437       61068 :   header->AttachLoopInformation();
    1438       61068 :   return header;
    1439             : }
    1440             : 
    1441             : 
    1442          10 : HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
    1443          10 :   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
    1444             : 
    1445             :   HValue* bit_field2 =
    1446          10 :       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
    1447          10 :   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
    1448             : }
    1449             : 
    1450             : 
    1451        1078 : HValue* HGraphBuilder::BuildEnumLength(HValue* map) {
    1452             :   NoObservableSideEffectsScope scope(this);
    1453             :   HValue* bit_field3 =
    1454        1078 :       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
    1455        2156 :   return BuildDecodeField<Map::EnumLengthBits>(bit_field3);
    1456             : }
    1457             : 
    1458             : 
    1459           0 : HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
    1460      310748 :   if (obj->type().IsHeapObject()) return obj;
    1461      180870 :   return Add<HCheckHeapObject>(obj);
    1462             : }
    1463             : 
    1464        8229 : void HGraphBuilder::FinishExitWithHardDeoptimization(DeoptimizeReason reason) {
    1465        8229 :   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
    1466        8229 :   FinishExitCurrentBlock(New<HAbnormalExit>());
    1467        8229 : }
    1468             : 
    1469             : 
    1470       82211 : HValue* HGraphBuilder::BuildCheckString(HValue* string) {
    1471       82211 :   if (!string->type().IsString()) {
    1472             :     DCHECK(!string->IsConstant() ||
    1473             :            !HConstant::cast(string)->HasStringValue());
    1474             :     BuildCheckHeapObject(string);
    1475       31586 :     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
    1476             :   }
    1477             :   return string;
    1478             : }
    1479             : 
    1480        6215 : HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* checked) {
    1481        5493 :   if (object->type().IsJSObject()) return object;
    1482        5166 :   HValue* function = checked->ActualValue();
    1483       15498 :   if (function->IsConstant() &&
    1484        5888 :       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    1485             :     Handle<JSFunction> f = Handle<JSFunction>::cast(
    1486         361 :         HConstant::cast(function)->handle(isolate()));
    1487             :     SharedFunctionInfo* shared = f->shared();
    1488         615 :     if (is_strict(shared->language_mode()) || shared->native()) return object;
    1489             :   }
    1490        4925 :   return Add<HWrapReceiver>(object, checked);
    1491             : }
    1492             : 
    1493             : 
    1494           0 : HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(
    1495             :     HValue* object, HValue* elements, ElementsKind kind, HValue* length,
    1496             :     HValue* capacity, HValue* key) {
    1497           0 :   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
    1498           0 :   HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
    1499           0 :   Add<HBoundsCheck>(key, max_capacity);
    1500             : 
    1501           0 :   HValue* new_capacity = BuildNewElementsCapacity(key);
    1502             :   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, kind,
    1503           0 :                                                    length, new_capacity);
    1504           0 :   return new_elements;
    1505             : }
    1506             : 
    1507             : 
    1508        2593 : HValue* HGraphBuilder::BuildCheckForCapacityGrow(
    1509             :     HValue* object,
    1510             :     HValue* elements,
    1511             :     ElementsKind kind,
    1512             :     HValue* length,
    1513             :     HValue* key,
    1514             :     bool is_js_array,
    1515        3056 :     PropertyAccessType access_type) {
    1516             :   IfBuilder length_checker(this);
    1517             : 
    1518        2593 :   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
    1519        2593 :   length_checker.If<HCompareNumericAndBranch>(key, length, token);
    1520             : 
    1521        2593 :   length_checker.Then();
    1522             : 
    1523             :   HValue* current_capacity = AddLoadFixedArrayLength(elements);
    1524             : 
    1525        2593 :   if (top_info()->IsStub()) {
    1526             :     IfBuilder capacity_checker(this);
    1527             :     capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
    1528           0 :                                                   Token::GTE);
    1529           0 :     capacity_checker.Then();
    1530             :     HValue* new_elements = BuildCheckAndGrowElementsCapacity(
    1531           0 :         object, elements, kind, length, current_capacity, key);
    1532             :     environment()->Push(new_elements);
    1533             :     capacity_checker.Else();
    1534             :     environment()->Push(elements);
    1535           0 :     capacity_checker.End();
    1536             :   } else {
    1537             :     HValue* result = Add<HMaybeGrowElements>(
    1538        2593 :         object, elements, key, current_capacity, is_js_array, kind);
    1539             :     environment()->Push(result);
    1540             :   }
    1541             : 
    1542        2593 :   if (is_js_array) {
    1543        5170 :     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
    1544             :     new_length->ClearFlag(HValue::kCanOverflow);
    1545             : 
    1546             :     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
    1547        2585 :                           new_length);
    1548             :   }
    1549             : 
    1550        2593 :   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         463 :                      kind);
    1556             :   }
    1557             : 
    1558             :   length_checker.Else();
    1559        2593 :   Add<HBoundsCheck>(key, length);
    1560             : 
    1561             :   environment()->Push(elements);
    1562        2593 :   length_checker.End();
    1563             : 
    1564        5186 :   return environment()->Pop();
    1565             : }
    1566             : 
    1567             : 
    1568         237 : HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
    1569             :                                                 HValue* elements,
    1570             :                                                 ElementsKind kind,
    1571         237 :                                                 HValue* length) {
    1572             :   Factory* factory = isolate()->factory();
    1573             : 
    1574             :   IfBuilder cow_checker(this);
    1575             : 
    1576         237 :   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
    1577         237 :   cow_checker.Then();
    1578             : 
    1579             :   HValue* capacity = AddLoadFixedArrayLength(elements);
    1580             : 
    1581             :   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
    1582         237 :                                                    kind, length, capacity);
    1583             : 
    1584             :   environment()->Push(new_elements);
    1585             : 
    1586             :   cow_checker.Else();
    1587             : 
    1588             :   environment()->Push(elements);
    1589             : 
    1590         237 :   cow_checker.End();
    1591             : 
    1592         474 :   return environment()->Pop();
    1593             : }
    1594             : 
    1595           0 : HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
    1596           0 :   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
    1597           0 :   HValue* seed = Add<HConstant>(seed_value);
    1598           0 :   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
    1599             : 
    1600             :   // hash = ~hash + (hash << 15);
    1601           0 :   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
    1602             :   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
    1603           0 :                                            graph()->GetConstantMinus1());
    1604           0 :   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
    1605             : 
    1606             :   // hash = hash ^ (hash >> 12);
    1607           0 :   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
    1608           0 :   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
    1609             : 
    1610             :   // hash = hash + (hash << 2);
    1611           0 :   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
    1612           0 :   hash = AddUncasted<HAdd>(hash, shifted_hash);
    1613             : 
    1614             :   // hash = hash ^ (hash >> 4);
    1615           0 :   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
    1616           0 :   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
    1617             : 
    1618             :   // hash = hash * 2057;
    1619           0 :   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
    1620             :   hash->ClearFlag(HValue::kCanOverflow);
    1621             : 
    1622             :   // hash = hash ^ (hash >> 16);
    1623           0 :   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
    1624           0 :   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
    1625             : }
    1626             : 
    1627           0 : HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
    1628             :                                                            HValue* elements,
    1629             :                                                            HValue* key,
    1630           0 :                                                            HValue* hash) {
    1631             :   HValue* capacity =
    1632             :       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
    1633           0 :                       nullptr, nullptr, FAST_ELEMENTS);
    1634             : 
    1635           0 :   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           0 :   Push(entry);
    1642           0 :   Push(count);
    1643             : 
    1644             :   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
    1645           0 :                                               graph()->CreateBasicBlock());
    1646             :   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
    1647           0 :                                                graph()->CreateBasicBlock());
    1648             :   LoopBuilder probe_loop(this);
    1649           0 :   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           0 :   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
    1655             :   int entry_size = SeededNumberDictionary::kEntrySize;
    1656           0 :   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           0 :       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
    1661             :   key_index->ClearFlag(HValue::kCanOverflow);
    1662             : 
    1663             :   HValue* candidate_key =
    1664           0 :       Add<HLoadKeyed>(elements, key_index, nullptr, nullptr, FAST_ELEMENTS);
    1665             :   IfBuilder if_undefined(this);
    1666             :   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
    1667           0 :                                              graph()->GetConstantUndefined());
    1668           0 :   if_undefined.Then();
    1669             :   {
    1670             :     // element == undefined means "not found". Call the runtime.
    1671             :     // TODO(jkummerow): walk the prototype chain instead.
    1672           0 :     Add<HPushArguments>(receiver, key);
    1673             :     Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
    1674           0 :                            2));
    1675             :   }
    1676             :   if_undefined.Else();
    1677             :   {
    1678             :     IfBuilder if_match(this);
    1679           0 :     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
    1680           0 :     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           0 :     if_update_with_internalized.And();
    1688             :     HValue* map = AddLoadMap(candidate_key, smi_check);
    1689             :     HValue* instance_type =
    1690           0 :         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
    1691             :     HValue* not_internalized_bit = AddUncasted<HBitwise>(
    1692             :         Token::BIT_AND, instance_type,
    1693           0 :         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
    1694             :     if_update_with_internalized.If<HCompareNumericAndBranch>(
    1695           0 :         not_internalized_bit, graph()->GetConstant0(), Token::NE);
    1696           0 :     if_update_with_internalized.And();
    1697             :     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
    1698           0 :         candidate_key, graph()->GetConstantHole());
    1699             :     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
    1700             :                                                                key, Token::EQ);
    1701           0 :     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           0 :     Add<HStoreKeyed>(elements, key_index, key, nullptr, FAST_ELEMENTS);
    1705             :     if_update_with_internalized.Else();
    1706             : 
    1707           0 :     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
    1708           0 :     if_match.JoinContinuation(&found_key_match_continuation);
    1709             : 
    1710             :     IfBuilder found_key_match(this, &found_key_match_continuation);
    1711           0 :     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           0 :         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           0 :                                       FAST_ELEMENTS);
    1719             :     int details_mask = PropertyDetails::KindField::kMask;
    1720             :     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
    1721           0 :                                     Add<HConstant>(details_mask));
    1722             :     IfBuilder details_compare(this);
    1723             :     details_compare.If<HCompareNumericAndBranch>(details, New<HConstant>(kData),
    1724           0 :                                                  Token::EQ);
    1725           0 :     details_compare.Then();
    1726             :     HValue* result_index =
    1727           0 :         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           0 :                          FAST_ELEMENTS));
    1731             :     details_compare.Else();
    1732           0 :     Add<HPushArguments>(receiver, key);
    1733             :     Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
    1734           0 :                            2));
    1735           0 :     details_compare.End();
    1736             : 
    1737             :     found_key_match.Else();
    1738           0 :     found_key_match.JoinContinuation(&return_or_loop_continuation);
    1739             :   }
    1740           0 :   if_undefined.JoinContinuation(&return_or_loop_continuation);
    1741             : 
    1742             :   IfBuilder return_or_loop(this, &return_or_loop_continuation);
    1743           0 :   return_or_loop.Then();
    1744           0 :   probe_loop.Break();
    1745             : 
    1746             :   return_or_loop.Else();
    1747           0 :   entry = AddUncasted<HAdd>(entry, count);
    1748             :   entry->ClearFlag(HValue::kCanOverflow);
    1749           0 :   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
    1750             :   count->ClearFlag(HValue::kCanOverflow);
    1751           0 :   Push(entry);
    1752           0 :   Push(count);
    1753             : 
    1754           0 :   probe_loop.EndBody();
    1755             : 
    1756           0 :   return_or_loop.End();
    1757             : 
    1758           0 :   return Pop();
    1759             : }
    1760             : 
    1761           9 : 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           9 :                      NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0());
    1769             : 
    1770             :   // Initialize the JSIteratorResult object.
    1771           9 :   HValue* native_context = BuildGetNativeContext();
    1772             :   HValue* map = Add<HLoadNamedField>(
    1773             :       native_context, nullptr,
    1774           9 :       HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
    1775           9 :   Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
    1776           9 :   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
    1777             :   Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
    1778           9 :                         empty_fixed_array);
    1779             :   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
    1780           9 :                         empty_fixed_array);
    1781             :   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
    1782             :                                     JSIteratorResult::kValueOffset),
    1783           9 :                         value);
    1784             :   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
    1785             :                                     JSIteratorResult::kDoneOffset),
    1786           9 :                         done);
    1787             :   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
    1788           9 :   return result;
    1789             : }
    1790             : 
    1791             : 
    1792       41182 : HValue* HGraphBuilder::BuildNumberToString(HValue* object, AstType* type) {
    1793             :   NoObservableSideEffectsScope scope(this);
    1794             : 
    1795             :   // Convert constant numbers at compile time.
    1796        5631 :   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
    1797         409 :     Handle<Object> number = HConstant::cast(object)->handle(isolate());
    1798         409 :     Handle<String> result = isolate()->factory()->NumberToString(number);
    1799         409 :     return Add<HConstant>(result);
    1800             :   }
    1801             : 
    1802             :   // Create a joinable continuation.
    1803             :   HIfContinuation found(graph()->CreateBasicBlock(),
    1804        9586 :                         graph()->CreateBasicBlock());
    1805             : 
    1806             :   // Load the number string cache.
    1807             :   HValue* number_string_cache =
    1808        4793 :       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        4793 :   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
    1815        4793 :   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
    1816             : 
    1817             :   // Check whether object is a smi.
    1818             :   IfBuilder if_objectissmi(this);
    1819        4793 :   if_objectissmi.If<HIsSmiAndBranch>(object);
    1820        4793 :   if_objectissmi.Then();
    1821             :   {
    1822             :     // Compute hash for smi similar to smi_get_hash().
    1823        4793 :     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
    1824             : 
    1825             :     // Load the key.
    1826        4793 :     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
    1827             :     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
    1828        4793 :                                   nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE);
    1829             : 
    1830             :     // Check if object == key.
    1831             :     IfBuilder if_objectiskey(this);
    1832        4793 :     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
    1833        4793 :     if_objectiskey.Then();
    1834             :     {
    1835             :       // Make the key_index available.
    1836        4793 :       Push(key_index);
    1837             :     }
    1838        4793 :     if_objectiskey.JoinContinuation(&found);
    1839             :   }
    1840             :   if_objectissmi.Else();
    1841             :   {
    1842        4793 :     if (type->Is(AstType::SignedSmall())) {
    1843        4256 :       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         537 :           object, isolate()->factory()->heap_number_map());
    1849         537 :       if_objectisnumber.Then();
    1850             :       {
    1851             :         // Compute hash for heap number similar to double_get_hash().
    1852             :         HValue* low = Add<HLoadNamedField>(
    1853             :             object, objectisnumber,
    1854         537 :             HObjectAccess::ForHeapNumberValueLowestBits());
    1855             :         HValue* high = Add<HLoadNamedField>(
    1856             :             object, objectisnumber,
    1857         537 :             HObjectAccess::ForHeapNumberValueHighestBits());
    1858         537 :         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
    1859         537 :         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
    1860             : 
    1861             :         // Load the key.
    1862         537 :         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
    1863             :         HValue* key =
    1864             :             Add<HLoadKeyed>(number_string_cache, key_index, nullptr, nullptr,
    1865         537 :                             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         537 :         if_keyisnotsmi.Then();
    1871             :         {
    1872             :           IfBuilder if_keyisheapnumber(this);
    1873             :           if_keyisheapnumber.If<HCompareMap>(
    1874         537 :               key, isolate()->factory()->heap_number_map());
    1875         537 :           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         537 :                                      HObjectAccess::ForHeapNumberValue()),
    1882             :                 Add<HLoadNamedField>(object, objectisnumber,
    1883             :                                      HObjectAccess::ForHeapNumberValue()),
    1884        1074 :                 Token::EQ);
    1885         537 :             if_keyeqobject.Then();
    1886             :             {
    1887             :               // Make the key_index available.
    1888         537 :               Push(key_index);
    1889             :             }
    1890         537 :             if_keyeqobject.JoinContinuation(&found);
    1891             :           }
    1892         537 :           if_keyisheapnumber.JoinContinuation(&found);
    1893             :         }
    1894         537 :         if_keyisnotsmi.JoinContinuation(&found);
    1895             :       }
    1896             :       if_objectisnumber.Else();
    1897             :       {
    1898         537 :         if (type->Is(AstType::Number())) {
    1899         537 :           if_objectisnumber.Deopt(DeoptimizeReason::kExpectedHeapNumber);
    1900             :         }
    1901             :       }
    1902         537 :       if_objectisnumber.JoinContinuation(&found);
    1903             :     }
    1904             :   }
    1905        4793 :   if_objectissmi.JoinContinuation(&found);
    1906             : 
    1907             :   // Check for cache hit.
    1908             :   IfBuilder if_found(this, &found);
    1909        4793 :   if_found.Then();
    1910             :   {
    1911             :     // Count number to string operation in native code.
    1912        4793 :     AddIncrementCounter(isolate()->counters()->number_to_string_native());
    1913             : 
    1914             :     // Load the value in case of cache hit.
    1915             :     HValue* key_index = Pop();
    1916        4793 :     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
    1917             :     Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr, nullptr,
    1918        4793 :                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
    1919             :   }
    1920             :   if_found.Else();
    1921             :   {
    1922             :     // Cache miss, fallback to runtime.
    1923        4793 :     Add<HPushArguments>(object);
    1924             :     Push(Add<HCallRuntime>(
    1925             :             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
    1926        4793 :             1));
    1927             :   }
    1928        4793 :   if_found.End();
    1929             : 
    1930             :   return Pop();
    1931             : }
    1932             : 
    1933       17879 : HValue* HGraphBuilder::BuildToNumber(HValue* input) {
    1934       27890 :   if (input->type().IsTaggedNumber() ||
    1935       18244 :       input->representation().IsSpecialization()) {
    1936             :     return input;
    1937             :   }
    1938        8233 :   Callable callable = CodeFactory::ToNumber(isolate());
    1939        8233 :   HValue* stub = Add<HConstant>(callable.code());
    1940        8233 :   HValue* values[] = {input};
    1941             :   HCallWithDescriptor* instr = Add<HCallWithDescriptor>(
    1942        8233 :       stub, 0, callable.descriptor(), ArrayVector(values));
    1943             :   instr->set_type(HType::TaggedNumber());
    1944             :   return instr;
    1945             : }
    1946             : 
    1947             : 
    1948         762 : HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
    1949             :   NoObservableSideEffectsScope scope(this);
    1950             : 
    1951             :   // Create a joinable continuation.
    1952             :   HIfContinuation wrap(graph()->CreateBasicBlock(),
    1953         762 :                        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         381 :   receiver_is_smi.If<HIsSmiAndBranch>(receiver);
    1961         381 :   receiver_is_smi.Then();
    1962             :   {
    1963             :     // Use global Number function.
    1964         381 :     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         381 :         Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
    1971             :     HValue* receiver_instance_type = Add<HLoadNamedField>(
    1972         381 :         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         381 :         Token::LT);
    1979         381 :     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         381 :           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         381 :           Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
    1992             :       constructor_function_index_is_invalid.ThenDeopt(
    1993             :           DeoptimizeReason::kUndefinedOrNullInToObject);
    1994         381 :       constructor_function_index_is_invalid.End();
    1995             : 
    1996             :       // Use the global constructor function.
    1997         381 :       Push(constructor_function_index);
    1998             :     }
    1999         381 :     receiver_is_not_spec_object.JoinContinuation(&wrap);
    2000             :   }
    2001         381 :   receiver_is_smi.JoinContinuation(&wrap);
    2002             : 
    2003             :   // Wrap the receiver if necessary.
    2004             :   IfBuilder if_wrap(this, &wrap);
    2005         381 :   if_wrap.Then();
    2006             :   {
    2007             :     // Grab the constructor function index.
    2008             :     HValue* constructor_index = Pop();
    2009             : 
    2010             :     // Load native context.
    2011         381 :     HValue* native_context = BuildGetNativeContext();
    2012             : 
    2013             :     // Determine the initial map for the global constructor.
    2014             :     HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
    2015         381 :                                           nullptr, nullptr, FAST_ELEMENTS);
    2016             :     HValue* constructor_initial_map = Add<HLoadNamedField>(
    2017         381 :         constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
    2018             :     // Allocate and initialize a JSValue wrapper.
    2019             :     HValue* value =
    2020         381 :         BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
    2021         381 :                       JS_VALUE_TYPE, HAllocationMode());
    2022             :     Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
    2023         381 :                           constructor_initial_map);
    2024         381 :     HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
    2025             :     Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
    2026         381 :                           empty_fixed_array);
    2027             :     Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
    2028         381 :                           empty_fixed_array);
    2029             :     Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
    2030             :                                      JSValue::kValueOffset),
    2031         381 :                           receiver);
    2032         381 :     Push(value);
    2033             :   }
    2034             :   if_wrap.Else();
    2035         381 :   { Push(receiver); }
    2036         381 :   if_wrap.End();
    2037         381 :   return Pop();
    2038             : }
    2039             : 
    2040             : 
    2041       23917 : HAllocate* HGraphBuilder::BuildAllocate(
    2042             :     HValue* object_size,
    2043             :     HType type,
    2044             :     InstanceType instance_type,
    2045       23917 :     HAllocationMode allocation_mode) {
    2046             :   // Compute the effective allocation size.
    2047             :   HValue* size = object_size;
    2048       23917 :   if (allocation_mode.CreateAllocationMementos()) {
    2049        7136 :     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       23917 :       graph()->GetConstant0(), allocation_mode.feedback_site());
    2057             : 
    2058             :   // Setup the allocation memento.
    2059       23917 :   if (allocation_mode.CreateAllocationMementos()) {
    2060             :     BuildCreateAllocationMemento(
    2061        7136 :         object, object_size, allocation_mode.current_site());
    2062             :   }
    2063             : 
    2064       23917 :   return object;
    2065             : }
    2066             : 
    2067             : 
    2068       15417 : HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
    2069       39099 :                                              HValue* right_length) {
    2070             :   // Compute the combined string length and check against max string length.
    2071       15417 :   HValue* length = AddUncasted<HAdd>(left_length, right_length);
    2072             :   // Check that length <= kMaxLength <=> length < MaxLength + 1.
    2073       15417 :   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
    2074       27266 :   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        3584 :     if_invalid.If<HCompareNumericAndBranch>(length, max_length, Token::GT);
    2079        3584 :     if_invalid.Then();
    2080             :     {
    2081             :       Add<HCallRuntime>(
    2082        3584 :           Runtime::FunctionForId(Runtime::kThrowInvalidStringLength), 0);
    2083             :     }
    2084        3584 :     if_invalid.End();
    2085             :   } else {
    2086       11833 :     graph()->MarkDependsOnStringLengthOverflow();
    2087       11833 :     Add<HBoundsCheck>(length, max_length);
    2088             :   }
    2089       15417 :   return length;
    2090             : }
    2091             : 
    2092             : 
    2093       15417 : HValue* HGraphBuilder::BuildCreateConsString(
    2094             :     HValue* length,
    2095             :     HValue* left,
    2096             :     HValue* right,
    2097       61668 :     HAllocationMode allocation_mode) {
    2098             :   // Determine the string instance types.
    2099       15417 :   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
    2100       15417 :   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       15417 :   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
    2109             :                                     HType::String(), CONS_STRING_TYPE,
    2110       15417 :                                     allocation_mode);
    2111             : 
    2112             :   // Compute intersection and difference of instance types.
    2113             :   HValue* anded_instance_types = AddUncasted<HBitwise>(
    2114       15417 :       Token::BIT_AND, left_instance_type, right_instance_type);
    2115             :   HValue* xored_instance_types = AddUncasted<HBitwise>(
    2116       15417 :       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       15417 :                   kStringEncodingMask | kOneByteDataHintMask))),
    2135       15417 :       graph()->GetConstant0(), Token::NE);
    2136       15417 :   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       15417 :                   kOneByteStringTag | kOneByteDataHintTag))),
    2145             :       Add<HConstant>(static_cast<int32_t>(
    2146       30834 :               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
    2147       15417 :   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       15417 :         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       15417 :         Add<HConstant>(isolate()->factory()->cons_string_map()));
    2160             :   }
    2161       15417 :   if_onebyte.End();
    2162             : 
    2163             :   // Initialize the cons string fields.
    2164             :   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
    2165       15417 :                         Add<HConstant>(String::kEmptyHashField));
    2166       15417 :   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
    2167       15417 :   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
    2168       15417 :   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
    2169             : 
    2170             :   // Count the native string addition.
    2171       15417 :   AddIncrementCounter(isolate()->counters()->string_add_native());
    2172             : 
    2173       15417 :   return result;
    2174             : }
    2175             : 
    2176             : 
    2177       14272 : 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       14272 :                                             HValue* length) {
    2184             :   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
    2185             :          src_encoding == String::ONE_BYTE_ENCODING);
    2186       14272 :   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
    2187       14272 :   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
    2188             :   {
    2189       14272 :     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
    2190             :     HValue* value =
    2191       14272 :         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
    2192       14272 :     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
    2193       14272 :     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
    2194             :   }
    2195       14272 :   loop.EndBody();
    2196       14272 : }
    2197             : 
    2198             : 
    2199        3568 : 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        3568 :           header_size + kObjectAlignmentMask)));
    2205             :   size->ClearFlag(HValue::kCanOverflow);
    2206             :   return AddUncasted<HBitwise>(
    2207             :       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
    2208        3568 :           ~kObjectAlignmentMask)));
    2209             : }
    2210             : 
    2211             : 
    2212       15417 : HValue* HGraphBuilder::BuildUncheckedStringAdd(
    2213             :     HValue* left,
    2214             :     HValue* right,
    2215       46384 :     HAllocationMode allocation_mode) {
    2216             :   // Determine the string lengths.
    2217       15417 :   HValue* left_length = AddLoadStringLength(left);
    2218       15417 :   HValue* right_length = AddLoadStringLength(right);
    2219             : 
    2220             :   // Compute the combined string length.
    2221       15417 :   HValue* length = BuildAddStringLengths(left_length, right_length);
    2222             : 
    2223             :   // Do some manual constant folding here.
    2224       15417 :   if (left_length->IsConstant()) {
    2225        1946 :     HConstant* c_left_length = HConstant::cast(left_length);
    2226             :     DCHECK_NE(0, c_left_length->Integer32Value());
    2227        1946 :     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
    2228             :       // The right string contains at least one character.
    2229        1946 :       return BuildCreateConsString(length, left, right, allocation_mode);
    2230             :     }
    2231       13471 :   } else if (right_length->IsConstant()) {
    2232        9903 :     HConstant* c_right_length = HConstant::cast(right_length);
    2233             :     DCHECK_NE(0, c_right_length->Integer32Value());
    2234        9903 :     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
    2235             :       // The left string contains at least one character.
    2236        9903 :       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        3568 :       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
    2244        3568 :   if_createcons.And();
    2245             :   if_createcons.If<HCompareNumericAndBranch>(
    2246        3568 :       length, Add<HConstant>(ConsString::kMaxLength), Token::LTE);
    2247        3568 :   if_createcons.Then();
    2248             :   {
    2249             :     // Create a cons string.
    2250        3568 :     Push(BuildCreateConsString(length, left, right, allocation_mode));
    2251             :   }
    2252             :   if_createcons.Else();
    2253             :   {
    2254             :     // Determine the string instance types.
    2255        3568 :     HValue* left_instance_type = AddLoadStringInstanceType(left);
    2256        3568 :     HValue* right_instance_type = AddLoadStringInstanceType(right);
    2257             : 
    2258             :     // Compute union and difference of instance types.
    2259             :     HValue* ored_instance_types = AddUncasted<HBitwise>(
    2260        3568 :         Token::BIT_OR, left_instance_type, right_instance_type);
    2261             :     HValue* xored_instance_types = AddUncasted<HBitwise>(
    2262        3568 :         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        3568 :             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
    2271        3568 :         graph()->GetConstant0(), Token::EQ);
    2272        3568 :     if_sameencodingandsequential.And();
    2273             :     STATIC_ASSERT(kSeqStringTag == 0);
    2274             :     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
    2275             :         AddUncasted<HBitwise>(
    2276             :             Token::BIT_AND, ored_instance_types,
    2277        3568 :             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
    2278        3568 :         graph()->GetConstant0(), Token::EQ);
    2279        3568 :     if_sameencodingandsequential.Then();
    2280             :     {
    2281             :       HConstant* string_map =
    2282        3568 :           Add<HConstant>(isolate()->factory()->string_map());
    2283             :       HConstant* one_byte_string_map =
    2284        3568 :           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        3568 :               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
    2293        3568 :           graph()->GetConstant0(), Token::NE);
    2294        3568 :       if_onebyte.Then();
    2295             :       {
    2296             :         // Allocate sequential one-byte string object.
    2297        3568 :         Push(length);
    2298        3568 :         Push(one_byte_string_map);
    2299             :       }
    2300             :       if_onebyte.Else();
    2301             :       {
    2302             :         // Allocate sequential two-byte string object.
    2303        3568 :         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
    2304             :         size->ClearFlag(HValue::kCanOverflow);
    2305             :         size->SetFlag(HValue::kUint32);
    2306        3568 :         Push(size);
    2307        3568 :         Push(string_map);
    2308             :       }
    2309        3568 :       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        3568 :       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
    2316             : 
    2317             :       IfBuilder if_size(this);
    2318             :       if_size.If<HCompareNumericAndBranch>(
    2319        3568 :           size, Add<HConstant>(kMaxRegularHeapObjectSize), Token::LT);
    2320        3568 :       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        3568 :             BuildAllocate(size, HType::String(), STRING_TYPE, allocation_mode);
    2326        3568 :         Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
    2327             : 
    2328             :         // Initialize the string fields.
    2329             :         Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
    2330        3568 :                               Add<HConstant>(String::kEmptyHashField));
    2331        3568 :         Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
    2332             : 
    2333             :         // Copy characters to the result string.
    2334             :         IfBuilder if_twobyte(this);
    2335        3568 :         if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
    2336        3568 :         if_twobyte.Then();
    2337             :         {
    2338             :           // Copy characters from the left string.
    2339             :           BuildCopySeqStringChars(
    2340             :               left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
    2341        3568 :               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        3568 :               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        3568 :               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        3568 :               left_length, String::ONE_BYTE_ENCODING, right_length);
    2359             :         }
    2360        3568 :         if_twobyte.End();
    2361             : 
    2362             :         // Count the native string addition.
    2363        3568 :         AddIncrementCounter(isolate()->counters()->string_add_native());
    2364             : 
    2365             :         // Return the sequential string.
    2366        3568 :         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        3568 :         Add<HPushArguments>(left, right);
    2373        3568 :         Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
    2374             :       }
    2375        3568 :       if_size.End();
    2376             :     }
    2377             :     if_sameencodingandsequential.Else();
    2378             :     {
    2379             :       // Fallback to the runtime to add the two strings.
    2380        3568 :       Add<HPushArguments>(left, right);
    2381        3568 :       Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
    2382             :     }
    2383        3568 :     if_sameencodingandsequential.End();
    2384             :   }
    2385        3568 :   if_createcons.End();
    2386             : 
    2387             :   return Pop();
    2388             : }
    2389             : 
    2390             : 
    2391       15417 : HValue* HGraphBuilder::BuildStringAdd(
    2392             :     HValue* left,
    2393             :     HValue* right,
    2394       61668 :     HAllocationMode allocation_mode) {
    2395             :   NoObservableSideEffectsScope no_effects(this);
    2396             : 
    2397             :   // Determine string lengths.
    2398       15417 :   HValue* left_length = AddLoadStringLength(left);
    2399       15417 :   HValue* right_length = AddLoadStringLength(right);
    2400             : 
    2401             :   // Check if left string is empty.
    2402             :   IfBuilder if_leftempty(this);
    2403             :   if_leftempty.If<HCompareNumericAndBranch>(
    2404       15417 :       left_length, graph()->GetConstant0(), Token::EQ);
    2405       15417 :   if_leftempty.Then();
    2406             :   {
    2407             :     // Count the native string addition.
    2408       15417 :     AddIncrementCounter(isolate()->counters()->string_add_native());
    2409             : 
    2410             :     // Just return the right string.
    2411       15417 :     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       15417 :         right_length, graph()->GetConstant0(), Token::EQ);
    2419       15417 :     if_rightempty.Then();
    2420             :     {
    2421             :       // Count the native string addition.
    2422       15417 :       AddIncrementCounter(isolate()->counters()->string_add_native());
    2423             : 
    2424             :       // Just return the left string.
    2425       15417 :       Push(left);
    2426             :     }
    2427             :     if_rightempty.Else();
    2428             :     {
    2429             :       // Add the two non-empty strings.
    2430       15417 :       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
    2431             :     }
    2432       15417 :     if_rightempty.End();
    2433             :   }
    2434       15417 :   if_leftempty.End();
    2435             : 
    2436       15417 :   return Pop();
    2437             : }
    2438             : 
    2439             : 
    2440       27712 : 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        9381 :     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       49657 :   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
    2459       21945 :       (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       27712 :   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        5891 :         elements, isolate()->factory()->fixed_array_map());
    2470             :     check_cow_map->ClearDependsOnFlag(kElementsKind);
    2471             :   }
    2472             :   HInstruction* length = NULL;
    2473       27712 :   if (is_js_array) {
    2474             :     length = Add<HLoadNamedField>(
    2475             :         checked_object->ActualValue(), checked_object,
    2476       22991 :         HObjectAccess::ForArrayLength(elements_kind));
    2477             :   } else {
    2478             :     length = AddLoadFixedArrayLength(elements);
    2479             :   }
    2480             :   length->set_type(HType::Smi());
    2481             :   HValue* checked_key = NULL;
    2482       27712 :   if (IsFixedTypedArrayElementsKind(elements_kind)) {
    2483        3894 :     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
    2484             : 
    2485             :     HValue* external_pointer = Add<HLoadNamedField>(
    2486             :         elements, nullptr,
    2487        3894 :         HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
    2488             :     HValue* base_pointer = Add<HLoadNamedField>(
    2489        3894 :         elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
    2490             :     HValue* backing_store = AddUncasted<HAdd>(external_pointer, base_pointer,
    2491        3894 :                                               AddOfExternalAndTagged);
    2492             : 
    2493        3894 :     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
    2494             :       NoObservableSideEffectsScope no_effects(this);
    2495             :       IfBuilder length_checker(this);
    2496          40 :       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
    2497          40 :       length_checker.Then();
    2498             :       IfBuilder negative_checker(this);
    2499             :       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
    2500          40 :           key, graph()->GetConstant0(), Token::GTE);
    2501          40 :       negative_checker.Then();
    2502             :       HInstruction* result = AddElementAccess(
    2503             :           backing_store, key, val, bounds_check, checked_object->ActualValue(),
    2504          40 :           elements_kind, access_type);
    2505          40 :       negative_checker.ElseDeopt(DeoptimizeReason::kNegativeKeyEncountered);
    2506          40 :       negative_checker.End();
    2507          40 :       length_checker.End();
    2508             :       return result;
    2509             :     } else {
    2510             :       DCHECK(store_mode == STANDARD_STORE);
    2511        3854 :       checked_key = Add<HBoundsCheck>(key, length);
    2512             :       return AddElementAccess(backing_store, checked_key, val, checked_object,
    2513             :                               checked_object->ActualValue(), elements_kind,
    2514        3854 :                               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       26011 :   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
    2525             :       !val->type().IsSmi()) {
    2526        1309 :     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
    2527             :   }
    2528             : 
    2529       23818 :   if (IsGrowStoreMode(store_mode)) {
    2530             :     NoObservableSideEffectsScope no_effects(this);
    2531             :     Representation representation = HStoreKeyed::RequiredValueRepresentation(
    2532        2593 :         elements_kind, STORE_TO_INITIALIZED_ENTRY);
    2533        2593 :     val = AddUncasted<HForceRepresentation>(val, representation);
    2534             :     elements = BuildCheckForCapacityGrow(checked_object, elements,
    2535             :                                          elements_kind, length, key,
    2536        2593 :                                          is_js_array, access_type);
    2537             :     checked_key = key;
    2538             :   } else {
    2539       21225 :     checked_key = Add<HBoundsCheck>(key, length);
    2540             : 
    2541       21225 :     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
    2542        3566 :       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
    2543             :         NoObservableSideEffectsScope no_effects(this);
    2544             :         elements = BuildCopyElementsOnWrite(checked_object, elements,
    2545         116 :                                             elements_kind, length);
    2546             :       } else {
    2547             :         HCheckMaps* check_cow_map = Add<HCheckMaps>(
    2548        3450 :             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       23818 :                           elements_kind, access_type, load_mode);
    2555             : }
    2556             : 
    2557             : 
    2558         534 : HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
    2559        1068 :                                                   HValue* capacity) {
    2560             :   int elements_size = IsFastDoubleElementsKind(kind)
    2561             :       ? kDoubleSize
    2562             :       : kPointerSize;
    2563             : 
    2564         534 :   HConstant* elements_size_value = Add<HConstant>(elements_size);
    2565             :   HInstruction* mul =
    2566         534 :       HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
    2567        1602 :                     elements_size_value);
    2568         534 :   AddInstruction(mul);
    2569             :   mul->ClearFlag(HValue::kCanOverflow);
    2570             : 
    2571             :   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
    2572             : 
    2573         534 :   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
    2574         534 :   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
    2575             :   total_size->ClearFlag(HValue::kCanOverflow);
    2576         534 :   return total_size;
    2577             : }
    2578             : 
    2579             : 
    2580         484 : HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
    2581             :   int base_size = JSArray::kSize;
    2582         242 :   if (mode == TRACK_ALLOCATION_SITE) {
    2583             :     base_size += AllocationMemento::kSize;
    2584             :   }
    2585         242 :   HConstant* size_in_bytes = Add<HConstant>(base_size);
    2586             :   return Add<HAllocate>(size_in_bytes, HType::JSArray(), NOT_TENURED,
    2587         242 :                         JS_OBJECT_TYPE, graph()->GetConstant0());
    2588             : }
    2589             : 
    2590             : 
    2591           0 : HConstant* HGraphBuilder::EstablishElementsAllocationSize(
    2592             :     ElementsKind kind,
    2593             :     int capacity) {
    2594             :   int base_size = IsFastDoubleElementsKind(kind)
    2595             :       ? FixedDoubleArray::SizeFor(capacity)
    2596           0 :       : FixedArray::SizeFor(capacity);
    2597             : 
    2598           0 :   return Add<HConstant>(base_size);
    2599             : }
    2600             : 
    2601             : 
    2602         534 : HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
    2603         534 :                                                 HValue* size_in_bytes) {
    2604             :   InstanceType instance_type = IsFastDoubleElementsKind(kind)
    2605             :       ? FIXED_DOUBLE_ARRAY_TYPE
    2606         534 :       : FIXED_ARRAY_TYPE;
    2607             : 
    2608             :   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
    2609         534 :                         instance_type, graph()->GetConstant0());
    2610             : }
    2611             : 
    2612             : 
    2613        2361 : void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
    2614             :                                                   ElementsKind kind,
    2615        2361 :                                                   HValue* capacity) {
    2616             :   Factory* factory = isolate()->factory();
    2617             :   Handle<Map> map = IsFastDoubleElementsKind(kind)
    2618             :       ? factory->fixed_double_array_map()
    2619        4722 :       : factory->fixed_array_map();
    2620             : 
    2621        2361 :   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
    2622             :   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
    2623        2361 :                         capacity);
    2624        2361 : }
    2625             : 
    2626             : 
    2627         292 : 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         292 :   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
    2632         292 :   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
    2633         292 :   HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
    2634         292 :   BuildInitializeElementsHeader(new_array, kind, capacity);
    2635         292 :   return new_array;
    2636             : }
    2637             : 
    2638             : 
    2639         242 : 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         242 :   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
    2647             : 
    2648         242 :   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
    2649             : 
    2650             :   Add<HStoreNamedField>(
    2651         242 :       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
    2652             : 
    2653             :   Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(),
    2654         242 :                         elements != nullptr ? elements : empty_fixed_array);
    2655             : 
    2656             :   Add<HStoreNamedField>(
    2657         242 :       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
    2658             : 
    2659         242 :   if (mode == TRACK_ALLOCATION_SITE) {
    2660             :     BuildCreateAllocationMemento(
    2661           0 :         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
    2662             :   }
    2663         242 : }
    2664             : 
    2665             : 
    2666       28070 : HInstruction* HGraphBuilder::AddElementAccess(
    2667             :     HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
    2668             :     HValue* backing_store_owner, ElementsKind elements_kind,
    2669         276 :     PropertyAccessType access_type, LoadKeyedHoleMode load_mode) {
    2670       28070 :   if (access_type == STORE) {
    2671             :     DCHECK(val != NULL);
    2672        8510 :     if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
    2673         335 :       val = Add<HClampToUint8>(val);
    2674             :     }
    2675             :     return Add<HStoreKeyed>(elements, checked_key, val, backing_store_owner,
    2676        8510 :                             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       19560 :                       elements_kind, load_mode);
    2684       19560 :   if (elements_kind == UINT32_ELEMENTS) {
    2685         276 :     graph()->RecordUint32Instruction(load);
    2686             :   }
    2687       19560 :   return load;
    2688             : }
    2689             : 
    2690             : 
    2691           0 : HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
    2692             :                                            HValue* dependency) {
    2693         133 :   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
    2694             : }
    2695             : 
    2696             : 
    2697          55 : HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
    2698             :                                                 HValue* dependency) {
    2699             :   return Add<HLoadNamedField>(
    2700       44673 :       object, dependency, HObjectAccess::ForElementsPointer());
    2701             : }
    2702             : 
    2703             : 
    2704          55 : HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
    2705             :     HValue* array,
    2706             :     HValue* dependency) {
    2707             :   return Add<HLoadNamedField>(
    2708       12927 :       array, dependency, HObjectAccess::ForFixedArrayLength());
    2709             : }
    2710             : 
    2711             : 
    2712         170 : HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
    2713             :                                                    ElementsKind kind,
    2714             :                                                    HValue* dependency) {
    2715             :   return Add<HLoadNamedField>(
    2716         170 :       array, dependency, HObjectAccess::ForArrayLength(kind));
    2717             : }
    2718             : 
    2719             : 
    2720           0 : HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
    2721             :   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
    2722           0 :                                                 graph_->GetConstant1());
    2723             : 
    2724           0 :   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
    2725             :   new_capacity->ClearFlag(HValue::kCanOverflow);
    2726             : 
    2727           0 :   HValue* min_growth = Add<HConstant>(16);
    2728             : 
    2729           0 :   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
    2730             :   new_capacity->ClearFlag(HValue::kCanOverflow);
    2731             : 
    2732           0 :   return new_capacity;
    2733             : }
    2734             : 
    2735             : 
    2736         292 : 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         292 :                      ElementsKindToShiftSize(new_kind)));
    2746             : 
    2747             :   HValue* new_elements =
    2748         292 :       BuildAllocateAndInitializeArray(new_kind, new_capacity);
    2749             : 
    2750             :   BuildCopyElements(elements, kind, new_elements,
    2751         292 :                     new_kind, length, new_capacity);
    2752             : 
    2753             :   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
    2754         292 :                         new_elements);
    2755             : 
    2756         292 :   return new_elements;
    2757             : }
    2758             : 
    2759             : 
    2760         534 : void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
    2761             :                                                ElementsKind elements_kind,
    2762             :                                                HValue* from,
    2763             :                                                HValue* to,
    2764         534 :                                                HValue* value) {
    2765         534 :   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         534 :   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
    2774           0 :     int constant_from = from->GetInteger32Constant();
    2775           0 :     int constant_to = to->GetInteger32Constant();
    2776             : 
    2777           0 :     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
    2778             :       initial_capacity = constant_to;
    2779             :     }
    2780             :   }
    2781             : 
    2782         534 :   if (initial_capacity >= 0) {
    2783           0 :     for (int i = 0; i < initial_capacity; i++) {
    2784           0 :       HInstruction* key = Add<HConstant>(i);
    2785           0 :       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         534 :     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
    2793             : 
    2794         534 :     HValue* key = builder.BeginBody(to, from, Token::GT);
    2795             : 
    2796         534 :     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
    2797             :     adjusted_key->ClearFlag(HValue::kCanOverflow);
    2798             : 
    2799         534 :     Add<HStoreKeyed>(elements, adjusted_key, value, nullptr, elements_kind);
    2800             : 
    2801         534 :     builder.EndBody();
    2802             :   }
    2803         534 : }
    2804             : 
    2805             : 
    2806         534 : void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
    2807             :                                               ElementsKind elements_kind,
    2808             :                                               HValue* from,
    2809         456 :                                               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         990 :                      : 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         534 :   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
    2820             :     elements_kind = FAST_HOLEY_ELEMENTS;
    2821             :   }
    2822             : 
    2823         534 :   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
    2824         534 : }
    2825             : 
    2826             : 
    2827           0 : void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
    2828             :                                         HValue* to_properties, HValue* length,
    2829           0 :                                         HValue* capacity) {
    2830             :   ElementsKind kind = FAST_ELEMENTS;
    2831             : 
    2832             :   BuildFillElementsWithValue(to_properties, kind, length, capacity,
    2833           0 :                              graph()->GetConstantUndefined());
    2834             : 
    2835           0 :   LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
    2836             : 
    2837           0 :   HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
    2838             : 
    2839           0 :   key = AddUncasted<HSub>(key, graph()->GetConstant1());
    2840             :   key->ClearFlag(HValue::kCanOverflow);
    2841             : 
    2842             :   HValue* element =
    2843           0 :       Add<HLoadKeyed>(from_properties, key, nullptr, nullptr, kind);
    2844             : 
    2845           0 :   Add<HStoreKeyed>(to_properties, key, element, nullptr, kind);
    2846             : 
    2847           0 :   builder.EndBody();
    2848           0 : }
    2849             : 
    2850             : 
    2851         292 : void HGraphBuilder::BuildCopyElements(HValue* from_elements,
    2852             :                                       ElementsKind from_elements_kind,
    2853             :                                       HValue* to_elements,
    2854             :                                       ElementsKind to_elements_kind,
    2855             :                                       HValue* length,
    2856         902 :                                       HValue* capacity) {
    2857             :   int constant_capacity = -1;
    2858         584 :   if (capacity != NULL &&
    2859         292 :       capacity->IsConstant() &&
    2860           0 :       HConstant::cast(capacity)->HasInteger32Value()) {
    2861           0 :     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
    2862           0 :     if (constant_candidate <= kElementLoopUnrollThreshold) {
    2863             :       constant_capacity = constant_candidate;
    2864             :     }
    2865             :   }
    2866             : 
    2867             :   bool pre_fill_with_holes =
    2868         309 :     IsFastDoubleElementsKind(from_elements_kind) &&
    2869             :     IsFastObjectElementsKind(to_elements_kind);
    2870         292 :   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          17 :                               graph()->GetConstant0(), NULL);
    2876             :   }
    2877             : 
    2878         292 :   if (constant_capacity != -1) {
    2879             :     // Unroll the loop for small elements kinds.
    2880           0 :     for (int i = 0; i < constant_capacity; i++) {
    2881           0 :       HValue* key_constant = Add<HConstant>(i);
    2882             :       HInstruction* value = Add<HLoadKeyed>(
    2883           0 :           from_elements, key_constant, nullptr, nullptr, from_elements_kind);
    2884             :       Add<HStoreKeyed>(to_elements, key_constant, value, nullptr,
    2885           0 :                        to_elements_kind);
    2886             :     }
    2887             :   } else {
    2888         584 :     if (!pre_fill_with_holes &&
    2889         275 :         (capacity == NULL || !length->Equals(capacity))) {
    2890             :       BuildFillElementsWithHole(to_elements, to_elements_kind,
    2891         275 :                                 length, NULL);
    2892             :     }
    2893             : 
    2894         292 :     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
    2895             : 
    2896             :     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
    2897         292 :                                     Token::GT);
    2898             : 
    2899         292 :     key = AddUncasted<HSub>(key, graph()->GetConstant1());
    2900             :     key->ClearFlag(HValue::kCanOverflow);
    2901             : 
    2902             :     HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr, nullptr,
    2903         292 :                                       from_elements_kind, ALLOW_RETURN_HOLE);
    2904             : 
    2905         107 :     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
    2906             :                          IsFastSmiElementsKind(to_elements_kind))
    2907         523 :       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
    2908             : 
    2909         292 :     if (IsHoleyElementsKind(from_elements_kind) &&
    2910             :         from_elements_kind != to_elements_kind) {
    2911             :       IfBuilder if_hole(this);
    2912          33 :       if_hole.If<HCompareHoleAndBranch>(element);
    2913          33 :       if_hole.Then();
    2914             :       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
    2915             :                                      ? Add<HConstant>(HConstant::kHoleNaN)
    2916          42 :                                      : graph()->GetConstantHole();
    2917          33 :       Add<HStoreKeyed>(to_elements, key, hole_constant, nullptr, kind);
    2918             :       if_hole.Else();
    2919             :       HStoreKeyed* store =
    2920          33 :           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
    2921             :       store->SetFlag(HValue::kTruncatingToNumber);
    2922          33 :       if_hole.End();
    2923             :     } else {
    2924             :       HStoreKeyed* store =
    2925         259 :           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
    2926             :       store->SetFlag(HValue::kTruncatingToNumber);
    2927             :     }
    2928             : 
    2929         292 :     builder.EndBody();
    2930             :   }
    2931             : 
    2932         292 :   Counters* counters = isolate()->counters();
    2933         292 :   AddIncrementCounter(counters->inlined_copied_elements());
    2934         292 : }
    2935             : 
    2936        7136 : void HGraphBuilder::BuildCreateAllocationMemento(
    2937             :     HValue* previous_object,
    2938             :     HValue* previous_object_size,
    2939       14272 :     HValue* allocation_site) {
    2940             :   DCHECK(allocation_site != NULL);
    2941             :   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
    2942        7136 :       previous_object, previous_object_size, HType::HeapObject());
    2943             :   AddStoreMapConstant(
    2944        7136 :       allocation_memento, isolate()->factory()->allocation_memento_map());
    2945             :   Add<HStoreNamedField>(
    2946             :       allocation_memento,
    2947             :       HObjectAccess::ForAllocationMementoSite(),
    2948        7136 :       allocation_site);
    2949        7136 :   if (FLAG_allocation_site_pretenuring) {
    2950             :     HValue* memento_create_count =
    2951             :         Add<HLoadNamedField>(allocation_site, nullptr,
    2952             :                              HObjectAccess::ForAllocationSiteOffset(
    2953        7136 :                                  AllocationSite::kPretenureCreateCountOffset));
    2954             :     memento_create_count = AddUncasted<HAdd>(
    2955        7136 :         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        7136 :             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
    2962             :   }
    2963        7136 : }
    2964             : 
    2965             : 
    2966       11523 : HInstruction* HGraphBuilder::BuildGetNativeContext() {
    2967             :   return Add<HLoadNamedField>(
    2968       11523 :       context(), nullptr,
    2969       23046 :       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
    2970             : }
    2971             : 
    2972             : 
    2973           0 : HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
    2974             :   // Get the global object, then the native context
    2975             :   HInstruction* context = Add<HLoadNamedField>(
    2976           0 :       closure, nullptr, HObjectAccess::ForFunctionContextPointer());
    2977             :   return Add<HLoadNamedField>(
    2978             :       context, nullptr,
    2979           0 :       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
    2980             : }
    2981             : 
    2982             : 
    2983           0 : HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) {
    2984           0 :   HValue* script_context = context();
    2985           0 :   if (depth != NULL) {
    2986             :     HValue* zero = graph()->GetConstant0();
    2987             : 
    2988           0 :     Push(script_context);
    2989           0 :     Push(depth);
    2990             : 
    2991             :     LoopBuilder loop(this);
    2992           0 :     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           0 :         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    3000           0 :     depth = AddUncasted<HSub>(depth, graph()->GetConstant1());
    3001             :     depth->ClearFlag(HValue::kCanOverflow);
    3002             : 
    3003             :     IfBuilder if_break(this);
    3004           0 :     if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ);
    3005           0 :     if_break.Then();
    3006             :     {
    3007           0 :       Push(script_context);  // The result.
    3008           0 :       loop.Break();
    3009             :     }
    3010             :     if_break.Else();
    3011             :     {
    3012           0 :       Push(script_context);
    3013           0 :       Push(depth);
    3014             :     }
    3015           0 :     loop.EndBody();
    3016           0 :     if_break.End();
    3017             : 
    3018             :     script_context = Pop();
    3019           0 :   } else if (depth_value > 0) {
    3020             :     // Unroll the above loop.
    3021           0 :     for (int i = 0; i < depth_value; i++) {
    3022             :       script_context = Add<HLoadNamedField>(
    3023             :           script_context, nullptr,
    3024           0 :           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    3025             :     }
    3026             :   }
    3027           0 :   return script_context;
    3028             : }
    3029             : 
    3030             : 
    3031           0 : HInstruction* HGraphBuilder::BuildGetArrayFunction() {
    3032           0 :   HInstruction* native_context = BuildGetNativeContext();
    3033             :   HInstruction* index =
    3034           0 :       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
    3035             :   return Add<HLoadKeyed>(native_context, index, nullptr, nullptr,
    3036           0 :                          FAST_ELEMENTS);
    3037             : }
    3038             : 
    3039             : 
    3040         143 : HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
    3041             :                                                          HValue* checked_object,
    3042         286 :                                                          FieldIndex index) {
    3043             :   NoObservableSideEffectsScope scope(this);
    3044             :   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
    3045         143 :       index.offset(), Representation::Tagged());
    3046             :   HInstruction* buffer = Add<HLoadNamedField>(
    3047         143 :       object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
    3048         143 :   HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);
    3049             : 
    3050             :   HInstruction* flags = Add<HLoadNamedField>(
    3051         143 :       buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
    3052             :   HValue* was_neutered_mask =
    3053         143 :       Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
    3054             :   HValue* was_neutered_test =
    3055         143 :       AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
    3056             : 
    3057             :   IfBuilder if_was_neutered(this);
    3058             :   if_was_neutered.If<HCompareNumericAndBranch>(
    3059         143 :       was_neutered_test, graph()->GetConstant0(), Token::NE);
    3060         143 :   if_was_neutered.Then();
    3061         143 :   Push(graph()->GetConstant0());
    3062             :   if_was_neutered.Else();
    3063         143 :   Push(field);
    3064         143 :   if_was_neutered.End();
    3065             : 
    3066         143 :   return Pop();
    3067             : }
    3068             : 
    3069           0 : HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
    3070           0 :   HValue* native_context = BuildGetNativeContext();
    3071           0 :   HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
    3072           0 :   return Add<HLoadNamedField>(native_context, nullptr, function_access);
    3073             : }
    3074             : 
    3075     1317163 : 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      790297 :       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      263433 :   function_state_ = &initial_function_state_;
    3091             :   InitializeAstVisitor(info->isolate());
    3092      263433 : }
    3093             : 
    3094             : 
    3095      466297 : HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
    3096             :                                                 HBasicBlock* second,
    3097             :                                                 BailoutId join_id) {
    3098      466297 :   if (first == NULL) {
    3099             :     return second;
    3100      188603 :   } else if (second == NULL) {
    3101             :     return first;
    3102             :   } else {
    3103      187790 :     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       45231 : HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
    3112             :                                                   BailoutId continue_id,
    3113             :                                                   HBasicBlock* exit_block,
    3114             :                                                   HBasicBlock* continue_block) {
    3115       45231 :   if (continue_block != NULL) {
    3116         681 :     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       45182 : HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
    3125             :                                                 HBasicBlock* loop_entry,
    3126             :                                                 HBasicBlock* body_exit,
    3127             :                                                 HBasicBlock* loop_successor,
    3128             :                                                 HBasicBlock* break_block) {
    3129       45182 :   if (body_exit != NULL) Goto(body_exit, loop_entry);
    3130       45182 :   loop_entry->PostProcessLoopHeader(statement);
    3131       45182 :   if (break_block != NULL) {
    3132        1879 :     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       45522 : HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
    3142       45522 :   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
    3143             :   Goto(loop_entry);
    3144             :   set_current_block(loop_entry);
    3145       45522 :   return loop_entry;
    3146             : }
    3147             : 
    3148             : 
    3149       45522 : HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
    3150       50386 :     IterationStatement* statement) {
    3151             :   HBasicBlock* loop_entry;
    3152             : 
    3153       45522 :   if (osr()->HasOsrEntryAt(statement)) {
    3154        2432 :     loop_entry = osr()->BuildOsrLoopEntry(statement);
    3155        2432 :     if (function_state()->IsInsideDoExpressionScope()) {
    3156             :       Bailout(kDoExpressionUnmodelable);
    3157             :     }
    3158             :   } else {
    3159       43090 :     loop_entry = BuildLoopEntry();
    3160             :   }
    3161       45522 :   return loop_entry;
    3162             : }
    3163             : 
    3164             : 
    3165           0 : void HBasicBlock::FinishExit(HControlInstruction* instruction,
    3166             :                              SourcePosition position) {
    3167      356825 :   Finish(instruction, position);
    3168             :   ClearEnvironment();
    3169           0 : }
    3170             : 
    3171             : 
    3172           0 : std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
    3173           0 :   return os << "B" << b.block_id();
    3174             : }
    3175             : 
    3176     1434577 : 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     1434577 :       disallow_adding_new_values_(false) {
    3196      286916 :   if (info->IsStub()) {
    3197             :     // For stubs, explicitly add the context to the environment.
    3198             :     start_environment_ =
    3199       46966 :         new (zone_) HEnvironment(zone_, descriptor.GetParameterCount() + 1);
    3200             :   } else {
    3201             :     start_environment_ =
    3202      526866 :         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
    3203             :   }
    3204      286916 :   start_environment_->set_ast_id(BailoutId::FunctionContext());
    3205      286916 :   entry_block_ = CreateBasicBlock();
    3206      286916 :   entry_block_->SetInitialEnvironment(start_environment_);
    3207      286916 : }
    3208             : 
    3209             : 
    3210     9208576 : HBasicBlock* HGraph::CreateBasicBlock() {
    3211     4604288 :   HBasicBlock* result = new(zone()) HBasicBlock(this);
    3212             :   blocks_.Add(result, zone());
    3213     4604290 :   return result;
    3214             : }
    3215             : 
    3216             : 
    3217      283265 : void HGraph::FinalizeUniqueness() {
    3218             :   DisallowHeapAllocation no_gc;
    3219     4787240 :   for (int i = 0; i < blocks()->length(); ++i) {
    3220    38569944 :     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
    3221    29561994 :       it.Current()->FinalizeUniqueness();
    3222             :     }
    3223             :   }
    3224      283265 : }
    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      283242 :   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
    3283             :                                                   HBasicBlock* block) {
    3284             :     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
    3285      283242 :     return result->SetupSuccessors(zone, block, NULL);
    3286             :   }
    3287             : 
    3288     7763339 :   PostorderProcessor* PerformStep(Zone* zone,
    3289             :                                   ZoneList<HBasicBlock*>* order) {
    3290             :     PostorderProcessor* next =
    3291     7763339 :         PerformNonBacktrackingStep(zone, order);
    3292     7763356 :     if (next != NULL) {
    3293             :       return next;
    3294             :     } else {
    3295     2600646 :       return Backtrack(zone, order);
    3296             :     }
    3297             :   }
    3298             : 
    3299             :  private:
    3300             :   explicit PostorderProcessor(PostorderProcessor* father)
    3301     1946757 :       : 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     6724219 :   PostorderProcessor* SetupSuccessors(Zone* zone,
    3314     5747630 :                                       HBasicBlock* block,
    3315             :                                       HBasicBlock* loop_header) {
    3316    19136151 :     if (block == NULL || block->IsOrdered() ||
    3317             :         block->parent_loop_header() != loop_header) {
    3318     2220436 :       kind_ = NONE;
    3319     2220436 :       block_ = NULL;
    3320     2220436 :       loop_ = NULL;
    3321     2220436 :       loop_header_ = NULL;
    3322     2220436 :       return this;
    3323             :     } else {
    3324     4503783 :       block_ = block;
    3325     4503783 :       loop_ = NULL;
    3326             :       block->MarkAsOrdered();
    3327             : 
    3328     4503783 :       if (block->IsLoopHeader()) {
    3329       59877 :         kind_ = SUCCESSORS_OF_LOOP_HEADER;
    3330       59877 :         loop_header_ = block;
    3331             :         InitializeSuccessors();
    3332       59877 :         PostorderProcessor* result = Push(zone);
    3333             :         return result->SetupLoopMembers(zone, block, block->loop_information(),
    3334       59877 :                                         loop_header);
    3335             :       } else {
    3336             :         DCHECK(block->IsFinished());
    3337     4443906 :         kind_ = SUCCESSORS;
    3338     4443906 :         loop_header_ = loop_header;
    3339             :         InitializeSuccessors();
    3340     4443906 :         return this;
    3341             :       }
    3342             :     }
    3343             :   }
    3344             : 
    3345             :   PostorderProcessor* SetupLoopMembers(Zone* zone,
    3346             :                                        HBasicBlock* block,
    3347             :                                        HLoopInformation* loop,
    3348             :                                        HBasicBlock* loop_header) {
    3349       69015 :     kind_ = LOOP_MEMBERS;
    3350       59877 :     block_ = block;
    3351       69015 :     loop_ = loop;
    3352       59877 :     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     1039153 :     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
    3362     1039153 :     block_ = block;
    3363     1039153 :     loop_ = loop;
    3364     1039153 :     loop_header_ = loop_header;
    3365             :     InitializeSuccessors();
    3366             :     return this;
    3367             :   }
    3368             : 
    3369             :   // This method "allocates" a new stack frame.
    3370     7539963 :   PostorderProcessor* Push(Zone* zone) {
    3371     7539963 :     if (child_ == NULL) {
    3372     1663515 :       child_ = new(zone) PostorderProcessor(this);
    3373             :     }
    3374     7539960 :     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     4503799 :     order->Add(block_, zone);
    3385             :   }
    3386             : 
    3387             :   // This method is the basic block to walk up the stack.
    3388     7832405 :   PostorderProcessor* Pop(Zone* zone,
    3389     1039153 :                           ZoneList<HBasicBlock*>* order) {
    3390     7832405 :     switch (kind_) {
    3391             :       case SUCCESSORS:
    3392             :       case SUCCESSORS_OF_LOOP_HEADER:
    3393             :         ClosePostorder(order, zone);
    3394     4503799 :         return father_;
    3395             :       case LOOP_MEMBERS:
    3396       69015 :         return father_;
    3397             :       case SUCCESSORS_OF_LOOP_MEMBER:
    3398     1039153 :         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        9138 :                                   block()->loop_information(), loop_header_);
    3403             :         } else {
    3404     1030015 :           return father_;
    3405             :         }
    3406             :       case NONE:
    3407     2220438 :         return father_;
    3408             :     }
    3409           0 :     UNREACHABLE();
    3410             :     return NULL;
    3411             :   }
    3412             : 
    3413             :   // Walks up the stack.
    3414     2600645 :   PostorderProcessor* Backtrack(Zone* zone,
    3415             :                                 ZoneList<HBasicBlock*>* order) {
    3416     2600645 :     PostorderProcessor* parent = Pop(zone, order);
    3417    10433035 :     while (parent != NULL) {
    3418             :       PostorderProcessor* next =
    3419     7549147 :           parent->PerformNonBacktrackingStep(zone, order);
    3420     7549140 :       if (next != NULL) {
    3421             :         return next;
    3422             :       } else {
    3423     5231755 :         parent = parent->Pop(zone, order);
    3424             :       }
    3425             :     }
    3426             :     return NULL;
    3427             :   }
    3428             : 
    3429    15312404 :   PostorderProcessor* PerformNonBacktrackingStep(
    3430             :       Zone* zone,
    3431      111600 :       ZoneList<HBasicBlock*>* order) {
    3432             :     HBasicBlock* next_block;
    3433    15312404 :     switch (kind_) {
    3434             :       case SUCCESSORS:
    3435     9434403 :         next_block = AdvanceSuccessors();
    3436     9434387 :         if (next_block != NULL) {
    3437     4990534 :           PostorderProcessor* result = Push(zone);
    3438     4990529 :           return result->SetupSuccessors(zone, next_block, loop_header_);
    3439             :         }
    3440             :         break;
    3441             :       case SUCCESSORS_OF_LOOP_HEADER:
    3442      171477 :         next_block = AdvanceSuccessors();
    3443      171477 :         if (next_block != NULL) {
    3444      111600 :           PostorderProcessor* result = Push(zone);
    3445      111600 :           return result->SetupSuccessors(zone, next_block, block());
    3446             :         }
    3447             :         break;
    3448             :       case LOOP_MEMBERS:
    3449             :         next_block = AdvanceLoopMembers();
    3450     1108168 :         if (next_block != NULL) {
    3451     1039153 :           PostorderProcessor* result = Push(zone);
    3452             :           return result->SetupSuccessorsOfLoopMember(next_block,
    3453     2078306 :                                                      loop_, loop_header_);
    3454             :         }
    3455             :         break;
    3456             :       case SUCCESSORS_OF_LOOP_MEMBER:
    3457     2377987 :         next_block = AdvanceSuccessors();
    3458     2377985 :         if (next_block != NULL) {
    3459     1338832 :           PostorderProcessor* result = Push(zone);
    3460     1338832 :           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     5542936 :     loop_index = 0;
    3472     5542936 :     loop_length = 0;
    3473     5542936 :     successor_iterator = HSuccessorIterator(block_->end());
    3474             :   }
    3475             : 
    3476    11983837 :   HBasicBlock* AdvanceSuccessors() {
    3477    23967662 :     if (!successor_iterator.Done()) {
    3478             :       HBasicBlock* result = successor_iterator.Current();
    3479             :       successor_iterator.Advance();
    3480     6440949 :       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       69015 :     loop_index = 0;
    3488       69015 :     loop_length = loop_->blocks()->length();
    3489             :   }
    3490             : 
    3491             :   HBasicBlock* AdvanceLoopMembers() {
    3492     1108168 :     if (loop_index < loop_length) {
    3493     2078306 :       HBasicBlock* result = loop_->blocks()->at(loop_index);
    3494     1039153 :       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     8329825 : void HGraph::OrderBlocks() {
    3514      283243 :   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     7936708 :       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
    3525             :   blocks_.Rewind(0);
    3526     8046583 :   while (postorder) {
    3527    15526680 :     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     2645570 :   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
    3539     2362327 :     HBasicBlock* bi = blocks_[i];
    3540     2362327 :     HBasicBlock* bj = blocks_[j];
    3541             :     bi->set_block_id(j);
    3542             :     bj->set_block_id(i);
    3543     2362327 :     blocks_[i] = bj;
    3544     2362327 :     blocks_[j] = bi;
    3545      283243 :   }
    3546      283243 : }
    3547             : 
    3548             : 
    3549      283242 : void HGraph::AssignDominators() {
    3550             :   HPhase phase("H_Assign dominators", this);
    3551     9574098 :   for (int i = 0; i < blocks_.length(); ++i) {
    3552    18777075 :     HBasicBlock* block = blocks_[i];
    3553     4503806 :     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       59876 :       block->AssignCommonDominator(block->predecessors()->first());
    3557       59877 :       block->AssignLoopSuccessorDominators();
    3558             :     } else {
    3559     9426338 :       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
    3560     9964828 :         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
    3561             :       }
    3562             :     }
    3563      283243 :   }
    3564      283242 : }
    3565             : 
    3566             : 
    3567      283200 : bool HGraph::CheckArgumentsPhiUses() {
    3568     5076532 :   int block_count = blocks_.length();
    3569     4776810 :   for (int i = 0; i < block_count; ++i) {
    3570     5093051 :     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
    3571      299722 :       HPhi* phi = blocks_[i]->phis()->at(j);
    3572             :       // We don't support phi uses of arguments for now.
    3573      599444 :       if (phi->CheckFlag(HValue::kIsArguments)) return false;
    3574             :     }
    3575             :   }
    3576             :   return true;
    3577             : }
    3578             : 
    3579             : 
    3580      283242 : bool HGraph::CheckConstPhiUses() {
    3581     5441366 :   int block_count = blocks_.length();
    3582     4778746 :   for (int i = 0; i < block_count; ++i) {
    3583     5820703 :     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
    3584      662620 :       HPhi* phi = blocks_[i]->phis()->at(j);
    3585             :       // Check for the hole value (from an uninitialized const).
    3586     3995610 :       for (int k = 0; k < phi->OperandCount(); k++) {
    3587     1335226 :         if (phi->OperandAt(k) == GetConstantHole()) return false;
    3588             :       }
    3589             :     }
    3590             :   }
    3591             :   return true;
    3592             : }
    3593             : 
    3594             : 
    3595      882024 : void HGraph::CollectPhis() {
    3596     5092415 :   int block_count = blocks_.length();
    3597      283197 :   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
    3598     4776785 :   for (int i = 0; i < block_count; ++i) {
    3599     5124848 :     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
    3600      315630 :       HPhi* phi = blocks_[i]->phis()->at(j);
    3601      315630 :       phi_list_->Add(phi, zone());
    3602             :     }
    3603             :   }
    3604      283197 : }
    3605             : 
    3606             : 
    3607             : // Implementation of utility class to encapsulate the translation state for
    3608             : // a (possibly inlined) function.
    3609      976003 : 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      741736 :       outer_(owner->function_state()) {
    3626      370868 :   if (outer_ != NULL) {
    3627             :     // State for an inline function.
    3628      107436 :     if (owner->ast_context()->IsTest()) {
    3629      585740 :       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
    3630       19395 :       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
    3631             :       if_true->MarkAsInlineReturnTarget(owner->current_block());
    3632             :       if_false->MarkAsInlineReturnTarget(owner->current_block());
    3633       19395 :       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       38790 :       test_context_ = new TestContext(owner, cond, if_true, if_false);
    3638             :     } else {
    3639       88041 :       function_return_ = owner->graph()->CreateBasicBlock();
    3640             :       function_return()->MarkAsInlineReturnTarget(owner->current_block());
    3641             :     }
    3642             :     // Set this after possibly allocating a new TestContext above.
    3643      107436 :     call_context_ = owner->ast_context();
    3644             :   }
    3645             : 
    3646             :   // Push on the state stack.
    3647             :   owner->set_function_state(this);
    3648             : 
    3649      370868 :   if (owner->is_tracking_positions()) {
    3650         122 :     outer_source_position_ = owner->source_position();
    3651             :     owner->EnterInlinedSource(inlining_id);
    3652         244 :     owner->SetSourcePosition(info->shared_info()->start_position());
    3653             :   }
    3654      370868 : }
    3655             : 
    3656             : 
    3657      107436 : FunctionState::~FunctionState() {
    3658      107436 :   delete test_context_;
    3659      107439 :   owner_->set_function_state(outer_);
    3660             : 
    3661      107436 :   if (owner_->is_tracking_positions()) {
    3662             :     owner_->set_source_position(outer_source_position_);
    3663           3 :     owner_->EnterInlinedSource(outer_->inlining_id());
    3664             :   }
    3665      107436 : }
    3666             : 
    3667             : 
    3668             : // Implementation of utility classes to represent an expression's context in
    3669             : // the AST.
    3670     7313663 : AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
    3671             :     : owner_(owner),
    3672             :       kind_(kind),
    3673             :       outer_(owner->ast_context()),
    3674    14627326 :       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           0 : }
    3681             : 
    3682             : 
    3683     7313660 : AstContext::~AstContext() {
    3684     7313660 :   owner_->set_ast_context(outer_);  // Pop.
    3685           0 : }
    3686             : 
    3687             : 
    3688      923364 : 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           0 : }
    3694             : 
    3695             : 
    3696     5359098 : 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           0 : }
    3702             : 
    3703             : 
    3704      656862 : void EffectContext::ReturnValue(HValue* value) {
    3705             :   // The value is simply ignored.
    3706      656862 : }
    3707             : 
    3708             : 
    3709     2629657 : 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     2629657 :   if (value->CheckFlag(HValue::kIsArguments)) {
    3713        1802 :     if (flag_ == ARGUMENTS_FAKED) {
    3714     2629928 :       value = owner()->graph()->GetConstantUndefined();
    3715        1774 :     } else if (!arguments_allowed()) {
    3716             :       owner()->Bailout(kBadValueContextForArgumentsValue);
    3717             :     }
    3718             :   }
    3719     2629657 :   owner()->Push(value);
    3720     2629658 : }
    3721             : 
    3722             : 
    3723       22610 : void TestContext::ReturnValue(HValue* value) {
    3724       22772 :   BuildBranch(value);
    3725       22610 : }
    3726             : 
    3727             : 
    3728      193692 : void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
    3729             :   DCHECK(!instr->IsControlInstruction());
    3730      336769 :   owner()->AddInstruction(instr);
    3731      193692 :   if (instr->HasObservableSideEffects()) {
    3732      143077 :     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    3733             :   }
    3734      193692 : }
    3735             : 
    3736             : 
    3737         108 : void EffectContext::ReturnControl(HControlInstruction* instr,
    3738             :                                   BailoutId ast_id) {
    3739             :   DCHECK(!instr->HasObservableSideEffects());
    3740         432 :   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
    3741         108 :   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
    3742         108 :   instr->SetSuccessorAt(0, empty_true);
    3743         108 :   instr->SetSuccessorAt(1, empty_false);
    3744         108 :   owner()->FinishCurrentBlock(instr);
    3745         108 :   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
    3746             :   owner()->set_current_block(join);
    3747         108 : }
    3748             : 
    3749             : 
    3750           0 : 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           0 :   if (!continuation->IsTrueReachable()) {
    3756           0 :     owner()->set_current_block(false_branch);
    3757           0 :   } else if (!continuation->IsFalseReachable()) {
    3758             :     owner()->set_current_block(true_branch);
    3759             :   } else {
    3760           0 :     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
    3761             :     owner()->set_current_block(join);
    3762             :   }
    3763           0 : }
    3764             : 
    3765             : 
    3766     2698665 : void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
    3767             :   DCHECK(!instr->IsControlInstruction());
    3768     5048166 :   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
    3769     8868226 :     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
    3770             :   }
    3771     2698665 :   owner()->AddInstruction(instr);
    3772     2698665 :   owner()->Push(instr);
    3773     2698665 :   if (instr->HasObservableSideEffects()) {
    3774      772231 :     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    3775             :   }
    3776             : }
    3777             : 
    3778             : 
    3779       16748 : void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
    3780             :   DCHECK(!instr->HasObservableSideEffects());
    3781       32297 :   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
    3782      200976 :     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
    3783             :   }
    3784       16748 :   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
    3785       16748 :   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
    3786       16748 :   instr->SetSuccessorAt(0, materialize_true);
    3787       16748 :   instr->SetSuccessorAt(1, materialize_false);
    3788       16748 :   owner()->FinishCurrentBlock(instr);
    3789             :   owner()->set_current_block(materialize_true);
    3790       33496 :   owner()->Push(owner()->graph()->GetConstantTrue());
    3791             :   owner()->set_current_block(materialize_false);
    3792       33496 :   owner()->Push(owner()->graph()->GetConstantFalse());
    3793             :   HBasicBlock* join =
    3794       16748 :     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
    3795             :   owner()->set_current_block(join);
    3796             : }
    3797             : 
    3798             : 
    3799           0 : 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           0 :   if (continuation->IsTrueReachable()) {
    3805           0 :     owner()->set_current_block(materialize_true);
    3806           0 :     owner()->Push(owner()->graph()->GetConstantTrue());
    3807             :     owner()->set_current_block(materialize_true);
    3808             :   }
    3809           0 :   if (continuation->IsFalseReachable()) {
    3810             :     owner()->set_current_block(materialize_false);
    3811           0 :     owner()->Push(owner()->graph()->GetConstantFalse());
    3812             :     owner()->set_current_block(materialize_false);
    3813             :   }
    3814           0 :   if (continuation->TrueAndFalseReachable()) {
    3815             :     HBasicBlock* join =
    3816           0 :         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
    3817             :     owner()->set_current_block(join);
    3818             :   }
    3819           0 : }
    3820             : 
    3821             : 
    3822      273278 : void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
    3823             :   DCHECK(!instr->IsControlInstruction());
    3824      273278 :   HOptimizedGraphBuilder* builder = owner();
    3825      273278 :   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      273278 :   if (instr->HasObservableSideEffects()) {
    3829      107802 :     builder->Push(instr);
    3830      107802 :     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    3831             :     builder->Pop();
    3832             :   }
    3833      273278 :   BuildBranch(instr);
    3834      273278 : }
    3835             : 
    3836             : 
    3837     2350521 : void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
    3838             :   DCHECK(!instr->HasObservableSideEffects());
    3839     3917535 :   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
    3840      783507 :   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
    3841      783507 :   instr->SetSuccessorAt(0, empty_true);
    3842      783507 :   instr->SetSuccessorAt(1, empty_false);
    3843      783507 :   owner()->FinishCurrentBlock(instr);
    3844      783507 :   owner()->Goto(empty_true, if_true(), owner()->function_state());
    3845      783507 :   owner()->Goto(empty_false, if_false(), owner()->function_state());
    3846             :   owner()->set_current_block(NULL);
    3847      783507 : }
    3848             : 
    3849             : 
    3850        1706 : void TestContext::ReturnContinuation(HIfContinuation* continuation,
    3851        1706 :                                      BailoutId ast_id) {
    3852             :   HBasicBlock* true_branch = NULL;
    3853             :   HBasicBlock* false_branch = NULL;
    3854             :   continuation->Continue(&true_branch, &false_branch);
    3855         853 :   if (continuation->IsTrueReachable()) {
    3856        2559 :     owner()->Goto(true_branch, if_true(), owner()->function_state());
    3857             :   }
    3858         853 :   if (continuation->IsFalseReachable()) {
    3859         853 :     owner()->Goto(false_branch, if_false(), owner()->function_state());
    3860             :   }
    3861             :   owner()->set_current_block(NULL);
    3862         853 : }
    3863             : 
    3864             : 
    3865      888150 : 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      296050 :   HOptimizedGraphBuilder* builder = owner();
    3871      592100 :   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
    3872             :     builder->Bailout(kArgumentsObjectValueInATestContext);
    3873             :   }
    3874      296050 :   ToBooleanHints expected(condition()->to_boolean_types());
    3875      296050 :   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
    3876      296050 : }
    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           0 : void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
    3902             :   current_info()->AbortOptimization(reason);
    3903             :   SetStackOverflow();
    3904           0 : }
    3905             : 
    3906             : 
    3907      922453 : void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
    3908             :   EffectContext for_effect(this);
    3909      922453 :   Visit(expr);
    3910      922453 : }
    3911             : 
    3912             : 
    3913     5044787 : void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
    3914             :                                            ArgumentsAllowedFlag flag) {
    3915             :   ValueContext for_value(this, flag);
    3916     5044787 :   Visit(expr);
    3917     5044784 : }
    3918             : 
    3919             : 
    3920      106415 : void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
    3921             :   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
    3922             :   for_value.set_typeof_mode(INSIDE_TYPEOF);
    3923      106415 :   Visit(expr);
    3924      106415 : }
    3925             : 
    3926             : 
    3927     1011803 : void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
    3928             :                                              HBasicBlock* true_block,
    3929             :                                              HBasicBlock* false_block) {
    3930             :   TestContext for_control(this, expr, true_block, false_block);
    3931     1011803 :   Visit(expr);
    3932     1011803 : }
    3933             : 
    3934             : 
    3935      621214 : void HOptimizedGraphBuilder::VisitExpressions(
    3936      993658 :     ZoneList<Expression*>* exprs) {
    3937     3229494 :   for (int i = 0; i < exprs->length(); ++i) {
    3938     4223277 :     CHECK_ALIVE(VisitForValue(exprs->at(i)));
    3939             :   }
    3940             : }
    3941             : 
    3942             : 
    3943      114573 : void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
    3944      105859 :                                               ArgumentsAllowedFlag flag) {
    3945      440830 :   for (int i = 0; i < exprs->length(); ++i) {
    3946      546706 :     CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
    3947             :   }
    3948             : }
    3949             : 
    3950             : 
    3951      786648 : bool HOptimizedGraphBuilder::BuildGraph() {
    3952      526865 :   if (IsDerivedConstructor(current_info()->literal()->kind())) {
    3953             :     Bailout(kSuperReference);
    3954           0 :     return false;
    3955             :   }
    3956             : 
    3957      263432 :   DeclarationScope* scope = current_info()->scope();
    3958      263432 :   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     1086859 :   HEnvironment* initial_env = environment()->CopyWithoutHistory();
    3976      263433 :   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
    3977             :   Goto(body_entry);
    3978             :   body_entry->SetJoinId(BailoutId::FunctionEntry());
    3979             :   set_current_block(body_entry);
    3980             : 
    3981      263433 :   VisitDeclarations(scope->declarations());
    3982             :   Add<HSimulate>(BailoutId::Declarations());
    3983             : 
    3984      263433 :   Add<HStackCheck>(HStackCheck::kFunctionEntry);
    3985             : 
    3986      263433 :   VisitStatements(current_info()->literal()->body());
    3987      263433 :   if (HasStackOverflow()) return false;
    3988             : 
    3989      259782 :   if (current_block() != NULL) {
    3990       44081 :     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      519564 :   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      259782 :       !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      519564 :       current_info()->IsStub() ||
    4011      779346 :       current_info()->shared_info()->deopt_count() + 1 < FLAG_max_deopt_count);
    4012             : 
    4013             :   // Perform any necessary OSR-specific cleanups or changes to the graph.
    4014      259782 :   osr()->FinishGraph();
    4015             : 
    4016      259782 :   return true;
    4017             : }
    4018             : 
    4019             : 
    4020      845946 : bool HGraph::Optimize(BailoutReason* bailout_reason) {
    4021      283243 :   OrderBlocks();
    4022      283243 :   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      562749 :   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
    4036      279506 :     Run<HEnvironmentLivenessAnalysisPhase>();
    4037             :   }
    4038             : 
    4039      283243 :   if (!CheckConstPhiUses()) {
    4040          43 :     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
    4041          43 :     return false;
    4042             :   }
    4043      283199 :   Run<HRedundantPhiEliminationPhase>();
    4044      283200 :   if (!CheckArgumentsPhiUses()) {
    4045           3 :     *bailout_reason = kUnsupportedPhiUseOfArguments;
    4046           3 :     return false;
    4047             :   }
    4048             : 
    4049             :   // Find and mark unreachable code to simplify optimizations, especially gvn,
    4050             :   // where unreachable code could unnecessarily defeat LICM.
    4051      283197 :   Run<HMarkUnreachableBlocksPhase>();
    4052             : 
    4053      283197 :   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
    4054      283196 :   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
    4055             : 
    4056      283197 :   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
    4057             : 
    4058      283197 :   CollectPhis();
    4059             : 
    4060      283197 :   if (has_osr()) osr()->FinishOsrValues();
    4061             : 
    4062      283197 :   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      283197 :   Run<HMergeRemovableSimulatesPhase>();
    4068             : 
    4069      283196 :   Run<HRepresentationChangesPhase>();
    4070             : 
    4071      283197 :   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      283197 :   Run<HUint32AnalysisPhase>();
    4077             : 
    4078      283197 :   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
    4079             : 
    4080      283197 :   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
    4081             : 
    4082      283197 :   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
    4083             : 
    4084      283197 :   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
    4085             : 
    4086      283197 :   Run<HRangeAnalysisPhase>();
    4087             : 
    4088             :   // Eliminate redundant stack checks on backwards branches.
    4089      283197 :   Run<HStackCheckEliminationPhase>();
    4090             : 
    4091      283197 :   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
    4092      283196 :   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
    4093      283195 :   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
    4094             : 
    4095      283195 :   RestoreActualValues();
    4096             : 
    4097             :   // Find unreachable code a second time, GVN and other optimizations may have
    4098             :   // made blocks unreachable that were previously reachable.
    4099      283197 :   Run<HMarkUnreachableBlocksPhase>();
    4100             : 
    4101      283197 :   return true;
    4102             : }
    4103             : 
    4104             : 
    4105      283192 : void HGraph::RestoreActualValues() {
    4106             :   HPhase phase("H_Restore actual values", this);
    4107             : 
    4108     4776647 :   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
    4109     4493450 :     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    29624382 :     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
    4119             :       HInstruction* instruction = it.Current();
    4120    25130936 :       if (instruction->ActualValue() == instruction) continue;
    4121      317881 :       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        6573 :         instruction->DeleteAndReplaceWith(instruction->ActualValue());
    4126             :       } else {
    4127             :         DCHECK(instruction->IsInformativeDefinition());
    4128      311308 :         if (instruction->IsPurelyInformativeDefinition()) {
    4129           0 :           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
    4130             :         } else {
    4131      311312 :           instruction->ReplaceAllUsesWith(instruction->ActualValue());
    4132             :         }
    4133             :       }
    4134             :     }
    4135      283197 :   }
    4136      283197 : }
    4137             : 
    4138             : 
    4139      595778 : void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
    4140     2598183 :   ZoneList<HValue*> arguments(count, zone());
    4141     2002405 :   for (int i = 0; i < count; ++i) {
    4142             :     arguments.Add(Pop(), zone());
    4143             :   }
    4144             : 
    4145      595778 :   HPushArguments* push_args = New<HPushArguments>();
    4146     2598182 :   while (!arguments.is_empty()) {
    4147     1406627 :     push_args->AddInput(arguments.RemoveLast());
    4148             :   }
    4149      595777 :   AddInstruction(push_args);
    4150      595777 : }
    4151             : 
    4152             : 
    4153             : template <class Instruction>
    4154         373 : HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
    4155         373 :   PushArgumentsFromEnvironment(call->argument_count());
    4156         373 :   return call;
    4157             : }
    4158             : 
    4159      790299 : void HOptimizedGraphBuilder::SetUpScope(DeclarationScope* scope) {
    4160     1380272 :   HEnvironment* prolog_env = environment();
    4161      263433 :   int parameter_count = environment()->parameter_count();
    4162      263433 :   ZoneList<HValue*> parameters(parameter_count, zone());
    4163      690138 :   for (int i = 0; i < parameter_count; ++i) {
    4164      426705 :     HInstruction* parameter = Add<HParameter>(static_cast<unsigned>(i));
    4165             :     parameters.Add(parameter, zone());
    4166             :     environment()->Bind(i, parameter);
    4167             :   }
    4168             : 
    4169      263433 :   HConstant* undefined_constant = graph()->GetConstantUndefined();
    4170             :   // Initialize specials and locals to undefined.
    4171     1199638 :   for (int i = parameter_count + 1; i < environment()->length(); ++i) {
    4172             :     environment()->Bind(i, undefined_constant);
    4173             :   }
    4174      263433 :   Add<HPrologue>();
    4175             : 
    4176      263433 :   HEnvironment* initial_env = environment()->CopyWithoutHistory();
    4177      263433 :   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      263431 :   prolog_env->BindContext(undefined_constant);
    4183             : 
    4184             :   // First special is HContext.
    4185      263432 :   HInstruction* context = Add<HContext>();
    4186      263432 :   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      263432 :   HArgumentsObject* arguments_object = New<HArgumentsObject>(parameter_count);
    4192      690134 :   for (int i = 0; i < parameter_count; ++i) {
    4193      426701 :     HValue* parameter = parameters.at(i);
    4194      426701 :     arguments_object->AddArgument(parameter, zone());
    4195             :   }
    4196             : 
    4197      263433 :   AddInstruction(arguments_object);
    4198             : 
    4199             :   // Handle the arguments and arguments shadow variables specially (they do
    4200             :   // not have declarations).
    4201      263433 :   if (scope->arguments() != NULL) {
    4202         854 :     environment()->Bind(scope->arguments(), arguments_object);
    4203             :   }
    4204             : 
    4205      263433 :   if (scope->rest_parameter() != nullptr) {
    4206             :     return Bailout(kRestParameter);
    4207             :   }
    4208             : 
    4209      526866 :   if (scope->this_function_var() != nullptr ||
    4210             :       scope->new_target_var() != nullptr) {
    4211             :     return Bailout(kSuperReference);
    4212             :   }
    4213             : 
    4214             :   // Trace the call.
    4215      263433 :   if (FLAG_trace && top_info()->IsOptimizing()) {
    4216           0 :     Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kTraceEnter), 0);
    4217             :   }
    4218             : }
    4219             : 
    4220             : 
    4221     3144400 : void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
    4222     5496208 :   for (int i = 0; i < statements->length(); i++) {
    4223     4807138 :     Statement* stmt = statements->at(i);
    4224     5203434 :     CHECK_ALIVE(Visit(stmt));
    4225     1665872 :     if (stmt->IsJump()) break;
    4226             :   }
    4227             : }
    4228             : 
    4229             : 
    4230     2056845 : void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
    4231             :   DCHECK(!HasStackOverflow());
    4232             :   DCHECK(current_block() != NULL);
    4233             :   DCHECK(current_block()->HasPredecessor());
    4234             : 
    4235      694460 :   Scope* outer_scope = scope();
    4236             :   Scope* scope = stmt->scope();
    4237             :   BreakAndContinueInfo break_info(stmt, outer_scope);
    4238             : 
    4239             :   { BreakAndContinueScope push(&break_info, this);
    4240      685615 :     if (scope != NULL) {
    4241        8478 :       if (scope->NeedsContext()) {
    4242             :         // Load the function object.
    4243         892 :         DeclarationScope* declaration_scope = scope->GetDeclarationScope();
    4244             :         HInstruction* function;
    4245             :         HValue* outer_context = environment()->context();
    4246         892 :         if (declaration_scope->is_script_scope() ||
    4247             :             declaration_scope->is_eval_scope()) {
    4248             :           function = new (zone())
    4249             :               HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
    4250         727 :                                HLoadContextSlot::kNoCheck);
    4251             :         } else {
    4252         165 :           function = New<HThisFunction>();
    4253             :         }
    4254         892 :         AddInstruction(function);
    4255             :         // Allocate a block context and store it to the stack frame.
    4256         892 :         HValue* scope_info = Add<HConstant>(scope->scope_info());
    4257         892 :         Add<HPushArguments>(scope_info, function);
    4258             :         HInstruction* inner_context = Add<HCallRuntime>(
    4259         892 :             Runtime::FunctionForId(Runtime::kPushBlockContext), 2);
    4260             :         inner_context->SetFlag(HValue::kHasNoObservableSideEffects);
    4261             :         set_scope(scope);
    4262         892 :         environment()->BindContext(inner_context);
    4263             :       }
    4264        8478 :       VisitDeclarations(scope->declarations());
    4265             :       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
    4266             :     }
    4267     2056845 :     CHECK_BAILOUT(VisitStatements(stmt->statements()));
    4268             :   }
    4269             :   set_scope(outer_scope);
    4270      698955 :   if (scope != NULL && current_block() != NULL &&
    4271        7252 :       scope->ContextLocalCount() > 0) {
    4272             :     HValue* inner_context = environment()->context();
    4273             :     HValue* outer_context = Add<HLoadNamedField>(
    4274             :         inner_context, nullptr,
    4275         869 :         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    4276             : 
    4277         869 :     environment()->BindContext(outer_context);
    4278             :   }
    4279      683654 :   HBasicBlock* break_block = break_info.break_block();
    4280      683654 :   if (break_block != NULL) {
    4281          69 :     if (current_block() != NULL) Goto(break_block);
    4282             :     break_block->SetJoinId(stmt->ExitId());
    4283             :     set_current_block(break_block);
    4284             :   }
    4285             : }
    4286             : 
    4287             : 
    4288      911753 : void HOptimizedGraphBuilder::VisitExpressionStatement(
    4289      912070 :     ExpressionStatement* stmt) {
    4290             :   DCHECK(!HasStackOverflow());
    4291             :   DCHECK(current_block() != NULL);
    4292             :   DCHECK(current_block()->HasPredecessor());
    4293      912070 :   VisitForEffect(stmt->expression());
    4294      911753 : }
    4295             : 
    4296             : 
    4297      389599 : void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
    4298             :   DCHECK(!HasStackOverflow());
    4299             :   DCHECK(current_block() != NULL);
    4300             :   DCHECK(current_block()->HasPredecessor());
    4301      389599 : }
    4302             : 
    4303             : 
    4304         371 : void HOptimizedGraphBuilder::VisitSloppyBlockFunctionStatement(
    4305         371 :     SloppyBlockFunctionStatement* stmt) {
    4306         371 :   Visit(stmt->statement());
    4307         371 : }
    4308             : 
    4309             : 
    4310     3311637 : void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
    4311             :   DCHECK(!HasStackOverflow());
    4312             :   DCHECK(current_block() != NULL);
    4313             :   DCHECK(current_block()->HasPredecessor());
    4314      414256 :   if (stmt->condition()->ToBooleanIsTrue()) {
    4315     1655145 :     Add<HSimulate>(stmt->ThenId());
    4316          33 :     Visit(stmt->then_statement());
    4317      414223 :   } else if (stmt->condition()->ToBooleanIsFalse()) {
    4318         427 :     Add<HSimulate>(stmt->ElseId());
    4319         427 :     Visit(stmt->else_statement());
    4320             :   } else {
    4321      413796 :     HBasicBlock* cond_true = graph()->CreateBasicBlock();
    4322      413796 :     HBasicBlock* cond_false = graph()->CreateBasicBlock();
    4323      827592 :     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      413793 :     CHECK(cond_true->HasPredecessor());
    4332      413793 :     CHECK(cond_false->HasPredecessor());
    4333             : 
    4334             :     cond_true->SetJoinId(stmt->ThenId());
    4335             :     set_current_block(cond_true);
    4336      827586 :     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      827520 :     CHECK_BAILOUT(Visit(stmt->else_statement()));
    4342             :     cond_false = current_block();
    4343             : 
    4344      413760 :     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
    4345             :     set_current_block(join);
    4346             :   }
    4347             : }
    4348             : 
    4349             : 
    4350        8143 : HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
    4351             :     BreakableStatement* stmt,
    4352             :     BreakType type,
    4353             :     Scope** scope,
    4354             :     int* drop_extra) {
    4355        8143 :   *drop_extra = 0;
    4356       65928 :   BreakAndContinueScope* current = this;
    4357       41413 :   while (current != NULL && current->info()->target() != stmt) {
    4358        8492 :     *drop_extra += current->info()->drop_extra();
    4359             :     current = current->next();
    4360             :   }
    4361             :   DCHECK(current != NULL);  // Always found (unless stack is malformed).
    4362        8143 :   *scope = current->info()->scope();
    4363             : 
    4364        8143 :   if (type == BREAK) {
    4365        7601 :     *drop_extra += current->info()->drop_extra();
    4366             :   }
    4367             : 
    4368             :   HBasicBlock* block = NULL;
    4369        8143 :   switch (type) {
    4370             :     case BREAK:
    4371        7601 :       block = current->info()->break_block();
    4372        7601 :       if (block == NULL) {
    4373        3762 :         block = current->owner()->graph()->CreateBasicBlock();
    4374             :         current->info()->set_break_block(block);
    4375             :       }
    4376             :       break;
    4377             : 
    4378             :     case CONTINUE:
    4379         542 :       block = current->info()->continue_block();
    4380         542 :       if (block == NULL) {
    4381         449 :         block = current->owner()->graph()->CreateBasicBlock();
    4382             :         current->info()->set_continue_block(block);
    4383             :       }
    4384             :       break;
    4385             :   }
    4386             : 
    4387        8143 :   return block;
    4388             : }
    4389             : 
    4390             : 
    4391         544 : void HOptimizedGraphBuilder::VisitContinueStatement(
    4392        1086 :     ContinueStatement* stmt) {
    4393             :   DCHECK(!HasStackOverflow());
    4394             :   DCHECK(current_block() != NULL);
    4395             :   DCHECK(current_block()->HasPredecessor());
    4396             : 
    4397         544 :   if (function_state()->IsInsideDoExpressionScope()) {
    4398         546 :     return Bailout(kDoExpressionUnmodelable);
    4399             :   }
    4400             : 
    4401         542 :   Scope* outer_scope = NULL;
    4402         542 :   Scope* inner_scope = scope();
    4403         542 :   int drop_extra = 0;
    4404             :   HBasicBlock* continue_block = break_scope()->Get(
    4405             :       stmt->target(), BreakAndContinueScope::CONTINUE,
    4406         542 :       &outer_scope, &drop_extra);
    4407             :   HValue* context = environment()->context();
    4408         542 :   Drop(drop_extra);
    4409         542 :   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
    4410         542 :   if (context_pop_count > 0) {
    4411           0 :     while (context_pop_count-- > 0) {
    4412             :       HInstruction* context_instruction = Add<HLoadNamedField>(
    4413             :           context, nullptr,
    4414           0 :           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    4415             :       context = context_instruction;
    4416             :     }
    4417           0 :     environment()->BindContext(context);
    4418             :   }
    4419             : 
    4420             :   Goto(continue_block);
    4421             :   set_current_block(NULL);
    4422             : }
    4423             : 
    4424             : 
    4425       15206 : void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
    4426             :   DCHECK(!HasStackOverflow());
    4427             :   DCHECK(current_block() != NULL);
    4428             :   DCHECK(current_block()->HasPredecessor());
    4429             : 
    4430        7605 :   if (function_state()->IsInsideDoExpressionScope()) {
    4431        7609 :     return Bailout(kDoExpressionUnmodelable);
    4432             :   }
    4433             : 
    4434        7601 :   Scope* outer_scope = NULL;
    4435        7601 :   Scope* inner_scope = scope();
    4436        7601 :   int drop_extra = 0;
    4437             :   HBasicBlock* break_block = break_scope()->Get(
    4438             :       stmt->target(), BreakAndContinueScope::BREAK,
    4439        7601 :       &outer_scope, &drop_extra);
    4440             :   HValue* context = environment()->context();
    4441        7601 :   Drop(drop_extra);
    4442        7601 :   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
    4443        7601 :   if (context_pop_count > 0) {
    4444         804 :     while (context_pop_count-- > 0) {
    4445             :       HInstruction* context_instruction = Add<HLoadNamedField>(
    4446             :           context, nullptr,
    4447         402 :           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    4448             :       context = context_instruction;
    4449             :     }
    4450         402 :     environment()->BindContext(context);
    4451             :   }
    4452             :   Goto(break_block);
    4453             :   set_current_block(NULL);
    4454             : }
    4455             : 
    4456             : 
    4457     1421756 : void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
    4458             :   DCHECK(!HasStackOverflow());
    4459             :   DCHECK(current_block() != NULL);
    4460             :   DCHECK(current_block()->HasPredecessor());
    4461      263374 :   FunctionState* state = function_state();
    4462      263374 :   AstContext* context = call_context();
    4463      547435 :   if (context == NULL) {
    4464             :     // Not an inlined return, so an actual one.
    4465      611285 :     CHECK_ALIVE(VisitForValue(stmt->expression()));
    4466      283899 :     HValue* result = environment()->Pop();
    4467      283899 :     Add<HReturn>(result);
    4468      263374 :   } 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         207 :     if (context->IsTest()) {
    4473          33 :       CHECK_ALIVE(VisitForEffect(stmt->expression()));
    4474          22 :       context->ReturnValue(graph()->GetConstantTrue());
    4475         196 :     } else if (context->IsEffect()) {
    4476          66 :       CHECK_ALIVE(VisitForEffect(stmt->expression()));
    4477             :       Goto(function_return(), state);
    4478             :     } else {
    4479             :       DCHECK(context->IsValue());
    4480         522 :       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         174 :                                          LAST_JS_RECEIVER_TYPE);
    4487         174 :       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
    4488         174 :       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
    4489         174 :       typecheck->SetSuccessorAt(0, if_spec_object);
    4490         174 :       typecheck->SetSuccessorAt(1, not_spec_object);
    4491         174 :       FinishCurrentBlock(typecheck);
    4492             :       AddLeaveInlined(if_spec_object, return_value, state);
    4493             :       AddLeaveInlined(not_spec_object, receiver, state);
    4494             :     }
    4495      263167 :   } 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         156 :     CHECK_ALIVE(VisitForEffect(stmt->expression()));
    4499          52 :     if (context->IsTest()) {
    4500             :       HValue* rhs = environment()->arguments_environment()->Lookup(1);
    4501           8 :       context->ReturnValue(rhs);
    4502          44 :     } 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      263115 :     if (context->IsTest()) {
    4513      220549 :       TestContext* test = TestContext::cast(context);
    4514      220549 :       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
    4515       42566 :     } 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       18936 :       CHECK_ALIVE(VisitForValue(stmt->expression()));
    4521             :       Pop();
    4522             :       Goto(function_return(), state);
    4523             :     } else {
    4524             :       DCHECK(context->IsValue());
    4525      108741 :       CHECK_ALIVE(VisitForValue(stmt->expression()));
    4526             :       AddLeaveInlined(Pop(), state);
    4527             :     }
    4528             :   }
    4529             :   set_current_block(NULL);
    4530             : }
    4531             : 
    4532             : 
    4533           0 : void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
    4534             :   DCHECK(!HasStackOverflow());
    4535             :   DCHECK(current_block() != NULL);
    4536             :   DCHECK(current_block()->HasPredecessor());
    4537           0 :   return Bailout(kWithStatement);
    4538             : }
    4539             : 
    4540             : 
    4541      103420 : 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        4573 :   int clause_count = clauses->length();
    4548      165318 :   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
    4549             : 
    4550       13719 :   CHECK_ALIVE(VisitForValue(stmt->tag()));
    4551        4573 :   Add<HSimulate>(stmt->EntryId());
    4552             :   HValue* tag_value = Top();
    4553        4573 :   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       34085 :   for (int i = 0; i < clause_count; ++i) {
    4558       57636 :     CaseClause* clause = clauses->at(i);
    4559       29514 :     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       56248 :     CHECK_BAILOUT(VisitForValue(clause->label()));
    4567       28122 :     if (current_block() == NULL) return Bailout(kUnsupportedSwitchStatement);
    4568             :     HValue* label_value = Pop();
    4569             : 
    4570       28122 :     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       28122 :         ScriptPositionToSourcePosition(clause->label()->position()),
    4577       84366 :         PUSH_BEFORE_SIMULATE, clause->id());
    4578             : 
    4579       28122 :     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
    4580       28122 :     HBasicBlock* body_block = graph()->CreateBasicBlock();
    4581             :     body_blocks.Add(body_block, zone());
    4582       28122 :     compare->SetSuccessorAt(0, body_block);
    4583       28122 :     compare->SetSuccessorAt(1, next_test_block);
    4584       28122 :     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       33150 :     for (int i = 0; i < clause_count; ++i) {
    4604       57764 :       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       28882 :       if (clause->is_default()) {
    4610        1388 :         if (last_block == NULL) continue;
    4611             :         normal_block = last_block;
    4612             :         last_block = NULL;  // Cleared to indicate we've handled it.
    4613             :       } else {
    4614       54988 :         normal_block = body_blocks[i];
    4615             :       }
    4616             : 
    4617       28882 :       if (fall_through_block == NULL) {
    4618             :         set_current_block(normal_block);
    4619             :       } else {
    4620             :         HBasicBlock* join = CreateJoin(fall_through_block,
    4621             :                                        normal_block,
    4622        7049 :                                        clause->EntryId());
    4623             :         set_current_block(join);
    4624             :       }
    4625             : 
    4626       57764 :       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        4268 :   HBasicBlock* break_block = break_info.break_block();
    4634        4268 :   if (break_block == NULL) {
    4635             :     set_current_block(CreateJoin(fall_through_block,
    4636             :                                  last_block,
    4637        2757 :                                  stmt->ExitId()));
    4638             :   } else {
    4639        1511 :     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
    4640        1511 :     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       90916 : void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
    4647             :                                            BailoutId stack_check_id,
    4648       45458 :                                            HBasicBlock* loop_entry) {
    4649       45458 :   Add<HSimulate>(stack_check_id);
    4650             :   HStackCheck* stack_check =
    4651       45458 :       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
    4652             :   DCHECK(loop_entry->IsLoopHeader());
    4653             :   loop_entry->loop_information()->set_stack_check(stack_check);
    4654       45458 :   CHECK_BAILOUT(Visit(stmt->body()));
    4655             : }
    4656             : 
    4657             : 
    4658        2896 : void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
    4659             :   DCHECK(!HasStackOverflow());
    4660             :   DCHECK(current_block() != NULL);
    4661             :   DCHECK(current_block()->HasPredecessor());
    4662             :   DCHECK(current_block() != NULL);
    4663         720 :   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
    4664             : 
    4665        2378 :   BreakAndContinueInfo break_info(stmt, scope());
    4666             :   {
    4667             :     BreakAndContinueScope push(&break_info, this);
    4668        1244 :     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
    4669             :   }
    4670             :   HBasicBlock* body_exit = JoinContinue(
    4671        1244 :       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
    4672             :   HBasicBlock* loop_successor = NULL;
    4673         622 :   if (body_exit != NULL) {
    4674             :     set_current_block(body_exit);
    4675         616 :     loop_successor = graph()->CreateBasicBlock();
    4676         616 :     if (stmt->cond()->ToBooleanIsFalse()) {
    4677          98 :       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         518 :       body_exit = graph()->CreateBasicBlock();
    4684        1036 :       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
    4685             :     }
    4686        1134 :     if (body_exit != NULL && body_exit->HasPredecessor()) {
    4687             :       body_exit->SetJoinId(stmt->BackEdgeId());
    4688             :     } else {
    4689             :       body_exit = NULL;
    4690             :     }
    4691         616 :     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         622 :                                       break_info.break_block());
    4702             :   set_current_block(loop_exit);
    4703             : }
    4704             : 
    4705             : 
    4706       16876 : void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
    4707             :   DCHECK(!HasStackOverflow());
    4708             :   DCHECK(current_block() != NULL);
    4709             :   DCHECK(current_block()->HasPredecessor());
    4710             :   DCHECK(current_block() != NULL);
    4711        4219 :   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
    4712             : 
    4713             :   // If the condition is constant true, do not generate a branch.
    4714             :   HBasicBlock* loop_successor = NULL;
    4715       16873 :   HBasicBlock* body_entry = graph()->CreateBasicBlock();
    4716        4219 :   loop_successor = graph()->CreateBasicBlock();
    4717        8441 :   CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
    4718        4219 :   if (body_entry->HasPredecessor()) {
    4719             :     body_entry->SetJoinId(stmt->BodyId());
    4720             :     set_current_block(body_entry);
    4721             :   }
    4722        4219 :   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        4219 :   if (current_block() != NULL) {
    4730             :     BreakAndContinueScope push(&break_info, this);
    4731        8438 :     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
    4732             :   }
    4733             :   HBasicBlock* body_exit = JoinContinue(
    4734        8432 :       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        4216 :                                       break_info.break_block());
    4740             :   set_current_block(loop_exit);
    4741             : }
    4742             : 
    4743             : 
    4744      308905 : void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
    4745             :   DCHECK(!HasStackOverflow());
    4746             :   DCHECK(current_block() != NULL);
    4747             :   DCHECK(current_block()->HasPredecessor());
    4748       39603 :   if (stmt->init() != NULL) {
    4749      310864 :     CHECK_ALIVE(Visit(stmt->init()));
    4750             :   }
    4751             :   DCHECK(current_block() != NULL);
    4752       39603 :   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
    4753             : 
    4754       39603 :   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
    4755       39603 :   HBasicBlock* body_entry = graph()->CreateBasicBlock();
    4756       39603 :   if (stmt->cond() != NULL) {
    4757       77316 :     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
    4758       38594 :     if (body_entry->HasPredecessor()) {
    4759             :       body_entry->SetJoinId(stmt->BodyId());
    4760             :       set_current_block(body_entry);
    4761             :     }
    4762       38594 :     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         945 :     HControlInstruction* branch = New<HBranch>(graph()->GetConstantTrue());
    4771         945 :     branch->SetSuccessorAt(0, body_entry);
    4772         945 :     branch->SetSuccessorAt(1, loop_successor);
    4773         945 :     FinishCurrentBlock(branch);
    4774             :     set_current_block(body_entry);
    4775             :   }
    4776             : 
    4777             :   BreakAndContinueInfo break_info(stmt, scope());
    4778       39539 :   if (current_block() != NULL) {
    4779             :     BreakAndContinueScope push(&break_info, this);
    4780       79078 :     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
    4781             :   }
    4782             :   HBasicBlock* body_exit = JoinContinue(
    4783       78688 :       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
    4784             : 
    4785       39344 :   if (stmt->next() != NULL && body_exit != NULL) {
    4786             :     set_current_block(body_exit);
    4787       74856 :     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       39295 :                                       break_info.break_block());
    4796             :   set_current_block(loop_exit);
    4797             : }
    4798             : 
    4799             : 
    4800        4391 : void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
    4801             :   DCHECK(!HasStackOverflow());
    4802             :   DCHECK(current_block() != NULL);
    4803             :   DCHECK(current_block()->HasPredecessor());
    4804             : 
    4805        2229 :   if (!stmt->each()->IsVariableProxy() ||
    4806        2222 :       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
    4807          40 :     return Bailout(kForInStatementWithNonLocalEachVariable);
    4808             :   }
    4809             : 
    4810        2162 :   Variable* each_var = stmt->each()->AsVariableProxy()->var();
    4811             : 
    4812        4318 :   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
    4813             :   HValue* enumerable = Top();  // Leave enumerable at the top.
    4814             : 
    4815        1078 :   IfBuilder if_undefined_or_null(this);
    4816             :   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
    4817        1078 :       enumerable, graph()->GetConstantUndefined());
    4818        1078 :   if_undefined_or_null.Or();
    4819             :   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
    4820        1078 :       enumerable, graph()->GetConstantNull());
    4821             :   if_undefined_or_null.ThenDeopt(DeoptimizeReason::kUndefinedOrNullInForIn);
    4822        1078 :   if_undefined_or_null.End();
    4823        1078 :   BuildForInBody(stmt, each_var, enumerable);
    4824             : }
    4825             : 
    4826             : 
    4827        2156 : void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
    4828             :                                             Variable* each_var,
    4829        1078 :                                             HValue* enumerable) {
    4830       11625 :   Handle<Map> meta_map = isolate()->factory()->meta_map();
    4831        1078 :   bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
    4832        1078 :   BuildCheckHeapObject(enumerable);
    4833        1078 :   Add<HCheckInstanceType>(enumerable, HCheckInstanceType::IS_JS_RECEIVER);
    4834             :   Add<HSimulate>(stmt->ToObjectId());
    4835        1078 :   if (fast) {
    4836         842 :     HForInPrepareMap* map = Add<HForInPrepareMap>(enumerable);
    4837         842 :     Push(map);
    4838             :     Add<HSimulate>(stmt->EnumId());
    4839             :     Drop(1);
    4840         842 :     Add<HCheckMaps>(map, meta_map);
    4841             : 
    4842             :     HForInCacheArray* array = Add<HForInCacheArray>(
    4843         842 :         enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
    4844         842 :     HValue* enum_length = BuildEnumLength(map);
    4845             : 
    4846             :     HForInCacheArray* index_cache = Add<HForInCacheArray>(
    4847         842 :         enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
    4848             :     array->set_index_cache(index_cache);
    4849             : 
    4850         842 :     Push(map);
    4851         842 :     Push(array);
    4852         842 :     Push(enum_length);
    4853             :     Add<HSimulate>(stmt->PrepareId());
    4854             :   } else {
    4855             :     Runtime::FunctionId function_id = Runtime::kForInEnumerate;
    4856         236 :     Add<HPushArguments>(enumerable);
    4857             :     HCallRuntime* array =
    4858         236 :         Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
    4859         236 :     Push(array);
    4860             :     Add<HSimulate>(stmt->EnumId());
    4861             :     Drop(1);
    4862             : 
    4863             :     IfBuilder if_fast(this);
    4864         236 :     if_fast.If<HCompareMap>(array, meta_map);
    4865         236 :     if_fast.Then();
    4866             :     {
    4867             :       HValue* cache_map = array;
    4868             :       HForInCacheArray* cache = Add<HForInCacheArray>(
    4869         236 :           enumerable, cache_map, DescriptorArray::kEnumCacheBridgeCacheIndex);
    4870         236 :       HValue* enum_length = BuildEnumLength(cache_map);
    4871         236 :       Push(cache_map);
    4872         236 :       Push(cache);
    4873         236 :       Push(enum_length);
    4874         236 :       Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
    4875             :     }
    4876             :     if_fast.Else();
    4877             :     {
    4878         236 :       Push(graph()->GetConstant1());
    4879         236 :       Push(array);
    4880         236 :       Push(AddLoadFixedArrayLength(array));
    4881         236 :       Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
    4882             :     }
    4883             :   }
    4884             : 
    4885        1078 :   Push(graph()->GetConstant0());
    4886             : 
    4887        1078 :   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        1078 :       New<HCompareNumericAndBranch>(index, limit, Token::LT);
    4901             :   compare_index->set_observed_input_representation(
    4902             :       Representation::Smi(), Representation::Smi());
    4903             : 
    4904        1078 :   HBasicBlock* loop_body = graph()->CreateBasicBlock();
    4905        1078 :   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
    4906             : 
    4907        1078 :   compare_index->SetSuccessorAt(0, loop_body);
    4908        1078 :   compare_index->SetSuccessorAt(1, loop_successor);
    4909        1078 :   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        1078 :   HValue* key = Add<HLoadKeyed>(array, index, index, nullptr, FAST_ELEMENTS);
    4918             : 
    4919             :   HBasicBlock* continue_block = nullptr;
    4920        1078 :   if (fast) {
    4921             :     // Check if expected map still matches that of the enumerable.
    4922         842 :     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         236 :     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         236 :     HBasicBlock* if_fast = graph()->CreateBasicBlock();
    4933         236 :     HBasicBlock* if_slow = graph()->CreateBasicBlock();
    4934         236 :     HBasicBlock* if_slow_pass = graph()->CreateBasicBlock();
    4935         236 :     HBasicBlock* if_slow_skip = graph()->CreateBasicBlock();
    4936         236 :     HBasicBlock* if_join = graph()->CreateBasicBlock();
    4937             : 
    4938             :     // Check if expected map still matches that of the enumerable.
    4939             :     HValue* enumerable_map =
    4940         236 :         Add<HLoadNamedField>(enumerable, nullptr, HObjectAccess::ForMap());
    4941             :     FinishCurrentBlock(
    4942         236 :         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         236 :       Push(key);
    4947             :       Goto(if_join);
    4948             :     }
    4949             :     set_current_block(if_slow);
    4950             :     {
    4951         236 :       Callable callable = CodeFactory::ForInFilter(isolate());
    4952         236 :       HValue* values[] = {key, enumerable};
    4953         236 :       HConstant* stub_value = Add<HConstant>(callable.code());
    4954             :       Push(Add<HCallWithDescriptor>(stub_value, 0, callable.descriptor(),
    4955         236 :                                     ArrayVector(values)));
    4956             :       Add<HSimulate>(stmt->FilterId());
    4957             :       FinishCurrentBlock(New<HCompareObjectEqAndBranch>(
    4958         472 :           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        3234 :     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
    4981             :   }
    4982             : 
    4983             :   HBasicBlock* body_exit = JoinContinue(
    4984        2098 :       stmt, stmt->IncrementId(), current_block(), break_info.continue_block());
    4985             : 
    4986        1049 :   if (body_exit != NULL) {
    4987             :     set_current_block(body_exit);
    4988             : 
    4989             :     HValue* current_index = Pop();
    4990             :     HValue* increment =
    4991         992 :         AddUncasted<HAdd>(current_index, graph()->GetConstant1());
    4992             :     increment->ClearFlag(HValue::kCanOverflow);
    4993         992 :     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        1049 :                                       break_info.break_block());
    5002             : 
    5003             :   set_current_block(loop_exit);
    5004             : }
    5005             : 
    5006             : 
    5007           0 : void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
    5008             :   DCHECK(!HasStackOverflow());
    5009             :   DCHECK(current_block() != NULL);
    5010             :   DCHECK(current_block()->HasPredecessor());
    5011           0 :   return Bailout(kForOfStatement);
    5012             : }
    5013             : 
    5014             : 
    5015           0 : void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
    5016             :   DCHECK(!HasStackOverflow());
    5017             :   DCHECK(current_block() != NULL);
    5018             :   DCHECK(current_block()->HasPredecessor());
    5019           0 :   return Bailout(kTryCatchStatement);
    5020             : }
    5021             : 
    5022             : 
    5023           0 : void HOptimizedGraphBuilder::VisitTryFinallyStatement(
    5024             :     TryFinallyStatement* stmt) {
    5025             :   DCHECK(!HasStackOverflow());
    5026             :   DCHECK(current_block() != NULL);
    5027             :   DCHECK(current_block()->HasPredecessor());
    5028           0 :   return Bailout(kTryFinallyStatement);
    5029             : }
    5030             : 
    5031             : 
    5032           0 : void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
    5033             :   DCHECK(!HasStackOverflow());
    5034             :   DCHECK(current_block() != NULL);
    5035             :   DCHECK(current_block()->HasPredecessor());
    5036           0 :   return Bailout(kDebuggerStatement);
    5037             : }
    5038             : 
    5039             : 
    5040           0 : void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
    5041           0 :   UNREACHABLE();
    5042             : }
    5043             : 
    5044             : 
    5045      424473 : 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      409471 :       expr, current_info()->script(), top_info());
    5051             :   // We also have a stack overflow if the recursive compilation did.
    5052      104243 :   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      104243 :   HConstant* shared_info_value = Add<HConstant>(shared_info);
    5056             :   HInstruction* instr;
    5057             :   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
    5058      104243 :   HValue* vector_value = Add<HConstant>(vector);
    5059             :   int index = FeedbackVector::GetIndex(expr->LiteralFeedbackSlot());
    5060      104243 :   HValue* index_value = Add<HConstant>(index);
    5061      104243 :   if (!expr->pretenure()) {
    5062       96742 :     Callable callable = CodeFactory::FastNewClosure(isolate());
    5063       96742 :     HValue* values[] = {shared_info_value, vector_value, index_value};
    5064       96742 :     HConstant* stub_value = Add<HConstant>(callable.code());
    5065             :     instr = New<HCallWithDescriptor>(stub_value, 0, callable.descriptor(),
    5066       96742 :                                      ArrayVector(values));
    5067             :   } else {
    5068        7501 :     Add<HPushArguments>(shared_info_value);
    5069        7501 :     Add<HPushArguments>(vector_value);
    5070        7501 :     Add<HPushArguments>(index_value);
    5071             :     Runtime::FunctionId function_id =
    5072        7501 :         expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
    5073        7501 :     instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 3);
    5074             :   }
    5075      208486 :   return ast_context()->ReturnInstruction(instr, expr->id());
    5076             : }
    5077             : 
    5078             : 
    5079           0 : void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
    5080             :   DCHECK(!HasStackOverflow());
    5081             :   DCHECK(current_block() != NULL);
    5082             :   DCHECK(current_block()->HasPredecessor());
    5083           0 :   return Bailout(kClassLiteral);
    5084             : }
    5085             : 
    5086             : 
    5087           0 : void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
    5088             :     NativeFunctionLiteral* expr) {
    5089             :   DCHECK(!HasStackOverflow());
    5090             :   DCHECK(current_block() != NULL);
    5091             :   DCHECK(current_block()->HasPredecessor());
    5092           0 :   return Bailout(kNativeFunctionLiteral);
    5093             : }
    5094             : 
    5095             : 
    5096         204 : void HOptimizedGraphBuilder::VisitDoExpression(DoExpression* expr) {
    5097             :   DoExpressionScope scope(this);
    5098             :   DCHECK(!HasStackOverflow());
    5099             :   DCHECK(current_block() != NULL);
    5100             :   DCHECK(current_block()->HasPredecessor());
    5101         248 :   CHECK_ALIVE(VisitBlock(expr->block()));
    5102          18 :   Visit(expr->result());
    5103             : }
    5104             : 
    5105             : 
    5106       93616 : void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
    5107             :   DCHECK(!HasStackOverflow());
    5108             :   DCHECK(current_block() != NULL);
    5109             :   DCHECK(current_block()->HasPredecessor());
    5110       28105 :   HBasicBlock* cond_true = graph()->CreateBasicBlock();
    5111        9373 :   HBasicBlock* cond_false = graph()->CreateBasicBlock();
    5112       18746 :   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        9373 :   if (cond_true->HasPredecessor()) {
    5117             :     cond_true->SetJoinId(expr->ThenId());
    5118             :     set_current_block(cond_true);
    5119       18746 :     CHECK_BAILOUT(Visit(expr->then_expression()));
    5120             :     cond_true = current_block();
    5121             :   } else {
    5122             :     cond_true = NULL;
    5123             :   }
    5124             : 
    5125        9366 :   if (cond_false->HasPredecessor()) {
    5126             :     cond_false->SetJoinId(expr->ElseId());
    5127             :     set_current_block(cond_false);
    5128       18732 :     CHECK_BAILOUT(Visit(expr->else_expression()));
    5129             :     cond_false = current_block();
    5130             :   } else {
    5131             :     cond_false = NULL;
    5132             :   }
    5133             : 
    5134        9366 :   if (!ast_context()->IsTest()) {
    5135        9350 :     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
    5136             :     set_current_block(join);
    5137       18700 :     if (join != NULL && !ast_context()->IsEffect()) {
    5138       18606 :       return ast_context()->ReturnValue(Pop());
    5139             :     }
    5140             :   }
    5141             : }
    5142             : 
    5143           0 : bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess(
    5144             :     Variable* var, LookupIterator* it, PropertyAccessType access_type) {
    5145      365671 :   if (var->is_this()) return false;
    5146      365671 :   return CanInlineGlobalPropertyAccess(it, access_type);
    5147             : }
    5148             : 
    5149      365872 : bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess(
    5150      365872 :     LookupIterator* it, PropertyAccessType access_type) {
    5151      365872 :   if (!current_info()->has_global_object()) {
    5152             :     return false;
    5153             :   }
    5154             : 
    5155      365872 :   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      310284 :       if (access_type == STORE && it->IsReadOnly()) return false;
    5164      300120 :       if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return false;
    5165      300120 :       return true;
    5166             :     case LookupIterator::JSPROXY:
    5167             :     case LookupIterator::TRANSITION:
    5168           0 :       UNREACHABLE();
    5169             :   }
    5170           0 :   UNREACHABLE();
    5171             :   return false;
    5172             : }
    5173             : 
    5174             : 
    5175      856650 : HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
    5176             :   DCHECK(var->IsContextSlot());
    5177      428325 :   HValue* context = environment()->context();
    5178      428325 :   int length = scope()->ContextChainLength(var->scope());
    5179      859703 :   while (length-- > 0) {
    5180             :     context = Add<HLoadNamedField>(
    5181             :         context, nullptr,
    5182        3053 :         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    5183             :   }
    5184      428325 :   return context;
    5185             : }
    5186             : 
    5187      290056 : void HOptimizedGraphBuilder::InlineGlobalPropertyLoad(LookupIterator* it,
    5188      290056 :                                                       BailoutId ast_id) {
    5189      290056 :   Handle<PropertyCell> cell = it->GetPropertyCell();
    5190      566539 :   top_info()->dependencies()->AssumePropertyCell(cell);
    5191             :   auto cell_type = it->property_details().cell_type();
    5192      290056 :   if (cell_type == PropertyCellType::kConstant ||
    5193             :       cell_type == PropertyCellType::kUndefined) {
    5194             :     Handle<Object> constant_object(cell->value(), isolate());
    5195      274177 :     if (constant_object->IsConsString()) {
    5196         102 :       constant_object = String::Flatten(Handle<String>::cast(constant_object));
    5197             :     }
    5198      274177 :     HConstant* constant = New<HConstant>(constant_object);
    5199      274177 :     return ast_context()->ReturnInstruction(constant, ast_id);
    5200             :   } else {
    5201       15879 :     auto access = HObjectAccess::ForPropertyCellValue();
    5202             :     UniqueSet<Map>* field_maps = nullptr;
    5203       15879 :     if (cell_type == PropertyCellType::kConstantType) {
    5204        8829 :       switch (cell->GetConstantType()) {
    5205             :         case PropertyCellConstantType::kSmi:
    5206        6458 :           access = access.WithRepresentation(Representation::Smi());
    5207        6458 :           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        2371 :           access = access.WithRepresentation(Representation::HeapObject());
    5214             :           Handle<Map> map(HeapObject::cast(cell->value())->map());
    5215        2371 :           if (map->is_stable()) {
    5216             :             field_maps = new (zone())
    5217             :                 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
    5218             :           }
    5219             :           break;
    5220             :         }
    5221             :       }
    5222             :     }
    5223       15879 :     HConstant* cell_constant = Add<HConstant>(cell);
    5224             :     HLoadNamedField* instr;
    5225       15879 :     if (field_maps == nullptr) {
    5226       13573 :       instr = New<HLoadNamedField>(cell_constant, nullptr, access);
    5227             :     } else {
    5228             :       instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps,
    5229        2306 :                                    HType::HeapObject());
    5230             :     }
    5231             :     instr->ClearDependsOnFlag(kInobjectFields);
    5232             :     instr->SetDependsOnFlag(kGlobalVars);
    5233       15879 :     return ast_context()->ReturnInstruction(instr, ast_id);
    5234             :   }
    5235             : }
    5236             : 
    5237     5423096 : void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
    5238             :   DCHECK(!HasStackOverflow());
    5239             :   DCHECK(current_block() != NULL);
    5240             :   DCHECK(current_block()->HasPredecessor());
    5241     4715043 :   Variable* variable = expr->var();
    5242     2829281 :   switch (variable->location()) {
    5243             :     case VariableLocation::UNALLOCATED: {
    5244      361398 :       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     3310913 :           isolate()->factory()->GlobalConstantFor(variable->name());
    5252      361398 :       if (!constant_value.is_null()) {
    5253       11367 :         HConstant* instr = New<HConstant>(constant_value);
    5254       22734 :         return ast_context()->ReturnInstruction(instr, expr->id());
    5255             :       }
    5256             : 
    5257      350031 :       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      350031 :         if (ScriptContextTable::Lookup(script_contexts, variable->name(),
    5265             :                                        &lookup)) {
    5266             :           Handle<Context> script_context = ScriptContextTable::GetContext(
    5267        5544 :               script_contexts, lookup.context_index);
    5268             :           Handle<Object> current_value =
    5269       11088 :               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        5544 :           if (current_value->IsTheHole(isolate())) {
    5274             :             return Bailout(kReferenceToUninitializedVariable);
    5275             :           }
    5276             :           HInstruction* result = New<HLoadNamedField>(
    5277             :               Add<HConstant>(script_context), nullptr,
    5278        5542 :               HObjectAccess::ForContextSlot(lookup.slot_index));
    5279       11084 :           return ast_context()->ReturnInstruction(result, expr->id());
    5280             :         }
    5281             :       }
    5282             : 
    5283      344487 :       LookupIterator it(global, variable->name(), LookupIterator::OWN);
    5284      344487 :       it.TryLookupCachedProperty();
    5285      344487 :       if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) {
    5286      289913 :         InlineGlobalPropertyLoad(&it, expr->id());
    5287      289913 :         return;
    5288             :       } else {
    5289             :         Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
    5290             :         FeedbackSlot slot = expr->VariableFeedbackSlot();
    5291             :         DCHECK(vector->IsLoadGlobalIC(slot));
    5292             : 
    5293       54574 :         HValue* vector_value = Add<HConstant>(vector);
    5294       54574 :         HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
    5295             :         Callable callable = CodeFactory::LoadGlobalICInOptimizedCode(
    5296      109148 :             isolate(), ast_context()->typeof_mode());
    5297       54574 :         HValue* stub = Add<HConstant>(callable.code());
    5298       54574 :         HValue* name = Add<HConstant>(variable->name());
    5299       54574 :         HValue* values[] = {name, slot_value, vector_value};
    5300             :         HCallWithDescriptor* instr = New<HCallWithDescriptor>(
    5301             :             Code::LOAD_GLOBAL_IC, stub, 0, callable.descriptor(),
    5302       54574 :             ArrayVector(values));
    5303      109148 :         return ast_context()->ReturnInstruction(instr, expr->id());
    5304             :       }
    5305             :     }
    5306             : 
    5307             :     case VariableLocation::PARAMETER:
    5308             :     case VariableLocation::LOCAL: {
    5309     2080247 :       HValue* value = LookupAndMakeLive(variable);
    5310     2080245 :       if (value == graph()->GetConstantHole()) {
    5311             :         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
    5312             :                variable->mode() != VAR);
    5313             :         return Bailout(kReferenceToUninitializedVariable);
    5314             :       }
    5315     2080122 :       return ast_context()->ReturnValue(value);
    5316             :     }
    5317             : 
    5318             :     case VariableLocation::CONTEXT: {
    5319      387636 :       HValue* context = BuildContextChainWalk(variable);
    5320             :       HLoadContextSlot::Mode mode;
    5321      387636 :       switch (variable->mode()) {
    5322             :         case LET:
    5323             :         case CONST:
    5324             :           mode = HLoadContextSlot::kCheckDeoptimize;
    5325             :           break;
    5326             :         default:
    5327             :           mode = HLoadContextSlot::kNoCheck;
    5328      373898 :           break;
    5329             :       }
    5330             :       HLoadContextSlot* instr =
    5331      387636 :           new(zone()) HLoadContextSlot(context, variable->index(), mode);
    5332      775272 :       return ast_context()->ReturnInstruction(instr, expr->id());
    5333             :     }
    5334             : 
    5335             :     case VariableLocation::LOOKUP:
    5336             :       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
    5337             : 
    5338             :     case VariableLocation::MODULE:
    5339           0 :       UNREACHABLE();
    5340             :   }
    5341             : }
    5342             : 
    5343             : 
    5344     2300514 : void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
    5345             :   DCHECK(!HasStackOverflow());
    5346             :   DCHECK(current_block() != NULL);
    5347             :   DCHECK(current_block()->HasPredecessor());
    5348     1150257 :   HConstant* instr = New<HConstant>(expr->value());
    5349     2300514 :   return ast_context()->ReturnInstruction(instr, expr->id());
    5350             : }
    5351             : 
    5352             : 
    5353       34696 : void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
    5354             :   DCHECK(!HasStackOverflow());
    5355             :   DCHECK(current_block() != NULL);
    5356             :   DCHECK(current_block()->HasPredecessor());
    5357       17348 :   Callable callable = CodeFactory::FastCloneRegExp(isolate());
    5358             :   int index = FeedbackVector::GetIndex(expr->literal_slot());
    5359       17348 :   HValue* values[] = {AddThisFunction(), Add<HConstant>(index),
    5360        8674 :                       Add<HConstant>(expr->pattern()),
    5361       34696 :                       Add<HConstant>(expr->flags())};
    5362        8674 :   HConstant* stub_value = Add<HConstant>(callable.code());
    5363             :   HInstruction* instr = New<HCallWithDescriptor>(
    5364        8674 :       stub_value, 0, callable.descriptor(), ArrayVector(values));
    5365       17348 :   return ast_context()->ReturnInstruction(instr, expr->id());
    5366             : }
    5367             : 
    5368             : 
    5369      770944 : static bool CanInlinePropertyAccess(Handle<Map> map) {
    5370      770944 :   if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
    5371      767964 :   if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
    5372     1432690 :   return map->IsJSObjectMap() && !map->is_dictionary_map() &&
    5373     1436147 :          !map->has_named_interceptor() &&
    5374             :          // TODO(verwaest): Whitelist contexts to which we have access.
    5375      722513 :          !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        7333 : static bool IsFastLiteral(Handle<JSObject> boilerplate,
    5383             :                           int max_depth,
    5384             :                           int* max_properties) {
    5385        7357 :   if (boilerplate->map()->is_deprecated() &&
    5386          24 :       !JSObject::TryMigrateInstance(boilerplate)) {
    5387             :     return false;
    5388             :   }
    5389             : 
    5390             :   DCHECK(max_depth >= 0 && *max_properties >= 0);
    5391        7333 :   if (max_depth == 0) return false;
    5392             : 
    5393             :   Isolate* isolate = boilerplate->GetIsolate();
    5394             :   Handle<FixedArrayBase> elements(boilerplate->elements());
    5395        9929 :   if (elements->length() > 0 &&
    5396        2596 :       elements->map() != isolate->heap()->fixed_cow_array_map()) {
    5397        1834 :     if (boilerplate->HasFastSmiOrObjectElements()) {
    5398             :       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
    5399             :       int length = elements->length();
    5400        8230 :       for (int i = 0; i < length; i++) {
    5401        6834 :         if ((*max_properties)-- == 0) return false;
    5402             :         Handle<Object> value(fast_elements->get(i), isolate);
    5403        6834 :         if (value->IsJSObject()) {
    5404         313 :           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
    5405         313 :           if (!IsFastLiteral(value_object,
    5406             :                              max_depth - 1,
    5407         313 :                              max_properties)) {
    5408           0 :             return false;
    5409             :           }
    5410             :         }
    5411             :       }
    5412         438 :     } else if (boilerplate->HasFastDoubleElements()) {
    5413         436 :       if (elements->Size() > kMaxRegularHeapObjectSize) return false;
    5414             :     } else {
    5415             :       return false;
    5416             :     }
    5417             :   }
    5418             : 
    5419             :   Handle<FixedArray> properties(boilerplate->properties());
    5420        7326 :   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       18169 :     for (int i = 0; i < limit; i++) {
    5427       10843 :       PropertyDetails details = descriptors->GetDetails(i);
    5428       14307 :       if (details.location() != kField) continue;
    5429             :       DCHECK_EQ(kData, details.kind());
    5430        7458 :       if ((*max_properties)-- == 0) return false;
    5431        7458 :       FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
    5432        7458 :       if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
    5433             :       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
    5434        7379 :                            isolate);
    5435        7379 :       if (value->IsJSObject()) {
    5436         349 :         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
    5437         349 :         if (!IsFastLiteral(value_object,
    5438             :                            max_depth - 1,
    5439         349 :                            max_properties)) {
    5440           0 :           return false;
    5441             :         }
    5442             :       }
    5443             :     }
    5444             :   }
    5445             :   return true;
    5446             : }
    5447             : 
    5448             : 
    5449      176078 : void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
    5450             :   DCHECK(!HasStackOverflow());
    5451             :   DCHECK(current_block() != NULL);
    5452             :   DCHECK(current_block()->HasPredecessor());
    5453             : 
    5454       22922 :   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       22922 :   int max_properties = kMaxFastLiteralProperties;
    5459             :   Handle<Object> literals_cell(
    5460       96578 :       closure->feedback_vector()->Get(expr->literal_slot()), isolate());
    5461             :   Handle<AllocationSite> site;
    5462             :   Handle<JSObject> boilerplate;
    5463       22922 :   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       26471 :   if (!boilerplate.is_null() &&
    5471        3549 :       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
    5472             :     AllocationSiteUsageContext site_context(isolate(), site, false);
    5473        3547 :     site_context.EnterNewScope();
    5474        3547 :     literal = BuildFastLiteral(boilerplate, &site_context);
    5475             :     site_context.ExitScope(site, boilerplate);
    5476             :   } else {
    5477       19375 :     NoObservableSideEffectsScope no_effects(this);
    5478             :     Handle<BoilerplateDescription> constant_properties =
    5479       19375 :         expr->GetOrBuildConstantProperties(isolate());
    5480             :     int literal_index = FeedbackVector::GetIndex(expr->literal_slot());
    5481       19375 :     int flags = expr->ComputeFlags(true);
    5482             : 
    5483             :     Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
    5484             :                         Add<HConstant>(constant_properties),
    5485       19375 :                         Add<HConstant>(flags));
    5486             : 
    5487             :     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
    5488       19375 :     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       22922 :   Push(literal);
    5494      174268 :   for (int i = 0; i < expr->properties()->length(); i++) {
    5495       90217 :     ObjectLiteral::Property* property = expr->properties()->at(i);
    5496      140544 :     if (property->is_computed_name()) return Bailout(kComputedPropertyName);
    5497       64767 :     if (property->IsCompileTimeValue()) continue;
    5498             : 
    5499       25450 :     Literal* key = property->key()->AsLiteral();
    5500             :     Expression* value = property->value();
    5501             : 
    5502       25450 :     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       24940 :         if (key->IsStringLiteral()) {
    5510             :           DCHECK(key->IsPropertyName());
    5511       24913 :           if (property->emit_store()) {
    5512       74682 :             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       24876 :             FeedbackSlot slot = property->GetSlot();
    5519       24876 :             if (map.is_null()) {
    5520             :               // If we don't know the monomorphic type, do a generic store.
    5521       56226 :               CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
    5522             :                                                     name, value));
    5523             :             } else {
    5524        6134 :               PropertyAccessInfo info(this, STORE, map, name);
    5525        6134 :               if (info.CanAccessMonomorphic()) {
    5526        6134 :                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
    5527             :                 DCHECK(!info.IsAccessorConstant());
    5528             :                 info.MarkAsInitializingStore();
    5529             :                 store = BuildMonomorphicAccess(
    5530             :                     &info, literal, checked_literal, value,
    5531        6134 :                     BailoutId::None(), BailoutId::None());
    5532             :                 DCHECK_NOT_NULL(store);
    5533             :               } else {
    5534           0 :                 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
    5535             :                                                       literal, name, value));
    5536             :               }
    5537             :             }
    5538       24876 :             if (store->IsInstruction()) {
    5539       24876 :               AddInstruction(HInstruction::cast(store));
    5540             :             }
    5541             :             DCHECK(store->HasObservableSideEffects());
    5542       24876 :             Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
    5543             : 
    5544             :             // Add [[HomeObject]] to function literals.
    5545       24876 :             if (FunctionLiteral::NeedsHomeObject(property->value())) {
    5546             :               Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
    5547             :               HInstruction* store_home = BuildNamedGeneric(
    5548           1 :                   STORE, NULL, property->GetSlot(1), value, sym, literal);
    5549           1 :               AddInstruction(store_home);
    5550             :               DCHECK(store_home->HasObservableSideEffects());
    5551           1 :               Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
    5552             :             }
    5553             :           } else {
    5554          57 :             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           0 :       default: UNREACHABLE();
    5564             :     }
    5565             :   }
    5566             : 
    5567       44734 :   return ast_context()->ReturnValue(Pop());
    5568             : }
    5569             : 
    5570             : 
    5571       50726 : 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       17229 :   int length = subexprs->length();
    5577             :   HInstruction* literal;
    5578             : 
    5579             :   Handle<AllocationSite> site;
    5580             :   Handle<FeedbackVector> vector(environment()->closure()->feedback_vector(),
    5581       74199 :                                 isolate());
    5582             :   Handle<Object> literals_cell(vector->Get(expr->literal_slot()), isolate());
    5583             :   Handle<JSObject> boilerplate_object;
    5584       17229 :   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       17229 :   int max_properties = kMaxFastLiteralProperties;
    5593       20351 :   if (!boilerplate_object.is_null() &&
    5594             :       IsFastLiteral(boilerplate_object, kMaxFastLiteralDepth,
    5595        3122 :                     &max_properties)) {
    5596             :     DCHECK(site->SitePointsToLiteral());
    5597             :     AllocationSiteUsageContext site_context(isolate(), site, false);
    5598        3117 :     site_context.EnterNewScope();
    5599        3117 :     literal = BuildFastLiteral(boilerplate_object, &site_context);
    5600             :     site_context.ExitScope(site, boilerplate_object);
    5601             :   } else {
    5602       14112 :     NoObservableSideEffectsScope no_effects(this);
    5603             :     Handle<ConstantElementsPair> constants =
    5604       14112 :         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       14112 :                         Add<HConstant>(constants), Add<HConstant>(flags));
    5610             : 
    5611             :     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
    5612       14112 :     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
    5613             : 
    5614             :     // Register to deopt if the boilerplate ElementsKind changes.
    5615       14112 :     if (!site.is_null()) {
    5616           5 :       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       17229 :   Push(literal);
    5623             : 
    5624             :   HInstruction* elements = NULL;
    5625             : 
    5626      965494 :   for (int i = 0; i < length; i++) {
    5627      948274 :     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      948274 :     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
    5633             : 
    5634       48822 :     CHECK_ALIVE(VisitForValue(subexpr));
    5635             :     HValue* value = Pop();
    5636             :     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
    5637             : 
    5638             :     elements = AddLoadElements(literal);
    5639             : 
    5640       16268 :     HValue* key = Add<HConstant>(i);
    5641             : 
    5642       16268 :     if (!boilerplate_object.is_null()) {
    5643             :       ElementsKind boilerplate_elements_kind =
    5644             :           boilerplate_object->GetElementsKind();
    5645        3463 :       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        3463 :                            boilerplate_elements_kind);
    5654             :           break;
    5655             :         }
    5656             :         default:
    5657           0 :           UNREACHABLE();
    5658             :           break;
    5659             :       }
    5660             :     } else {
    5661             :       HInstruction* instr = BuildKeyedGeneric(
    5662       12805 :           STORE, expr, expr->LiteralFeedbackSlot(), literal, key, value);
    5663       12805 :       AddInstruction(instr);
    5664             :     }
    5665             : 
    5666             :     Add<HSimulate>(expr->GetIdForElement(i));
    5667             :   }
    5668             : 
    5669       34440 :   return ast_context()->ReturnValue(Pop());
    5670             : }
    5671             : 
    5672             : 
    5673        7416 : HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
    5674             :                                                 Handle<Map> map) {
    5675        7416 :   BuildCheckHeapObject(object);
    5676        7416 :   return Add<HCheckMaps>(object, map);
    5677             : }
    5678             : 
    5679             : 
    5680       52412 : HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
    5681             :     PropertyAccessInfo* info,
    5682             :     HValue* checked_object) {
    5683             :   // Check if this is a load of an immutable or constant property.
    5684      104824 :   if (checked_object->ActualValue()->IsConstant()) {
    5685             :     Handle<Object> object(
    5686       39965 :         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
    5687             : 
    5688       11662 :     if (object->IsJSObject()) {
    5689             :       LookupIterator it(object, info->name(),
    5690       11662 :                         LookupIterator::OWN_SKIP_INTERCEPTOR);
    5691       11662 :       if (it.IsFound()) {
    5692             :         bool is_reaonly_non_configurable =
    5693       12405 :             it.IsReadOnly() && !it.IsConfigurable();
    5694       11656 :         if (is_reaonly_non_configurable ||
    5695             :             (FLAG_track_constant_fields && info->IsDataConstantField())) {
    5696         747 :           Handle<Object> value = JSReceiver::GetDataProperty(&it);
    5697         747 :           if (!is_reaonly_non_configurable) {
    5698             :             DCHECK(!it.is_dictionary_holder());
    5699             :             // Add dependency on the map that introduced the field.
    5700           0 :             Handle<Map> field_owner_map = it.GetFieldOwnerMap();
    5701           0 :             top_info()->dependencies()->AssumeFieldOwner(field_owner_map);
    5702             :           }
    5703         747 :           return New<HConstant>(value);
    5704             :         }
    5705             :       }
    5706             :     }
    5707             :   }
    5708             : 
    5709       51665 :   HObjectAccess access = info->access();
    5710       52105 :   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          17 :         access.WithRepresentation(Representation::Tagged()));
    5716             :     // Load the double value from it.
    5717          17 :     access = HObjectAccess::ForHeapNumberValue();
    5718             :   }
    5719             : 
    5720             :   SmallMapList* map_list = info->field_maps();
    5721       51665 :   if (map_list->length() == 0) {
    5722       43347 :     return New<HLoadNamedField>(checked_object, checked_object, access);
    5723             :   }
    5724             : 
    5725             :   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
    5726       33282 :   for (int i = 0; i < map_list->length(); ++i) {
    5727        8323 :     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
    5728             :   }
    5729             :   return New<HLoadNamedField>(
    5730        8318 :       checked_object, checked_object, access, maps, info->field_type());
    5731             : }
    5732             : 
    5733       42546 : 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       21285 :   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       21551 :   if (field_access.representation().IsDouble() &&
    5746             :       (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
    5747             :     HObjectAccess heap_number_access =
    5748          24 :         field_access.WithRepresentation(Representation::Tagged());
    5749          24 :     if (transition_to_field) {
    5750             :       // The store requires a mutable HeapNumber to be allocated.
    5751           0 :       NoObservableSideEffectsScope no_side_effects(this);
    5752           0 :       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           0 :                          MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
    5758             :       AddStoreMapConstant(
    5759           0 :           heap_number, isolate()->factory()->mutable_heap_number_map());
    5760             :       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
    5761           0 :                             value);
    5762             :       instr = New<HStoreNamedField>(checked_object->ActualValue(),
    5763             :                                     heap_number_access,
    5764           0 :                                     heap_number);
    5765             :     } else {
    5766             :       // Already holds a HeapNumber; load the box and write its value field.
    5767             :       HInstruction* heap_number =
    5768          24 :           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          24 :                                       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       21261 :       if (field_access.representation().IsHeapObject()) {
    5808       12725 :         BuildCheckHeapObject(value);
    5809             :       }
    5810             : 
    5811       21261 :       if (!info->field_maps()->is_empty()) {
    5812             :         DCHECK(field_access.representation().IsHeapObject());
    5813        2170 :         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       21261 :                                     value, info->StoreMode());
    5819             :     }
    5820             :   }
    5821             : 
    5822       21285 :   if (transition_to_field) {
    5823       10955 :     Handle<Map> transition(info->transition());
    5824             :     DCHECK(!transition->is_deprecated());
    5825       10955 :     instr->SetTransition(Add<HConstant>(transition));
    5826             :   }
    5827             :   return instr;
    5828             : }
    5829             : 
    5830             : Handle<FieldType>
    5831      106642 : HOptimizedGraphBuilder::PropertyAccessInfo::GetFieldTypeFromMap(
    5832      106642 :     Handle<Map> map) const {
    5833             :   DCHECK(IsFound());
    5834             :   DCHECK(number_ < map->NumberOfOwnDescriptors());
    5835      319926 :   return handle(map->instance_descriptors()->GetFieldType(number_), isolate());
    5836             : }
    5837             : 
    5838       10804 : bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
    5839       20819 :     PropertyAccessInfo* info) {
    5840       10804 :   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       10756 :   if (IsNumberType()) return false;
    5846             : 
    5847             :   // Values are only compatible for monomorphic load if they all behave the same
    5848             :   // regarding value wrappers.
    5849       10756 :   if (IsValueWrapped() != info->IsValueWrapped()) return false;
    5850             : 
    5851       10745 :   if (!LookupDescriptor()) return false;
    5852             : 
    5853       10684 :   if (!IsFound()) {
    5854       11194 :     return (!info->IsFound() || info->has_holder()) &&
    5855        9609 :            map()->prototype() == info->map()->prototype();
    5856             :   }
    5857             : 
    5858             :   // Mismatch if the other access info found the property in the prototype
    5859             :   // chain.
    5860        6407 :   if (info->has_holder()) return false;
    5861             : 
    5862        5881 :   if (IsAccessorConstant()) {
    5863          86 :     return accessor_.is_identical_to(info->accessor_) &&
    5864          81 :         api_holder_.is_identical_to(info->api_holder_);
    5865             :   }
    5866             : 
    5867        5800 :   if (IsDataConstant()) {
    5868          30 :     return constant_.is_identical_to(info->constant_);
    5869             :   }
    5870             : 
    5871             :   DCHECK(IsData());
    5872        5770 :   if (!info->IsData()) return false;
    5873             : 
    5874        5769 :   Representation r = access_.representation();
    5875        5769 :   if (IsLoad()) {
    5876       16342 :     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
    5877             :   } else {
    5878         475 :     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
    5879             :   }
    5880        5754 :   if (info->access_.offset() != access_.offset()) return false;
    5881        3204 :   if (info->access_.IsInobject() != access_.IsInobject()) return false;
    5882        3204 :   if (IsLoad()) {
    5883        3162 :     if (field_maps_.is_empty()) {
    5884             :       info->field_maps_.Clear();
    5885          94 :     } else if (!info->field_maps_.is_empty()) {
    5886         267 :       for (int i = 0; i < field_maps_.length(); ++i) {
    5887          89 :         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          42 :     if (field_maps_.length() != info->field_maps_.length()) return false;
    5895          42 :     for (int i = 0; i < field_maps_.length(); ++i) {
    5896           0 :       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
    5897             :         return false;
    5898             :       }
    5899             :     }
    5900             :   }
    5901        3204 :   info->GeneralizeRepresentation(r);
    5902        3204 :   info->field_type_ = info->field_type_.Combine(field_type_);
    5903        3204 :   return true;
    5904             : }
    5905             : 
    5906             : 
    5907      315241 : bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
    5908      315241 :   if (!map_->IsJSObjectMap()) return true;
    5909      294564 :   LookupDescriptor(*map_, *name_);
    5910      294564 :   return LoadResult(map_);
    5911             : }
    5912             : 
    5913             : 
    5914      467913 : bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
    5915      424559 :   if (!IsLoad() && IsProperty() && IsReadOnly()) {
    5916             :     return false;
    5917             :   }
    5918             : 
    5919      372638 :   if (IsData()) {
    5920             :     // Construct the object field access.
    5921       91509 :     int index = GetLocalFieldIndexFromMap(map);
    5922       91509 :     access_ = HObjectAccess::ForField(map, index, representation(), name_);
    5923             : 
    5924             :     // Load field map for heap objects.
    5925       91509 :     return LoadFieldMaps(map);
    5926      281129 :   } else if (IsAccessorConstant()) {
    5927             :     Handle<Object> accessors = GetAccessorsFromMap(map);
    5928       12225 :     if (!accessors->IsAccessorPair()) return false;
    5929             :     Object* raw_accessor =
    5930             :         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
    5931        3718 :                  : Handle<AccessorPair>::cast(accessors)->setter();
    5932        3836 :     if (!raw_accessor->IsJSFunction() &&
    5933             :         !raw_accessor->IsFunctionTemplateInfo())
    5934             :       return false;
    5935             :     Handle<Object> accessor = handle(HeapObject::cast(raw_accessor));
    5936        3619 :     CallOptimization call_optimization(accessor);
    5937        3619 :     if (call_optimization.is_simple_api_call()) {
    5938             :       CallOptimization::HolderLookup holder_lookup;
    5939             :       api_holder_ =
    5940          51 :           call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
    5941             :     }
    5942        3619 :     accessor_ = accessor;
    5943      273207 :   } else if (IsDataConstant()) {
    5944      192781 :     constant_ = GetConstantFromMap(map);
    5945             :   }
    5946             : 
    5947             :   return true;
    5948             : }
    5949             : 
    5950             : 
    5951      106642 : bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
    5952      142492 :     Handle<Map> map) {
    5953             :   // Clear any previously collected field maps/type.
    5954             :   field_maps_.Clear();
    5955      106642 :   field_type_ = HType::Tagged();
    5956             : 
    5957             :   // Figure out the field type from the accessor map.
    5958      106642 :   Handle<FieldType> field_type = GetFieldTypeFromMap(map);
    5959             : 
    5960             :   // Collect the (stable) maps from the field type.
    5961      106642 :   if (field_type->IsClass()) {
    5962             :     DCHECK(access_.representation().IsHeapObject());
    5963       13136 :     Handle<Map> field_map = field_type->AsClass();
    5964       13136 :     if (field_map->is_stable()) {
    5965             :       field_maps_.Add(field_map, zone());
    5966             :     }
    5967             :   }
    5968             : 
    5969      106642 :   if (field_maps_.is_empty()) {
    5970             :     // Store is not safe if the field map was cleared.
    5971      123697 :     return IsLoad() || !field_type->IsNone();
    5972             :   }
    5973             : 
    5974             :   // Determine field HType from field type.
    5975       11950 :   field_type_ = HType::FromFieldType(field_type, zone());
    5976             :   DCHECK(field_type_.IsHeapObject());
    5977             : 
    5978             :   // Add dependency on the map that introduced the field.
    5979       23900 :   top_info()->dependencies()->AssumeFieldOwner(GetFieldOwnerFromMap(map));
    5980       11950 :   return true;
    5981             : }
    5982             : 
    5983             : 
    5984      224480 : bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
    5985       96799 :   Handle<Map> map = this->map();
    5986       96799 :   if (name_->IsPrivate()) {
    5987             :     NotFound();
    5988         108 :     return !map->has_hidden_prototype();
    5989             :   }
    5990             : 
    5991      146250 :   while (map->prototype()->IsJSObject()) {
    5992      128477 :     holder_ = handle(JSObject::cast(map->prototype()));
    5993      128477 :     if (holder_->map()->is_deprecated()) {
    5994           0 :       JSObject::TryMigrateInstance(holder_);
    5995             :     }
    5996             :     map = Handle<Map>(holder_->map());
    5997      128477 :     if (!CanInlinePropertyAccess(map)) {
    5998             :       NotFound();
    5999         796 :       return false;
    6000             :     }
    6001      127681 :     LookupDescriptor(*map, *name_);
    6002      127681 :     if (IsFound()) return LoadResult(map);
    6003             :   }
    6004             : 
    6005             :   NotFound();
    6006       17773 :   return !map->prototype()->IsJSReceiver();
    6007             : }
    6008             : 
    6009             : 
    6010       97659 : bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
    6011             :   InstanceType instance_type = map_->instance_type();
    6012       98494 :   return instance_type == JS_TYPED_ARRAY_TYPE && name_->IsString() &&
    6013       97659 :          IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name_));
    6014             : }
    6015             : 
    6016             : 
    6017      987075 : bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
    6018      335489 :   if (!CanInlinePropertyAccess(map_)) return false;
    6019      346873 :   if (IsJSObjectFieldAccessor()) return IsLoad();
    6020      376766 :   if (map_->IsJSFunctionMap() && map_->is_constructor() &&
    6021      338274 :       !map_->has_non_instance_prototype() &&
    6022             :       name_.is_identical_to(isolate()->factory()->prototype_string())) {
    6023        6119 :     return IsLoad();
    6024             :   }
    6025      304496 :   if (!LookupDescriptor()) return false;
    6026      517407 :   if (IsFound()) return IsLoad() || !IsReadOnly();
    6027       96826 :   if (IsIntegerIndexedExotic()) return false;
    6028       96799 :   if (!LookupInPrototypes()) return false;
    6029       95877 :   if (IsLoad()) return true;
    6030             : 
    6031       16976 :   if (IsAccessorConstant()) return true;
    6032       16838 :   LookupTransition(*map_, *name_, NONE);
    6033       33350 :   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       15133 :         map_->GetInObjectProperties();
    6039             :     PropertyDetails details =
    6040       15133 :         transition()->instance_descriptors()->GetDetails(descriptor);
    6041       15133 :     Representation representation = details.representation();
    6042       15133 :     access_ = HObjectAccess::ForField(map_, index, representation, name_);
    6043             : 
    6044             :     // Load field map for heap objects.
    6045       15133 :     return LoadFieldMaps(transition());
    6046             :   }
    6047             :   return false;
    6048             : }
    6049             : 
    6050             : 
    6051      286581 : bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
    6052      264825 :     SmallMapList* maps) {
    6053             :   DCHECK(map_.is_identical_to(maps->first()));
    6054      286581 :   if (!CanAccessMonomorphic()) return false;
    6055             :   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
    6056      282127 :   if (maps->length() > kMaxLoadPolymorphism) return false;
    6057      282127 :   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
    6058      282127 :   if (GetJSObjectFieldAccess(&access)) {
    6059       19806 :     for (int i = 1; i < maps->length(); ++i) {
    6060        1858 :       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
    6061        3705 :       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
    6062        2086 :       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
    6063        3694 :       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      265581 :   if (IsNumberType()) return false;
    6072             : 
    6073             :   // Multiple maps cannot transition to the same target map.
    6074             :   DCHECK(!IsLoad() || !IsTransition());
    6075      273760 :   if (IsTransition() && maps->length() > 1) return false;
    6076             : 
    6077      274675 :   for (int i = 1; i < maps->length(); ++i) {
    6078       10804 :     PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
    6079       10804 :     if (!test_info.IsCompatible(this)) return false;
    6080             :   }
    6081             : 
    6082             :   return true;
    6083             : }
    6084             : 
    6085             : 
    6086      183001 : Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
    6087             :   Handle<JSFunction> ctor;
    6088      183001 :   if (Map::GetConstructorFunction(
    6089             :           map_, handle(current_info()->closure()->context()->native_context()))
    6090      366002 :           .ToHandle(&ctor)) {
    6091             :     return handle(ctor->initial_map());
    6092             :   }
    6093      152186 :   return map_;
    6094             : }
    6095             : 
    6096             : 
    6097             : static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
    6098        8983 :   return !map->IsJSObjectMap() &&
    6099       70520 :          is_sloppy(target->shared()->language_mode()) &&
    6100             :          !target->shared()->native();
    6101             : }
    6102             : 
    6103             : 
    6104        4862 : bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
    6105             :     Handle<JSFunction> target) const {
    6106        4862 :   return NeedsWrapping(map_, target);
    6107             : }
    6108             : 
    6109             : 
    6110      198991 : HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
    6111      342011 :     PropertyAccessInfo* info, HValue* object, HValue* checked_object,
    6112             :     HValue* value, BailoutId ast_id, BailoutId return_id,
    6113        1118 :     bool can_inline_accessor) {
    6114      198991 :   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
    6115      198991 :   if (info->GetJSObjectFieldAccess(&access)) {
    6116             :     DCHECK(info->IsLoad());
    6117       22451 :     return New<HLoadNamedField>(object, checked_object, access);
    6118             :   }
    6119             : 
    6120      188051 :   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
    6121      194136 :       info->map()->IsJSFunctionMap() && info->map()->is_constructor()) {
    6122             :     DCHECK(!info->map()->has_non_instance_prototype());
    6123        6085 :     return New<HLoadFunctionPrototype>(checked_object);
    6124             :   }
    6125             : 
    6126             :   HValue* checked_holder = checked_object;
    6127      175881 :   if (info->has_holder()) {
    6128       97326 :     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
    6129       48663 :     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
    6130             :   }
    6131             : 
    6132      175881 :   if (!info->IsFound()) {
    6133             :     DCHECK(info->IsLoad());
    6134        2107 :     return graph()->GetConstantUndefined();
    6135             :   }
    6136             : 
    6137      173774 :   if (info->IsData()) {
    6138       62738 :     if (info->IsLoad()) {
    6139       52408 :       return BuildLoadNamedField(info, checked_holder);
    6140             :     } else {
    6141       10330 :       return BuildStoreNamedField(info, checked_object, value);
    6142             :     }
    6143             :   }
    6144             : 
    6145      111036 :   if (info->IsTransition()) {
    6146             :     DCHECK(!info->IsLoad());
    6147       10955 :     return BuildStoreNamedField(info, checked_object, value);
    6148             :   }
    6149             : 
    6150      100081 :   if (info->IsAccessorConstant()) {
    6151             :     MaybeHandle<Name> maybe_name =
    6152             :         FunctionTemplateInfo::TryGetCachedPropertyName(isolate(),
    6153        3319 :                                                        info->accessor());
    6154        3319 :     if (!maybe_name.is_null()) {
    6155           4 :       Handle<Name> name = maybe_name.ToHandleChecked();
    6156           4 :       PropertyAccessInfo cache_info(this, LOAD, info->map(), name);
    6157             :       // Load new target.
    6158           4 :       if (cache_info.CanAccessMonomorphic()) {
    6159           4 :         return BuildLoadNamedField(&cache_info, checked_object);
    6160             :       }
    6161             :     }
    6162             : 
    6163        3315 :     Push(checked_object);
    6164             :     int argument_count = 1;
    6165        3315 :     if (!info->IsLoad()) {
    6166             :       argument_count = 2;
    6167         246 :       Push(value);
    6168             :     }
    6169             : 
    6170        6615 :     if (info->accessor()->IsJSFunction() &&
    6171        3300 :         info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) {
    6172           0 :       HValue* function = Add<HConstant>(info->accessor());
    6173           0 :       PushArgumentsFromEnvironment(argument_count);
    6174             :       return NewCallFunction(function, argument_count, TailCallMode::kDisallow,
    6175             :                              ConvertReceiverMode::kNotNullOrUndefined,
    6176           0 :                              TailCallMode::kDisallow);
    6177        3315 :     } else if (FLAG_inline_accessors && can_inline_accessor) {
    6178             :       bool success = info->IsLoad()
    6179        3069 :           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
    6180             :           : TryInlineSetter(
    6181        6384 :               info->accessor(), info->map(), ast_id, return_id, value);
    6182        4433 :       if (success || HasStackOverflow()) return NULL;
    6183             :     }
    6184             : 
    6185        1118 :     PushArgumentsFromEnvironment(argument_count);
    6186        1118 :     if (!info->accessor()->IsJSFunction()) {
    6187             :       Bailout(kInliningBailedOut);
    6188           0 :       return nullptr;
    6189             :     }
    6190             :     return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()),
    6191             :                                    argument_count, TailCallMode::kDisallow,
    6192        1118 :                                    TailCallMode::kDisallow);
    6193             :   }
    6194             : 
    6195             :   DCHECK(info->IsDataConstant());
    6196       96762 :   if (info->IsLoad()) {
    6197       96748 :     return New<HConstant>(info->constant());
    6198             :   } else {
    6199          14 :     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
    6200             :   }
    6201             : }
    6202             : 
    6203       10166 : void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
    6204             :     PropertyAccessType access_type, Expression* expr, FeedbackSlot slot,
    6205             :     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
    6206       29291 :     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       58820 :   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
    6217       19286 :     PropertyAccessInfo info(this, access_type, maps->at(i), name);
    6218       19286 :     if (info.IsStringType()) {
    6219          35 :       if (handled_string) continue;
    6220             :       handled_string = true;
    6221             :     }
    6222       19286 :     if (info.CanAccessMonomorphic()) {
    6223       14897 :       count++;
    6224       14897 :       if (info.IsNumberType()) {
    6225             :         handle_smi = true;
    6226          42 :         break;
    6227             :       }
    6228             :     }
    6229             :   }
    6230             : 
    6231       10166 :   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       48654 :   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
    6241       19244 :     PropertyAccessInfo info(this, access_type, maps->at(i), name);
    6242       19244 :     if (info.IsStringType()) {
    6243        4424 :       if (handled_string) continue;
    6244             :       handled_string = true;
    6245             :     }
    6246       19244 :     if (!info.CanAccessMonomorphic()) continue;
    6247             : 
    6248       14855 :     if (count == 0) {
    6249       50757 :       join = graph()->CreateBasicBlock();
    6250        6192 :       if (handle_smi) {
    6251           0 :         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
    6252           0 :         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
    6253           0 :         number_block = graph()->CreateBasicBlock();
    6254             :         smi_check = New<HIsSmiAndBranch>(
    6255           0 :             object, empty_smi_block, not_smi_block);
    6256           0 :         FinishCurrentBlock(smi_check);
    6257             :         GotoNoSimulate(empty_smi_block, number_block);
    6258             :         set_current_block(not_smi_block);
    6259             :       } else {
    6260        6192 :         BuildCheckHeapObject(object);
    6261             :       }
    6262             :     }
    6263       14855 :     ++count;
    6264       14855 :     HBasicBlock* if_true = graph()->CreateBasicBlock();
    6265       14855 :     HBasicBlock* if_false = graph()->CreateBasicBlock();
    6266             :     HUnaryControlInstruction* compare;
    6267             : 
    6268             :     HValue* dependency;
    6269       14855 :     if (info.IsNumberType()) {
    6270           0 :       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
    6271           0 :       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
    6272             :       dependency = smi_check;
    6273       14855 :     } else if (info.IsStringType()) {
    6274          22 :       compare = New<HIsStringAndBranch>(object, if_true, if_false);
    6275             :       dependency = compare;
    6276             :     } else {
    6277       14833 :       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
    6278             :       dependency = compare;
    6279             :     }
    6280       14855 :     FinishCurrentBlock(compare);
    6281             : 
    6282       14855 :     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       14855 :                                return_id, FLAG_polymorphic_inlining);
    6292             : 
    6293             :     HValue* result = NULL;
    6294       14855 :     switch (access_type) {
    6295             :       case LOAD:
    6296             :         result = access;
    6297        9465 :         break;
    6298             :       case STORE:
    6299             :         result = value;
    6300        5390 :         break;
    6301             :     }
    6302             : 
    6303       14855 :     if (access == NULL) {
    6304         127 :       if (HasStackOverflow()) return;
    6305             :     } else {
    6306       14728 :       if (access->IsInstruction()) {
    6307             :         HInstruction* instr = HInstruction::cast(access);
    6308       14728 :         if (!instr->IsLinked()) AddInstruction(instr);
    6309             :       }
    6310       14728 :       if (!ast_context()->IsEffect()) Push(result);
    6311             :     }
    6312             : 
    6313       14855 :     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       10166 :   if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
    6321             :     FinishExitWithHardDeoptimization(
    6322        5891 :         DeoptimizeReason::kUnknownMapInPolymorphicAccess);
    6323             :   } else {
    6324             :     HInstruction* instr =
    6325        4275 :         BuildNamedGeneric(access_type, expr, slot, object, name, value);
    6326        4275 :     AddInstruction(instr);
    6327        4275 :     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
    6328             : 
    6329        4275 :     if (join != NULL) {
    6330             :       Goto(join);
    6331             :     } else {
    6332        3974 :       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    6333        7057 :       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
    6334             :       return;
    6335             :     }
    6336             :   }
    6337             : 
    6338             :   DCHECK(join != NULL);
    6339        6192 :   if (join->HasPredecessor()) {
    6340             :     join->SetJoinId(ast_id);
    6341             :     set_current_block(join);
    6342       10449 :     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
    6343             :   } else {
    6344             :     set_current_block(NULL);
    6345             :   }
    6346             : }
    6347             : 
    6348      800964 : static bool ComputeReceiverTypes(Expression* expr, HValue* receiver,
    6349             :                                  SmallMapList** t,
    6350             :                                  HOptimizedGraphBuilder* builder) {
    6351      865894 :   Zone* zone = builder->zone();
    6352      800964 :   SmallMapList* maps = expr->GetReceiverTypes();
    6353      800964 :   *t = maps;
    6354      800964 :   bool monomorphic = expr->IsMonomorphic();
    6355      800964 :   if (maps != nullptr && receiver->HasMonomorphicJSObjectType()) {
    6356      168886 :     if (maps->length() > 0) {
    6357      207972 :       Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
    6358      103986 :       maps->FilterForPossibleTransitions(root_map);
    6359      103986 :       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       64900 :       Handle<Map> candidate_map = receiver->GetMonomorphicJSObjectMap();
    6365       89802 :       for (HInstruction* current = builder->current_block()->last();
    6366             :            current != nullptr; current = current->previous()) {
    6367      171826 :         if (current->IsBlockEntry()) break;
    6368       84427 :         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        7208 :           if (!current->IsStoreNamedField()) break;
    6372             :           HStoreNamedField* map_change = HStoreNamedField::cast(current);
    6373          30 :           if (!map_change->value()->IsConstant()) break;
    6374             :           HConstant* map_constant = HConstant::cast(map_change->value());
    6375          30 :           if (!map_constant->representation().IsTagged()) break;
    6376          30 :           Handle<Object> map = map_constant->handle(builder->isolate());
    6377          30 :           if (!map.is_identical_to(candidate_map)) break;
    6378             :         }
    6379       77238 :         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       52336 :           break;
    6386             :         }
    6387             :       }
    6388             :     }
    6389             :   }
    6390     1097138 :   return monomorphic && CanInlinePropertyAccess(maps->first());
    6391             : }
    6392             : 
    6393             : 
    6394      178002 : static bool AreStringTypes(SmallMapList* maps) {
    6395      384396 :   for (int i = 0; i < maps->length(); i++) {
    6396      178425 :     if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
    6397             :   }
    6398             :   return true;
    6399             : }
    6400             : 
    6401      130739 : void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
    6402             :                                         FeedbackSlot slot, BailoutId ast_id,
    6403             :                                         BailoutId return_id,
    6404      210271 :                                         bool is_uninitialized) {
    6405       73202 :   if (!prop->key()->IsPropertyName()) {
    6406             :     // Keyed store.
    6407             :     HValue* value = Pop();
    6408             :     HValue* key = Pop();
    6409             :     HValue* object = Pop();
    6410       15665 :     bool has_side_effects = false;
    6411             :     HValue* result =
    6412             :         HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
    6413       15665 :                                  return_id, STORE, &has_side_effects);
    6414       15665 :     if (has_side_effects) {
    6415       15556 :       if (!ast_context()->IsEffect()) Push(value);
    6416       15556 :       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    6417       15556 :       if (!ast_context()->IsEffect()) Drop(1);
    6418             :     }
    6419       15665 :     if (result == NULL) return;
    6420       15596 :     return ast_context()->ReturnValue(value);
    6421             :   }
    6422             : 
    6423             :   // Named store.
    6424             :   HValue* value = Pop();
    6425             :   HValue* object = Pop();
    6426             : 
    6427      115074 :   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      115074 :                                     object, name, value, is_uninitialized);
    6433       57537 :   if (access == NULL) return;
    6434             : 
    6435       54521 :   if (!ast_context()->IsEffect()) Push(value);
    6436       54521 :   if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
    6437       54521 :   if (access->HasObservableSideEffects()) {
    6438       54507 :     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    6439             :   }
    6440       54521 :   if (!ast_context()->IsEffect()) Drop(1);
    6441       54521 :   return ast_context()->ReturnValue(value);
    6442             : }
    6443             : 
    6444             : 
    6445      371772 : void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
    6446      229192 :   Property* prop = expr->target()->AsProperty();
    6447             :   DCHECK(prop != NULL);
    6448      229162 :   CHECK_ALIVE(VisitForValue(prop->obj()));
    6449       71307 :   if (!prop->key()->IsPropertyName()) {
    6450       45611 :     CHECK_ALIVE(VisitForValue(prop->key()));
    6451             :   }
    6452      213887 :   CHECK_ALIVE(VisitForValue(expr->value()));
    6453             :   BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
    6454      142562 :              expr->AssignmentId(), expr->IsUninitialized());
    6455             : }
    6456             : 
    6457       10064 : HInstruction* HOptimizedGraphBuilder::InlineGlobalPropertyStore(
    6458             :     LookupIterator* it, HValue* value, BailoutId ast_id) {
    6459       10064 :   Handle<PropertyCell> cell = it->GetPropertyCell();
    6460       14086 :   top_info()->dependencies()->AssumePropertyCell(cell);
    6461             :   auto cell_type = it->property_details().cell_type();
    6462       10064 :   if (cell_type == PropertyCellType::kConstant ||
    6463             :       cell_type == PropertyCellType::kUndefined) {
    6464             :     Handle<Object> constant(cell->value(), isolate());
    6465        2464 :     if (value->IsConstant()) {
    6466             :       HConstant* c_value = HConstant::cast(value);
    6467        2332 :       if (!constant.is_identical_to(c_value->handle(isolate()))) {
    6468             :         Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment,
    6469         921 :                          Deoptimizer::EAGER);
    6470             :       }
    6471             :     } else {
    6472        1298 :       HValue* c_constant = Add<HConstant>(constant);
    6473             :       IfBuilder builder(this);
    6474        1298 :       if (constant->IsNumber()) {
    6475         779 :         builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
    6476             :       } else {
    6477         519 :         builder.If<HCompareObjectEqAndBranch>(value, c_constant);
    6478             :       }
    6479        1298 :       builder.Then();
    6480             :       builder.Else();
    6481             :       Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment,
    6482        1298 :                        Deoptimizer::EAGER);
    6483        1298 :       builder.End();
    6484             :     }
    6485             :   }
    6486       10064 :   HConstant* cell_constant = Add<HConstant>(cell);
    6487       10064 :   auto access = HObjectAccess::ForPropertyCellValue();
    6488       10064 :   if (cell_type == PropertyCellType::kConstantType) {
    6489        4182 :     switch (cell->GetConstantType()) {
    6490             :       case PropertyCellConstantType::kSmi:
    6491        3790 :         access = access.WithRepresentation(Representation::Smi());
    6492        3790 :         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         392 :         if (!cell_value_map->is_stable()) {
    6501             :           Bailout(kUnstableConstantTypeHeapObject);
    6502             :           return nullptr;
    6503             :         }
    6504         392 :         top_info()->dependencies()->AssumeMapStable(cell_value_map);
    6505             :         // Now check that the new {value} is a HeapObject with the same map
    6506         392 :         Add<HCheckHeapObject>(value);
    6507         392 :         value = Add<HCheckMaps>(value, cell_value_map);
    6508         392 :         access = access.WithRepresentation(Representation::HeapObject());
    6509             :         break;
    6510             :       }
    6511             :     }
    6512             :   }
    6513       10064 :   HInstruction* instr = New<HStoreNamedField>(cell_constant, access, value);
    6514             :   instr->ClearChangesFlag(kInobjectFields);
    6515             :   instr->SetChangesFlag(kGlobalVars);
    6516       10064 :   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       74721 : void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
    6523             :                                                             HValue* value,
    6524             :                                                             FeedbackSlot slot,
    6525             :                                                             BailoutId ast_id) {
    6526       21202 :   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       21202 :     if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
    6534          18 :       if (lookup.mode == CONST) {
    6535             :         return Bailout(kNonInitializerAssignmentToConst);
    6536             :       }
    6537             :       Handle<Context> script_context =
    6538          16 :           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
    6539             : 
    6540             :       Handle<Object> current_value =
    6541       22314 :           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          16 :       if (current_value->IsTheHole(isolate())) {
    6546             :         return Bailout(kReferenceToUninitializedVariable);
    6547             :       }
    6548             : 
    6549             :       HStoreNamedField* instr = Add<HStoreNamedField>(
    6550             :           Add<HConstant>(script_context),
    6551          15 :           HObjectAccess::ForContextSlot(lookup.slot_index), value);
    6552             :       USE(instr);
    6553             :       DCHECK(instr->HasObservableSideEffects());
    6554          15 :       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    6555          15 :       return;
    6556             :     }
    6557             :   }
    6558             : 
    6559       21184 :   LookupIterator it(global, var->name(), LookupIterator::OWN);
    6560       21184 :   if (CanInlineGlobalPropertyAccess(var, &it, STORE)) {
    6561       10051 :     HInstruction* instr = InlineGlobalPropertyStore(&it, value, ast_id);
    6562       10051 :     if (!instr) return;
    6563       10051 :     AddInstruction(instr);
    6564       10051 :     if (instr->HasObservableSideEffects()) {
    6565       10051 :       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    6566             :     }
    6567             :   } else {
    6568             :     HValue* global_object = Add<HLoadNamedField>(
    6569             :         BuildGetNativeContext(), nullptr,
    6570       11133 :         HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
    6571             :     Handle<FeedbackVector> vector =
    6572       11133 :         handle(current_feedback_vector(), isolate());
    6573       11133 :     HValue* name = Add<HConstant>(var->name());
    6574       11133 :     HValue* vector_value = Add<HConstant>(vector);
    6575       11133 :     HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
    6576             :     DCHECK(vector->IsStoreGlobalIC(slot));
    6577             :     DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode());
    6578             :     Callable callable = CodeFactory::StoreGlobalICInOptimizedCode(
    6579       11133 :         isolate(), function_language_mode());
    6580       11133 :     HValue* stub = Add<HConstant>(callable.code());
    6581       11133 :     HValue* values[] = {global_object, name, value, slot_value, vector_value};
    6582             :     HCallWithDescriptor* instr =
    6583             :         Add<HCallWithDescriptor>(Code::STORE_GLOBAL_IC, stub, 0,
    6584       11133 :                                  callable.descriptor(), ArrayVector(values));
    6585             :     USE(instr);
    6586             :     DCHECK(instr->HasObservableSideEffects());
    6587       11133 :     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    6588             :   }
    6589             : }
    6590             : 
    6591             : 
    6592      110388 : void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
    6593             :   Expression* target = expr->target();
    6594       54677 :   VariableProxy* proxy = target->AsVariableProxy();
    6595         993 :   Property* prop = target->AsProperty();
    6596             :   DCHECK(proxy == NULL || prop == NULL);
    6597             : 
    6598             :   // We have a second position recorded in the FullCodeGenerator to have
    6599             :   // type feedback for the binary operation.
    6600             :   BinaryOperation* operation = expr->binary_operation();
    6601             : 
    6602       27504 :   if (proxy != NULL) {
    6603       55115 :     Variable* var = proxy->var();
    6604       27173 :     if (var->mode() == LET)  {
    6605             :       return Bailout(kUnsupportedLetCompoundAssignment);
    6606             :     }
    6607             : 
    6608       55339 :     CHECK_ALIVE(VisitForValue(operation));
    6609             : 
    6610       27035 :     switch (var->location()) {
    6611             :       case VariableLocation::UNALLOCATED:
    6612             :         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
    6613        1900 :                                        expr->AssignmentId());
    6614        1900 :         break;
    6615             : 
    6616             :       case VariableLocation::PARAMETER:
    6617             :       case VariableLocation::LOCAL:
    6618       24404 :         if (var->mode() == CONST) {
    6619             :           return Bailout(kNonInitializerAssignmentToConst);
    6620             :         }
    6621       24354 :         BindIfLive(var, Top());
    6622       24354 :         break;
    6623             : 
    6624             :       case VariableLocation::CONTEXT: {
    6625             :         // Bail out if we try to mutate a parameter value in a function
    6626             :         // using the arguments object.  We do not (yet) correctly handle the
    6627             :         // arguments property of the function.
    6628         731 :         if (current_info()->scope()->arguments() != NULL) {
    6629             :           // Parameters will be allocated to context slots.  We have no
    6630             :           // direct way to detect that the variable is a parameter so we do
    6631             :           // a linear search of the parameter variables.
    6632           2 :           int count = current_info()->scope()->num_parameters();
    6633           4 :           for (int i = 0; i < count; ++i) {
    6634           4 :             if (var == current_info()->scope()->parameter(i)) {
    6635             :               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
    6636             :             }
    6637             :           }
    6638             :         }
    6639             : 
    6640             :         HStoreContextSlot::Mode mode;
    6641             : 
    6642         731 :         switch (var->mode()) {
    6643             :           case LET:
    6644             :             mode = HStoreContextSlot::kCheckDeoptimize;
    6645             :             break;
    6646             :           case CONST:
    6647         555 :             if (var->throw_on_const_assignment(function_language_mode())) {
    6648             :               return Bailout(kNonInitializerAssignmentToConst);
    6649             :             } else {
    6650          12 :               return ast_context()->ReturnValue(Pop());
    6651             :             }
    6652             :           default:
    6653             :             mode = HStoreContextSlot::kNoCheck;
    6654             :         }
    6655             : 
    6656         176 :         HValue* context = BuildContextChainWalk(var);
    6657             :         HStoreContextSlot* instr = Add<HStoreContextSlot>(
    6658         176 :             context, var->index(), mode, Top());
    6659         176 :         if (instr->HasObservableSideEffects()) {
    6660         176 :           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
    6661             :         }
    6662             :         break;
    6663             :       }
    6664             : 
    6665             :       case VariableLocation::LOOKUP:
    6666             :         return Bailout(kCompoundAssignmentToLookupSlot);
    6667             : 
    6668             :       case VariableLocation::MODULE:
    6669           0 :         UNREACHABLE();
    6670             :     }
    6671       52860 :     return ast_context()->ReturnValue(Pop());
    6672             : 
    6673         331 :   } else if (prop != NULL) {
    6674         993 :     CHECK_ALIVE(VisitForValue(prop->obj()));
    6675             :     HValue* object = Top();
    6676             :     HValue* key = NULL;
    6677         430 :     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
    6678         696 :       CHECK_ALIVE(VisitForValue(prop->key()));
    6679             :       key = Top();
    6680             :     }
    6681             : 
    6682         993 :     CHECK_ALIVE(PushLoad(prop, object, key));
    6683             : 
    6684         993 :     CHECK_ALIVE(VisitForValue(expr->value()));
    6685             :     HValue* right = Pop();
    6686             :     HValue* left = Pop();
    6687             : 
    6688         331 :     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
    6689             : 
    6690             :     BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
    6691         662 :                expr->AssignmentId(), expr->IsUninitialized());
    6692             :   } else {
    6693             :     return Bailout(kInvalidLhsInCompoundAssignment);
    6694             :   }
    6695             : }
    6696             : 
    6697             : 
    6698     2880048 : void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
    6699             :   DCHECK(!HasStackOverflow());
    6700             :   DCHECK(current_block() != NULL);
    6701             :   DCHECK(current_block()->HasPredecessor());
    6702             : 
    6703     1157814 :   VariableProxy* proxy = expr->target()->AsVariableProxy();
    6704      628329 :   Property* prop = expr->target()->AsProperty();
    6705             :   DCHECK(proxy == NULL || prop == NULL);
    6706             : 
    6707      628329 :   if (expr->is_compound()) {
    6708       27504 :     HandleCompoundAssignment(expr);
    6709       27504 :     return;
    6710             :   }
    6711             : 
    6712      600825 :   if (prop != NULL) {
    6713       71340 :     HandlePropertyAssignment(expr);
    6714      529485 :   } else if (proxy != NULL) {
    6715      575966 :     Variable* var = proxy->var();
    6716             : 
    6717      529485 :     if (var->mode() == CONST) {
    6718       66799 :       if (expr->op() != Token::INIT) {
    6719         626 :         if (var->throw_on_const_assignment(function_language_mode())) {
    6720             :           return Bailout(kNonInitializerAssignmentToConst);
    6721             :         } else {
    6722      526653 :           CHECK_ALIVE(VisitForValue(expr->value()));
    6723           6 :           return ast_context()->ReturnValue(Pop());
    6724             :         }
    6725             :       }
    6726             :     }
    6727             : 
    6728             :     // Handle the assignment.
    6729      528859 :     switch (var->location()) {
    6730             :       case VariableLocation::UNALLOCATED:
    6731       46437 :         CHECK_ALIVE(VisitForValue(expr->value()));
    6732             :         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
    6733       15475 :                                        expr->AssignmentId());
    6734       30950 :         return ast_context()->ReturnValue(Pop());
    6735             : 
    6736             :       case VariableLocation::PARAMETER:
    6737             :       case VariableLocation::LOCAL: {
    6738             :         // Perform an initialization check for let declared variables
    6739             :         // or parameters.
    6740      473749 :         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
    6741             :           HValue* env_value = environment()->Lookup(var);
    6742         481 :           if (env_value == graph()->GetConstantHole()) {
    6743             :             return Bailout(kAssignmentToLetVariableBeforeInitialization);
    6744             :           }
    6745             :         }
    6746             :         // We do not allow the arguments object to occur in a context where it
    6747             :         // may escape, but assignments to stack-allocated locals are
    6748             :         // permitted.
    6749     1418628 :         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
    6750             :         HValue* value = Pop();
    6751      471148 :         BindIfLive(var, value);
    6752      471148 :         return ast_context()->ReturnValue(value);
    6753             :       }
    6754             : 
    6755             :       case VariableLocation::CONTEXT: {
    6756             :         // Bail out if we try to mutate a parameter value in a function using
    6757             :         // the arguments object.  We do not (yet) correctly handle the
    6758             :         // arguments property of the function.
    6759       39629 :         if (current_info()->scope()->arguments() != NULL) {
    6760             :           // Parameters will rewrite to context slots.  We have no direct way
    6761             :           // to detect that the variable is a parameter.
    6762          17 :           int count = current_info()->scope()->num_parameters();
    6763          34 :           for (int i = 0; i < count; ++i) {
    6764          44 :             if (var == current_info()->scope()->parameter(i)) {
    6765             :               return Bailout(kAssignmentToParameterInArgumentsObject);
    6766             :             }
    6767             :           }
    6768             :         }
    6769             : 
    6770      118785 :         CHECK_ALIVE(VisitForValue(expr->value()));
    6771             :         HStoreContextSlot::Mode mode;
    6772       39537 :         if (expr->op() == Token::ASSIGN) {
    6773        6944 :           switch (var->mode()) {
    6774             :             case LET:
    6775             :               mode = HStoreContextSlot::kCheckDeoptimize;
    6776             :               break;
    6777             :             case CONST:
    6778             :               // If we reached this point, the only possibility
    6779             :               // is a sloppy assignment to a function name.
    6780             :               DCHECK(function_language_mode() == SLOPPY &&
    6781             :                      !var->throw_on_const_assignment(SLOPPY));
    6782           0 :               return ast_context()->ReturnValue(Pop());
    6783             :             default:
    6784             :               mode = HStoreContextSlot::kNoCheck;
    6785             :           }
    6786             :         } else {
    6787             :           DCHECK_EQ(Token::INIT, expr->op());
    6788             :           mode = HStoreContextSlot::kNoCheck;
    6789             :         }
    6790             : 
    6791       39537 :         HValue* context = BuildContextChainWalk(var);
    6792             :         HStoreContextSlot* instr = Add<HStoreContextSlot>(
    6793       39537 :             context, var->index(), mode, Top());
    6794       39537 :         if (instr->HasObservableSideEffects()) {
    6795       39537 :           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
    6796             :         }
    6797       79074 :         return ast_context()->ReturnValue(Pop());
    6798             :       }
    6799             : 
    6800             :       case VariableLocation::LOOKUP:
    6801             :         return Bailout(kAssignmentToLOOKUPVariable);
    6802             : 
    6803             :       case VariableLocation::MODULE:
    6804           0 :         UNREACHABLE();
    6805             :     }
    6806             :   } else {
    6807             :     return Bailout(kInvalidLeftHandSideInAssignment);
    6808             :   }
    6809             : }
    6810             : 
    6811           0 : void HOptimizedGraphBuilder::VisitSuspend(Suspend* expr) {
    6812             :   // Generators are not optimized, so we should never get here.
    6813           0 :   UNREACHABLE();
    6814             : }
    6815             : 
    6816             : 
    6817       21266 : void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
    6818             :   DCHECK(!HasStackOverflow());
    6819             :   DCHECK(current_block() != NULL);
    6820             :   DCHECK(current_block()->HasPredecessor());
    6821        7124 :   if (!ast_context()->IsEffect()) {
    6822             :     // The parser turns invalid left-hand sides in assignments into throw
    6823             :     // statements, which may not be in effect contexts. We might still try
    6824             :     // to optimize such functions; bail out now if we do.
    6825             :     return Bailout(kInvalidLeftHandSideInAssignment);
    6826             :   }
    6827       21213 :   CHECK_ALIVE(VisitForValue(expr->exception()));
    6828             : 
    6829        7071 :   HValue* value = environment()->Pop();
    6830        7071 :   if (!is_tracking_positions()) SetSourcePosition(expr->position());
    6831        7071 :   Add<HPushArguments>(value);
    6832        7071 :   Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1);
    6833             :   Add<HSimulate>(expr->id());
    6834             : 
    6835             :   // If the throw definitely exits the function, we can finish with a dummy
    6836             :   // control flow at this point.  This is not the case if the throw is inside
    6837             :   // an inlined function which may be replaced.
    6838        7071 :   if (call_context() == NULL) {
    6839        4726 :     FinishExitCurrentBlock(New<HAbnormalExit>());
    6840             :   }
    6841             : }
    6842             : 
    6843             : 
    6844       37970 : HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
    6845       37970 :   if (string->IsConstant()) {
    6846             :     HConstant* c_string = HConstant::cast(string);
    6847       11849 :     if (c_string->HasStringValue()) {
    6848       11849 :       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
    6849             :     }
    6850             :   }
    6851             :   return Add<HLoadNamedField>(
    6852             :       Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
    6853       26121 :       HObjectAccess::ForMapInstanceType());
    6854             : }
    6855             : 
    6856             : 
    6857       62041 : HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
    6858       62041 :   return AddInstruction(BuildLoadStringLength(string));
    6859             : }
    6860             : 
    6861             : 
    6862       62041 : HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* string) {
    6863       62041 :   if (string->IsConstant()) {
    6864             :     HConstant* c_string = HConstant::cast(string);
    6865       23745 :     if (c_string->HasStringValue()) {
    6866       23745 :       return New<HConstant>(c_string->StringValue()->length());
    6867             :     }
    6868             :   }
    6869             :   return New<HLoadNamedField>(string, nullptr,
    6870       38296 :                               HObjectAccess::ForStringLength());
    6871             : }
    6872             : 
    6873      321543 : HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
    6874             :     PropertyAccessType access_type, Expression* expr, FeedbackSlot slot,
    6875             :     HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
    6876      321543 :   if (is_uninitialized) {
    6877             :     Add<HDeoptimize>(
    6878             :         DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess,
    6879      505560 :         Deoptimizer::SOFT);
    6880             :   }
    6881             :   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
    6882             : 
    6883      321543 :   HValue* key = Add<HConstant>(name);
    6884      321543 :   HValue* vector_value = Add<HConstant>(vector);
    6885      321543 :   HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
    6886             : 
    6887      321543 :   if (access_type == LOAD) {
    6888      256790 :     HValue* values[] = {object, key, slot_value, vector_value};
    6889      513579 :     if (!expr->AsProperty()->key()->IsPropertyName()) {
    6890             :       DCHECK(vector->IsKeyedLoadIC(slot));
    6891             :       // It's possible that a keyed load of a constant string was converted
    6892             :       // to a named load. Here, at the last minute, we need to make sure to
    6893             :       // use a generic Keyed Load if we are using the type vector, because
    6894             :       // it has to share information with full code.
    6895         126 :       Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
    6896         126 :       HValue* stub = Add<HConstant>(callable.code());
    6897             :       HCallWithDescriptor* result =
    6898             :           New<HCallWithDescriptor>(Code::KEYED_LOAD_IC, stub, 0,
    6899         126 :                                    callable.descriptor(), ArrayVector(values));
    6900             :       return result;
    6901             :     }
    6902             :     DCHECK(vector->IsLoadIC(slot));
    6903      256664 :     Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
    6904      256663 :     HValue* stub = Add<HConstant>(callable.code());
    6905             :     HCallWithDescriptor* result = New<HCallWithDescriptor>(
    6906      256664 :         Code::LOAD_IC, stub, 0, callable.descriptor(), ArrayVector(values));
    6907             :     return result;
    6908             : 
    6909             :   } else {
    6910       64753 :     HValue* values[] = {object, key, value, slot_value, vector_value};
    6911       64753 :     if (vector->IsKeyedStoreIC(slot)) {
    6912             :       // It's possible that a keyed store of a constant string was converted
    6913             :       // to a named store. Here, at the last minute, we need to make sure to
    6914             :       // use a generic Keyed Store if we are using the type vector, because
    6915             :       // it has to share information with full code.
    6916             :       DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode());
    6917             :       Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
    6918         171 :           isolate(), function_language_mode());
    6919         171 :       HValue* stub = Add<HConstant>(callable.code());
    6920             :       HCallWithDescriptor* result =
    6921             :           New<HCallWithDescriptor>(Code::KEYED_STORE_IC, stub, 0,
    6922         171 :                                    callable.descriptor(), ArrayVector(values));
    6923             :       return result;
    6924             :     }
    6925             :     HCallWithDescriptor* result;
    6926       64582 :     if (vector->IsStoreOwnIC(slot)) {
    6927       18742 :       Callable callable = CodeFactory::StoreOwnICInOptimizedCode(isolate());
    6928       18742 :       HValue* stub = Add<HConstant>(callable.code());
    6929             :       result = New<HCallWithDescriptor>(
    6930       18742 :           Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values));
    6931             :     } else {
    6932             :       DCHECK(vector->IsStoreIC(slot));
    6933             :       DCHECK_EQ(vector->GetLanguageMode(slot), function_language_mode());
    6934             :       Callable callable = CodeFactory::StoreICInOptimizedCode(
    6935       45840 :           isolate(), function_language_mode());
    6936       45840 :       HValue* stub = Add<HConstant>(callable.code());
    6937             :       result = New<HCallWithDescriptor>(
    6938       45840 :           Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values));
    6939             :     }
    6940       64582 :     return result;
    6941             :   }
    6942             : }
    6943             : 
    6944       95519 : HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
    6945             :     PropertyAccessType access_type, Expression* expr, FeedbackSlot slot,
    6946             :     HValue* object, HValue* key, HValue* value) {
    6947      191038 :   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
    6948       95519 :   HValue* vector_value = Add<HConstant>(vector);
    6949       95519 :   HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
    6950             : 
    6951       95519 :   if (access_type == LOAD) {
    6952       72441 :     HValue* values[] = {object, key, slot_value, vector_value};
    6953             : 
    6954       72441 :     Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
    6955       72441 :     HValue* stub = Add<HConstant>(callable.code());
    6956             :     HCallWithDescriptor* result =
    6957             :         New<HCallWithDescriptor>(Code::KEYED_LOAD_IC, stub, 0,
    6958       72441 :                                  callable.descriptor(), ArrayVector(values));
    6959             :     return result;
    6960             :   } else {
    6961       23078 :     HValue* values[] = {object, key, value, slot_value, vector_value};
    6962             : 
    6963             :     Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
    6964       23078 :         isolate(), function_language_mode());
    6965       23078 :     HValue* stub = Add<HConstant>(callable.code());
    6966             :     HCallWithDescriptor* result =
    6967             :         New<HCallWithDescriptor>(Code::KEYED_STORE_IC, stub, 0,
    6968       23078 :                                  callable.descriptor(), ArrayVector(values));
    6969             :     return result;
    6970             :   }
    6971             : }
    6972             : 
    6973             : 
    6974       24602 : LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
    6975             :   // Loads from a "stock" fast holey double arrays can elide the hole check.
    6976             :   // Loads from a "stock" fast holey array can convert the hole to undefined
    6977             :   // with impunity.
    6978             :   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
    6979             :   bool holey_double_elements =
    6980       88651 :       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS);
    6981             :   bool holey_elements =
    6982       24602 :       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS);
    6983       28362 :   if ((holey_double_elements || holey_elements) &&
    6984        3760 :       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
    6985             :     load_mode =
    6986        3695 :         holey_double_elements ? ALLOW_RETURN_HOLE : CONVERT_HOLE_TO_UNDEFINED;
    6987             : 
    6988             :     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
    6989        3695 :     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
    6990        3695 :     BuildCheckPrototypeMaps(prototype, object_prototype);
    6991        3695 :     graph()->MarkDependsOnEmptyArrayProtoElements();
    6992             :   }
    6993       24602 :   return load_mode;
    6994             : }
    6995             : 
    6996             : 
    6997       21913 : HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
    6998             :     HValue* object,
    6999             :     HValue* key,
    7000             :     HValue* val,
    7001             :     HValue* dependency,
    7002             :     Handle<Map> map,
    7003             :     PropertyAccessType access_type,
    7004             :     KeyedAccessStoreMode store_mode) {
    7005       21913 :   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
    7006             : 
    7007       26064 :   if (access_type == STORE && map->prototype()->IsJSObject()) {
    7008             :     // monomorphic stores need a prototype chain check because shape
    7009             :     // changes could allow callbacks on elements in the chain that
    7010             :     // aren't compatible with monomorphic keyed stores.
    7011        4056 :     PrototypeIterator iter(map);
    7012             :     JSObject* holder = NULL;
    7013       17676 :     while (!iter.IsAtEnd()) {
    7014             :       // JSProxies can't occur here because we wouldn't have installed a
    7015             :       // non-generic IC if there were any.
    7016             :       holder = *PrototypeIterator::GetCurrent<JSObject>(iter);
    7017        9564 :       iter.Advance();
    7018             :     }
    7019             :     DCHECK(holder && holder->IsJSObject());
    7020             : 
    7021             :     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
    7022        4056 :                             Handle<JSObject>(holder));
    7023             :   }
    7024             : 
    7025       21913 :   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
    7026             :   return BuildUncheckedMonomorphicElementAccess(
    7027             :       checked_object, key, val,
    7028             :       map->instance_type() == JS_ARRAY_TYPE,
    7029             :       map->elements_kind(), access_type,
    7030       21913 :       load_mode, store_mode);
    7031             : }
    7032             : 
    7033             : 
    7034       32532 : static bool CanInlineElementAccess(Handle<Map> map) {
    7035       32181 :   return map->IsJSObjectMap() &&
    7036       36217 :          (map->has_fast_elements() || map->has_fixed_typed_array_elements()) &&
    7037       64444 :          !map->has_indexed_interceptor() && !map->is_access_check_needed();
    7038             : }
    7039             : 
    7040             : 
    7041        1827 : HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
    7042             :     HValue* object,
    7043             :     HValue* key,
    7044             :     HValue* val,
    7045             :     SmallMapList* maps) {
    7046             :   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
    7047             :   // double), always use the "worst case" code without a transition.  This is
    7048             :   // much faster than transitioning the elements to the worst case, trading a
    7049             :   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
    7050             :   bool has_double_maps = false;
    7051             :   bool has_smi_or_object_maps = false;
    7052             :   bool has_js_array_access = false;
    7053             :   bool has_non_js_array_access = false;
    7054             :   bool has_seen_holey_elements = false;
    7055             :   Handle<Map> most_general_consolidated_map;
    7056       10120 :   for (int i = 0; i < maps->length(); ++i) {
    7057             :     Handle<Map> map = maps->at(i);
    7058        3819 :     if (!CanInlineElementAccess(map)) return NULL;
    7059             :     // Don't allow mixing of JSArrays with JSObjects.
    7060        3686 :     if (map->instance_type() == JS_ARRAY_TYPE) {
    7061        3526 :       if (has_non_js_array_access) return NULL;
    7062             :       has_js_array_access = true;
    7063         160 :     } else if (has_js_array_access) {
    7064             :       return NULL;
    7065             :     } else {
    7066             :       has_non_js_array_access = true;
    7067             :     }
    7068             :     // Don't allow mixed, incompatible elements kinds.
    7069        3567 :     if (map->has_fast_double_elements()) {
    7070         374 :       if (has_smi_or_object_maps) return NULL;
    7071             :       has_double_maps = true;
    7072        3193 :     } else if (map->has_fast_smi_or_object_elements()) {
    7073        3167 :       if (has_double_maps) return NULL;
    7074             :       has_smi_or_object_maps = true;
    7075             :     } else {
    7076             :       return NULL;
    7077             :     }
    7078             :     // Remember if we've ever seen holey elements.
    7079        3233 :     if (IsHoleyElementsKind(map->elements_kind())) {
    7080             :       has_seen_holey_elements = true;
    7081             :     }
    7082             :     // Remember the most general elements kind, the code for its load will
    7083             :     // properly handle all of the more specific cases.
    7084        4787 :     if ((i == 0) || IsMoreGeneralElementsKindTransition(
    7085             :             most_general_consolidated_map->elements_kind(),
    7086        1554 :             map->elements_kind())) {
    7087             :       most_general_consolidated_map = map;
    7088             :     }
    7089             :   }
    7090        1241 :   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
    7091             : 
    7092        3282 :   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
    7093             :   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
    7094             :   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
    7095             :   ElementsKind consolidated_elements_kind = has_seen_holey_elements
    7096             :       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
    7097        1241 :       : most_general_consolidated_map->elements_kind();
    7098             :   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
    7099        1241 :   if (has_seen_holey_elements) {
    7100             :     // Make sure that all of the maps we are handling have the initial array
    7101             :     // prototype.
    7102             :     bool saw_non_array_prototype = false;
    7103        1961 :     for (int i = 0; i < maps->length(); ++i) {
    7104             :       Handle<Map> map = maps->at(i);
    7105        2670 :       if (map->prototype() != *isolate()->initial_array_prototype()) {
    7106             :         // We can't guarantee that loading the hole is safe. The prototype may
    7107             :         // have an element at this position.
    7108             :         saw_non_array_prototype = true;
    7109             :         break;
    7110             :       }
    7111             :     }
    7112             : 
    7113        1105 :     if (!saw_non_array_prototype) {
    7114             :       Handle<Map> holey_map = handle(
    7115         198 :           isolate()->get_initial_js_array_map(consolidated_elements_kind));
    7116         198 :       load_mode = BuildKeyedHoleMode(holey_map);
    7117         198 :       if (load_mode != NEVER_RETURN_HOLE) {
    7118        1006 :         for (int i = 0; i < maps->length(); ++i) {
    7119             :           Handle<Map> map = maps->at(i);
    7120             :           // The prototype check was already done for the holey map in
    7121             :           // BuildKeyedHoleMode.
    7122         408 :           if (!map.is_identical_to(holey_map)) {
    7123             :             Handle<JSObject> prototype(JSObject::cast(map->prototype()),
    7124             :                                        isolate());
    7125             :             Handle<JSObject> object_prototype =
    7126         254 :                 isolate()->initial_object_prototype();
    7127         254 :             BuildCheckPrototypeMaps(prototype, object_prototype);
    7128             :           }
    7129             :         }
    7130             :       }
    7131             :     }
    7132             :   }
    7133             :   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
    7134             :       checked_object, key, val,
    7135             :       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
    7136        1241 :       consolidated_elements_kind, LOAD, load_mode, STANDARD_STORE);
    7137        1241 :   return instr;
    7138             : }
    7139             : 
    7140        3110 : HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
    7141             :     Expression* expr, FeedbackSlot slot, HValue* object, HValue* key,
    7142             :     HValue* val, SmallMapList* maps, PropertyAccessType access_type,
    7143             :     KeyedAccessStoreMode store_mode, bool* has_side_effects) {
    7144        3110 :   *has_side_effects = false;
    7145        9473 :   BuildCheckHeapObject(object);
    7146             : 
    7147        3110 :   if (access_type == LOAD) {
    7148             :     HInstruction* consolidated_load =
    7149        1827 :         TryBuildConsolidatedElementLoad(object, key, val, maps);
    7150        1827 :     if (consolidated_load != NULL) {
    7151        1241 :       *has_side_effects |= consolidated_load->HasObservableSideEffects();
    7152        1241 :       return consolidated_load;
    7153             :     }
    7154             :   }
    7155             : 
    7156             :   // Elements_kind transition support.
    7157             :   MapHandleList transition_target(maps->length());
    7158             :   // Collect possible transition targets.
    7159             :   MapHandleList possible_transitioned_maps(maps->length());
    7160       11722 :   for (int i = 0; i < maps->length(); ++i) {
    7161        4000 :     Handle<Map> map = maps->at(i);
    7162             :     // Loads from strings or loads with a mix of string and non-string maps
    7163             :     // shouldn't be handled polymorphically.
    7164             :     DCHECK(access_type != LOAD || !map->IsStringMap());
    7165             :     ElementsKind elements_kind = map->elements_kind();
    7166        7783 :     if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
    7167             :         elements_kind != GetInitialFastElementsKind()) {
    7168        2634 :       possible_transitioned_maps.Add(map);
    7169             :     }
    7170        4000 :     if (IsSloppyArgumentsElementsKind(elements_kind)) {
    7171             :       HInstruction* result =
    7172           8 :           BuildKeyedGeneric(access_type, expr, slot, object, key, val);
    7173           8 :       *has_side_effects = result->HasObservableSideEffects();
    7174           8 :       return AddInstruction(result);
    7175             :     }
    7176             :   }
    7177             :   // Get transition target for each map (NULL == no transition).
    7178        9833 :   for (int i = 0; i < maps->length(); ++i) {
    7179             :     Handle<Map> map = maps->at(i);
    7180             :     Map* transitioned_map =
    7181        3986 :         map->FindElementsKindTransitionedMap(&possible_transitioned_maps);
    7182        3986 :     if (transitioned_map != nullptr) {
    7183             :       DCHECK(!map->is_stable());
    7184         808 :       transition_target.Add(handle(transitioned_map));
    7185             :     } else {
    7186        3178 :       transition_target.Add(Handle<Map>());
    7187             :     }
    7188             :   }
    7189             : 
    7190             :   MapHandleList untransitionable_maps(maps->length());
    7191             :   HTransitionElementsKind* transition = NULL;
    7192       11694 :   for (int i = 0; i < maps->length(); ++i) {
    7193        3986 :     Handle<Map> map = maps->at(i);
    7194             :     DCHECK(map->IsMap());
    7195        3986 :     if (!transition_target.at(i).is_null()) {
    7196             :       DCHECK(Map::IsValidElementsTransition(
    7197             :           map->elements_kind(),
    7198             :           transition_target.at(i)->elements_kind()));
    7199             :       transition = Add<HTransitionElementsKind>(object, map,
    7200         808 :                                                 transition_target.at(i));
    7201             :     } else {
    7202        3178 :       untransitionable_maps.Add(map);
    7203             :     }
    7204             :   }
    7205             : 
    7206             :   // If only one map is left after transitioning, handle this case
    7207             :   // monomorphically.
    7208             :   DCHECK(untransitionable_maps.length() >= 1);
    7209        1861 :   if (untransitionable_maps.length() == 1) {
    7210         618 :     Handle<Map> untransitionable_map = untransitionable_maps[0];
    7211             :     HInstruction* instr = NULL;
    7212         618 :     if (!CanInlineElementAccess(untransitionable_map)) {
    7213             :       instr = AddInstruction(
    7214         134 :           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
    7215             :     } else {
    7216             :       instr = BuildMonomorphicElementAccess(
    7217             :           object, key, val, transition, untransitionable_map, access_type,
    7218         484 :           store_mode);
    7219             :     }
    7220         618 :     *has_side_effects |= instr->HasObservableSideEffects();
    7221         618 :     return access_type == STORE ? val : instr;
    7222             :   }
    7223             : 
    7224        1243 :   HBasicBlock* join = graph()->CreateBasicBlock();
    7225             : 
    7226        3803 :   for (int i = 0; i < untransitionable_maps.length(); ++i) {
    7227        5120 :     Handle<Map> map = untransitionable_maps[i];
    7228             :     ElementsKind elements_kind = map->elements_kind();
    7229        2560 :     HBasicBlock* this_map = graph()->CreateBasicBlock();
    7230        2560 :     HBasicBlock* other_map = graph()->CreateBasicBlock();
    7231             :     HCompareMap* mapcompare =
    7232        2560 :         New<HCompareMap>(object, map, this_map, other_map);
    7233        2560 :     FinishCurrentBlock(mapcompare);
    7234             : 
    7235             :     set_current_block(this_map);
    7236             :     HInstruction* access = NULL;
    7237        2560 :     if (!CanInlineElementAccess(map)) {
    7238             :       access = AddInstruction(
    7239          69 :           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
    7240             :     } else {
    7241             :       DCHECK(IsFastElementsKind(elements_kind) ||
    7242             :              IsFixedTypedArrayElementsKind(elements_kind));
    7243        2491 :       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
    7244             :       // Happily, mapcompare is a checked object.
    7245             :       access = BuildUncheckedMonomorphicElementAccess(
    7246             :           mapcompare, key, val,
    7247             :           map->instance_type() == JS_ARRAY_TYPE,
    7248             :           elements_kind, access_type,
    7249             :           load_mode,
    7250        2491 :           store_mode);
    7251             :     }
    7252        2560 :     *has_side_effects |= access->HasObservableSideEffects();
    7253             :     // The caller will use has_side_effects and add a correct Simulate.
    7254             :     access->SetFlag(HValue::kHasNoObservableSideEffects);
    7255        2560 :     if (access_type == LOAD) {
    7256         364 :       Push(access);
    7257             :     }
    7258             :     NoObservableSideEffectsScope scope(this);
    7259             :     GotoNoSimulate(join);
    7260             :     set_current_block(other_map);
    7261             :   }
    7262             : 
    7263             :   // Ensure that we visited at least one map above that goes to join. This is
    7264             :   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
    7265             :   // rather than joining the join block. If this becomes an issue, insert a
    7266             :   // generic access in the case length() == 0.
    7267             :   DCHECK(join->predecessors()->length() > 0);
    7268             :   // Deopt if none of the cases matched.
    7269             :   NoObservableSideEffectsScope scope(this);
    7270             :   FinishExitWithHardDeoptimization(
    7271        1243 :       DeoptimizeReason::kUnknownMapInPolymorphicElementAccess);
    7272             :   set_current_block(join);
    7273        1243 :   return access_type == STORE ? val : Pop();
    7274             : }
    7275             : 
    7276      107851 : HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
    7277             :     HValue* obj, HValue* key, HValue* val, Expression* expr, FeedbackSlot slot,
    7278             :     BailoutId ast_id, BailoutId return_id, PropertyAccessType access_type,
    7279             :     bool* has_side_effects) {
    7280             :   // A keyed name access with type feedback may contain the name.
    7281      122577 :   Handle<FeedbackVector> vector = handle(current_feedback_vector(), isolate());
    7282             :   HValue* expected_key = key;
    7283      215702 :   if (!key->ActualValue()->IsConstant()) {
    7284             :     Name* name = nullptr;
    7285       93552 :     if (access_type == LOAD) {
    7286             :       KeyedLoadICNexus nexus(vector, slot);
    7287       81014 :       name = nexus.FindFirstName();
    7288             :     } else {
    7289             :       KeyedStoreICNexus nexus(vector, slot);
    7290       12538 :       name = nexus.FindFirstName();
    7291             :     }
    7292       93552 :     if (name != nullptr) {
    7293             :       Handle<Name> handle_name(name);
    7294         426 :       expected_key = Add<HConstant>(handle_name);
    7295             :       // We need a check against the key.
    7296             :       bool in_new_space = isolate()->heap()->InNewSpace(*handle_name);
    7297         426 :       Unique<Name> unique_name = Unique<Name>::CreateUninitialized(handle_name);
    7298         426 :       Add<HCheckValue>(key, unique_name, in_new_space);
    7299             :     }
    7300             :   }
    7301      215702 :   if (expected_key->ActualValue()->IsConstant()) {
    7302             :     Handle<Object> constant =
    7303       14725 :         HConstant::cast(expected_key->ActualValue())->handle(isolate());
    7304             :     uint32_t array_index;
    7305       15287 :     if ((constant->IsString() &&
    7306       29481 :          !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) ||
    7307             :         constant->IsSymbol()) {
    7308         809 :       if (!constant->IsUniqueName()) {
    7309             :         constant = isolate()->factory()->InternalizeString(
    7310           1 :             Handle<String>::cast(constant));
    7311             :       }
    7312             :       HValue* access =
    7313             :           BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
    7314         809 :                            Handle<Name>::cast(constant), val, false);
    7315        2207 :       if (access == NULL || access->IsPhi() ||
    7316             :           HInstruction::cast(access)->IsLinked()) {
    7317         259 :         *has_side_effects = false;
    7318             :       } else {
    7319             :         HInstruction* instr = HInstruction::cast(access);
    7320         550 :         AddInstruction(instr);
    7321         550 :         *has_side_effects = instr->HasObservableSideEffects();
    7322             :       }
    7323         809 :       return access;
    7324             :     }
    7325             :   }
    7326             : 
    7327             :   DCHECK(!expr->IsPropertyName());
    7328             :   HInstruction* instr = NULL;
    7329             : 
    7330             :   SmallMapList* maps;
    7331      107042 :   bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, this);
    7332             : 
    7333             :   bool force_generic = false;
    7334      107042 :   if (expr->GetKeyType() == PROPERTY) {
    7335             :     // Non-Generic accesses assume that elements are being accessed, and will
    7336             :     // deopt for non-index keys, which the IC knows will occur.
    7337             :     // TODO(jkummerow): Consider adding proper support for property accesses.
    7338             :     force_generic = true;
    7339             :     monomorphic = false;
    7340      207396 :   } else if (access_type == STORE &&
    7341       22344 :              (monomorphic || (maps != NULL && !maps->is_empty()))) {
    7342             :     // Stores can't be mono/polymorphic if their prototype chain has dictionary
    7343             :     // elements. However a receiver map that has dictionary elements itself
    7344             :     // should be left to normal mono/poly behavior (the other maps may benefit
    7345             :     // from highly optimized stores).
    7346       18531 :     for (int i = 0; i < maps->length(); i++) {
    7347             :       Handle<Map> current_map = maps->at(i);
    7348        6637 :       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
    7349             :         force_generic = true;
    7350             :         monomorphic = false;
    7351             :         break;
    7352             :       }
    7353             :     }
    7354      267791 :   } else if (access_type == LOAD && !monomorphic &&
    7355      141962 :              (maps != NULL && !maps->is_empty())) {
    7356             :     // Polymorphic loads have to go generic if any of the maps are strings.
    7357             :     // If some, but not all of the maps are strings, we should go generic
    7358             :     // because polymorphic access wants to key on ElementsKind and isn't
    7359             :     // compatible with strings.
    7360        9616 :     for (int i = 0; i < maps->length(); i++) {
    7361             :       Handle<Map> current_map = maps->at(i);
    7362        3897 :       if (current_map->IsStringMap()) {
    7363             :         force_generic = true;
    7364             :         break;
    7365             :       }
    7366             :     }
    7367             :   }
    7368             : 
    7369      107042 :   if (monomorphic) {
    7370       43070 :     Handle<Map> map = maps->first();
    7371       21535 :     if (!CanInlineElementAccess(map)) {
    7372             :       instr = AddInstruction(
    7373         106 :           BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
    7374             :     } else {
    7375       21429 :       BuildCheckHeapObject(obj);
    7376             :       instr = BuildMonomorphicElementAccess(
    7377       21429 :           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
    7378             :     }
    7379      167647 :   } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
    7380             :     return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
    7381             :                                           access_type, expr->GetStoreMode(),
    7382        3110 :                                           has_side_effects);
    7383             :   } else {
    7384       82397 :     if (access_type == STORE) {
    7385       20225 :       if (expr->IsAssignment() &&
    7386       20102 :           expr->AsAssignment()->HasNoTypeInformation()) {
    7387             :         Add<HDeoptimize>(
    7388             :             DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess,
    7389        9450 :             Deoptimizer::SOFT);
    7390             :       }
    7391             :     } else {
    7392      144446 :       if (expr->AsProperty()->HasNoTypeInformation()) {
    7393             :         Add<HDeoptimize>(
    7394             :             DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess,
    7395       67193 :             Deoptimizer::SOFT);
    7396             :       }
    7397             :     }
    7398             :     instr = AddInstruction(
    7399       82397 :         BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
    7400             :   }
    7401      103932 :   *has_side_effects = instr->HasObservableSideEffects();
    7402      103932 :   return instr;
    7403             : }
    7404             : 
    7405             : 
    7406         571 : void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
    7407             :   // Outermost function already has arguments on the stack.
    7408         340 :   if (function_state()->outer() == NULL) return;
    7409             : 
    7410         340 :   if (function_state()->arguments_pushed()) return;
    7411             : 
    7412             :   // Push arguments when entering inlined function.
    7413         462 :   HEnterInlined* entry = function_state()->entry();
    7414             :   entry->set_arguments_pushed();
    7415             : 
    7416             :   HArgumentsObject* arguments = entry->arguments_object();
    7417             :   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
    7418             : 
    7419             :   HInstruction* insert_after = entry;
    7420        1958 :   for (int i = 0; i < arguments_values->length(); i++) {
    7421        1727 :     HValue* argument = arguments_values->at(i);
    7422         748 :     HInstruction* push_argument = New<HPushArguments>(argument);
    7423         748 :     push_argument->InsertAfter(insert_after);
    7424             :     insert_after = push_argument;
    7425             :   }
    7426             : 
    7427         231 :   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
    7428             :   arguments_elements->ClearFlag(HValue::kUseGVN);
    7429         231 :   arguments_elements->InsertAfter(insert_after);
    7430             :   function_state()->set_arguments_elements(arguments_elements);
    7431             : }
    7432             : 
    7433         751 : bool HOptimizedGraphBuilder::IsAnyParameterContextAllocated() {
    7434         751 :   int count = current_info()->scope()->num_parameters();
    7435        2121 :   for (int i = 0; i < count; ++i) {
    7436        4221 :     if (current_info()->scope()->parameter(i)->location() ==
    7437             :         VariableLocation::CONTEXT) {
    7438             :       return true;
    7439             :     }
    7440             :   }
    7441             :   return false;
    7442             : }
    7443             : 
    7444      323331 : bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
    7445      596320 :   VariableProxy* proxy = expr->obj()->AsVariableProxy();
    7446      313753 :   if (proxy == NULL) return false;
    7447      282567 :   if (!proxy->var()->IsStackAllocated()) return false;
    7448      448625 :   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
    7449             :     return false;
    7450             :   }
    7451             : 
    7452             :   HInstruction* result = NULL;
    7453        1462 :   if (expr->key()->IsPropertyName()) {
    7454        1408 :     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
    7455         704 :     if (!String::Equals(name, isolate()->factory()->length_string())) {
    7456           7 :       return false;
    7457             :     }
    7458             : 
    7459             :     // Make sure we visit the arguments object so that the liveness analysis
    7460             :     // still records the access.
    7461        2091 :     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
    7462             :     Drop(1);
    7463             : 
    7464         697 :     if (function_state()->outer() == NULL) {
    7465         447 :       HInstruction* elements = Add<HArgumentsElements>(false);
    7466         447 :       result = New<HArgumentsLength>(elements);
    7467             :     } else {
    7468             :       // Number of arguments without receiver.
    7469             :       int argument_count = environment()->
    7470         250 :           arguments_environment()->parameter_count() - 1;
    7471         250 :       result = New<HConstant>(argument_count);
    7472             :     }
    7473             :   } else {
    7474             :     // We need to take into account the KEYED_LOAD_IC feedback to guard the
    7475             :     // HBoundsCheck instructions below.
    7476        1059 :     if (!expr->IsMonomorphic() && !expr->IsUninitialized()) return false;
    7477         751 :     if (IsAnyParameterContextAllocated()) return false;
    7478        2142 :     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
    7479        2142 :     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
    7480             :     HValue* key = Pop();
    7481             :     Drop(1);  // Arguments object.
    7482         714 :     if (function_state()->outer() == NULL) {
    7483         374 :       HInstruction* elements = Add<HArgumentsElements>(false);
    7484         374 :       HInstruction* length = Add<HArgumentsLength>(elements);
    7485         374 :       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
    7486         374 :       result = New<HAccessArgumentsAt>(elements, length, checked_key);
    7487             :     } else {
    7488         340 :       EnsureArgumentsArePushedForAccess();
    7489             : 
    7490             :       // Number of arguments without receiver.
    7491         340 :       HInstruction* elements = function_state()->arguments_elements();
    7492             :       int argument_count = environment()->
    7493         340 :           arguments_environment()->parameter_count() - 1;
    7494         340 :       HInstruction* length = Add<HConstant>(argument_count);
    7495         340 :       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
    7496         340 :       result = New<HAccessArgumentsAt>(elements, length, checked_key);
    7497             :     }
    7498             :   }
    7499        2822 :   ast_context()->ReturnInstruction(result, expr->id());
    7500        1411 :   return true;
    7501             : }
    7502             : 
    7503      486255 : HValue* HOptimizedGraphBuilder::BuildNamedAccess(
    7504             :     PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
    7505             :     Expression* expr, FeedbackSlot slot, HValue* object, Handle<Name> name,
    7506             :     HValue* value, bool is_uninitialized) {
    7507             :   SmallMapList* maps;
    7508      486255 :   ComputeReceiverTypes(expr, object, &maps, this);
    7509             :   DCHECK(maps != NULL);
    7510             : 
    7511             :   // Check for special case: Access via a single map to the global proxy
    7512             :   // can also be handled monomorphically.
    7513      972510 :   if (maps->length() > 0) {
    7514             :     Handle<Object> map_constructor =
    7515      376648 :         handle(maps->first()->GetConstructor(), isolate());
    7516      188324 :     if (map_constructor->IsJSFunction()) {
    7517             :       Handle<Context> map_context =
    7518             :           handle(Handle<JSFunction>::cast(map_constructor)->context());
    7519      153202 :       Handle<Context> current_context(current_info()->context());
    7520             :       bool is_same_context_global_proxy_access =
    7521      295748 :           maps->length() == 1 &&  // >1 map => fallback to polymorphic
    7522      153520 :           maps->first()->IsJSGlobalProxyMap() &&
    7523             :           (*map_context == *current_context);
    7524      153202 :       if (is_same_context_global_proxy_access) {
    7525         201 :         Handle<JSGlobalObject> global_object(current_info()->global_object());
    7526         201 :         LookupIterator it(global_object, name, LookupIterator::OWN);
    7527         201 :         if (CanInlineGlobalPropertyAccess(&it, access)) {
    7528         156 :           BuildCheckHeapObject(object);
    7529         156 :           Add<HCheckMaps>(object, maps);
    7530         156 :           if (access == LOAD) {
    7531         143 :             InlineGlobalPropertyLoad(&it, expr->id());
    7532         143 :             return nullptr;
    7533             :           } else {
    7534          13 :             return InlineGlobalPropertyStore(&it, value, expr->id());
    7535             :           }
    7536             :         }
    7537             :       }
    7538             :     }
    7539             : 
    7540      376336 :     PropertyAccessInfo info(this, access, maps->first(), name);
    7541      188168 :     if (!info.CanAccessAsMonomorphic(maps)) {
    7542             :       HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
    7543       10166 :                                         object, value, maps, name);
    7544       10166 :       return NULL;
    7545             :     }
    7546             : 
    7547             :     HValue* checked_object;
    7548             :     // AstType::Number() is only supported by polymorphic load/call handling.
    7549             :     DCHECK(!info.IsNumberType());
    7550      178002 :     BuildCheckHeapObject(object);
    7551      178002 :     if (AreStringTypes(maps)) {
    7552             :       checked_object =
    7553       13773 :           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
    7554             :     } else {
    7555      164229 :       checked_object = Add<HCheckMaps>(object, maps);
    7556             :     }
    7557             :     return BuildMonomorphicAccess(
    7558      178002 :         &info, object, checked_object, value, ast_id, return_id);
    7559             :   }
    7560             : 
    7561             :   return BuildNamedGeneric(access, expr, slot, object, name, value,
    7562      297931 :                            is_uninitialized);
    7563             : }
    7564             : 
    7565             : 
    7566      207899 : void HOptimizedGraphBuilder::PushLoad(Property* expr,
    7567             :                                       HValue* object,
    7568             :                                       HValue* key) {
    7569             :   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
    7570      207899 :   Push(object);
    7571      207899 :   if (key != NULL) Push(key);
    7572      207899 :   BuildLoad(expr, expr->LoadId());
    7573      207899 : }
    7574             : 
    7575             : 
    7576     1468180 : void HOptimizedGraphBuilder::BuildLoad(Property* expr,
    7577      583449 :                                        BailoutId ast_id) {
    7578             :   HInstruction* instr = NULL;
    7579      520272 :   if (expr->IsStringAccess() && expr->GetKeyType() == ELEMENT) {
    7580             :     HValue* index = Pop();
    7581             :     HValue* string = Pop();
    7582          81 :     HInstruction* char_code = BuildStringCharCodeAt(string, index);
    7583          81 :     AddInstruction(char_code);
    7584         162 :     if (char_code->IsConstant()) {
    7585          21 :       HConstant* c_code = HConstant::cast(char_code);
    7586          42 :       if (c_code->HasNumberValue() && std::isnan(c_code->DoubleValue())) {
    7587          11 :         Add<HDeoptimize>(DeoptimizeReason::kOutOfBounds, Deoptimizer::EAGER);
    7588             :       }
    7589             :     }
    7590          81 :     instr = NewUncasted<HStringCharFromCode>(char_code);
    7591             : 
    7592      520095 :   } else if (expr->key()->IsPropertyName()) {
    7593      427909 :     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
    7594             :     HValue* object = Pop();
    7595             : 
    7596             :     HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
    7597             :                                      expr->PropertyFeedbackSlot(), object, name,
    7598      855818 :                                      NULL, expr->IsUninitialized());
    7599      427909 :     if (value == NULL) return;
    7600      418656 :     if (value->IsPhi()) return ast_context()->ReturnValue(value);
    7601             :     instr = HInstruction::cast(value);
    7602      419560 :     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
    7603             : 
    7604             :   } else {
    7605             :     HValue* key = Pop();
    7606             :     HValue* obj = Pop();
    7607             : 
    7608       92186 :     bool has_side_effects = false;
    7609             :     HValue* load = HandleKeyedElementAccess(
    7610             :         obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
    7611       92186 :         expr->LoadId(), LOAD, &has_side_effects);
    7612       92186 :     if (has_side_effects) {
    7613       72567 :       if (ast_context()->IsEffect()) {
    7614          28 :         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    7615             :       } else {
    7616       72539 :         Push(load);
    7617       72539 :         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    7618             :         Drop(1);
    7619             :       }
    7620             :     }
    7621       92186 :     if (load == NULL) return;
    7622       92145 :     return ast_context()->ReturnValue(load);
    7623             :   }
    7624      417833 :   return ast_context()->ReturnInstruction(instr, ast_id);
    7625             : }
    7626             : 
    7627             : 
    7628     1654363 : void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
    7629             :   DCHECK(!HasStackOverflow());
    7630             :   DCHECK(current_block() != NULL);
    7631             :   DCHECK(current_block()->HasPredecessor());
    7632             : 
    7633      313753 :   if (TryArgumentsAccess(expr)) return;
    7634             : 
    7635      716056 :   CHECK_ALIVE(VisitForValue(expr->obj()));
    7636      533182 :   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
    7637      274116 :     CHECK_ALIVE(VisitForValue(expr->key()));
    7638             :   }
    7639             : 
    7640      312277 :   BuildLoad(expr, expr->id());
    7641             : }
    7642             : 
    7643       94743 : HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant,
    7644         216 :                                                    bool ensure_no_elements) {
    7645             :   HCheckMaps* check = Add<HCheckMaps>(
    7646       94743 :       Add<HConstant>(constant), handle(constant->map()));
    7647             :   check->ClearDependsOnFlag(kElementsKind);
    7648       94743 :   if (ensure_no_elements) {
    7649             :     // TODO(ishell): remove this once we support NO_ELEMENTS elements kind.
    7650             :     HValue* elements = AddLoadElements(check, nullptr);
    7651             :     HValue* empty_elements =
    7652         216 :         Add<HConstant>(isolate()->factory()->empty_fixed_array());
    7653             :     IfBuilder if_empty(this);
    7654             :     if_empty.IfNot<HCompareObjectEqAndBranch>(elements, empty_elements);
    7655             :     if_empty.ThenDeopt(DeoptimizeReason::kWrongMap);
    7656         216 :     if_empty.End();
    7657             :   }
    7658       94743 :   return check;
    7659             : }
    7660             : 
    7661       61069 : HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
    7662             :                                                      Handle<JSObject> holder,
    7663       61069 :                                                      bool ensure_no_elements) {
    7664       61069 :   PrototypeIterator iter(isolate(), prototype, kStartAtReceiver);
    7665      245350 :   while (holder.is_null() ||
    7666             :          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
    7667             :     BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter),
    7668       36195 :                           ensure_no_elements);
    7669       36195 :     iter.Advance();
    7670       36195 :     if (iter.IsAtEnd()) {
    7671             :       return NULL;
    7672             :     }
    7673             :   }
    7674       58548 :   return BuildConstantMapCheck(holder);
    7675             : }
    7676             : 
    7677             : 
    7678        1565 : void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
    7679             :                                                    Handle<Map> receiver_map) {
    7680        1565 :   if (!holder.is_null()) {
    7681             :     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
    7682        1557 :     BuildCheckPrototypeMaps(prototype, holder);
    7683             :   }
    7684        1565 : }
    7685             : 
    7686         133 : void HOptimizedGraphBuilder::BuildEnsureCallable(HValue* object) {
    7687         133 :   NoObservableSideEffectsScope scope(this);
    7688             :   const Runtime::Function* throw_called_non_callable =
    7689         133 :       Runtime::FunctionForId(Runtime::kThrowCalledNonCallable);
    7690             : 
    7691             :   IfBuilder is_not_function(this);
    7692         133 :   HValue* smi_check = is_not_function.If<HIsSmiAndBranch>(object);
    7693         133 :   is_not_function.Or();
    7694             :   HValue* map = AddLoadMap(object, smi_check);
    7695             :   HValue* bit_field =
    7696         133 :       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
    7697             :   HValue* bit_field_masked = AddUncasted<HBitwise>(
    7698         133 :       Token::BIT_AND, bit_field, Add<HConstant>(1 << Map::kIsCallable));
    7699             :   is_not_function.IfNot<HCompareNumericAndBranch>(
    7700         133 :       bit_field_masked, Add<HConstant>(1 << Map::kIsCallable), Token::EQ);
    7701         133 :   is_not_function.Then();
    7702             :   {
    7703         133 :     Add<HPushArguments>(object);
    7704         133 :     Add<HCallRuntime>(throw_called_non_callable, 1);
    7705             :   }
    7706         133 :   is_not_function.End();
    7707         133 : }
    7708             : 
    7709      118037 : HInstruction* HOptimizedGraphBuilder::NewCallFunction(
    7710             :     HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode,
    7711             :     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) {
    7712      118037 :   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
    7713          89 :     BuildEnsureCallable(function);
    7714             :   } else {
    7715             :     DCHECK_EQ(TailCallMode::kDisallow, tail_call_mode);
    7716             :   }
    7717      236074 :   HValue* arity = Add<HConstant>(argument_count - 1);
    7718             : 
    7719      118037 :   HValue* op_vals[] = {function, arity};
    7720             : 
    7721             :   Callable callable =
    7722      118037 :       CodeFactory::Call(isolate(), convert_mode, tail_call_mode);
    7723      118037 :   HConstant* stub = Add<HConstant>(callable.code());
    7724             : 
    7725             :   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
    7726             :                                   ArrayVector(op_vals),
    7727      118037 :                                   syntactic_tail_call_mode);
    7728             : }
    7729             : 
    7730      243641 : HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC(
    7731             :     HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode,
    7732             :     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode,
    7733             :     FeedbackSlot slot) {
    7734      243641 :   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
    7735          44 :     BuildEnsureCallable(function);
    7736             :   } else {
    7737             :     DCHECK_EQ(TailCallMode::kDisallow, tail_call_mode);
    7738             :   }
    7739      243641 :   int arity = argument_count - 1;
    7740      487282 :   Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
    7741      243641 :   HValue* arity_val = Add<HConstant>(arity);
    7742      243641 :   HValue* index_val = Add<HConstant>(vector->GetIndex(slot));
    7743      243641 :   HValue* vector_val = Add<HConstant>(vector);
    7744             : 
    7745      243641 :   HValue* op_vals[] = {function, arity_val, index_val, vector_val};
    7746             :   Callable callable =
    7747      243641 :       CodeFactory::CallIC(isolate(), convert_mode, tail_call_mode);
    7748      243641 :   HConstant* stub = Add<HConstant>(callable.code());
    7749             : 
    7750             :   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
    7751             :                                   ArrayVector(op_vals),
    7752      243641 :                                   syntactic_tail_call_mode);
    7753             : }
    7754             : 
    7755      140084 : HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction(
    7756             :     Handle<JSFunction> function, int argument_count,
    7757             :     TailCallMode syntactic_tail_call_mode, TailCallMode tail_call_mode) {
    7758      140084 :   HValue* target = Add<HConstant>(function);
    7759             :   return New<HInvokeFunction>(target, function, argument_count,
    7760      140084 :                               syntactic_tail_call_mode, tail_call_mode);
    7761             : }
    7762             : 
    7763             : 
    7764             : class FunctionSorter {
    7765             :  public:
    7766             :   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
    7767        6756 :       : index_(index), ticks_(ticks), size_(size) {}
    7768             : 
    7769             :   int index() const { return index_; }
    7770             :   int ticks() const { return ticks_; }
    7771             :   int size() const { return size_; }
    7772             : 
    7773             :  private:
    7774             :   int index_;
    7775             :   int ticks_;
    7776             :   int size_;
    7777             : };
    7778             : 
    7779             : 
    7780        1648 : inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
    7781         849 :   int diff = lhs.ticks() - rhs.ticks();
    7782         849 :   if (diff != 0) return diff > 0;
    7783         799 :   return lhs.size() < rhs.size();
    7784             : }
    7785             : 
    7786             : 
    7787        6128 : void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
    7788             :                                                         HValue* receiver,
    7789             :                                                         SmallMapList* maps,
    7790        7127 :                                                         Handle<String> name) {
    7791        1689 :   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
    7792        8445 :   FunctionSorter order[kMaxCallPolymorphism];
    7793             : 
    7794             :   bool handle_smi = false;
    7795             :   bool handled_string = false;
    7796             :   int ordered_functions = 0;
    7797             : 
    7798             :   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
    7799             :   TailCallMode tail_call_mode =
    7800        1689 :       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
    7801             : 
    7802             :   int i;
    7803        7896 :   for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
    7804             :        ++i) {
    7805        2259 :     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
    7806        5598 :     if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
    7807             :         info.constant()->IsJSFunction()) {
    7808        1562 :       if (info.IsStringType()) {
    7809           1 :         if (handled_string) continue;
    7810             :         handled_string = true;
    7811             :       }
    7812             :       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
    7813        1562 :       if (info.IsNumberType()) {
    7814             :         handle_smi = true;
    7815             :       }
    7816             :       expr->set_target(target);
    7817             :       order[ordered_functions++] = FunctionSorter(
    7818        3124 :           i, target->shared()->profiler_ticks(), InliningAstSize(target));
    7819             :     }
    7820             :   }
    7821             : 
    7822        1689 :   std::sort(order, order + ordered_functions);
    7823             : 
    7824        1689 :   if (i < maps->length()) {
    7825             :     maps->Clear();
    7826             :     ordered_functions = -1;
    7827             :   }
    7828             : 
    7829             :   HBasicBlock* number_block = NULL;
    7830             :   HBasicBlock* join = NULL;
    7831             :   handled_string = false;
    7832             :   int count = 0;
    7833             : 
    7834        3251 :   for (int fn = 0; fn < ordered_functions; ++fn) {
    7835        1562 :     int i = order[fn].index();
    7836        1562 :     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
    7837        1562 :     if (info.IsStringType()) {
    7838           1 :       if (handled_string) continue;
    7839             :       handled_string = true;
    7840             :     }
    7841             :     // Reloads the target.
    7842        1562 :     info.CanAccessMonomorphic();
    7843             :     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
    7844             : 
    7845             :     expr->set_target(target);
    7846        1562 :     if (count == 0) {
    7847             :       // Only needed once.
    7848       10788 :       join = graph()->CreateBasicBlock();
    7849        1126 :       if (handle_smi) {
    7850         705 :         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
    7851         705 :         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
    7852         705 :         number_block = graph()->CreateBasicBlock();
    7853             :         FinishCurrentBlock(New<HIsSmiAndBranch>(
    7854         705 :                 receiver, empty_smi_block, not_smi_block));
    7855             :         GotoNoSimulate(empty_smi_block, number_block);
    7856             :         set_current_block(not_smi_block);
    7857             :       } else {
    7858         421 :         BuildCheckHeapObject(receiver);
    7859             :       }
    7860             :     }
    7861        1562 :     ++count;
    7862        1562 :     HBasicBlock* if_true = graph()->CreateBasicBlock();
    7863        1562 :     HBasicBlock* if_false = graph()->CreateBasicBlock();
    7864             :     HUnaryControlInstruction* compare;
    7865             : 
    7866        1562 :     Handle<Map> map = info.map();
    7867        1562 :     if (info.IsNumberType()) {
    7868         705 :       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
    7869         705 :       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
    7870         857 :     } else if (info.IsStringType()) {
    7871           1 :       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
    7872             :     } else {
    7873         856 :       compare = New<HCompareMap>(receiver, map, if_true, if_false);
    7874             :     }
    7875        1562 :     FinishCurrentBlock(compare);
    7876             : 
    7877        1562 :     if (info.IsNumberType()) {
    7878             :       GotoNoSimulate(if_true, number_block);
    7879             :       if_true = number_block;
    7880             :     }
    7881             : 
    7882             :     set_current_block(if_true);
    7883             : 
    7884        1562 :     AddCheckPrototypeMaps(info.holder(), map);
    7885             : 
    7886        1562 :     HValue* function = Add<HConstant>(expr->target());
    7887             :     environment()->SetExpressionStackAt(0, function);
    7888        1562 :     Push(receiver);
    7889        4686 :     CHECK_ALIVE(VisitExpressions(expr->arguments()));
    7890        1562 :     bool needs_wrapping = info.NeedsWrappingFor(target);
    7891        1562 :     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
    7892        1562 :     if (FLAG_trace_inlining && try_inline) {
    7893             :       Handle<JSFunction> caller = current_info()->closure();
    7894             :       std::unique_ptr<char[]> caller_name =
    7895           0 :           caller->shared()->DebugName()->ToCString();
    7896             :       PrintF("Trying to inline the polymorphic call to %s from %s\n",
    7897             :              name->ToCString().get(),
    7898           0 :              caller_name.get());
    7899             :     }
    7900        1562 :     if (try_inline && TryInlineCall(expr)) {
    7901             :       // Trying to inline will signal that we should bailout from the
    7902             :       // entire compilation by setting stack overflow on the visitor.
    7903          82 :       if (HasStackOverflow()) return;
    7904             :     } else {
    7905             :       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
    7906             :       // use the regular call builtin for method calls to wrap the receiver.
    7907             :       // TODO(verwaest): Support creation of value wrappers directly in
    7908             :       // HWrapReceiver.
    7909             :       HInstruction* call =
    7910             :           needs_wrapping
    7911             :               ? NewCallFunction(
    7912             :                     function, argument_count, syntactic_tail_call_mode,
    7913             :                     ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode)
    7914             :               : NewCallConstantFunction(target, argument_count,
    7915             :                                         syntactic_tail_call_mode,
    7916        1480 :                                         tail_call_mode);
    7917        1480 :       PushArgumentsFromEnvironment(argument_count);
    7918        1480 :       AddInstruction(call);
    7919             :       Drop(1);  // Drop the function.
    7920        1480 :       if (!ast_context()->IsEffect()) Push(call);
    7921             :     }
    7922             : 
    7923        1562 :     if (current_block() != NULL) Goto(join);
    7924             :     set_current_block(if_false);
    7925             :   }
    7926             : 
    7927             :   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
    7928             :   // know about and do not want to handle ones we've never seen.  Otherwise
    7929             :   // use a generic IC.
    7930        1689 :   if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
    7931             :     FinishExitWithHardDeoptimization(
    7932        1095 :         DeoptimizeReason::kUnknownMapInPolymorphicCall);
    7933             :   } else {
    7934         594 :     Property* prop = expr->expression()->AsProperty();
    7935             :     HInstruction* function =
    7936             :         BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
    7937        1188 :                           name, NULL, prop->IsUninitialized());
    7938         594 :     AddInstruction(function);
    7939         594 :     Push(function);
    7940             :     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
    7941             : 
    7942             :     environment()->SetExpressionStackAt(1, function);
    7943             :     environment()->SetExpressionStackAt(0, receiver);
    7944        1782 :     CHECK_ALIVE(VisitExpressions(expr->arguments()));
    7945             : 
    7946             :     HInstruction* call = NewCallFunction(
    7947             :         function, argument_count, syntactic_tail_call_mode,
    7948         594 :         ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode);
    7949             : 
    7950         594 :     PushArgumentsFromEnvironment(argument_count);
    7951             : 
    7952             :     Drop(1);  // Function.
    7953             : 
    7954         594 :     if (join != NULL) {
    7955          31 :       AddInstruction(call);
    7956          31 :       if (!ast_context()->IsEffect()) Push(call);
    7957             :       Goto(join);
    7958             :     } else {
    7959        1126 :       return ast_context()->ReturnInstruction(call, expr->id());
    7960             :     }
    7961             :   }
    7962             : 
    7963             :   // We assume that control flow is always live after an expression.  So
    7964             :   // even without predecessors to the join block, we set it as the exit
    7965             :   // block and continue by adding instructions there.
    7966             :   DCHECK(join != NULL);
    7967        1126 :   if (join->HasPredecessor()) {
    7968             :     set_current_block(join);
    7969             :     join->SetJoinId(expr->id());
    7970        1982 :     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
    7971             :   } else {
    7972             :     set_current_block(NULL);
    7973             :   }
    7974             : }
    7975             : 
    7976      145828 : void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
    7977             :                                          Handle<JSFunction> caller,
    7978             :                                          const char* reason,
    7979             :                                          TailCallMode tail_call_mode) {
    7980      145828 :   if (FLAG_trace_inlining) {
    7981             :     std::unique_ptr<char[]> target_name =
    7982           0 :         target->shared()->DebugName()->ToCString();
    7983             :     std::unique_ptr<char[]> caller_name =
    7984           0 :         caller->shared()->DebugName()->ToCString();
    7985           0 :     if (reason == NULL) {
    7986             :       const char* call_mode =
    7987           0 :           tail_call_mode == TailCallMode::kAllow ? "tail called" : "called";
    7988             :       PrintF("Inlined %s %s from %s.\n", target_name.get(), call_mode,
    7989           0 :              caller_name.get());
    7990             :     } else {
    7991             :       PrintF("Did not inline %s called from %s (%s).\n",
    7992           0 :              target_name.get(), caller_name.get(), reason);
    7993             :     }
    7994             :   }
    7995      145828 : }
    7996             : 
    7997             : 
    7998             : static const int kNotInlinable = 1000000000;
    7999             : 
    8000             : 
    8001      248447 : int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
    8002      248447 :   if (!FLAG_use_inlining) return kNotInlinable;
    8003             : 
    8004             :   // Precondition: call is monomorphic and we have found a target with the
    8005             :   // appropriate arity.
    8006      245188 :   Handle<JSFunction> caller = current_info()->closure();
    8007             :   Handle<SharedFunctionInfo> target_shared(target->shared());
    8008             : 
    8009             :   // Always inline functions that force inlining.
    8010      245188 :   if (target_shared->force_inline()) {
    8011             :     return 0;
    8012             :   }
    8013      242799 :   if (!target->shared()->IsUserJavaScript()) {
    8014             :     return kNotInlinable;
    8015             :   }
    8016             : 
    8017      142916 :   if (target_shared->IsApiFunction()) {
    8018           0 :     TraceInline(target, caller, "target is api function");
    8019           0 :     return kNotInlinable;
    8020             :   }
    8021             : 
    8022             :   // Do a quick check on source code length to avoid parsing large
    8023             :   // inlining candidates.
    8024      285832 :   if (target_shared->SourceSize() >
    8025      142916 :       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
    8026        7595 :     TraceInline(target, caller, "target text too big");
    8027        7595 :     return kNotInlinable;
    8028             :   }
    8029             : 
    8030             :   // Target must be inlineable.
    8031             :   BailoutReason noopt_reason = target_shared->disable_optimization_reason();
    8032      135321 :   if (!target_shared->IsInlineable() && noopt_reason != kHydrogenFilter) {
    8033         808 :     TraceInline(target, caller, "target not inlineable");
    8034         808 :     return kNotInlinable;
    8035             :   }
    8036      134513 :   if (noopt_reason != kNoReason && noopt_reason != kHydrogenFilter) {
    8037           0 :     TraceInline(target, caller, "target contains unsupported syntax [early]");
    8038           0 :     return kNotInlinable;
    8039             :   }
    8040             : 
    8041             :   int nodes_added = target_shared->ast_node_count();
    8042      134513 :   return nodes_added;
    8043             : }
    8044             : 
    8045      246938 : bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
    8046             :                                        int arguments_count,
    8047             :                                        HValue* implicit_return_value,
    8048             :                                        BailoutId ast_id, BailoutId return_id,
    8049             :                                        InliningKind inlining_kind,
    8050      675063 :                                        TailCallMode syntactic_tail_call_mode) {
    8051      246938 :   if (target->context()->native_context() !=
    8052     1670778 :       top_info()->closure()->context()->native_context()) {
    8053             :     return false;
    8054             :   }
    8055      246885 :   int nodes_added = InliningAstSize(target);
    8056      246885 :   if (nodes_added == kNotInlinable) return false;
    8057             : 
    8058      136810 :   Handle<JSFunction> caller = current_info()->closure();
    8059      273620 :   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
    8060           7 :     TraceInline(target, caller, "target AST is too large [early]");
    8061           7 :     return false;
    8062             :   }
    8063             : 
    8064             :   // Don't inline deeper than the maximum number of inlining levels.
    8065      305860 :   HEnvironment* env = environment();
    8066             :   int current_level = 1;
    8067      442663 :   while (env->outer() != NULL) {
    8068      171231 :     if (current_level == FLAG_max_inlining_levels) {
    8069        2174 :       TraceInline(target, caller, "inline depth limit reached");
    8070        2174 :       return false;
    8071             :     }
    8072      169057 :     if (env->outer()->frame_type() == JS_FUNCTION) {
    8073      129382 :       current_level++;
    8074             :     }
    8075             :     env = env->outer();
    8076             :   }
    8077             : 
    8078             :   // Don't inline recursive functions.
    8079      471624 :   for (FunctionState* state = function_state();
    8080             :        state != NULL;
    8081             :        state = state->outer()) {
    8082      239339 :     if (*state->compilation_info()->closure() == *target) {
    8083        7054 :       TraceInline(target, caller, "target is recursive");
    8084        7054 :       return false;
    8085             :     }
    8086             :   }
    8087             : 
    8088             :   // We don't want to add more than a certain number of nodes from inlining.
    8089             :   // Always inline small methods (<= 10 nodes).
    8090      255150 :   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
    8091      127575 :                            kUnlimitedMaxInlinedNodesCumulative)) {
    8092        4963 :     TraceInline(target, caller, "cumulative AST node limit reached");
    8093        4963 :     return false;
    8094             :   }
    8095             : 
    8096             :   // Parse and allocate variables.
    8097             :   // Use the same AstValueFactory for creating strings in the sub-compilation
    8098             :   // step, but don't transfer ownership to target_info.
    8099             :   Handle<SharedFunctionInfo> target_shared(target->shared());
    8100      367836 :   ParseInfo parse_info(target_shared, top_info()->parse_info()->zone_shared());
    8101             :   parse_info.set_ast_value_factory(
    8102      122612 :       top_info()->parse_info()->ast_value_factory());
    8103             :   parse_info.set_ast_value_factory_owned(false);
    8104             : 
    8105             :   CompilationInfo target_info(parse_info.zone(), &parse_info,
    8106      245224 :                               target->GetIsolate(), target);
    8107             : 
    8108      243596 :   if (inlining_kind != CONSTRUCT_CALL_RETURN &&
    8109             :       IsClassConstructor(target_shared->kind())) {
    8110           0 :     TraceInline(target, caller, "target is classConstructor");
    8111           0 :     return false;
    8112             :   }
    8113             : 
    8114      122612 :   if (target_shared->HasDebugInfo()) {
    8115          29 :     TraceInline(target, caller, "target is being debugged");
    8116          29 :     return false;
    8117             :   }
    8118      122583 :   if (!Compiler::ParseAndAnalyze(&target_info)) {
    8119           1 :     if (target_info.isolate()->has_pending_exception()) {
    8120             :       // Parse or scope error, never optimize this function.
    8121             :       SetStackOverflow();
    8122           1 :       target_shared->DisableOptimization(kParseScopeError);
    8123             :     }
    8124           1 :     TraceInline(target, caller, "parse failure");
    8125           1 :     return false;
    8126             :   }
    8127      122582 :   if (target_shared->must_use_ignition_turbo()) {
    8128       11835 :     TraceInline(target, caller, "ParseAndAnalyze found incompatibility");
    8129       11835 :     return false;
    8130             :   }
    8131             : 
    8132      221494 :   if (target_info.scope()->NeedsContext()) {
    8133        3270 :     TraceInline(target, caller, "target has context-allocated variables");
    8134        3270 :     return false;
    8135             :   }
    8136             : 
    8137      214954 :   if (target_info.scope()->rest_parameter() != nullptr) {
    8138           0 :     TraceInline(target, caller, "target uses rest parameters");
    8139           0 :     return false;
    8140             :   }
    8141             : 
    8142      537262 :   FunctionLiteral* function = target_info.literal();
    8143             : 
    8144             :   // The following conditions must be checked again after re-parsing, because
    8145             :   // earlier the information might not have been complete due to lazy parsing.
    8146             :   nodes_added = function->ast_node_count();
    8147      214954 :   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
    8148           0 :     TraceInline(target, caller, "target AST is too large [late]");
    8149           0 :     return false;
    8150             :   }
    8151      107477 :   if (function->dont_optimize()) {
    8152           0 :     TraceInline(target, caller, "target contains unsupported syntax [late]");
    8153           0 :     return false;
    8154             :   }
    8155             : 
    8156             :   // If the function uses the arguments object check that inlining of functions
    8157             :   // with arguments object is enabled and the arguments-variable is
    8158             :   // stack allocated.
    8159      107477 :   if (function->scope()->arguments() != NULL) {
    8160         380 :     if (!FLAG_inline_arguments) {
    8161           0 :       TraceInline(target, caller, "target uses arguments object");
    8162           0 :       return false;
    8163             :     }
    8164             :   }
    8165             : 
    8166             :   // Unsupported variable references present.
    8167      214954 :   if (function->scope()->this_function_var() != nullptr ||
    8168      107477 :       function->scope()->new_target_var() != nullptr) {
    8169           0 :     TraceInline(target, caller, "target uses new target or this function");
    8170           0 :     return false;
    8171             :   }
    8172             : 
    8173             :   // All declarations must be inlineable.
    8174      107477 :   Declaration::List* decls = target_info.scope()->declarations();
    8175      396304 :   for (Declaration* decl : *decls) {
    8176      181384 :     if (decl->IsFunctionDeclaration() ||
    8177       90675 :         !decl->proxy()->var()->IsStackAllocated()) {
    8178          34 :       TraceInline(target, caller, "target has non-trivial declaration");
    8179             :       return false;
    8180             :     }
    8181             :   }
    8182             : 
    8183             :   // Generate the deoptimization data for the unoptimized version of
    8184             :   // the target function if we don't already have it.
    8185      107443 :   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
    8186           7 :     TraceInline(target, caller, "could not generate deoptimization info");
    8187           7 :     return false;
    8188             :   }
    8189             : 
    8190             :   // Remember that we inlined this function. This needs to be called right
    8191             :   // after the EnsureDeoptimizationSupport call so that the code flusher
    8192             :   // does not remove the code with the deoptimization support.
    8193             :   int inlining_id = top_info()->AddInlinedFunction(target_info.shared_info(),
    8194      214872 :                                                    source_position());
    8195             : 
    8196             :   // ----------------------------------------------------------------
    8197             :   // After this point, we've made a decision to inline this function (so
    8198             :   // TryInline should always return true).
    8199             : 
    8200             :   // If target was lazily compiled, it's literals array may not yet be set up.
    8201      107436 :   JSFunction::EnsureLiterals(target);
    8202             : 
    8203             :   // Type-check the inlined function.
    8204             :   DCHECK(target_shared->has_deoptimization_support());
    8205             :   AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
    8206             :            target_info.scope(), target_info.osr_ast_id(), target_info.literal(),
    8207             :            &bounds_)
    8208      107436 :       .Run();
    8209             : 
    8210             :   // Save the pending call context. Set up new one for the inlined function.
    8211             :   // The function state is new-allocated because we need to delete it
    8212             :   // in two different places.
    8213             :   FunctionState* target_state = new FunctionState(
    8214             :       this, &target_info, inlining_kind, inlining_id,
    8215      214872 :       function_state()->ComputeTailCallMode(syntactic_tail_call_mode));
    8216             : 
    8217      107436 :   HConstant* undefined = graph()->GetConstantUndefined();
    8218             : 
    8219             :   HEnvironment* inner_env = environment()->CopyForInlining(
    8220             :       target, arguments_count, function, undefined,
    8221      214872 :       function_state()->inlining_kind(), syntactic_tail_call_mode);
    8222             : 
    8223      107436 :   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
    8224      107436 :   inner_env->BindContext(context);
    8225             : 
    8226             :   // Create a dematerialized arguments object for the function, also copy the
    8227             :   // current arguments values to use them for materialization.
    8228      107436 :   HEnvironment* arguments_env = inner_env->arguments_environment();
    8229             :   int parameter_count = arguments_env->parameter_count();
    8230      107436 :   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
    8231      407129 :   for (int i = 0; i < parameter_count; i++) {
    8232      299693 :     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
    8233             :   }
    8234             : 
    8235             :   // If the function uses arguments object then bind bind one.
    8236      107436 :   if (function->scope()->arguments() != NULL) {
    8237             :     DCHECK(function->scope()->arguments()->IsStackAllocated());
    8238         380 :     inner_env->Bind(function->scope()->arguments(), arguments_object);
    8239             :   }
    8240             : 
    8241             :   // Capture the state before invoking the inlined function for deopt in the
    8242             :   // inlined function. This simulate has no bailout-id since it's not directly
    8243             :   // reachable for deopt, and is only used to capture the state. If the simulate
    8244             :   // becomes reachable by merging, the ast id of the simulate merged into it is
    8245             :   // adopted.
    8246             :   Add<HSimulate>(BailoutId::None());
    8247             : 
    8248             :   current_block()->UpdateEnvironment(inner_env);
    8249             :   Scope* saved_scope = scope();
    8250      107436 :   set_scope(target_info.scope());
    8251             :   HEnterInlined* enter_inlined = Add<HEnterInlined>(
    8252             :       return_id, target, context, arguments_count, function,
    8253             :       function_state()->inlining_kind(), function->scope()->arguments(),
    8254      214872 :       arguments_object, syntactic_tail_call_mode);
    8255      107436 :   if (is_tracking_positions()) {
    8256             :     enter_inlined->set_inlining_id(inlining_id);
    8257             :   }
    8258             : 
    8259             :   function_state()->set_entry(enter_inlined);
    8260             : 
    8261      107436 :   VisitDeclarations(target_info.scope()->declarations());
    8262      107436 :   VisitStatements(function->body());
    8263             :   set_scope(saved_scope);
    8264      107436 :   if (HasStackOverflow()) {
    8265             :     // Bail out if the inline function did, as we cannot residualize a call
    8266             :     // instead, but do not disable optimization for the outer function.
    8267          36 :     TraceInline(target, caller, "inline graph construction failed");
    8268          36 :     target_shared->DisableOptimization(kInliningBailedOut);
    8269             :     current_info()->RetryOptimization(kInliningBailedOut);
    8270          36 :     delete target_state;
    8271             :     return true;
    8272             :   }
    8273             : 
    8274             :   // Update inlined nodes count.
    8275      107400 :   inlined_count_ += nodes_added;
    8276             : 
    8277             :   Handle<Code> unoptimized_code(target_shared->code());
    8278             :   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
    8279             :   Handle<TypeFeedbackInfo> type_info(
    8280             :       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
    8281             :   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
    8282             : 
    8283      107400 :   TraceInline(target, caller, NULL, syntactic_tail_call_mode);
    8284             : 
    8285      107400 :   if (current_block() != NULL) {
    8286       60303 :     FunctionState* state = function_state();
    8287       60303 :     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
    8288             :       // Falling off the end of an inlined construct call. In a test context the
    8289             :       // return value will always evaluate to true, in a value context the
    8290             :       // return value is the newly allocated receiver.
    8291         842 :       if (call_context()->IsTest()) {
    8292          12 :         inlined_test_context()->ReturnValue(graph()->GetConstantTrue());
    8293         830 :       } else if (call_context()->IsEffect()) {
    8294             :         Goto(function_return(), state);
    8295             :       } else {
    8296             :         DCHECK(call_context()->IsValue());
    8297             :         AddLeaveInlined(implicit_return_value, state);
    8298             :       }
    8299       59461 :     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
    8300             :       // Falling off the end of an inlined setter call. The returned value is
    8301             :       // never used, the value of an assignment is always the value of the RHS
    8302             :       // of the assignment.
    8303         145 :       if (call_context()->IsTest()) {
    8304             :         inlined_test_context()->ReturnValue(implicit_return_value);
    8305         131 :       } else if (call_context()->IsEffect()) {
    8306             :         Goto(function_return(), state);
    8307             :       } else {
    8308             :         DCHECK(call_context()->IsValue());
    8309             :         AddLeaveInlined(implicit_return_value, state);
    8310             :       }
    8311             :     } else {
    8312             :       // Falling off the end of a normal inlined function. This basically means
    8313             :       // returning undefined.
    8314       59316 :       if (call_context()->IsTest()) {
    8315         136 :         inlined_test_context()->ReturnValue(graph()->GetConstantFalse());
    8316       59180 :       } else if (call_context()->IsEffect()) {
    8317             :         Goto(function_return(), state);
    8318             :       } else {
    8319             :         DCHECK(call_context()->IsValue());
    8320             :         AddLeaveInlined(undefined, state);
    8321             :       }
    8322             :     }
    8323             :   }
    8324             : 
    8325             :   // Fix up the function exits.
    8326      107400 :   if (inlined_test_context() != NULL) {
    8327       19395 :     HBasicBlock* if_true = inlined_test_context()->if_true();
    8328       19395 :     HBasicBlock* if_false = inlined_test_context()->if_false();
    8329             : 
    8330       19395 :     HEnterInlined* entry = function_state()->entry();
    8331             : 
    8332             :     // Pop the return test context from the expression context stack.
    8333             :     DCHECK(ast_context() == inlined_test_context());
    8334             :     ClearInlinedTestContext();
    8335       19395 :     delete target_state;
    8336             : 
    8337             :     // Forward to the real test context.
    8338       19395 :     if (if_true->HasPredecessor()) {
    8339       19395 :       entry->RegisterReturnTarget(if_true, zone());
    8340             :       if_true->SetJoinId(ast_id);
    8341       19395 :       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
    8342             :       Goto(if_true, true_target, function_state());
    8343             :     }
    8344       19395 :     if (if_false->HasPredecessor()) {
    8345       19395 :       entry->RegisterReturnTarget(if_false, zone());
    8346             :       if_false->SetJoinId(ast_id);
    8347       19395 :       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
    8348             :       Goto(if_false, false_target, function_state());
    8349             :     }
    8350             :     set_current_block(NULL);
    8351       19395 :     return true;
    8352             : 
    8353       88005 :   } else if (function_return()->HasPredecessor()) {
    8354       88005 :     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
    8355             :     function_return()->SetJoinId(ast_id);
    8356             :     set_current_block(function_return());
    8357             :   } else {
    8358             :     set_current_block(NULL);
    8359             :   }
    8360       88005 :   delete target_state;
    8361      122612 :   return true;
    8362             : }
    8363             : 
    8364             : 
    8365      477784 : bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
    8366             :   return TryInline(expr->target(), expr->arguments()->length(), NULL,
    8367             :                    expr->id(), expr->ReturnId(), NORMAL_RETURN,
    8368      238892 :                    expr->tail_call_mode());
    8369             : }
    8370             : 
    8371             : 
    8372        9102 : bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
    8373             :                                                 HValue* implicit_return_value) {
    8374             :   return TryInline(expr->target(), expr->arguments()->length(),
    8375             :                    implicit_return_value, expr->id(), expr->ReturnId(),
    8376        4551 :                    CONSTRUCT_CALL_RETURN, TailCallMode::kDisallow);
    8377             : }
    8378             : 
    8379        3069 : bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter,
    8380             :                                              Handle<Map> receiver_map,
    8381             :                                              BailoutId ast_id,
    8382             :                                              BailoutId return_id) {
    8383        3069 :   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
    8384        3034 :   if (getter->IsJSFunction()) {
    8385        3034 :     Handle<JSFunction> getter_function = Handle<JSFunction>::cast(getter);
    8386        5924 :     return TryInlineBuiltinGetterCall(getter_function, receiver_map, ast_id) ||
    8387             :            TryInline(getter_function, 0, NULL, ast_id, return_id,
    8388        2890 :                      GETTER_CALL_RETURN, TailCallMode::kDisallow);
    8389             :   }
    8390             :   return false;
    8391             : }
    8392             : 
    8393         246 : bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
    8394             :                                              Handle<Map> receiver_map,
    8395             :                                              BailoutId id,
    8396             :                                              BailoutId assignment_id,
    8397             :                                              HValue* implicit_return_value) {
    8398         246 :   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
    8399         468 :   return setter->IsJSFunction() &&
    8400             :          TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value,
    8401             :                    id, assignment_id, SETTER_CALL_RETURN,
    8402         468 :                    TailCallMode::kDisallow);
    8403             : }
    8404             : 
    8405             : 
    8406         371 : bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
    8407         371 :                                                    Call* expr,
    8408             :                                                    int arguments_count) {
    8409             :   return TryInline(function, arguments_count, NULL, expr->id(),
    8410         371 :                    expr->ReturnId(), NORMAL_RETURN, expr->tail_call_mode());
    8411             : }
    8412             : 
    8413             : 
    8414      215284 : bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
    8415      197968 :   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
    8416             :   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
    8417             :   // We intentionally ignore expr->tail_call_mode() here because builtins
    8418             :   // we inline here do not observe if they were tail called or not.
    8419       48988 :   switch (id) {
    8420             :     case kMathCos:
    8421             :     case kMathExp:
    8422             :     case kMathRound:
    8423             :     case kMathFround:
    8424             :     case kMathFloor:
    8425             :     case kMathAbs:
    8426             :     case kMathSin:
    8427             :     case kMathSqrt:
    8428             :     case kMathLog:
    8429             :     case kMathClz32:
    8430        8624 :       if (expr->arguments()->length() == 1) {
    8431          68 :         HValue* argument = Pop();
    8432             :         Drop(2);  // Receiver and function.
    8433        8624 :         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
    8434       17248 :         ast_context()->ReturnInstruction(op, expr->id());
    8435        8624 :         return true;
    8436             :       }
    8437             :       break;
    8438             :     case kMathImul:
    8439          34 :       if (expr->arguments()->length() == 2) {
    8440             :         HValue* right = Pop();
    8441             :         HValue* left = Pop();
    8442             :         Drop(2);  // Receiver and function.
    8443             :         HInstruction* op =
    8444          68 :             HMul::NewImul(isolate(), zone(), context(), left, right);
    8445          68 :         ast_context()->ReturnInstruction(op, expr->id());
    8446          34 :         return true;
    8447             :       }
    8448             :       break;
    8449             :     default:
    8450             :       // Not supported for inlining yet.
    8451             :       break;
    8452             :   }
    8453             :   return false;
    8454             : }
    8455             : 
    8456             : 
    8457             : // static
    8458        2548 : bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
    8459             :     Handle<Map> jsarray_map) {
    8460             :   DCHECK(!jsarray_map->is_dictionary_map());
    8461             :   Isolate* isolate = jsarray_map->GetIsolate();
    8462             :   Handle<Name> length_string = isolate->factory()->length_string();
    8463             :   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
    8464             :   int number =
    8465             :       descriptors->SearchWithCache(isolate, *length_string, *jsarray_map);
    8466             :   DCHECK_NE(DescriptorArray::kNotFound, number);
    8467        5096 :   return descriptors->GetDetails(number).IsReadOnly();
    8468             : }
    8469             : 
    8470             : 
    8471             : // static
    8472        2695 : bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
    8473             :     Handle<Map> receiver_map) {
    8474        5202 :   return !receiver_map.is_null() && receiver_map->prototype()->IsJSObject() &&
    8475        2592 :          receiver_map->instance_type() == JS_ARRAY_TYPE &&
    8476        2559 :          IsFastElementsKind(receiver_map->elements_kind()) &&
    8477        5106 :          !receiver_map->is_dictionary_map() && receiver_map->is_extensible() &&
    8478        5254 :          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
    8479        5243 :          !IsReadOnlyLengthDescriptor(receiver_map);
    8480             : }
    8481             : 
    8482        3034 : bool HOptimizedGraphBuilder::TryInlineBuiltinGetterCall(
    8483         144 :     Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id) {
    8484        3034 :   if (!function->shared()->HasBuiltinFunctionId()) return false;
    8485             :   BuiltinFunctionId id = function->shared()->builtin_function_id();
    8486             : 
    8487             :   // Try to inline getter calls like DataView.prototype.byteLength/byteOffset
    8488             :   // as operations in the calling function.
    8489         170 :   switch (id) {
    8490             :     case kDataViewBuffer: {
    8491           0 :       if (!receiver_map->IsJSDataViewMap()) return false;
    8492             :       HObjectAccess access = HObjectAccess::ForMapAndOffset(
    8493           0 :           receiver_map, JSDataView::kBufferOffset);
    8494             :       HValue* object = Pop();  // receiver
    8495           0 :       HInstruction* result = New<HLoadNamedField>(object, object, access);
    8496           0 :       ast_context()->ReturnInstruction(result, ast_id);
    8497           0 :       return true;
    8498             :     }
    8499             :     case kDataViewByteLength:
    8500             :     case kDataViewByteOffset: {
    8501          12 :       if (!receiver_map->IsJSDataViewMap()) return false;
    8502             :       int offset = (id == kDataViewByteLength) ? JSDataView::kByteLengthOffset
    8503          12 :                                                : JSDataView::kByteOffsetOffset;
    8504             :       HObjectAccess access =
    8505          12 :           HObjectAccess::ForMapAndOffset(receiver_map, offset);
    8506             :       HValue* object = Pop();  // receiver
    8507          12 :       HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
    8508             :       HInstruction* result =
    8509          12 :           New<HLoadNamedField>(object, checked_object, access);
    8510          12 :       ast_context()->ReturnInstruction(result, ast_id);
    8511          12 :       return true;
    8512             :     }
    8513             :     case kTypedArrayByteLength:
    8514             :     case kTypedArrayByteOffset:
    8515             :     case kTypedArrayLength: {
    8516         132 :       if (!receiver_map->IsJSTypedArrayMap()) return false;
    8517             :       int offset = (id == kTypedArrayLength)
    8518             :                        ? JSTypedArray::kLengthOffset
    8519             :                        : (id == kTypedArrayByteLength)
    8520             :                              ? JSTypedArray::kByteLengthOffset
    8521         132 :                              : JSTypedArray::kByteOffsetOffset;
    8522             :       HObjectAccess access =
    8523         132 :           HObjectAccess::ForMapAndOffset(receiver_map, offset);
    8524             :       HValue* object = Pop();  // receiver
    8525         132 :       HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
    8526             :       HInstruction* result =
    8527         132 :           New<HLoadNamedField>(object, checked_object, access);
    8528         132 :       ast_context()->ReturnInstruction(result, ast_id);
    8529         132 :       return true;
    8530             :     }
    8531             :     default:
    8532             :       return false;
    8533             :   }
    8534             : }
    8535             : 
    8536             : // static
    8537         123 : bool HOptimizedGraphBuilder::NoElementsInPrototypeChain(
    8538             :     Handle<Map> receiver_map) {
    8539             :   // TODO(ishell): remove this once we support NO_ELEMENTS elements kind.
    8540         123 :   PrototypeIterator iter(receiver_map);
    8541             :   Handle<Object> empty_fixed_array =
    8542         123 :       iter.isolate()->factory()->empty_fixed_array();
    8543             :   while (true) {
    8544             :     Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
    8545         231 :     if (current->elements() != *empty_fixed_array) return false;
    8546         216 :     iter.Advance();
    8547         216 :     if (iter.IsAtEnd()) {
    8548             :       return true;
    8549             :     }
    8550             :   }
    8551             : }
    8552             : 
    8553       86284 : bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
    8554             :     Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id,
    8555       32202 :     int args_count_no_receiver) {
    8556       86284 :   if (!function->shared()->HasBuiltinFunctionId()) return false;
    8557             :   BuiltinFunctionId id = function->shared()->builtin_function_id();
    8558       48814 :   int argument_count = args_count_no_receiver + 1;  // Plus receiver.
    8559             : 
    8560       48814 :   if (receiver_map.is_null()) {
    8561        6199 :     HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
    8562        1224 :     if (receiver->IsConstant() &&
    8563         554 :         HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
    8564             :       receiver_map =
    8565             :           handle(Handle<HeapObject>::cast(
    8566          73 :                      HConstant::cast(receiver)->handle(isolate()))->map());
    8567             :     }
    8568             :   }
    8569             :   // Try to inline calls like Math.* as operations in the calling function.
    8570       48814 :   switch (id) {
    8571             :     case kObjectHasOwnProperty: {
    8572             :       // It's not safe to look through the phi for elements if we're compiling
    8573             :       // for osr.
    8574          34 :       if (top_info()->is_osr()) return false;
    8575          19 :       if (argument_count != 2) return false;
    8576             :       HValue* key = Top();
    8577          19 :       if (!key->IsLoadKeyed()) return false;
    8578             :       HValue* elements = HLoadKeyed::cast(key)->elements();
    8579           3 :       if (!elements->IsPhi() || elements->OperandCount() != 1) return false;
    8580           0 :       if (!elements->OperandAt(0)->IsForInCacheArray()) return false;
    8581           0 :       HForInCacheArray* cache = HForInCacheArray::cast(elements->OperandAt(0));
    8582             :       HValue* receiver = environment()->ExpressionStackAt(1);
    8583           0 :       if (!receiver->IsPhi() || receiver->OperandCount() != 1) return false;
    8584           0 :       if (cache->enumerable() != receiver->OperandAt(0)) return false;
    8585             :       Drop(3);  // key, receiver, function
    8586           0 :       Add<HCheckMapValue>(receiver, cache->map());
    8587           0 :       ast_context()->ReturnValue(graph()->GetConstantTrue());
    8588           0 :       return true;
    8589             :     }
    8590             :     case kStringCharCodeAt:
    8591             :     case kStringCharAt:
    8592         353 :       if (argument_count == 2) {
    8593             :         HValue* index = Pop();
    8594             :         HValue* string = Pop();
    8595             :         Drop(1);  // Function.
    8596             :         HInstruction* char_code =
    8597         347 :             BuildStringCharCodeAt(string, index);
    8598         347 :         if (id == kStringCharCodeAt) {
    8599         213 :           ast_context()->ReturnInstruction(char_code, ast_id);
    8600         213 :           return true;
    8601             :         }
    8602         134 :         AddInstruction(char_code);
    8603         134 :         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
    8604         134 :         ast_context()->ReturnInstruction(result, ast_id);
    8605         134 :         return true;
    8606             :       }
    8607             :       break;
    8608             :     case kStringFromCharCode:
    8609         319 :       if (argument_count == 2) {
    8610             :         HValue* argument = Pop();
    8611             :         Drop(2);  // Receiver and function.
    8612             :         argument = AddUncasted<HForceRepresentation>(
    8613         294 :             argument, Representation::Integer32());
    8614             :         argument->SetFlag(HValue::kTruncatingToInt32);
    8615         294 :         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
    8616         294 :         ast_context()->ReturnInstruction(result, ast_id);
    8617         294 :         return true;
    8618             :       }
    8619             :       break;
    8620             :     case kMathCos:
    8621             :     case kMathExp:
    8622             :     case kMathRound:
    8623             :     case kMathFround:
    8624             :     case kMathFloor:
    8625             :     case kMathAbs:
    8626             :     case kMathSin:
    8627             :     case kMathSqrt:
    8628             :     case kMathLog:
    8629             :     case kMathClz32:
    8630       20580 :       if (argument_count == 2) {
    8631             :         HValue* argument = Pop();
    8632             :         Drop(2);  // Receiver and function.
    8633       20573 :         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
    8634       20573 :         ast_context()->ReturnInstruction(op, ast_id);
    8635       20573 :         return true;
    8636             :       }
    8637             :       break;
    8638             :     case kMathPow:
    8639        1140 :       if (argument_count == 3) {
    8640             :         HValue* right = Pop();
    8641             :         HValue* left = Pop();
    8642             :         Drop(2);  // Receiver and function.
    8643             :         HInstruction* result = NULL;
    8644             :         // Use sqrt() if exponent is 0.5 or -0.5.
    8645        2036 :         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
    8646         876 :           double exponent = HConstant::cast(right)->DoubleValue();
    8647         876 :           if (exponent == 0.5) {
    8648          49 :             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
    8649         827 :           } else if (exponent == -0.5) {
    8650             :             HValue* one = graph()->GetConstant1();
    8651             :             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
    8652          46 :                 left, kMathPowHalf);
    8653             :             // MathPowHalf doesn't have side effects so there's no need for
    8654             :             // an environment simulation here.
    8655             :             DCHECK(!sqrt->HasObservableSideEffects());
    8656          46 :             result = NewUncasted<HDiv>(one, sqrt);
    8657         781 :           } else if (exponent == 2.0) {
    8658          43 :             result = NewUncasted<HMul>(left, left);
    8659             :           }
    8660             :         }
    8661             : 
    8662        1129 :         if (result == NULL) {
    8663         991 :           result = NewUncasted<HPower>(left, right);
    8664             :         }
    8665        1129 :         ast_context()->ReturnInstruction(result, ast_id);
    8666        1129 :         return true;
    8667             :       }
    8668             :       break;
    8669             :     case kMathMax:
    8670             :     case kMathMin:
    8671        1800 :       if (argument_count == 3) {
    8672             :         HValue* right = Pop();
    8673             :         HValue* left = Pop();
    8674             :         Drop(2);  // Receiver and function.
    8675             :         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
    8676        1750 :                                                      : HMathMinMax::kMathMax;
    8677        1750 :         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
    8678        1750 :         ast_context()->ReturnInstruction(result, ast_id);
    8679        1750 :         return true;
    8680             :       }
    8681             :       break;
    8682             :     case kMathImul:
    8683          30 :       if (argument_count == 3) {
    8684             :         HValue* right = Pop();
    8685             :         HValue* left = Pop();
    8686             :         Drop(2);  // Receiver and function.
    8687             :         HInstruction* result =
    8688          60 :             HMul::NewImul(isolate(), zone(), context(), left, right);
    8689          30 :         ast_context()->ReturnInstruction(result, ast_id);
    8690          30 :         return true;
    8691             :       }
    8692             :       break;
    8693             :     case kArrayPop: {
    8694         185 :       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
    8695             :       ElementsKind elements_kind = receiver_map->elements_kind();
    8696             : 
    8697             :       Drop(args_count_no_receiver);
    8698             :       HValue* result;
    8699             :       HValue* reduced_length;
    8700             :       HValue* receiver = Pop();
    8701             : 
    8702         144 :       HValue* checked_object = AddCheckMap(receiver, receiver_map);
    8703             :       HValue* length =
    8704             :           Add<HLoadNamedField>(checked_object, nullptr,
    8705         144 :                                HObjectAccess::ForArrayLength(elements_kind));
    8706             : 
    8707             :       Drop(1);  // Function.
    8708             : 
    8709             :       { NoObservableSideEffectsScope scope(this);
    8710             :         IfBuilder length_checker(this);
    8711             : 
    8712             :         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
    8713         144 :             length, graph()->GetConstant0(), Token::EQ);
    8714         144 :         length_checker.Then();
    8715             : 
    8716         282 :         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
    8717             : 
    8718             :         length_checker.Else();
    8719             :         HValue* elements = AddLoadElements(checked_object);
    8720             :         // Ensure that we aren't popping from a copy-on-write array.
    8721         144 :         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
    8722             :           elements = BuildCopyElementsOnWrite(checked_object, elements,
    8723         121 :                                               elements_kind, length);
    8724             :         }
    8725         144 :         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
    8726             :         result = AddElementAccess(elements, reduced_length, nullptr,
    8727         144 :                                   bounds_check, nullptr, elements_kind, LOAD);
    8728             :         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
    8729             :                            ? graph()->GetConstantHole()
    8730         265 :                            : Add<HConstant>(HConstant::kHoleNaN);
    8731         144 :         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
    8732             :           elements_kind = FAST_HOLEY_ELEMENTS;
    8733             :         }
    8734             :         AddElementAccess(elements, reduced_length, hole, bounds_check, nullptr,
    8735         144 :                          elements_kind, STORE);
    8736             :         Add<HStoreNamedField>(
    8737             :             checked_object, HObjectAccess::ForArrayLength(elements_kind),
    8738         144 :             reduced_length, STORE_TO_INITIALIZED_ENTRY);
    8739             : 
    8740         144 :         if (!ast_context()->IsEffect()) Push(result);
    8741             : 
    8742         144 :         length_checker.End();
    8743             :       }
    8744         144 :       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
    8745         144 :       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    8746         144 :       if (!ast_context()->IsEffect()) Drop(1);
    8747             : 
    8748         144 :       ast_context()->ReturnValue(result);
    8749         144 :       return true;
    8750             :     }
    8751             :     case kArrayPush: {
    8752        2362 :       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
    8753             :       ElementsKind elements_kind = receiver_map->elements_kind();
    8754             : 
    8755             :       // If there may be elements accessors in the prototype chain, the fast
    8756             :       // inlined version can't be used.
    8757        2248 :       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
    8758             :       // If there currently can be no elements accessors on the prototype chain,
    8759             :       // it doesn't mean that there won't be any later. Install a full prototype
    8760             :       // chain check to trap element accessors being installed on the prototype
    8761             :       // chain, which would cause elements to go to dictionary mode and result
    8762             :       // in a map change.
    8763             :       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
    8764        2243 :       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
    8765             : 
    8766             :       // Protect against adding elements to the Array prototype, which needs to
    8767             :       // route through appropriate bottlenecks.
    8768        4473 :       if (isolate()->IsFastArrayConstructorPrototypeChainIntact() &&
    8769             :           !prototype->IsJSArray()) {
    8770             :         return false;
    8771             :       }
    8772             : 
    8773             :       const int argc = args_count_no_receiver;
    8774        2072 :       if (argc != 1) return false;
    8775             : 
    8776             :       HValue* value_to_push = Pop();
    8777             :       HValue* array = Pop();
    8778             :       Drop(1);  // Drop function.
    8779             : 
    8780             :       HInstruction* new_size = NULL;
    8781             :       HValue* length = NULL;
    8782             : 
    8783             :       {
    8784             :         NoObservableSideEffectsScope scope(this);
    8785             : 
    8786             :         length = Add<HLoadNamedField>(
    8787        2067 :             array, nullptr, HObjectAccess::ForArrayLength(elements_kind));
    8788             : 
    8789        2067 :         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
    8790             : 
    8791        2067 :         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
    8792        2067 :         HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
    8793             :         BuildUncheckedMonomorphicElementAccess(
    8794             :             checked_array, length, value_to_push, is_array, elements_kind,
    8795        2067 :             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
    8796             : 
    8797        2067 :         if (!ast_context()->IsEffect()) Push(new_size);
    8798        2067 :         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    8799        2067 :         if (!ast_context()->IsEffect()) Drop(1);
    8800             :       }
    8801             : 
    8802        2067 :       ast_context()->ReturnValue(new_size);
    8803        2067 :       return true;
    8804             :     }
    8805             :     case kArrayShift: {
    8806         148 :       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
    8807         123 :       if (!NoElementsInPrototypeChain(receiver_map)) return false;
    8808             :       ElementsKind kind = receiver_map->elements_kind();
    8809             : 
    8810             :       // If there may be elements accessors in the prototype chain, the fast
    8811             :       // inlined version can't be used.
    8812         108 :       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
    8813             : 
    8814             :       // If there currently can be no elements accessors on the prototype chain,
    8815             :       // it doesn't mean that there won't be any later. Install a full prototype
    8816             :       // chain check to trap element accessors being installed on the prototype
    8817             :       // chain, which would cause elements to go to dictionary mode and result
    8818             :       // in a map change.
    8819             :       BuildCheckPrototypeMaps(
    8820             :           handle(JSObject::cast(receiver_map->prototype()), isolate()),
    8821         108 :           Handle<JSObject>::null(), true);
    8822             : 
    8823             :       // Threshold for fast inlined Array.shift().
    8824         108 :       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
    8825             : 
    8826             :       Drop(args_count_no_receiver);
    8827             :       HValue* result;
    8828             :       HValue* receiver = Pop();
    8829         108 :       HValue* checked_object = AddCheckMap(receiver, receiver_map);
    8830             :       HValue* length = Add<HLoadNamedField>(
    8831         108 :           receiver, checked_object, HObjectAccess::ForArrayLength(kind));
    8832             : 
    8833             :       Drop(1);  // Function.
    8834             :       {
    8835             :         NoObservableSideEffectsScope scope(this);
    8836             : 
    8837             :         IfBuilder if_lengthiszero(this);
    8838             :         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
    8839         108 :             length, graph()->GetConstant0(), Token::EQ);
    8840         108 :         if_lengthiszero.Then();
    8841             :         {
    8842         178 :           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
    8843             :         }
    8844             :         if_lengthiszero.Else();
    8845             :         {
    8846             :           HValue* elements = AddLoadElements(receiver);
    8847             : 
    8848             :           // Check if we can use the fast inlined Array.shift().
    8849             :           IfBuilder if_inline(this);
    8850             :           if_inline.If<HCompareNumericAndBranch>(
    8851         108 :               length, inline_threshold, Token::LTE);
    8852         108 :           if (IsFastSmiOrObjectElementsKind(kind)) {
    8853             :             // We cannot handle copy-on-write backing stores here.
    8854             :             if_inline.AndIf<HCompareMap>(
    8855             :                 elements, isolate()->factory()->fixed_array_map());
    8856             :           }
    8857         108 :           if_inline.Then();
    8858             :           {
    8859             :             // Remember the result.
    8860         108 :             if (!ast_context()->IsEffect()) {
    8861             :               Push(AddElementAccess(elements, graph()->GetConstant0(), nullptr,
    8862          70 :                                     lengthiszero, nullptr, kind, LOAD));
    8863             :             }
    8864             : 
    8865             :             // Compute the new length.
    8866             :             HValue* new_length = AddUncasted<HSub>(
    8867         108 :                 length, graph()->GetConstant1());
    8868             :             new_length->ClearFlag(HValue::kCanOverflow);
    8869             : 
    8870             :             // Copy the remaining elements.
    8871         108 :             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
    8872             :             {
    8873             :               HValue* new_key = loop.BeginBody(
    8874         108 :                   graph()->GetConstant0(), new_length, Token::LT);
    8875         108 :               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
    8876             :               key->ClearFlag(HValue::kCanOverflow);
    8877             :               ElementsKind copy_kind =
    8878         108 :                   kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
    8879             :               HValue* element =
    8880             :                   AddUncasted<HLoadKeyed>(elements, key, lengthiszero, nullptr,
    8881         108 :                                           copy_kind, ALLOW_RETURN_HOLE);
    8882             :               HStoreKeyed* store = Add<HStoreKeyed>(elements, new_key, element,
    8883         108 :                                                     nullptr, copy_kind);
    8884             :               store->SetFlag(HValue::kTruncatingToNumber);
    8885             :             }
    8886         108 :             loop.EndBody();
    8887             : 
    8888             :             // Put a hole at the end.
    8889             :             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
    8890             :                                ? graph()->GetConstantHole()
    8891         211 :                                : Add<HConstant>(HConstant::kHoleNaN);
    8892         108 :             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
    8893             :             Add<HStoreKeyed>(elements, new_length, hole, nullptr, kind,
    8894         108 :                              INITIALIZING_STORE);
    8895             : 
    8896             :             // Remember new length.
    8897             :             Add<HStoreNamedField>(
    8898             :                 receiver, HObjectAccess::ForArrayLength(kind),
    8899         108 :                 new_length, STORE_TO_INITIALIZED_ENTRY);
    8900             :           }
    8901             :           if_inline.Else();
    8902             :           {
    8903         108 :             Add<HPushArguments>(receiver);
    8904             :             result = AddInstruction(NewCallConstantFunction(
    8905         108 :                 function, 1, TailCallMode::kDisallow, TailCallMode::kDisallow));
    8906         108 :             if (!ast_context()->IsEffect()) Push(result);
    8907             :           }
    8908         108 :           if_inline.End();
    8909             :         }
    8910         108 :         if_lengthiszero.End();
    8911             :       }
    8912         108 :       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
    8913         108 :       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    8914         108 :       if (!ast_context()->IsEffect()) Drop(1);
    8915         108 :       ast_context()->ReturnValue(result);
    8916         108 :       return true;
    8917             :     }
    8918             :     case kArrayIndexOf:
    8919             :     case kArrayLastIndexOf: {
    8920         191 :       if (receiver_map.is_null()) return false;
    8921         191 :       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
    8922         191 :       if (!receiver_map->prototype()->IsJSObject()) return false;
    8923             :       ElementsKind kind = receiver_map->elements_kind();
    8924         185 :       if (!IsFastElementsKind(kind)) return false;
    8925         185 :       if (argument_count != 2) return false;
    8926         170 :       if (!receiver_map->is_extensible()) return false;
    8927             : 
    8928             :       // If there may be elements accessors in the prototype chain, the fast
    8929             :       // inlined version can't be used.
    8930         170 :       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
    8931             : 
    8932             :       // If there currently can be no elements accessors on the prototype chain,
    8933             :       // it doesn't mean that there won't be any later. Install a full prototype
    8934             :       // chain check to trap element accessors being installed on the prototype
    8935             :       // chain, which would cause elements to go to dictionary mode and result
    8936             :       // in a map change.
    8937             :       BuildCheckPrototypeMaps(
    8938             :           handle(JSObject::cast(receiver_map->prototype()), isolate()),
    8939         170 :           Handle<JSObject>::null());
    8940             : 
    8941             :       HValue* search_element = Pop();
    8942             :       HValue* receiver = Pop();
    8943             :       Drop(1);  // Drop function.
    8944             : 
    8945             :       ArrayIndexOfMode mode = (id == kArrayIndexOf)
    8946         170 :           ? kFirstIndexOf : kLastIndexOf;
    8947         170 :       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
    8948             : 
    8949         170 :       if (!ast_context()->IsEffect()) Push(index);
    8950         170 :       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    8951         170 :       if (!ast_context()->IsEffect()) Drop(1);
    8952         170 :       ast_context()->ReturnValue(index);
    8953         170 :       return true;
    8954             :     }
    8955             :     default:
    8956             :       // Not yet supported for inlining.
    8957             :       break;
    8958             :   }
    8959             :   return false;
    8960             : }
    8961             : 
    8962             : 
    8963      567930 : bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
    8964             :                                                       HValue* receiver) {
    8965      189310 :   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
    8966             :   Handle<JSFunction> function = expr->target();
    8967      189310 :   int argc = expr->arguments()->length();
    8968             :   SmallMapList receiver_maps;
    8969             :   return TryInlineApiCall(function, receiver, &receiver_maps, argc, expr->id(),
    8970      189310 :                           kCallApiFunction, expr->tail_call_mode());
    8971             : }
    8972             : 
    8973             : 
    8974       59301 : bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
    8975      118602 :     Call* expr,
    8976             :     HValue* receiver,
    8977             :     SmallMapList* receiver_maps) {
    8978       59301 :   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
    8979             :   Handle<JSFunction> function = expr->target();
    8980       59301 :   int argc = expr->arguments()->length();
    8981             :   return TryInlineApiCall(function, receiver, receiver_maps, argc, expr->id(),
    8982       59301 :                           kCallApiMethod, expr->tail_call_mode());
    8983             : }
    8984             : 
    8985        3069 : bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function,
    8986             :                                                 Handle<Map> receiver_map,
    8987             :                                                 BailoutId ast_id) {
    8988        3069 :   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
    8989        6138 :   SmallMapList receiver_maps(1, zone());
    8990             :   receiver_maps.Add(receiver_map, zone());
    8991             :   return TryInlineApiCall(function,
    8992             :                           NULL,  // Receiver is on expression stack.
    8993             :                           &receiver_maps, 0, ast_id, kCallApiGetter,
    8994        3069 :                           TailCallMode::kDisallow);
    8995             : }
    8996             : 
    8997         246 : bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function,
    8998             :                                                 Handle<Map> receiver_map,
    8999             :                                                 BailoutId ast_id) {
    9000         492 :   SmallMapList receiver_maps(1, zone());
    9001             :   receiver_maps.Add(receiver_map, zone());
    9002             :   return TryInlineApiCall(function,
    9003             :                           NULL,  // Receiver is on expression stack.
    9004             :                           &receiver_maps, 1, ast_id, kCallApiSetter,
    9005         246 :                           TailCallMode::kDisallow);
    9006             : }
    9007             : 
    9008      251926 : bool HOptimizedGraphBuilder::TryInlineApiCall(
    9009             :     Handle<Object> function, HValue* receiver, SmallMapList* receiver_maps,
    9010             :     int argc, BailoutId ast_id, ApiCallType call_type,
    9011       11220 :     TailCallMode syntactic_tail_call_mode) {
    9012      251926 :   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
    9013      503837 :   if (function->IsJSFunction() &&
    9014             :       Handle<JSFunction>::cast(function)->context()->native_context() !=
    9015      302693 :           top_info()->closure()->context()->native_context()) {
    9016             :     return false;
    9017             :   }
    9018      251875 :   if (argc > CallApiCallbackStub::kArgMax) {
    9019             :     return false;
    9020             :   }
    9021             : 
    9022      251848 :   CallOptimization optimization(function);
    9023      251848 :   if (!optimization.is_simple_api_call()) return false;
    9024             :   Handle<Map> holder_map;
    9025       16547 :   for (int i = 0; i < receiver_maps->length(); ++i) {
    9026             :     auto map = receiver_maps->at(i);
    9027             :     // Don't inline calls to receivers requiring accesschecks.
    9028        2662 :     if (map->is_access_check_needed()) return false;
    9029             :   }
    9030       11223 :   if (call_type == kCallApiFunction) {
    9031             :     // Cannot embed a direct reference to the global proxy map
    9032             :     // as it maybe dropped on deserialization.
    9033        8561 :     CHECK(!isolate()->serializer_enabled());
    9034             :     DCHECK(function->IsJSFunction());
    9035             :     DCHECK_EQ(0, receiver_maps->length());
    9036             :     receiver_maps->Add(
    9037             :         handle(Handle<JSFunction>::cast(function)->global_proxy()->map()),
    9038             :         zone());
    9039             :   }
    9040             :   CallOptimization::HolderLookup holder_lookup =
    9041       11223 :       CallOptimization::kHolderNotFound;
    9042             :   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
    9043       11223 :       receiver_maps->first(), &holder_lookup);
    9044       11223 :   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
    9045             : 
    9046       11220 :   if (FLAG_trace_inlining) {
    9047           0 :     PrintF("Inlining api function ");
    9048           0 :     function->ShortPrint();
    9049           0 :     PrintF("\n");
    9050             :   }
    9051             : 
    9052             :   bool is_function = false;
    9053             :   bool is_store = false;
    9054       11220 :   switch (call_type) {
    9055             :     case kCallApiFunction:
    9056             :     case kCallApiMethod:
    9057             :       // Need to check that none of the receiver maps could have changed.
    9058       11173 :       Add<HCheckMaps>(receiver, receiver_maps);
    9059             :       // Need to ensure the chain between receiver and api_holder is intact.
    9060       11173 :       if (holder_lookup == CallOptimization::kHolderFound) {
    9061           3 :         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
    9062             :       } else {
    9063             :         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
    9064             :       }
    9065             :       // Includes receiver.
    9066       11173 :       PushArgumentsFromEnvironment(argc + 1);
    9067             :       is_function = true;
    9068       11173 :       break;
    9069             :     case kCallApiGetter:
    9070             :       // Receiver and prototype chain cannot have changed.
    9071             :       DCHECK_EQ(0, argc);
    9072             :       DCHECK_NULL(receiver);
    9073             :       // Receiver is on expression stack.
    9074             :       receiver = Pop();
    9075          35 :       Add<HPushArguments>(receiver);
    9076          35 :       break;
    9077             :     case kCallApiSetter:
    9078             :       {
    9079             :         is_store = true;
    9080             :         // Receiver and prototype chain cannot have changed.
    9081             :         DCHECK_EQ(1, argc);
    9082             :         DCHECK_NULL(receiver);
    9083             :         // Receiver and value are on expression stack.
    9084             :         HValue* value = Pop();
    9085             :         receiver = Pop();
    9086          12 :         Add<HPushArguments>(receiver, value);
    9087          12 :         break;
    9088             :      }
    9089             :   }
    9090             : 
    9091             :   HValue* holder = NULL;
    9092       11220 :   switch (holder_lookup) {
    9093             :     case CallOptimization::kHolderFound:
    9094           3 :       holder = Add<HConstant>(api_holder);
    9095           3 :       break;
    9096             :     case CallOptimization::kHolderIsReceiver:
    9097             :       holder = receiver;
    9098       11217 :       break;
    9099             :     case CallOptimization::kHolderNotFound:
    9100           0 :       UNREACHABLE();
    9101             :       break;
    9102             :   }
    9103             :   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
    9104             :   Handle<Object> call_data_obj(api_call_info->data(), isolate());
    9105       11220 :   HValue* call_data = Add<HConstant>(call_data_obj);
    9106             :   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
    9107             :   ExternalReference ref = ExternalReference(&fun,
    9108             :                                             ExternalReference::DIRECT_API_CALL,
    9109       11220 :                                             isolate());
    9110       11220 :   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
    9111             : 
    9112       11220 :   HValue* op_vals[] = {Add<HConstant>(function), call_data, holder,
    9113       11220 :                        api_function_address};
    9114             : 
    9115             :   HInstruction* call = nullptr;
    9116       11220 :   CHECK(argc <= CallApiCallbackStub::kArgMax);
    9117       11220 :   if (!is_function) {
    9118             :     CallApiCallbackStub stub(isolate(), is_store,
    9119          47 :                              !optimization.is_constant_call());
    9120          47 :     Handle<Code> code = stub.GetCode();
    9121          47 :     HConstant* code_value = Add<HConstant>(code);
    9122             :     call = New<HCallWithDescriptor>(
    9123             :         code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
    9124          47 :         Vector<HValue*>(op_vals, arraysize(op_vals)), syntactic_tail_call_mode);
    9125             :   } else {
    9126             :     CallApiCallbackStub stub(isolate(), argc, false);
    9127       11173 :     Handle<Code> code = stub.GetCode();
    9128       11173 :     HConstant* code_value = Add<HConstant>(code);
    9129             :     call = New<HCallWithDescriptor>(
    9130             :         code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
    9131       11173 :         Vector<HValue*>(op_vals, arraysize(op_vals)), syntactic_tail_call_mode);
    9132             :     Drop(1);  // Drop function.
    9133             :   }
    9134             : 
    9135       11220 :   ast_context()->ReturnInstruction(call, ast_id);
    9136       11220 :   return true;
    9137             : }
    9138             : 
    9139             : 
    9140       10579 : void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
    9141       10444 :                                                 int arguments_count) {
    9142             :   Handle<JSFunction> known_function;
    9143        5357 :   int args_count_no_receiver = arguments_count - 1;
    9144       16071 :   if (function->IsConstant() &&
    9145        6941 :       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    9146             :     known_function =
    9147         396 :         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
    9148         792 :     if (TryInlineBuiltinMethodCall(known_function, Handle<Map>(), expr->id(),
    9149         396 :                                    args_count_no_receiver)) {
    9150          25 :       if (FLAG_trace_inlining) {
    9151           0 :         PrintF("Inlining builtin ");
    9152           0 :         known_function->ShortPrint();
    9153           0 :         PrintF("\n");
    9154             :       }
    9155             :       return;
    9156             :     }
    9157             : 
    9158         371 :     if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
    9159             :       return;
    9160             :     }
    9161             :   }
    9162             : 
    9163             :   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
    9164             :   TailCallMode tail_call_mode =
    9165        5222 :       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
    9166             : 
    9167        5222 :   PushArgumentsFromEnvironment(arguments_count);
    9168             :   HInvokeFunction* call =
    9169             :       New<HInvokeFunction>(function, known_function, arguments_count,
    9170        5222 :                            syntactic_tail_call_mode, tail_call_mode);
    9171             :   Drop(1);  // Function
    9172       10444 :   ast_context()->ReturnInstruction(call, expr->id());
    9173             : }
    9174             : 
    9175             : 
    9176       96690 : bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
    9177             :   DCHECK(expr->expression()->IsProperty());
    9178             : 
    9179       91405 :   if (!expr->IsMonomorphic()) {
    9180             :     return false;
    9181             :   }
    9182       90407 :   Handle<Map> function_map = expr->GetReceiverTypes()->first();
    9183      104294 :   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
    9184             :       !expr->target()->shared()->HasBuiltinFunctionId()) {
    9185             :     return false;
    9186             :   }
    9187             : 
    9188        6730 :   switch (expr->target()->shared()->builtin_function_id()) {
    9189             :     case kFunctionCall: {
    9190        5285 :       if (expr->arguments()->length() == 0) return false;
    9191        5264 :       BuildFunctionCall(expr);
    9192        5264 :       return true;
    9193             :     }
    9194             :     case kFunctionApply: {
    9195             :       // For .apply, only the pattern f.apply(receiver, arguments)
    9196             :       // is supported.
    9197         325 :       if (!CanBeFunctionApplyArguments(expr)) return false;
    9198             : 
    9199         231 :       BuildFunctionApply(expr);
    9200         231 :       return true;
    9201             :     }
    9202             :     default: { return false; }
    9203             :   }
    9204             :   UNREACHABLE();
    9205             : }
    9206             : 
    9207             : 
    9208             : // f.apply(...)
    9209         965 : void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
    9210             :   ZoneList<Expression*>* args = expr->arguments();
    9211         462 :   CHECK_ALIVE(VisitForValue(args->at(0)));
    9212             :   HValue* receiver = Pop();  // receiver
    9213             :   HValue* function = Pop();  // f
    9214             :   Drop(1);  // apply
    9215             : 
    9216             :   // Make sure the arguments object is live.
    9217         462 :   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
    9218         231 :   LookupAndMakeLive(arg_two->var());
    9219             : 
    9220         462 :   Handle<Map> function_map = expr->GetReceiverTypes()->first();
    9221         231 :   HValue* checked_function = AddCheckMap(function, function_map);
    9222             : 
    9223         231 :   if (function_state()->outer() == NULL) {
    9224             :     TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
    9225             :     TailCallMode tail_call_mode =
    9226         136 :         function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
    9227             : 
    9228         136 :     HInstruction* elements = Add<HArgumentsElements>(false);
    9229         136 :     HInstruction* length = Add<HArgumentsLength>(elements);
    9230         136 :     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
    9231             :     HInstruction* result = New<HApplyArguments>(
    9232         136 :         function, wrapped_receiver, length, elements, tail_call_mode);
    9233         272 :     ast_context()->ReturnInstruction(result, expr->id());
    9234             :   } else {
    9235             :     // We are inside inlined function and we know exactly what is inside
    9236             :     // arguments object. But we need to be able to materialize at deopt.
    9237             :     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
    9238             :               function_state()->entry()->arguments_object()->arguments_count());
    9239          95 :     HArgumentsObject* args = function_state()->entry()->arguments_object();
    9240             :     const ZoneList<HValue*>* arguments_values = args->arguments_values();
    9241          95 :     int arguments_count = arguments_values->length();
    9242          95 :     Push(function);
    9243          95 :     Push(BuildWrapReceiver(receiver, checked_function));
    9244         245 :     for (int i = 1; i < arguments_count; i++) {
    9245         150 :       Push(arguments_values->at(i));
    9246             :     }
    9247          95 :     HandleIndirectCall(expr, function, arguments_count);
    9248             :   }
    9249             : }
    9250             : 
    9251             : 
    9252             : // f.call(...)
    9253       21054 : void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
    9254             :   HValue* function = Top();  // f
    9255       10528 :   Handle<Map> function_map = expr->GetReceiverTypes()->first();
    9256        5264 :   HValue* checked_function = AddCheckMap(function, function_map);
    9257             : 
    9258             :   // f and call are on the stack in the unoptimized code
    9259             :   // during evaluation of the arguments.
    9260       10530 :   CHECK_ALIVE(VisitExpressions(expr->arguments()));
    9261             : 
    9262        5262 :   int args_length = expr->arguments()->length();
    9263        5262 :   int receiver_index = args_length - 1;
    9264             :   // Patch the receiver.
    9265             :   HValue* receiver = BuildWrapReceiver(
    9266        5262 :       environment()->ExpressionStackAt(receiver_index), checked_function);
    9267             :   environment()->SetExpressionStackAt(receiver_index, receiver);
    9268             : 
    9269             :   // Call must not be on the stack from now on.
    9270        5262 :   int call_index = args_length + 1;
    9271        5262 :   environment()->RemoveExpressionStackAt(call_index);
    9272             : 
    9273        5262 :   HandleIndirectCall(expr, function, args_length);
    9274             : }
    9275             : 
    9276             : 
    9277      202205 : HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
    9278             :                                                     Handle<JSFunction> target) {
    9279             :   SharedFunctionInfo* shared = target->shared();
    9280      396700 :   if (is_sloppy(shared->language_mode()) && !shared->native()) {
    9281             :     // Cannot embed a direct reference to the global proxy
    9282             :     // as is it dropped on deserialization.
    9283      341525 :     CHECK(!isolate()->serializer_enabled());
    9284      139320 :     Handle<JSObject> global_proxy(target->context()->global_proxy());
    9285      139320 :     return Add<HConstant>(global_proxy);
    9286             :   }
    9287       62885 :   return graph()->GetConstantUndefined();
    9288             : }
    9289             : 
    9290             : 
    9291         170 : HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
    9292             :                                                   HValue* search_element,
    9293             :                                                   ElementsKind kind,
    9294             :                                                   ArrayIndexOfMode mode) {
    9295             :   DCHECK(IsFastElementsKind(kind));
    9296             : 
    9297         680 :   NoObservableSideEffectsScope no_effects(this);
    9298             : 
    9299             :   HValue* elements = AddLoadElements(receiver);
    9300         170 :   HValue* length = AddLoadArrayLength(receiver, kind);
    9301             : 
    9302             :   HValue* initial;
    9303             :   HValue* terminating;
    9304             :   Token::Value token;
    9305             :   LoopBuilder::Direction direction;
    9306         170 :   if (mode == kFirstIndexOf) {
    9307             :     initial = graph()->GetConstant0();
    9308             :     terminating = length;
    9309             :     token = Token::LT;
    9310             :     direction = LoopBuilder::kPostIncrement;
    9311             :   } else {
    9312             :     DCHECK_EQ(kLastIndexOf, mode);
    9313             :     initial = length;
    9314             :     terminating = graph()->GetConstant0();
    9315             :     token = Token::GT;
    9316             :     direction = LoopBuilder::kPreDecrement;
    9317             :   }
    9318             : 
    9319         170 :   Push(graph()->GetConstantMinus1());
    9320         170 :   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
    9321             :     // Make sure that we can actually compare numbers correctly below, see
    9322             :     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
    9323             :     search_element = AddUncasted<HForceRepresentation>(
    9324             :         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
    9325          85 :                                                     : Representation::Double());
    9326             : 
    9327          85 :     LoopBuilder loop(this, context(), direction);
    9328             :     {
    9329          85 :       HValue* index = loop.BeginBody(initial, terminating, token);
    9330             :       HValue* element = AddUncasted<HLoadKeyed>(
    9331          85 :           elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
    9332             :       IfBuilder if_issame(this);
    9333             :       if_issame.If<HCompareNumericAndBranch>(element, search_element,
    9334          85 :                                              Token::EQ_STRICT);
    9335          85 :       if_issame.Then();
    9336             :       {
    9337             :         Drop(1);
    9338          85 :         Push(index);
    9339          85 :         loop.Break();
    9340             :       }
    9341          85 :       if_issame.End();
    9342             :     }
    9343          85 :     loop.EndBody();
    9344             :   } else {
    9345             :     IfBuilder if_isstring(this);
    9346          85 :     if_isstring.If<HIsStringAndBranch>(search_element);
    9347          85 :     if_isstring.Then();
    9348             :     {
    9349          85 :       LoopBuilder loop(this, context(), direction);
    9350             :       {
    9351          85 :         HValue* index = loop.BeginBody(initial, terminating, token);
    9352             :         HValue* element = AddUncasted<HLoadKeyed>(
    9353          85 :             elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
    9354             :         IfBuilder if_issame(this);
    9355          85 :         if_issame.If<HIsStringAndBranch>(element);
    9356             :         if_issame.AndIf<HStringCompareAndBranch>(
    9357             :             element, search_element, Token::EQ_STRICT);
    9358          85 :         if_issame.Then();
    9359             :         {
    9360             :           Drop(1);
    9361          85 :           Push(index);
    9362          85 :           loop.Break();
    9363             :         }
    9364          85 :         if_issame.End();
    9365             :       }
    9366          85 :       loop.EndBody();
    9367             :     }
    9368             :     if_isstring.Else();
    9369             :     {
    9370             :       IfBuilder if_isnumber(this);
    9371          85 :       if_isnumber.If<HIsSmiAndBranch>(search_element);
    9372             :       if_isnumber.OrIf<HCompareMap>(
    9373             :           search_element, isolate()->factory()->heap_number_map());
    9374          85 :       if_isnumber.Then();
    9375             :       {
    9376             :         HValue* search_number =
    9377             :             AddUncasted<HForceRepresentation>(search_element,
    9378          85 :                                               Representation::Double());
    9379          85 :         LoopBuilder loop(this, context(), direction);
    9380             :         {
    9381          85 :           HValue* index = loop.BeginBody(initial, terminating, token);
    9382             :           HValue* element = AddUncasted<HLoadKeyed>(
    9383          85 :               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
    9384             : 
    9385             :           IfBuilder if_element_isnumber(this);
    9386          85 :           if_element_isnumber.If<HIsSmiAndBranch>(element);
    9387             :           if_element_isnumber.OrIf<HCompareMap>(
    9388             :               element, isolate()->factory()->heap_number_map());
    9389          85 :           if_element_isnumber.Then();
    9390             :           {
    9391             :             HValue* number =
    9392             :                 AddUncasted<HForceRepresentation>(element,
    9393          85 :                                                   Representation::Double());
    9394             :             IfBuilder if_issame(this);
    9395             :             if_issame.If<HCompareNumericAndBranch>(
    9396          85 :                 number, search_number, Token::EQ_STRICT);
    9397          85 :             if_issame.Then();
    9398             :             {
    9399             :               Drop(1);
    9400          85 :               Push(index);
    9401          85 :               loop.Break();
    9402             :             }
    9403          85 :             if_issame.End();
    9404             :           }
    9405          85 :           if_element_isnumber.End();
    9406             :         }
    9407          85 :         loop.EndBody();
    9408             :       }
    9409             :       if_isnumber.Else();
    9410             :       {
    9411          85 :         LoopBuilder loop(this, context(), direction);
    9412             :         {
    9413          85 :           HValue* index = loop.BeginBody(initial, terminating, token);
    9414             :           HValue* element = AddUncasted<HLoadKeyed>(
    9415          85 :               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
    9416             :           IfBuilder if_issame(this);
    9417             :           if_issame.If<HCompareObjectEqAndBranch>(
    9418          85 :               element, search_element);
    9419          85 :           if_issame.Then();
    9420             :           {
    9421             :             Drop(1);
    9422          85 :             Push(index);
    9423          85 :             loop.Break();
    9424             :           }
    9425          85 :           if_issame.End();
    9426             :         }
    9427          85 :         loop.EndBody();
    9428             :       }
    9429          85 :       if_isnumber.End();
    9430             :     }
    9431          85 :     if_isstring.End();
    9432             :   }
    9433             : 
    9434         170 :   return Pop();
    9435             : }
    9436             : 
    9437             : template <class T>
    9438      209261 : bool HOptimizedGraphBuilder::TryHandleArrayCall(T* expr, HValue* function) {
    9439      416546 :   if (!array_function().is_identical_to(expr->target())) {
    9440             :     return false;
    9441             :   }
    9442             : 
    9443             :   Handle<AllocationSite> site = expr->allocation_site();
    9444        2881 :   if (site.is_null()) return false;
    9445             : 
    9446         615 :   Add<HCheckValue>(function, array_function());
    9447             : 
    9448         615 :   int arguments_count = expr->arguments()->length();
    9449         615 :   if (TryInlineArrayCall(expr, arguments_count, site)) return true;
    9450             : 
    9451             :   HInstruction* call = PreProcessCall(New<HCallNewArray>(
    9452         373 :       function, arguments_count + 1, site->GetElementsKind(), site));
    9453         373 :   if (expr->IsCall()) Drop(1);
    9454         746 :   ast_context()->ReturnInstruction(call, expr->id());
    9455             : 
    9456         373 :   return true;
    9457             : }
    9458             : 
    9459             : 
    9460      114898 : bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
    9461             :   ZoneList<Expression*>* args = expr->arguments();
    9462      114898 :   if (args->length() != 2) return false;
    9463       16767 :   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
    9464       14300 :   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
    9465        2467 :   HValue* arg_two_value = environment()->Lookup(arg_two->var());
    9466        2467 :   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
    9467             :   DCHECK_NOT_NULL(current_info()->scope()->arguments());
    9468         264 :   return true;
    9469             : }
    9470             : 
    9471             : 
    9472     6473234 : void HOptimizedGraphBuilder::VisitCall(Call* expr) {
    9473             :   DCHECK(!HasStackOverflow());
    9474             :   DCHECK(current_block() != NULL);
    9475             :   DCHECK(current_block()->HasPredecessor());
    9476     3107847 :   if (!is_tracking_positions()) SetSourcePosition(expr->position());
    9477             :   Expression* callee = expr->expression();
    9478      652215 :   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
    9479             :   HInstruction* call = NULL;
    9480             : 
    9481             :   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
    9482             :   TailCallMode tail_call_mode =
    9483      652215 :       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
    9484             : 
    9485     1372376 :   Property* prop = callee->AsProperty();
    9486      652214 :   if (prop != NULL) {
    9487      665735 :     CHECK_ALIVE(VisitForValue(prop->obj()));
    9488             :     HValue* receiver = Top();
    9489             : 
    9490             :     SmallMapList* maps;
    9491      207667 :     ComputeReceiverTypes(expr, receiver, &maps, this);
    9492             : 
    9493      414911 :     if (prop->key()->IsPropertyName() && maps->length() > 0) {
    9494       98413 :       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
    9495      196826 :       PropertyAccessInfo info(this, LOAD, maps->first(), name);
    9496       98413 :       if (!info.CanAccessAsMonomorphic(maps)) {
    9497        1689 :         HandlePolymorphicCallNamed(expr, receiver, maps, name);
    9498        1689 :         return;
    9499             :       }
    9500             :     }
    9501             :     HValue* key = NULL;
    9502      205978 :     if (!prop->key()->IsPropertyName()) {
    9503        1269 :       CHECK_ALIVE(VisitForValue(prop->key()));
    9504             :       key = Pop();
    9505             :     }
    9506             : 
    9507      617934 :     CHECK_ALIVE(PushLoad(prop, receiver, key));
    9508             :     HValue* function = Pop();
    9509             : 
    9510      617934 :     if (function->IsConstant() &&
    9511      388890 :         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    9512             :       // Push the function under the receiver.
    9513             :       environment()->SetExpressionStackAt(0, function);
    9514       91405 :       Push(receiver);
    9515             : 
    9516             :       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
    9517       91405 :           HConstant::cast(function)->handle(isolate()));
    9518             :       expr->set_target(known_function);
    9519             : 
    9520      132394 :       if (TryIndirectCall(expr)) return;
    9521      257708 :       CHECK_ALIVE(VisitExpressions(expr->arguments()));
    9522             : 
    9523      256666 :       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
    9524       85888 :       if (TryInlineBuiltinMethodCall(known_function, map, expr->id(),
    9525       85888 :                                      expr->arguments()->length())) {
    9526       26587 :         if (FLAG_trace_inlining) {
    9527           0 :           PrintF("Inlining builtin ");
    9528           0 :           known_function->ShortPrint();
    9529           0 :           PrintF("\n");
    9530             :         }
    9531             :         return;
    9532             :       }
    9533       59301 :       if (TryInlineApiMethodCall(expr, receiver, maps)) return;
    9534             : 
    9535             :       // Wrap the receiver if necessary.
    9536      113372 :       if (NeedsWrapping(maps->first(), known_function)) {
    9537             :         // Since HWrapReceiver currently cannot actually wrap numbers and
    9538             :         // strings, use the regular call builtin for method calls to wrap
    9539             :         // the receiver.
    9540             :         // TODO(verwaest): Support creation of value wrappers directly in
    9541             :         // HWrapReceiver.
    9542             :         call = NewCallFunction(
    9543             :             function, argument_count, syntactic_tail_call_mode,
    9544           9 :             ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode);
    9545       56677 :       } else if (TryInlineCall(expr)) {
    9546             :         return;
    9547             :       } else {
    9548             :         call =
    9549             :             NewCallConstantFunction(known_function, argument_count,
    9550       50407 :                                     syntactic_tail_call_mode, tail_call_mode);
    9551             :       }
    9552             : 
    9553             :     } else {
    9554             :       ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
    9555      114606 :       if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
    9556             :         // We have to use EAGER deoptimization here because Deoptimizer::SOFT
    9557             :         // gets ignored by the always-opt flag, which leads to incorrect code.
    9558             :         Add<HDeoptimize>(
    9559             :             DeoptimizeReason::kInsufficientTypeFeedbackForCallWithArguments,
    9560          26 :             Deoptimizer::EAGER);
    9561             :         arguments_flag = ARGUMENTS_FAKED;
    9562             :       }
    9563             : 
    9564             :       // Push the function under the receiver.
    9565             :       environment()->SetExpressionStackAt(0, function);
    9566      114573 :       Push(receiver);
    9567             : 
    9568      343702 :       CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
    9569             :       call = NewCallFunction(function, argument_count, syntactic_tail_call_mode,
    9570             :                              ConvertReceiverMode::kNotNullOrUndefined,
    9571      114556 :                              tail_call_mode);
    9572             :     }
    9573      164972 :     PushArgumentsFromEnvironment(argument_count);
    9574             : 
    9575             :   } else {
    9576      444534 :     if (expr->is_possibly_eval()) {
    9577             :       return Bailout(kPossibleDirectCallToEval);
    9578             :     }
    9579             : 
    9580             :     // The function is on the stack in the unoptimized code during
    9581             :     // evaluation of the arguments.
    9582     1333604 :     CHECK_ALIVE(VisitForValue(expr->expression()));
    9583             :     HValue* function = Top();
    9584     1333605 :     if (function->IsConstant() &&
    9585      769285 :         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    9586      162337 :       Handle<Object> constant = HConstant::cast(function)->handle(isolate());
    9587             :       Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
    9588             :       expr->SetKnownGlobalTarget(target);
    9589             :     }
    9590             : 
    9591             :     // Placeholder for the receiver.
    9592      444535 :     Push(graph()->GetConstantUndefined());
    9593     1333547 :     CHECK_ALIVE(VisitExpressions(expr->arguments()));
    9594             : 
    9595      642450 :     if (expr->IsMonomorphic() &&
    9596             :         !IsClassConstructor(expr->target()->shared()->kind())) {
    9597      197968 :       Add<HCheckValue>(function, expr->target());
    9598             : 
    9599             :       // Patch the global object on the stack by the expected receiver.
    9600      197968 :       HValue* receiver = ImplicitReceiverFor(function, expr->target());
    9601             :       const int receiver_index = argument_count - 1;
    9602             :       environment()->SetExpressionStackAt(receiver_index, receiver);
    9603             : 
    9604      197968 :       if (TryInlineBuiltinFunctionCall(expr)) {
    9605        8658 :         if (FLAG_trace_inlining) {
    9606           0 :           PrintF("Inlining builtin ");
    9607           0 :           expr->target()->ShortPrint();
    9608           0 :           PrintF("\n");
    9609             :         }
    9610             :         return;
    9611             :       }
    9612      189310 :       if (TryInlineApiFunctionCall(expr, receiver)) return;
    9613      180752 :       if (TryHandleArrayCall(expr, function)) return;
    9614      180663 :       if (TryInlineCall(expr)) return;
    9615             : 
    9616       82744 :       PushArgumentsFromEnvironment(argument_count);
    9617             :       call = NewCallConstantFunction(expr->target(), argument_count,
    9618       82744 :                                      syntactic_tail_call_mode, tail_call_mode);
    9619             :     } else {
    9620      246509 :       PushArgumentsFromEnvironment(argument_count);
    9621      246508 :       if (expr->is_uninitialized()) {
    9622             :         // We've never seen this call before, so let's have Crankshaft learn
    9623             :         // through the type vector.
    9624             :         call = NewCallFunctionViaIC(function, argument_count,
    9625             :                                     syntactic_tail_call_mode,
    9626             :                                     ConvertReceiverMode::kNullOrUndefined,
    9627      243640 :                                     tail_call_mode, expr->CallFeedbackICSlot());
    9628             :       } else {
    9629             :         call = NewCallFunction(
    9630             :             function, argument_count, syntactic_tail_call_mode,
    9631        2868 :             ConvertReceiverMode::kNullOrUndefined, tail_call_mode);
    9632             :       }
    9633             :     }
    9634             :   }
    9635             : 
    9636             :   Drop(1);  // Drop the function.
    9637      988450 :   return ast_context()->ReturnInstruction(call, expr->id());
    9638             : }
    9639             : 
    9640         615 : bool HOptimizedGraphBuilder::TryInlineArrayCall(Expression* expression,
    9641             :                                                 int argument_count,
    9642         242 :                                                 Handle<AllocationSite> site) {
    9643         615 :   Handle<JSFunction> caller = current_info()->closure();
    9644         615 :   Handle<JSFunction> target = array_function();
    9645             : 
    9646         615 :   if (!site->CanInlineCall()) {
    9647         103 :     TraceInline(target, caller, "AllocationSite requested no inlining.");
    9648         103 :     return false;
    9649             :   }
    9650             : 
    9651         512 :   if (argument_count > 1) {
    9652          38 :     TraceInline(target, caller, "Too many arguments to inline.");
    9653          38 :     return false;
    9654             :   }
    9655             : 
    9656             :   int array_length = 0;
    9657             :   // Do not inline if the constant length argument is not a smi or outside the
    9658             :   // valid range for unrolled loop initialization.
    9659         474 :   if (argument_count == 1) {
    9660             :     HValue* argument = Top();
    9661         376 :     if (!argument->IsConstant()) {
    9662             :       TraceInline(target, caller,
    9663         138 :                   "Dont inline [new] Array(n) where n isn't constant.");
    9664         138 :       return false;
    9665             :     }
    9666             : 
    9667         476 :     HConstant* constant_argument = HConstant::cast(argument);
    9668         238 :     if (!constant_argument->HasSmiValue()) {
    9669             :       TraceInline(target, caller,
    9670           0 :                   "Constant length outside of valid inlining range.");
    9671           0 :       return false;
    9672             :     }
    9673             :     array_length = constant_argument->Integer32Value();
    9674         238 :     if (array_length < 0 || array_length > kElementLoopUnrollThreshold) {
    9675             :       TraceInline(target, caller,
    9676          94 :                   "Constant length outside of valid inlining range.");
    9677          94 :       return false;
    9678             :     }
    9679             :   }
    9680             : 
    9681         242 :   TraceInline(target, caller, NULL);
    9682             : 
    9683        1093 :   NoObservableSideEffectsScope no_effects(this);
    9684             : 
    9685             :   // Register on the site for deoptimization if the transition feedback changes.
    9686         242 :   top_info()->dependencies()->AssumeTransitionStable(site);
    9687             : 
    9688             :   // Build the array.
    9689             :   ElementsKind kind = site->GetElementsKind();
    9690             :   HValue* capacity;
    9691             :   HValue* length;
    9692         242 :   if (array_length == 0) {
    9693             :     STATIC_ASSERT(0 < JSArray::kPreallocatedArrayElements);
    9694             :     const int initial_capacity = JSArray::kPreallocatedArrayElements;
    9695         125 :     capacity = Add<HConstant>(initial_capacity);
    9696             :     length = graph()->GetConstant0();
    9697             :   } else {
    9698             :     length = Top();
    9699             :     capacity = length;
    9700             :     kind = GetHoleyElementsKind(kind);
    9701             :   }
    9702             : 
    9703             :   // These HForceRepresentations are because we store these as fields in the
    9704             :   // objects we construct, and an int32-to-smi HChange could deopt. Accept
    9705             :   // the deopt possibility now, before allocation occurs.
    9706         242 :   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
    9707         242 :   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
    9708             : 
    9709             :   // Generate size calculation code here in order to make it dominate
    9710             :   // the JSArray allocation.
    9711         242 :   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
    9712             : 
    9713             :   // Bail out for large objects.
    9714         242 :   HValue* max_size = Add<HConstant>(kMaxRegularHeapObjectSize);
    9715         242 :   Add<HBoundsCheck>(elements_size, max_size);
    9716             : 
    9717             :   // Allocate (dealing with failure appropriately).
    9718             :   AllocationSiteMode mode = DONT_TRACK_ALLOCATION_SITE;
    9719         242 :   HAllocate* new_object = AllocateJSArrayObject(mode);
    9720             : 
    9721             :   // Fill in the fields: map, properties, length.
    9722         242 :   Handle<Map> map_constant(isolate()->get_initial_js_array_map(kind));
    9723         242 :   HValue* map = Add<HConstant>(map_constant);
    9724             : 
    9725             :   BuildJSArrayHeader(new_object, map,
    9726             :                      nullptr,  // set elements to empty fixed array
    9727         242 :                      mode, kind, nullptr, length);
    9728             : 
    9729             :   // Allocate and initialize the elements.
    9730         242 :   HAllocate* elements = BuildAllocateElements(kind, elements_size);
    9731         242 :   BuildInitializeElementsHeader(elements, kind, capacity);
    9732         242 :   BuildFillElementsWithHole(elements, kind, graph()->GetConstant0(), capacity);
    9733             : 
    9734             :   // Set the elements.
    9735             :   Add<HStoreNamedField>(new_object, HObjectAccess::ForElementsPointer(),
    9736         242 :                         elements);
    9737             : 
    9738         242 :   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
    9739             :   Drop(args_to_drop);
    9740         242 :   ast_context()->ReturnValue(new_object);
    9741             :   return true;
    9742             : }
    9743             : 
    9744             : 
    9745             : // Checks whether allocation using the given constructor can be inlined.
    9746       15273 : static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
    9747       29086 :   return constructor->has_initial_map() &&
    9748       13778 :          !IsDerivedConstructor(constructor->shared()->kind()) &&
    9749       13342 :          !constructor->initial_map()->is_dictionary_map() &&
    9750       19829 :          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
    9751             :          constructor->initial_map()->instance_size() <
    9752       15273 :              HAllocate::kMaxInlineSize;
    9753             : }
    9754             : 
    9755      255001 : void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
    9756             :   DCHECK(!HasStackOverflow());
    9757             :   DCHECK(current_block() != NULL);
    9758             :   DCHECK(current_block()->HasPredecessor());
    9759      187906 :   if (!is_tracking_positions()) SetSourcePosition(expr->position());
    9760       32072 :   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
    9761             :   Factory* factory = isolate()->factory();
    9762             : 
    9763             :   // The constructor function is on the stack in the unoptimized code
    9764             :   // during evaluation of the arguments.
    9765       96216 :   CHECK_ALIVE(VisitForValue(expr->expression()));
    9766             :   HValue* function = Top();
    9767       96216 :   CHECK_ALIVE(VisitExpressions(expr->arguments()));
    9768             : 
    9769       96216 :   if (function->IsConstant() &&
    9770       56654 :       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    9771       12279 :     Handle<Object> constant = HConstant::cast(function)->handle(isolate());
    9772             :     expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
    9773             :   }
    9774             : 
    9775       64144 :   if (FLAG_inline_construct &&
    9776       47345 :       expr->IsMonomorphic() &&
    9777       15273 :       IsAllocationInlineable(expr->target())) {
    9778             :     Handle<JSFunction> constructor = expr->target();
    9779             :     DCHECK(
    9780             :         constructor->shared()->construct_stub() ==
    9781             :             isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric) ||
    9782             :         constructor->shared()->construct_stub() ==
    9783             :             isolate()->builtins()->builtin(Builtins::kJSConstructStubApi) ||
    9784             :         constructor->shared()->construct_stub() ==
    9785             :             isolate()->builtins()->builtin(
    9786             :                 Builtins::kJSBuiltinsConstructStubForBase));
    9787        4551 :     HValue* check = Add<HCheckValue>(function, constructor);
    9788             : 
    9789             :     // Force completion of inobject slack tracking before generating
    9790             :     // allocation code to finalize instance size.
    9791        4551 :     constructor->CompleteInobjectSlackTrackingIfActive();
    9792             : 
    9793             :     // Calculate instance size from initial map of constructor.
    9794             :     DCHECK(constructor->has_initial_map());
    9795             :     Handle<Map> initial_map(constructor->initial_map());
    9796             :     int instance_size = initial_map->instance_size();
    9797             : 
    9798             :     // Allocate an instance of the implicit receiver object.
    9799        4551 :     HValue* size_in_bytes = Add<HConstant>(instance_size);
    9800             :     HAllocationMode allocation_mode;
    9801             :     HAllocate* receiver = BuildAllocate(
    9802        4551 :         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
    9803             :     receiver->set_known_initial_map(initial_map);
    9804             : 
    9805             :     // Initialize map and fields of the newly allocated object.
    9806             :     { NoObservableSideEffectsScope no_effects(this);
    9807             :       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
    9808             :       Add<HStoreNamedField>(receiver,
    9809             :           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
    9810        4551 :           Add<HConstant>(initial_map));
    9811        4551 :       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
    9812             :       Add<HStoreNamedField>(receiver,
    9813             :           HObjectAccess::ForMapAndOffset(initial_map,
    9814             :                                          JSObject::kPropertiesOffset),
    9815        4551 :           empty_fixed_array);
    9816             :       Add<HStoreNamedField>(receiver,
    9817             :           HObjectAccess::ForMapAndOffset(initial_map,
    9818             :                                          JSObject::kElementsOffset),
    9819        4551 :           empty_fixed_array);
    9820        4551 :       BuildInitializeInobjectProperties(receiver, initial_map);
    9821             :     }
    9822             : 
    9823             :     // Replace the constructor function with a newly allocated receiver using
    9824             :     // the index of the receiver from the top of the expression stack.
    9825             :     const int receiver_index = argument_count - 1;
    9826             :     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
    9827             :     environment()->SetExpressionStackAt(receiver_index, receiver);
    9828             : 
    9829        4551 :     if (TryInlineConstruct(expr, receiver)) {
    9830             :       // Inlining worked, add a dependency on the initial map to make sure that
    9831             :       // this code is deoptimized whenever the initial map of the constructor
    9832             :       // changes.
    9833        1049 :       top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
    9834        1049 :       return;
    9835             :     }
    9836             : 
    9837             :     // TODO(mstarzinger): For now we remove the previous HAllocate and all
    9838             :     // corresponding instructions and instead add HPushArguments for the
    9839             :     // arguments in case inlining failed.  What we actually should do is for
    9840             :     // inlining to try to build a subgraph without mutating the parent graph.
    9841        3502 :     HInstruction* instr = current_block()->last();
    9842       37373 :     do {
    9843             :       HInstruction* prev_instr = instr->previous();
    9844       37373 :       instr->DeleteAndReplaceWith(NULL);
    9845             :       instr = prev_instr;
    9846             :     } while (instr != check);
    9847             :     environment()->SetExpressionStackAt(receiver_index, function);
    9848             :   } else {
    9849             :     // The constructor function is both an operand to the instruction and an
    9850             :     // argument to the construct call.
    9851       27521 :     if (TryHandleArrayCall(expr, function)) return;
    9852             :   }
    9853             : 
    9854       30497 :   HValue* arity = Add<HConstant>(argument_count - 1);
    9855       30497 :   HValue* op_vals[] = {function, function, arity};
    9856       30497 :   Callable callable = CodeFactory::Construct(isolate());
    9857       30497 :   HConstant* stub = Add<HConstant>(callable.code());
    9858       30497 :   PushArgumentsFromEnvironment(argument_count);
    9859             :   HInstruction* construct = New<HCallWithDescriptor>(
    9860       30497 :       stub, argument_count, callable.descriptor(), ArrayVector(op_vals));
    9861       60994 :   return ast_context()->ReturnInstruction(construct, expr->id());
    9862             : }
    9863             : 
    9864             : 
    9865       11877 : void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
    9866             :     HValue* receiver, Handle<Map> initial_map) {
    9867       11877 :   if (initial_map->GetInObjectProperties() != 0) {
    9868        8033 :     HConstant* undefined = graph()->GetConstantUndefined();
    9869       67784 :     for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
    9870       25859 :       int property_offset = initial_map->GetInObjectPropertyOffset(i);
    9871             :       Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
    9872             :                                           initial_map, property_offset),
    9873       25859 :                             undefined);
    9874             :     }
    9875             :   }
    9876       11877 : }
    9877             : 
    9878          32 : void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
    9879             :   DCHECK(expr->arguments()->length() == 0);
    9880          16 :   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
    9881          32 :   return ast_context()->ReturnInstruction(max_smi, expr->id());
    9882             : }
    9883             : 
    9884             : 
    9885           0 : void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
    9886           0 :     CallRuntime* expr) {
    9887             :   DCHECK(expr->arguments()->length() == 0);
    9888             :   HConstant* result = New<HConstant>(static_cast<int32_t>(
    9889           0 :         FLAG_typed_array_max_size_in_heap));
    9890           0 :   return ast_context()->ReturnInstruction(result, expr->id());
    9891             : }
    9892             : 
    9893             : 
    9894           0 : void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
    9895           0 :     CallRuntime* expr) {
    9896             :   DCHECK(expr->arguments()->length() == 1);
    9897           0 :   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
    9898             :   HValue* buffer = Pop();
    9899             :   HInstruction* result = New<HLoadNamedField>(
    9900           0 :       buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
    9901           0 :   return ast_context()->ReturnInstruction(result, expr->id());
    9902             : }
    9903             : 
    9904             : 
    9905           9 : void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
    9906          27 :     CallRuntime* expr) {
    9907          18 :   NoObservableSideEffectsScope scope(this);
    9908             :   DCHECK(expr->arguments()->length() == 1);
    9909          27 :   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
    9910             :   HValue* view = Pop();
    9911             : 
    9912             :   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
    9913             :       view, nullptr,
    9914           9 :       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset)));
    9915             : }
    9916             : 
    9917             : 
    9918          35 : void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
    9919         105 :     CallRuntime* expr) {
    9920          70 :   NoObservableSideEffectsScope scope(this);
    9921             :   DCHECK(expr->arguments()->length() == 1);
    9922         105 :   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
    9923             :   HValue* view = Pop();
    9924             : 
    9925             :   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
    9926             :       view, nullptr,
    9927          35 :       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
    9928             : }
    9929             : 
    9930          44 : void HOptimizedGraphBuilder::GenerateArrayBufferViewWasNeutered(
    9931         132 :     CallRuntime* expr) {
    9932          88 :   NoObservableSideEffectsScope scope(this);
    9933             :   DCHECK_EQ(expr->arguments()->length(), 1);
    9934         132 :   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
    9935             :   HValue* view = Pop();
    9936             : 
    9937             :   HInstruction* buffer = Add<HLoadNamedField>(
    9938          44 :       view, nullptr, HObjectAccess::ForJSArrayBufferViewBuffer());
    9939             :   HInstruction* flags = Add<HLoadNamedField>(
    9940          44 :       buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
    9941             :   HValue* was_neutered_mask =
    9942          44 :       Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
    9943             :   HValue* was_neutered =
    9944          44 :       AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
    9945          44 :   return ast_context()->ReturnValue(was_neutered);
    9946             : }
    9947             : 
    9948          99 : void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
    9949         297 :     CallRuntime* expr) {
    9950         198 :   NoObservableSideEffectsScope scope(this);
    9951             :   DCHECK(expr->arguments()->length() == 1);
    9952         297 :   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
    9953             :   HValue* view = Pop();
    9954             : 
    9955             :   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
    9956             :       view, nullptr,
    9957          99 :       FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset)));
    9958             : }
    9959             : 
    9960             : 
    9961      212669 : void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
    9962             :   DCHECK(!HasStackOverflow());
    9963             :   DCHECK(current_block() != NULL);
    9964             :   DCHECK(current_block()->HasPredecessor());
    9965       72674 :   if (expr->is_jsruntime()) {
    9966             :     // Crankshaft always specializes to the native context, so we can just grab
    9967             :     // the constant function from the current native context and embed that into
    9968             :     // the code object.
    9969             :     Handle<JSFunction> known_function(
    9970             :         JSFunction::cast(
    9971        4237 :             current_info()->native_context()->get(expr->context_index())),
    9972       49461 :         isolate());
    9973             : 
    9974             :     // The callee and the receiver both have to be pushed onto the operand stack
    9975             :     // before arguments are being evaluated.
    9976        4237 :     HConstant* function = Add<HConstant>(known_function);
    9977        4237 :     HValue* receiver = ImplicitReceiverFor(function, known_function);
    9978        4237 :     Push(function);
    9979        4237 :     Push(receiver);
    9980             : 
    9981        4237 :     int argument_count = expr->arguments()->length() + 1;  // Count receiver.
    9982       12711 :     CHECK_ALIVE(VisitExpressions(expr->arguments()));
    9983        4237 :     PushArgumentsFromEnvironment(argument_count);
    9984             :     HInstruction* call = NewCallConstantFunction(known_function, argument_count,
    9985             :                                                  TailCallMode::kDisallow,
    9986        4237 :                                                  TailCallMode::kDisallow);
    9987             :     Drop(1);  // Function
    9988        8474 :     return ast_context()->ReturnInstruction(call, expr->id());
    9989             :   }
    9990             : 
    9991             :   const Runtime::Function* function = expr->function();
    9992             :   DCHECK(function != NULL);
    9993       68437 :   switch (function->function_id) {
    9994             : #define CALL_INTRINSIC_GENERATOR(Name) \
    9995             :   case Runtime::kInline##Name:         \
    9996             :     return Generate##Name(expr);
    9997             : 
    9998        1624 :     FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
    9999             : #undef CALL_INTRINSIC_GENERATOR
   10000             :     default: {
   10001       41030 :       int argument_count = expr->arguments()->length();
   10002      123047 :       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   10003       40987 :       PushArgumentsFromEnvironment(argument_count);
   10004       40987 :       HCallRuntime* call = New<HCallRuntime>(function, argument_count);
   10005       81974 :       return ast_context()->ReturnInstruction(call, expr->id());
   10006             :     }
   10007             :   }
   10008             : }
   10009             : 
   10010             : 
   10011      259309 : void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
   10012             :   DCHECK(!HasStackOverflow());
   10013             :   DCHECK(current_block() != NULL);
   10014             :   DCHECK(current_block()->HasPredecessor());
   10015      259309 :   switch (expr->op()) {
   10016        1248 :     case Token::DELETE: return VisitDelete(expr);
   10017        4151 :     case Token::VOID: return VisitVoid(expr);
   10018       40230 :     case Token::TYPEOF: return VisitTypeof(expr);
   10019      213680 :     case Token::NOT: return VisitNot(expr);
   10020           0 :     default: UNREACHABLE();
   10021             :   }
   10022             : }
   10023             : 
   10024             : 
   10025        6083 : void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
   10026        3560 :   Property* prop = expr->expression()->AsProperty();
   10027        1287 :   VariableProxy* proxy = expr->expression()->AsVariableProxy();
   10028        1248 :   if (prop != NULL) {
   10029        3576 :     CHECK_ALIVE(VisitForValue(prop->obj()));
   10030        3426 :     CHECK_ALIVE(VisitForValue(prop->key()));
   10031             :     HValue* key = Pop();
   10032             :     HValue* obj = Pop();
   10033             :     HValue* language_mode = Add<HConstant>(
   10034        1142 :         static_cast<int32_t>(function_language_mode()), Representation::Smi());
   10035        1142 :     Add<HPushArguments>(obj, key, language_mode);
   10036             :     HInstruction* instr =
   10037        1142 :         New<HCallRuntime>(Runtime::FunctionForId(Runtime::kDeleteProperty), 3);
   10038        2284 :     return ast_context()->ReturnInstruction(instr, expr->id());
   10039          78 :   } else if (proxy != NULL) {
   10040             :     Variable* var = proxy->var();
   10041          39 :     if (var->IsUnallocated()) {
   10042             :       Bailout(kDeleteWithGlobalVariable);
   10043          16 :     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
   10044             :       // Result of deleting non-global variables is false.  'this' is not really
   10045             :       // a variable, though we implement it as one.  The subexpression does not
   10046             :       // have side effects.
   10047             :       HValue* value = var->is_this() ? graph()->GetConstantTrue()
   10048          32 :                                      : graph()->GetConstantFalse();
   10049          16 :       return ast_context()->ReturnValue(value);
   10050             :     } else {
   10051             :       Bailout(kDeleteWithNonGlobalVariable);
   10052             :     }
   10053             :   } else {
   10054             :     // Result of deleting non-property, non-variable reference is true.
   10055             :     // Evaluate the subexpression for side effects.
   10056         117 :     CHECK_ALIVE(VisitForEffect(expr->expression()));
   10057          78 :     return ast_context()->ReturnValue(graph()->GetConstantTrue());
   10058             :   }
   10059             : }
   10060             : 
   10061             : 
   10062       12453 : void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
   10063       12453 :   CHECK_ALIVE(VisitForEffect(expr->expression()));
   10064        8302 :   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   10065             : }
   10066             : 
   10067             : 
   10068      120689 : void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
   10069       80460 :   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
   10070             :   HValue* value = Pop();
   10071       40229 :   HInstruction* instr = New<HTypeof>(value);
   10072       80458 :   return ast_context()->ReturnInstruction(instr, expr->id());
   10073             : }
   10074             : 
   10075             : 
   10076      438308 : void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
   10077      213680 :   if (ast_context()->IsTest()) {
   10078      208184 :     TestContext* context = TestContext::cast(ast_context());
   10079             :     VisitForControl(expr->expression(),
   10080             :                     context->if_false(),
   10081      208184 :                     context->if_true());
   10082      208184 :     return;
   10083             :   }
   10084             : 
   10085        5496 :   if (ast_context()->IsEffect()) {
   10086          21 :     VisitForEffect(expr->expression());
   10087          21 :     return;
   10088             :   }
   10089             : 
   10090             :   DCHECK(ast_context()->IsValue());
   10091       16421 :   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
   10092        5475 :   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
   10093       10950 :   CHECK_BAILOUT(VisitForControl(expr->expression(),
   10094             :                                 materialize_false,
   10095             :                                 materialize_true));
   10096             : 
   10097        5473 :   if (materialize_false->HasPredecessor()) {
   10098             :     materialize_false->SetJoinId(expr->MaterializeFalseId());
   10099             :     set_current_block(materialize_false);
   10100        5473 :     Push(graph()->GetConstantFalse());
   10101             :   } else {
   10102             :     materialize_false = NULL;
   10103             :   }
   10104             : 
   10105        5473 :   if (materialize_true->HasPredecessor()) {
   10106             :     materialize_true->SetJoinId(expr->MaterializeTrueId());
   10107             :     set_current_block(materialize_true);
   10108        5473 :     Push(graph()->GetConstantTrue());
   10109             :   } else {
   10110             :     materialize_true = NULL;
   10111             :   }
   10112             : 
   10113             :   HBasicBlock* join =
   10114        5473 :     CreateJoin(materialize_false, materialize_true, expr->id());
   10115             :   set_current_block(join);
   10116       16419 :   if (join != NULL) return ast_context()->ReturnValue(Pop());
   10117             : }
   10118             : 
   10119     2541928 : static Representation RepresentationFor(AstType* type) {
   10120             :   DisallowHeapAllocation no_allocation;
   10121     2541928 :   if (type->Is(AstType::None())) return Representation::None();
   10122     2427222 :   if (type->Is(AstType::SignedSmall())) return Representation::Smi();
   10123     1473001 :   if (type->Is(AstType::Signed32())) return Representation::Integer32();
   10124     1473001 :   if (type->Is(AstType::Number())) return Representation::Double();
   10125             :   return Representation::Tagged();
   10126             : }
   10127             : 
   10128       88220 : HInstruction* HOptimizedGraphBuilder::BuildIncrement(CountOperation* expr) {
   10129             :   // The input to the count operation is on top of the expression stack.
   10130       44110 :   Representation rep = RepresentationFor(expr->type());
   10131       44110 :   if (rep.IsNone() || rep.IsTagged()) {
   10132             :     rep = Representation::Smi();
   10133             :   }
   10134             : 
   10135             :   // We need an explicit HValue representing ToNumber(input).  The
   10136             :   // actual HChange instruction we need is (sometimes) added in a later
   10137             :   // phase, so it is not available now to be used as an input to HAdd and
   10138             :   // as the return value.
   10139       88220 :   HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
   10140       44110 :   if (!rep.IsDouble()) {
   10141             :     number_input->SetFlag(HInstruction::kFlexibleRepresentation);
   10142             :     number_input->SetFlag(HInstruction::kCannotBeTagged);
   10143             :   }
   10144       44110 :   Push(number_input);
   10145             : 
   10146             :   // The addition has no side effects, so we do not need
   10147             :   // to simulate the expression stack after this instruction.
   10148             :   // Any later failures deopt to the load of the input or earlier.
   10149             :   HConstant* delta = (expr->op() == Token::INC)
   10150             :       ? graph()->GetConstant1()
   10151       44110 :       : graph()->GetConstantMinus1();
   10152       44110 :   HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
   10153       88220 :   if (instr->IsAdd()) {
   10154             :     HAdd* add = HAdd::cast(instr);
   10155             :     add->set_observed_input_representation(1, rep);
   10156             :     add->set_observed_input_representation(2, Representation::Smi());
   10157             :   }
   10158             :   instr->ClearAllSideEffects();
   10159             :   instr->SetFlag(HInstruction::kCannotBeTagged);
   10160       44110 :   return instr;
   10161             : }
   10162             : 
   10163         911 : void HOptimizedGraphBuilder::BuildStoreForEffect(
   10164             :     Expression* expr, Property* prop, FeedbackSlot slot, BailoutId ast_id,
   10165             :     BailoutId return_id, HValue* object, HValue* key, HValue* value) {
   10166             :   EffectContext for_effect(this);
   10167         911 :   Push(object);
   10168         911 :   if (key != NULL) Push(key);
   10169         911 :   Push(value);
   10170         911 :   BuildStore(expr, prop, slot, ast_id, return_id);
   10171         911 : }
   10172             : 
   10173             : 
   10174      218684 : void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
   10175             :   DCHECK(!HasStackOverflow());
   10176             :   DCHECK(current_block() != NULL);
   10177             :   DCHECK(current_block()->HasPredecessor());
   10178       93164 :   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   10179             :   Expression* target = expr->expression();
   10180       89204 :   VariableProxy* proxy = target->AsVariableProxy();
   10181        4776 :   Property* prop = target->AsProperty();
   10182       45398 :   if (proxy == NULL && prop == NULL) {
   10183             :     return Bailout(kInvalidLhsInCountOperation);
   10184             :   }
   10185             : 
   10186             :   // Match the full code generator stack by simulating an extra stack
   10187             :   // element for postfix operations in a non-effect context.  The return
   10188             :   // value is ToNumber(input).
   10189             :   bool returns_original_input =
   10190       82952 :       expr->is_postfix() && !ast_context()->IsEffect();
   10191             :   HValue* input = NULL;  // ToNumber(original_input).
   10192             :   HValue* after = NULL;  // The result after incrementing or decrementing.
   10193             : 
   10194       45398 :   if (proxy != NULL) {
   10195       88278 :     Variable* var = proxy->var();
   10196       43806 :     if (var->mode() == CONST) {
   10197             :       return Bailout(kNonInitializerAssignmentToConst);
   10198             :     }
   10199             :     // Argument of the count operation is a variable, not a property.
   10200             :     DCHECK(prop == NULL);
   10201      127656 :     CHECK_ALIVE(VisitForValue(target));
   10202             : 
   10203       42520 :     after = BuildIncrement(expr);
   10204       42520 :     input = returns_original_input ? Top() : Pop();
   10205       42520 :     Push(after);
   10206             : 
   10207       42520 :     switch (var->location()) {
   10208             :       case VariableLocation::UNALLOCATED:
   10209             :         HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
   10210        3827 :                                        expr->AssignmentId());
   10211        3827 :         break;
   10212             : 
   10213             :       case VariableLocation::PARAMETER:
   10214             :       case VariableLocation::LOCAL:
   10215       37717 :         BindIfLive(var, after);
   10216       37717 :         break;
   10217             : 
   10218             :       case VariableLocation::CONTEXT: {
   10219         976 :         HValue* context = BuildContextChainWalk(var);
   10220             :         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
   10221         976 :             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
   10222             :         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
   10223         976 :                                                           mode, after);
   10224         976 :         if (instr->HasObservableSideEffects()) {
   10225         976 :           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   10226             :         }
   10227             :         break;
   10228             :       }
   10229             : 
   10230             :       case VariableLocation::LOOKUP:
   10231             :         return Bailout(kLookupVariableInCountOperation);
   10232             : 
   10233             :       case VariableLocation::MODULE:
   10234           0 :         UNREACHABLE();
   10235             :     }
   10236             : 
   10237       42520 :     Drop(returns_original_input ? 2 : 1);
   10238       85040 :     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
   10239             :   }
   10240             : 
   10241             :   // Argument of the count operation is a property.
   10242             :   DCHECK(prop != NULL);
   10243        2505 :   if (returns_original_input) Push(graph()->GetConstantUndefined());
   10244             : 
   10245        4776 :   CHECK_ALIVE(VisitForValue(prop->obj()));
   10246             :   HValue* object = Top();
   10247             : 
   10248             :   HValue* key = NULL;
   10249        2942 :   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   10250         724 :     CHECK_ALIVE(VisitForValue(prop->key()));
   10251             :     key = Top();
   10252             :   }
   10253             : 
   10254        4770 :   CHECK_ALIVE(PushLoad(prop, object, key));
   10255             : 
   10256        1590 :   after = BuildIncrement(expr);
   10257             : 
   10258        1590 :   if (returns_original_input) {
   10259             :     input = Pop();
   10260             :     // Drop object and key to push it again in the effect context below.
   10261         911 :     Drop(key == NULL ? 1 : 2);
   10262             :     environment()->SetExpressionStackAt(0, input);
   10263        2733 :     CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
   10264             :                                     expr->AssignmentId(), object, key, after));
   10265        1822 :     return ast_context()->ReturnValue(Pop());
   10266             :   }
   10267             : 
   10268             :   environment()->SetExpressionStackAt(0, after);
   10269             :   return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
   10270         679 :                     expr->AssignmentId());
   10271             : }
   10272             : 
   10273             : 
   10274         548 : HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
   10275             :     HValue* string,
   10276             :     HValue* index) {
   10277         770 :   if (string->IsConstant() && index->IsConstant()) {
   10278             :     HConstant* c_string = HConstant::cast(string);
   10279         175 :     HConstant* c_index = HConstant::cast(index);
   10280         386 :     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
   10281             :       int32_t i = c_index->NumberValueAsInteger32();
   10282             :       Handle<String> s = c_string->StringValue();
   10283         339 :       if (i < 0 || i >= s->length()) {
   10284          44 :         return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
   10285             :       }
   10286         131 :       return New<HConstant>(s->Get(i));
   10287             :     }
   10288             :   }
   10289         373 :   string = BuildCheckString(string);
   10290         373 :   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
   10291         373 :   return New<HStringCharCodeAt>(string, index);
   10292             : }
   10293             : 
   10294             : 
   10295             : // Checks if the given shift amounts have following forms:
   10296             : // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
   10297         579 : static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
   10298             :                                              HValue* const32_minus_sa) {
   10299        1056 :   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
   10300          96 :     const HConstant* c1 = HConstant::cast(sa);
   10301          96 :     const HConstant* c2 = HConstant::cast(const32_minus_sa);
   10302         144 :     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
   10303          96 :         (c1->Integer32Value() + c2->Integer32Value() == 32);
   10304             :   }
   10305         531 :   if (!const32_minus_sa->IsSub()) return false;
   10306             :   HSub* sub = HSub::cast(const32_minus_sa);
   10307        1008 :   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
   10308             : }
   10309             : 
   10310             : 
   10311             : // Checks if the left and the right are shift instructions with the oposite
   10312             : // directions that can be replaced by one rotate right instruction or not.
   10313             : // Returns the operand and the shift amount for the rotate instruction in the
   10314             : // former case.
   10315       18281 : bool HGraphBuilder::MatchRotateRight(HValue* left,
   10316             :                                      HValue* right,
   10317             :                                      HValue** operand,
   10318             :                                      HValue** shift_amount) {
   10319             :   HShl* shl;
   10320             :   HShr* shr;
   10321       20778 :   if (left->IsShl() && right->IsShr()) {
   10322             :     shl = HShl::cast(left);
   10323             :     shr = HShr::cast(right);
   10324       17956 :   } else if (left->IsShr() && right->IsShl()) {
   10325             :     shl = HShl::cast(right);
   10326             :     shr = HShr::cast(left);
   10327             :   } else {
   10328             :     return false;
   10329             :   }
   10330         570 :   if (shl->left() != shr->left()) return false;
   10331             : 
   10332         579 :   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
   10333          24 :       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
   10334             :     return false;
   10335             :   }
   10336         549 :   *operand = shr->left();
   10337         549 :   *shift_amount = shr->right();
   10338         549 :   return true;
   10339             : }
   10340             : 
   10341             : 
   10342        8340 : bool CanBeZero(HValue* right) {
   10343        8340 :   if (right->IsConstant()) {
   10344       12634 :     HConstant* right_const = HConstant::cast(right);
   10345       12634 :     if (right_const->HasInteger32Value() &&
   10346        6142 :        (right_const->Integer32Value() & 0x1f) != 0) {
   10347             :       return false;
   10348             :     }
   10349             :   }
   10350        3443 :   return true;
   10351             : }
   10352             : 
   10353       16816 : HValue* HGraphBuilder::EnforceNumberType(HValue* number, AstType* expected) {
   10354       16816 :   if (expected->Is(AstType::SignedSmall())) {
   10355       11753 :     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
   10356             :   }
   10357        5063 :   if (expected->Is(AstType::Signed32())) {
   10358             :     return AddUncasted<HForceRepresentation>(number,
   10359           0 :                                              Representation::Integer32());
   10360             :   }
   10361             :   return number;
   10362             : }
   10363             : 
   10364     2574159 : HValue* HGraphBuilder::TruncateToNumber(HValue* value, AstType** expected) {
   10365      670160 :   if (value->IsConstant()) {
   10366             :     HConstant* constant = HConstant::cast(value);
   10367             :     Maybe<HConstant*> number =
   10368      268986 :         constant->CopyToTruncatedNumber(isolate(), zone());
   10369      268986 :     if (number.IsJust()) {
   10370        7135 :       *expected = AstType::Number();
   10371        7135 :       return AddInstruction(number.FromJust());
   10372             :     }
   10373             :   }
   10374             : 
   10375             :   // We put temporary values on the stack, which don't correspond to anything
   10376             :   // in baseline code. Since nothing is observable we avoid recording those
   10377             :   // pushes with a NoObservableSideEffectsScope.
   10378             :   NoObservableSideEffectsScope no_effects(this);
   10379             : 
   10380      663025 :   AstType* expected_type = *expected;
   10381             : 
   10382             :   // Separate the number type from the rest.
   10383             :   AstType* expected_obj =
   10384      663025 :       AstType::Intersect(expected_type, AstType::NonNumber(), zone());
   10385             :   AstType* expected_number =
   10386      663025 :       AstType::Intersect(expected_type, AstType::Number(), zone());
   10387             : 
   10388             :   // We expect to get a number.
   10389             :   // (We need to check first, since AstType::None->Is(AstType::Any()) == true.
   10390      663025 :   if (expected_obj->Is(AstType::None())) {
   10391             :     DCHECK(!expected_number->Is(AstType::None()));
   10392             :     return value;
   10393             :   }
   10394             : 
   10395      663025 :   if (expected_obj->Is(AstType::Undefined())) {
   10396             :     // This is already done by HChange.
   10397       39977 :     *expected = AstType::Union(expected_number, AstType::Number(), zone());
   10398       39977 :     return value;
   10399             :   }
   10400             : 
   10401             :   return value;
   10402             : }
   10403             : 
   10404             : 
   10405      385432 : HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
   10406     1156296 :     BinaryOperation* expr,
   10407             :     HValue* left,
   10408             :     HValue* right,
   10409             :     PushBeforeSimulateBehavior push_sim_result) {
   10410      385432 :   AstType* left_type = bounds_.get(expr->left()).lower;
   10411      385432 :   AstType* right_type = bounds_.get(expr->right()).lower;
   10412      385432 :   AstType* result_type = bounds_.get(expr).lower;
   10413      385432 :   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
   10414             :   Handle<AllocationSite> allocation_site = expr->allocation_site();
   10415             : 
   10416             :   HAllocationMode allocation_mode;
   10417      385432 :   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
   10418       21914 :     allocation_mode = HAllocationMode(allocation_site);
   10419             :   }
   10420             :   HValue* result = HGraphBuilder::BuildBinaryOperation(
   10421             :       expr->op(), left, right, left_type, right_type, result_type,
   10422      385432 :       fixed_right_arg, allocation_mode, expr->id());
   10423             :   // Add a simulate after instructions with observable side effects, and
   10424             :   // after phis, which are the result of BuildBinaryOperation when we
   10425             :   // inlined some complex subgraph.
   10426      425962 :   if (result->HasObservableSideEffects() || result->IsPhi()) {
   10427      356851 :     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   10428      356546 :       Push(result);
   10429      356546 :       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10430             :       Drop(1);
   10431             :     } else {
   10432         305 :       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10433             :     }
   10434             :   }
   10435      385432 :   return result;
   10436             : }
   10437             : 
   10438      395422 : HValue* HGraphBuilder::BuildBinaryOperation(
   10439             :     Token::Value op, HValue* left, HValue* right, AstType* left_type,
   10440             :     AstType* right_type, AstType* result_type, Maybe<int> fixed_right_arg,
   10441     1087137 :     HAllocationMode allocation_mode, BailoutId opt_id) {
   10442             :   bool maybe_string_add = false;
   10443      395422 :   if (op == Token::ADD) {
   10444             :     // If we are adding constant string with something for which we don't have
   10445             :     // a feedback yet, assume that it's also going to be a string and don't
   10446             :     // generate deopt instructions.
   10447      241824 :     if (!left_type->IsInhabited() && right->IsConstant() &&
   10448             :         HConstant::cast(right)->HasStringValue()) {
   10449       10128 :       left_type = AstType::String();
   10450             :     }
   10451             : 
   10452      226510 :     if (!right_type->IsInhabited() && left->IsConstant() &&
   10453             :         HConstant::cast(left)->HasStringValue()) {
   10454        5693 :       right_type = AstType::String();
   10455             :     }
   10456             : 
   10457      364059 :     maybe_string_add = (left_type->Maybe(AstType::String()) ||
   10458      319528 :                         left_type->Maybe(AstType::Receiver()) ||
   10459      522932 :                         right_type->Maybe(AstType::String()) ||
   10460      158907 :                         right_type->Maybe(AstType::Receiver()));
   10461             :   }
   10462             : 
   10463      395422 :   Representation left_rep = RepresentationFor(left_type);
   10464      395422 :   Representation right_rep = RepresentationFor(right_type);
   10465             : 
   10466      395422 :   if (!left_type->IsInhabited()) {
   10467             :     Add<HDeoptimize>(
   10468             :         DeoptimizeReason::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
   10469       31154 :         Deoptimizer::SOFT);
   10470       31154 :     left_type = AstType::Any();
   10471       31154 :     left_rep = RepresentationFor(left_type);
   10472       31154 :     maybe_string_add = op == Token::ADD;
   10473             :   }
   10474             : 
   10475      395422 :   if (!right_type->IsInhabited()) {
   10476             :     Add<HDeoptimize>(
   10477             :         DeoptimizeReason::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
   10478       39134 :         Deoptimizer::SOFT);
   10479       39134 :     right_type = AstType::Any();
   10480       39134 :     right_rep = RepresentationFor(right_type);
   10481       39134 :     maybe_string_add = op == Token::ADD;
   10482             :   }
   10483             : 
   10484      395422 :   if (!maybe_string_add) {
   10485      335080 :     left = TruncateToNumber(left, &left_type);
   10486      335080 :     right = TruncateToNumber(right, &right_type);
   10487             :   }
   10488             : 
   10489             :   // Special case for string addition here.
   10490      995122 :   if (op == Token::ADD &&
   10491      525676 :       (left_type->Is(AstType::String()) || right_type->Is(AstType::String()))) {
   10492             :     // Validate type feedback for left argument.
   10493       88410 :     if (left_type->Is(AstType::String())) {
   10494       43579 :       left = BuildCheckString(left);
   10495             :     }
   10496             : 
   10497             :     // Validate type feedback for right argument.
   10498       88410 :     if (right_type->Is(AstType::String())) {
   10499       38259 :       right = BuildCheckString(right);
   10500             :     }
   10501             : 
   10502             :     // Convert left argument as necessary.
   10503       88410 :     if (left_type->Is(AstType::Number())) {
   10504             :       DCHECK(right_type->Is(AstType::String()));
   10505         422 :       left = BuildNumberToString(left, left_type);
   10506       87566 :     } else if (!left_type->Is(AstType::String())) {
   10507             :       DCHECK(right_type->Is(AstType::String()));
   10508             :       return AddUncasted<HStringAdd>(
   10509             :           left, right, allocation_mode.GetPretenureMode(),
   10510         204 :           STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
   10511             :     }
   10512             : 
   10513             :     // Convert right argument as necessary.
   10514       88002 :     if (right_type->Is(AstType::Number())) {
   10515             :       DCHECK(left_type->Is(AstType::String()));
   10516        4780 :       right = BuildNumberToString(right, right_type);
   10517       78442 :     } else if (!right_type->Is(AstType::String())) {
   10518             :       DCHECK(left_type->Is(AstType::String()));
   10519             :       return AddUncasted<HStringAdd>(
   10520             :           left, right, allocation_mode.GetPretenureMode(),
   10521        1166 :           STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
   10522             :     }
   10523             : 
   10524             :     // Fast paths for empty constant strings.
   10525             :     Handle<String> left_string =
   10526       10769 :         left->IsConstant() && HConstant::cast(left)->HasStringValue()
   10527             :             ? HConstant::cast(left)->StringValue()
   10528       53604 :             : Handle<String>();
   10529             :     Handle<String> right_string =
   10530       26984 :         right->IsConstant() && HConstant::cast(right)->HasStringValue()
   10531             :             ? HConstant::cast(right)->StringValue()
   10532       69819 :             : Handle<String>();
   10533       53604 :     if (!left_string.is_null() && left_string->length() == 0) return right;
   10534       69114 :     if (!right_string.is_null() && right_string->length() == 0) return left;
   10535       40928 :     if (!left_string.is_null() && !right_string.is_null()) {
   10536             :       return AddUncasted<HStringAdd>(
   10537             :           left, right, allocation_mode.GetPretenureMode(),
   10538        1533 :           STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
   10539             :     }
   10540             : 
   10541             :     // Register the dependent code with the allocation site.
   10542       39395 :     if (!allocation_mode.feedback_site().is_null()) {
   10543             :       DCHECK(!graph()->info()->IsStub());
   10544             :       Handle<AllocationSite> site(allocation_mode.feedback_site());
   10545       20317 :       top_info()->dependencies()->AssumeTenuringDecision(site);
   10546             :     }
   10547             : 
   10548             :     // Inline the string addition into the stub when creating allocation
   10549             :     // mementos to gather allocation site feedback, or if we can statically
   10550             :     // infer that we're going to create a cons string.
   10551       82590 :     if ((graph()->info()->IsStub() &&
   10552       35827 :          allocation_mode.CreateAllocationMementos()) ||
   10553        8696 :         (left->IsConstant() &&
   10554        8696 :          HConstant::cast(left)->HasStringValue() &&
   10555             :          HConstant::cast(left)->StringValue()->length() + 1 >=
   10556       73276 :            ConsString::kMinLength) ||
   10557       23917 :         (right->IsConstant() &&
   10558       23917 :          HConstant::cast(right)->HasStringValue() &&
   10559             :          HConstant::cast(right)->StringValue()->length() + 1 >=
   10560             :            ConsString::kMinLength)) {
   10561       15417 :       return BuildStringAdd(left, right, allocation_mode);
   10562             :     }
   10563             : 
   10564             :     // Fallback to using the string add stub.
   10565             :     return AddUncasted<HStringAdd>(
   10566             :         left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE,
   10567       23978 :         allocation_mode.feedback_site());
   10568             :   }
   10569             : 
   10570             :   // Special case for +x here.
   10571      351217 :   if (op == Token::MUL) {
   10572       36329 :     if (left->EqualsInteger32Constant(1)) {
   10573          50 :       return BuildToNumber(right);
   10574             :     }
   10575       36279 :     if (right->EqualsInteger32Constant(1)) {
   10576        9512 :       return BuildToNumber(left);
   10577             :     }
   10578             :   }
   10579             : 
   10580      341655 :   if (graph()->info()->IsStub()) {
   10581        5867 :     left = EnforceNumberType(left, left_type);
   10582        5867 :     right = EnforceNumberType(right, right_type);
   10583             :   }
   10584             : 
   10585      341655 :   Representation result_rep = RepresentationFor(result_type);
   10586             : 
   10587      341655 :   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
   10588       31116 :                           (right_rep.IsTagged() && !right_rep.IsSmi());
   10589             : 
   10590             :   HInstruction* instr = NULL;
   10591             :   // Only the stub is allowed to call into the runtime, since otherwise we would
   10592             :   // inline several instructions (including the two pushes) for every tagged
   10593             :   // operation in optimized code, which is more expensive, than a stub call.
   10594      341655 :   if (graph()->info()->IsStub() && is_non_primitive) {
   10595         785 :     HValue* values[] = {left, right};
   10596             : #define GET_STUB(Name)                                                       \
   10597             :   do {                                                                       \
   10598             :     Callable callable = CodeFactory::Name(isolate());                        \
   10599             :     HValue* stub = Add<HConstant>(callable.code());                          \
   10600             :     instr = AddUncasted<HCallWithDescriptor>(stub, 0, callable.descriptor(), \
   10601             :                                              ArrayVector(values));           \
   10602             :   } while (false)
   10603             : 
   10604         785 :     switch (op) {
   10605             :       default:
   10606           0 :         UNREACHABLE();
   10607             :       case Token::ADD:
   10608         586 :         GET_STUB(Add);
   10609         293 :         break;
   10610             :       case Token::SUB:
   10611         154 :         GET_STUB(Subtract);
   10612          77 :         break;
   10613             :       case Token::MUL:
   10614         242 :         GET_STUB(Multiply);
   10615         121 :         break;
   10616             :       case Token::DIV:
   10617          58 :         GET_STUB(Divide);
   10618          29 :         break;
   10619             :       case Token::MOD:
   10620          52 :         GET_STUB(Modulus);
   10621          26 :         break;
   10622             :       case Token::BIT_OR:
   10623         136 :         GET_STUB(BitwiseOr);
   10624          68 :         break;
   10625             :       case Token::BIT_AND:
   10626          48 :         GET_STUB(BitwiseAnd);
   10627          24 :         break;
   10628             :       case Token::BIT_XOR:
   10629          72 :         GET_STUB(BitwiseXor);
   10630          36 :         break;
   10631             :       case Token::SAR:
   10632          62 :         GET_STUB(ShiftRight);
   10633          31 :         break;
   10634             :       case Token::SHR:
   10635         116 :         GET_STUB(ShiftRightLogical);
   10636          58 :         break;
   10637             :       case Token::SHL:
   10638          44 :         GET_STUB(ShiftLeft);
   10639          22 :         break;
   10640             :     }
   10641             : #undef GET_STUB
   10642             :   } else {
   10643      340870 :     switch (op) {
   10644             :       case Token::ADD:
   10645      159780 :         instr = AddUncasted<HAdd>(left, right);
   10646      159780 :         break;
   10647             :       case Token::SUB:
   10648       19655 :         instr = AddUncasted<HSub>(left, right);
   10649       19655 :         break;
   10650             :       case Token::MUL:
   10651       26646 :         instr = AddUncasted<HMul>(left, right);
   10652       26646 :         break;
   10653             :       case Token::MOD: {
   10654        6308 :         if (fixed_right_arg.IsJust() &&
   10655         711 :             !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
   10656             :           HConstant* fixed_right =
   10657         456 :               Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
   10658             :           IfBuilder if_same(this);
   10659         456 :           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
   10660         456 :           if_same.Then();
   10661         456 :           if_same.ElseDeopt(DeoptimizeReason::kUnexpectedRHSOfBinaryOperation);
   10662             :           right = fixed_right;
   10663             :         }
   10664        5597 :         instr = AddUncasted<HMod>(left, right);
   10665        5597 :         break;
   10666             :       }
   10667             :       case Token::DIV:
   10668       52162 :         instr = AddUncasted<HDiv>(left, right);
   10669       52162 :         break;
   10670             :       case Token::BIT_XOR:
   10671             :       case Token::BIT_AND:
   10672       22828 :         instr = AddUncasted<HBitwise>(op, left, right);
   10673       22828 :         break;
   10674             :       case Token::BIT_OR: {
   10675             :         HValue *operand, *shift_amount;
   10676       73791 :         if (left_type->Is(AstType::Signed32()) &&
   10677       45846 :             right_type->Is(AstType::Signed32()) &&
   10678       18281 :             MatchRotateRight(left, right, &operand, &shift_amount)) {
   10679         549 :           instr = AddUncasted<HRor>(operand, shift_amount);
   10680             :         } else {
   10681       27016 :           instr = AddUncasted<HBitwise>(op, left, right);
   10682             :         }
   10683             :         break;
   10684             :       }
   10685             :       case Token::SAR:
   10686       10416 :         instr = AddUncasted<HSar>(left, right);
   10687       10416 :         break;
   10688             :       case Token::SHR:
   10689        8340 :         instr = AddUncasted<HShr>(left, right);
   10690       16680 :         if (instr->IsShr() && CanBeZero(right)) {
   10691        3443 :           graph()->RecordUint32Instruction(instr);
   10692             :         }
   10693             :         break;
   10694             :       case Token::SHL:
   10695        7881 :         instr = AddUncasted<HShl>(left, right);
   10696        7881 :         break;
   10697             :       default:
   10698           0 :         UNREACHABLE();
   10699             :     }
   10700             :   }
   10701             : 
   10702      341655 :   if (instr->IsBinaryOperation()) {
   10703             :     HBinaryOperation* binop = HBinaryOperation::cast(instr);
   10704             :     binop->set_observed_input_representation(1, left_rep);
   10705             :     binop->set_observed_input_representation(2, right_rep);
   10706      340672 :     binop->initialize_output_representation(result_rep);
   10707      340672 :     if (graph()->info()->IsStub()) {
   10708             :       // Stub should not call into stub.
   10709             :       instr->SetFlag(HValue::kCannotBeTagged);
   10710             :       // And should truncate on HForceRepresentation already.
   10711        5082 :       if (left->IsForceRepresentation()) {
   10712             :         left->CopyFlag(HValue::kTruncatingToSmi, instr);
   10713             :         left->CopyFlag(HValue::kTruncatingToInt32, instr);
   10714             :       }
   10715        5082 :       if (right->IsForceRepresentation()) {
   10716             :         right->CopyFlag(HValue::kTruncatingToSmi, instr);
   10717             :         right->CopyFlag(HValue::kTruncatingToInt32, instr);
   10718             :       }
   10719             :     }
   10720             :   }
   10721      341655 :   return instr;
   10722             : }
   10723             : 
   10724             : // Check for the form (%_ClassOf(foo) === 'BarClass').
   10725      744285 : static bool IsClassOfTest(CompareOperation* expr) {
   10726      419597 :   if (expr->op() != Token::EQ_STRICT) return false;
   10727      324602 :   CallRuntime* call = expr->left()->AsCallRuntime();
   10728      316908 :   if (call == NULL) return false;
   10729       15560 :   Literal* literal = expr->right()->AsLiteral();
   10730        7780 :   if (literal == NULL) return false;
   10731        7780 :   if (!literal->value()->IsString()) return false;
   10732        7694 :   if (call->is_jsruntime()) return false;
   10733        7688 :   if (call->function()->function_id != Runtime::kInlineClassOf) return false;
   10734             :   DCHECK_EQ(call->arguments()->length(), 1);
   10735        7688 :   return true;
   10736             : }
   10737             : 
   10738      514229 : void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
   10739             :   DCHECK(!HasStackOverflow());
   10740             :   DCHECK(current_block() != NULL);
   10741             :   DCHECK(current_block()->HasPredecessor());
   10742      514229 :   switch (expr->op()) {
   10743             :     case Token::COMMA:
   10744        6032 :       return VisitComma(expr);
   10745             :     case Token::OR:
   10746             :     case Token::AND:
   10747      122210 :       return VisitLogicalExpression(expr);
   10748             :     default:
   10749      385987 :       return VisitArithmeticExpression(expr);
   10750             :   }
   10751             : }
   10752             : 
   10753             : 
   10754       18087 : void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
   10755       18096 :   CHECK_ALIVE(VisitForEffect(expr->left()));
   10756             :   // Visit the right subexpression in the same AST context as the entire
   10757             :   // expression.
   10758        6023 :   Visit(expr->right());
   10759             : }
   10760             : 
   10761             : 
   10762      666741 : void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
   10763      122210 :   bool is_logical_and = expr->op() == Token::AND;
   10764      122210 :   if (ast_context()->IsTest()) {
   10765      110995 :     TestContext* context = TestContext::cast(ast_context());
   10766             :     // Translate left subexpression.
   10767      155423 :     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   10768      110995 :     if (is_logical_and) {
   10769       90162 :       CHECK_BAILOUT(VisitForControl(expr->left(),
   10770             :                                     eval_right,
   10771             :                                     context->if_false()));
   10772             :     } else {
   10773      131828 :       CHECK_BAILOUT(VisitForControl(expr->left(),
   10774             :                                     context->if_true(),
   10775             :                                     eval_right));
   10776             :     }
   10777             : 
   10778             :     // Translate right subexpression by visiting it in the same AST
   10779             :     // context as the entire expression.
   10780      110995 :     CHECK(eval_right->HasPredecessor());
   10781             :     eval_right->SetJoinId(expr->RightId());
   10782             :     set_current_block(eval_right);
   10783      110995 :     Visit(expr->right());
   10784       11215 :   } else if (ast_context()->IsValue()) {
   10785       33537 :     CHECK_ALIVE(VisitForValue(expr->left()));
   10786             :     DCHECK(current_block() != NULL);
   10787             :     HValue* left_value = Top();
   10788             : 
   10789             :     // Short-circuit left values that always evaluate to the same boolean value.
   10790       22264 :     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
   10791             :       // l (evals true)  && r -> r
   10792             :       // l (evals true)  || r -> l
   10793             :       // l (evals false) && r -> l
   10794             :       // l (evals false) || r -> r
   10795         161 :       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
   10796             :         Drop(1);
   10797         267 :         CHECK_ALIVE(VisitForValue(expr->right()));
   10798             :       }
   10799         322 :       return ast_context()->ReturnValue(Pop());
   10800             :     }
   10801             : 
   10802             :     // We need an extra block to maintain edge-split form.
   10803       11018 :     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   10804       11018 :     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   10805       11018 :     ToBooleanHints expected(expr->left()->to_boolean_types());
   10806             :     HBranch* test = is_logical_and
   10807        6267 :         ? New<HBranch>(left_value, expected, eval_right, empty_block)
   10808       17285 :         : New<HBranch>(left_value, expected, empty_block, eval_right);
   10809       11018 :     FinishCurrentBlock(test);
   10810             : 
   10811             :     set_current_block(eval_right);
   10812             :     Drop(1);  // Value of the left subexpression.
   10813       22036 :     CHECK_BAILOUT(VisitForValue(expr->right()));
   10814             : 
   10815             :     HBasicBlock* join_block =
   10816       11016 :       CreateJoin(empty_block, current_block(), expr->id());
   10817             :     set_current_block(join_block);
   10818       22032 :     return ast_context()->ReturnValue(Pop());
   10819             : 
   10820             :   } else {
   10821             :     DCHECK(ast_context()->IsEffect());
   10822             :     // In an effect context, we don't need the value of the left subexpression,
   10823             :     // only its control flow and side effects.  We need an extra block to
   10824             :     // maintain edge-split form.
   10825          36 :     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   10826          36 :     HBasicBlock* right_block = graph()->CreateBasicBlock();
   10827          36 :     if (is_logical_and) {
   10828          60 :       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
   10829             :     } else {
   10830          12 :       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
   10831             :     }
   10832             : 
   10833             :     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
   10834             :     // actually two empty blocks (one here and one inserted by
   10835             :     // TestContext::BuildBranch, and that they both have an HSimulate though the
   10836             :     // second one is not a merge node, and that we really have no good AST ID to
   10837             :     // put on that first HSimulate.
   10838             : 
   10839             :     // Technically, we should be able to handle the case when one side of
   10840             :     // the test is not connected, but this can trip up liveness analysis
   10841             :     // if we did not fully connect the test context based on some optimistic
   10842             :     // assumption. If such an assumption was violated, we would end up with
   10843             :     // an environment with optimized-out values. So we should always
   10844             :     // conservatively connect the test context.
   10845             : 
   10846          36 :     CHECK(right_block->HasPredecessor());
   10847          36 :     CHECK(empty_block->HasPredecessor());
   10848             : 
   10849             :     empty_block->SetJoinId(expr->id());
   10850             : 
   10851             :     right_block->SetJoinId(expr->RightId());
   10852             :     set_current_block(right_block);
   10853          72 :     CHECK_BAILOUT(VisitForEffect(expr->right()));
   10854             :     right_block = current_block();
   10855             : 
   10856             :     HBasicBlock* join_block =
   10857          36 :       CreateJoin(empty_block, right_block, expr->id());
   10858             :     set_current_block(join_block);
   10859             :     // We did not materialize any value in the predecessor environments,
   10860             :     // so there is no need to handle it here.
   10861             :   }
   10862             : }
   10863             : 
   10864             : 
   10865     2312434 : void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
   10866     1157075 :   CHECK_ALIVE(VisitForValue(expr->left()));
   10867     1155359 :   CHECK_ALIVE(VisitForValue(expr->right()));
   10868      385101 :   SetSourcePosition(expr->position());
   10869             :   HValue* right = Pop();
   10870             :   HValue* left = Pop();
   10871             :   HValue* result =
   10872             :       BuildBinaryOperation(expr, left, right,
   10873      385101 :           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   10874      385101 :                                     : PUSH_BEFORE_SIMULATE);
   10875      385101 :   return ast_context()->ReturnValue(result);
   10876             : }
   10877             : 
   10878             : 
   10879       66185 : void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
   10880             :                                                         Expression* sub_expr,
   10881      132370 :                                                         Handle<String> check) {
   10882      132370 :   CHECK_ALIVE(VisitForTypeOf(sub_expr));
   10883       66185 :   SetSourcePosition(expr->position());
   10884             :   HValue* value = Pop();
   10885       66185 :   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
   10886      132370 :   return ast_context()->ReturnControl(instr, expr->id());
   10887             : }
   10888             : 
   10889             : namespace {
   10890             : 
   10891      411904 : bool IsLiteralCompareStrict(Isolate* isolate, HValue* left, Token::Value op,
   10892             :                             HValue* right) {
   10893      721121 :   return op == Token::EQ_STRICT &&
   10894        7349 :          ((left->IsConstant() &&
   10895      430135 :            !HConstant::cast(left)->handle(isolate)->IsNumber() &&
   10896      723371 :            !HConstant::cast(left)->handle(isolate)->IsString()) ||
   10897      171993 :           (right->IsConstant() &&
   10898      722599 :            !HConstant::cast(right)->handle(isolate)->IsNumber() &&
   10899     1367065 :            !HConstant::cast(right)->handle(isolate)->IsString()));
   10900             : }
   10901             : 
   10902             : }  // namespace
   10903             : 
   10904     5040022 : void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   10905             :   DCHECK(!HasStackOverflow());
   10906             :   DCHECK(current_block() != NULL);
   10907             :   DCHECK(current_block()->HasPredecessor());
   10908             : 
   10909     1752475 :   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   10910             : 
   10911             :   // Check for a few fast cases. The AST visiting behavior must be in sync
   10912             :   // with the full codegen: We don't push both left and right values onto
   10913             :   // the expression stack when one side is a special-case literal.
   10914      503361 :   Expression* sub_expr = NULL;
   10915             :   Literal* literal;
   10916      503361 :   if (expr->IsLiteralCompareTypeof(&sub_expr, &literal)) {
   10917             :     return HandleLiteralCompareTypeof(expr, sub_expr,
   10918      132370 :                                       Handle<String>::cast(literal->value()));
   10919             :   }
   10920      437176 :   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
   10921       12051 :     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
   10922             :   }
   10923      425125 :   if (expr->IsLiteralCompareNull(&sub_expr)) {
   10924        5528 :     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
   10925             :   }
   10926             : 
   10927      419597 :   if (IsClassOfTest(expr)) {
   10928       15376 :     CallRuntime* call = expr->left()->AsCallRuntime();
   10929             :     DCHECK(call->arguments()->length() == 1);
   10930       23064 :     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   10931             :     HValue* value = Pop();
   10932       15376 :     Literal* literal = expr->right()->AsLiteral();
   10933        7688 :     Handle<String> rhs = Handle<String>::cast(literal->value());
   10934        7688 :     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
   10935       15376 :     return ast_context()->ReturnControl(instr, expr->id());
   10936             :   }
   10937             : 
   10938      411909 :   AstType* left_type = bounds_.get(expr->left()).lower;
   10939      411909 :   AstType* right_type = bounds_.get(expr->right()).lower;
   10940             :   AstType* combined_type = expr->combined_type();
   10941             : 
   10942     1235723 :   CHECK_ALIVE(VisitForValue(expr->left()));
   10943     1235714 :   CHECK_ALIVE(VisitForValue(expr->right()));
   10944             : 
   10945             :   HValue* right = Pop();
   10946             :   HValue* left = Pop();
   10947             :   Token::Value op = expr->op();
   10948             : 
   10949      411904 :   if (IsLiteralCompareStrict(isolate(), left, op, right)) {
   10950             :     HCompareObjectEqAndBranch* result =
   10951        5616 :         New<HCompareObjectEqAndBranch>(left, right);
   10952       11232 :     return ast_context()->ReturnControl(result, expr->id());
   10953             :   }
   10954             : 
   10955      406288 :   if (op == Token::INSTANCEOF) {
   10956             :     // Check to see if the rhs of the instanceof is a known function.
   10957        4617 :     if (right->IsConstant() &&
   10958        2463 :         HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
   10959             :       Handle<JSFunction> function =
   10960         430 :           Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
   10961             :       // Make sure that the {function} already has a meaningful initial map
   10962             :       // (i.e. we constructed at least one instance using the constructor
   10963             :       // {function}), and has an instance as .prototype.
   10964         826 :       if (function->has_initial_map() &&
   10965             :           !function->map()->has_non_instance_prototype()) {
   10966             :         // Lookup @@hasInstance on the {function}.
   10967             :         Handle<Map> function_map(function->map(), isolate());
   10968             :         PropertyAccessInfo has_instance(
   10969             :             this, LOAD, function_map,
   10970         395 :             isolate()->factory()->has_instance_symbol());
   10971             :         // Check if we are using the Function.prototype[@@hasInstance].
   10972        1190 :         if (has_instance.CanAccessMonomorphic() &&
   10973         724 :             has_instance.IsDataConstant() &&
   10974             :             has_instance.constant().is_identical_to(
   10975        1053 :                 isolate()->function_has_instance())) {
   10976             :           // Add appropriate receiver map check and prototype chain
   10977             :           // checks to guard the @@hasInstance lookup chain.
   10978         323 :           AddCheckMap(right, function_map);
   10979         323 :           if (has_instance.has_holder()) {
   10980             :             Handle<JSObject> prototype(
   10981         646 :                 JSObject::cast(has_instance.map()->prototype()), isolate());
   10982         323 :             BuildCheckPrototypeMaps(prototype, has_instance.holder());
   10983             :           }
   10984             :           // Perform the prototype chain walk.
   10985             :           Handle<Map> initial_map(function->initial_map(), isolate());
   10986         323 :           top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
   10987             :           HInstruction* prototype =
   10988         323 :               Add<HConstant>(handle(initial_map->prototype(), isolate()));
   10989             :           HHasInPrototypeChainAndBranch* result =
   10990         323 :               New<HHasInPrototypeChainAndBranch>(left, prototype);
   10991         646 :           return ast_context()->ReturnControl(result, expr->id());
   10992             :         }
   10993             :       }
   10994             :     }
   10995             : 
   10996        1216 :     Callable callable = CodeFactory::InstanceOf(isolate());
   10997        1216 :     HValue* stub = Add<HConstant>(callable.code());
   10998        1216 :     HValue* values[] = {left, right};
   10999             :     HCallWithDescriptor* result = New<HCallWithDescriptor>(
   11000        1216 :         stub, 0, callable.descriptor(), ArrayVector(values));
   11001             :     result->set_type(HType::Boolean());
   11002        2432 :     return ast_context()->ReturnInstruction(result, expr->id());
   11003             : 
   11004      404749 :   } else if (op == Token::IN) {
   11005        1194 :     Callable callable = CodeFactory::HasProperty(isolate());
   11006        1194 :     HValue* stub = Add<HConstant>(callable.code());
   11007        1194 :     HValue* values[] = {left, right};
   11008             :     HInstruction* result =
   11009             :         New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
   11010        1194 :                                  Vector<HValue*>(values, arraysize(values)));
   11011        2388 :     return ast_context()->ReturnInstruction(result, expr->id());
   11012             :   }
   11013             : 
   11014             :   PushBeforeSimulateBehavior push_behavior =
   11015      403555 :     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   11016      403555 :                               : PUSH_BEFORE_SIMULATE;
   11017             :   HControlInstruction* compare = BuildCompareInstruction(
   11018             :       op, left, right, left_type, right_type, combined_type,
   11019             :       ScriptPositionToSourcePosition(expr->left()->position()),
   11020             :       ScriptPositionToSourcePosition(expr->right()->position()),
   11021     1210665 :       push_behavior, expr->id());
   11022      403555 :   if (compare == NULL) return;  // Bailed out.
   11023      807090 :   return ast_context()->ReturnControl(compare, expr->id());
   11024             : }
   11025             : 
   11026      431677 : HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
   11027        1018 :     Token::Value op, HValue* left, HValue* right, AstType* left_type,
   11028             :     AstType* right_type, AstType* combined_type, SourcePosition left_position,
   11029             :     SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
   11030             :     BailoutId bailout_id) {
   11031             :   // Cases handled below depend on collected type feedback. They should
   11032             :   // soft deoptimize when there is no type feedback.
   11033      431677 :   if (!combined_type->IsInhabited()) {
   11034             :     Add<HDeoptimize>(
   11035             :         DeoptimizeReason::
   11036             :             kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
   11037      294867 :         Deoptimizer::SOFT);
   11038             :     combined_type = left_type = right_type = AstType::Any();
   11039             :   }
   11040             : 
   11041      431677 :   Representation left_rep = RepresentationFor(left_type);
   11042      431677 :   Representation right_rep = RepresentationFor(right_type);
   11043      431677 :   Representation combined_rep = RepresentationFor(combined_type);
   11044             : 
   11045      431677 :   if (combined_type->Is(AstType::Receiver())) {
   11046         639 :     if (Token::IsEqualityOp(op)) {
   11047             :       // HCompareObjectEqAndBranch can only deal with object, so
   11048             :       // exclude numbers.
   11049         642 :       if ((left->IsConstant() &&
   11050        1246 :            HConstant::cast(left)->HasNumberValue()) ||
   11051           9 :           (right->IsConstant() &&
   11052             :            HConstant::cast(right)->HasNumberValue())) {
   11053             :         Add<HDeoptimize>(
   11054             :             DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant,
   11055           9 :             Deoptimizer::SOFT);
   11056             :         // The caller expects a branch instruction, so make it happy.
   11057           9 :         return New<HBranch>(graph()->GetConstantTrue());
   11058             :       }
   11059         618 :       if (op == Token::EQ) {
   11060             :         // For abstract equality we need to check both sides are receivers.
   11061         109 :         if (combined_type->IsClass()) {
   11062          18 :           Handle<Map> map = combined_type->AsClass()->Map();
   11063          18 :           AddCheckMap(left, map);
   11064          18 :           AddCheckMap(right, map);
   11065             :         } else {
   11066          91 :           BuildCheckHeapObject(left);
   11067          91 :           Add<HCheckInstanceType>(left, HCheckInstanceType::IS_JS_RECEIVER);
   11068             :           BuildCheckHeapObject(right);
   11069          91 :           Add<HCheckInstanceType>(right, HCheckInstanceType::IS_JS_RECEIVER);
   11070             :         }
   11071             :       } else {
   11072             :         // For strict equality we only need to check one side.
   11073             :         HValue* operand_to_check =
   11074        1018 :             left->block()->block_id() < right->block()->block_id() ? left
   11075         509 :                                                                    : right;
   11076         509 :         if (combined_type->IsClass()) {
   11077          32 :           Handle<Map> map = combined_type->AsClass()->Map();
   11078          32 :           AddCheckMap(operand_to_check, map);
   11079             :         } else {
   11080         477 :           BuildCheckHeapObject(operand_to_check);
   11081             :           Add<HCheckInstanceType>(operand_to_check,
   11082         477 :                                   HCheckInstanceType::IS_JS_RECEIVER);
   11083             :         }
   11084             :       }
   11085             :       HCompareObjectEqAndBranch* result =
   11086         618 :           New<HCompareObjectEqAndBranch>(left, right);
   11087         618 :       return result;
   11088             :     } else {
   11089          12 :       if (combined_type->IsClass()) {
   11090             :         // TODO(bmeurer): This is an optimized version of an x < y, x > y,
   11091             :         // x <= y or x >= y, where both x and y are spec objects with the
   11092             :         // same map. The CompareIC collects this map for us. So if we know
   11093             :         // that there's no @@toPrimitive on the map (including the prototype
   11094             :         // chain), and both valueOf and toString are the default initial
   11095             :         // implementations (on the %ObjectPrototype%), then we can reduce
   11096             :         // the comparison to map checks on x and y, because the comparison
   11097             :         // will turn into a comparison of "[object CLASS]" to itself (the
   11098             :         // default outcome of toString, since valueOf returns a spec object).
   11099             :         // This is pretty much adhoc, so in TurboFan we could do a lot better
   11100             :         // and inline the interesting parts of ToPrimitive (actually we could
   11101             :         // even do that in Crankshaft but we don't want to waste too much
   11102             :         // time on this now).
   11103             :         DCHECK(Token::IsOrderedRelationalCompareOp(op));
   11104             :         Handle<Map> map = combined_type->AsClass()->Map();
   11105             :         PropertyAccessInfo value_of(this, LOAD, map,
   11106          12 :                                     isolate()->factory()->valueOf_string());
   11107             :         PropertyAccessInfo to_primitive(
   11108          12 :             this, LOAD, map, isolate()->factory()->to_primitive_symbol());
   11109             :         PropertyAccessInfo to_string(this, LOAD, map,
   11110          12 :                                      isolate()->factory()->toString_string());
   11111             :         PropertyAccessInfo to_string_tag(
   11112          12 :             this, LOAD, map, isolate()->factory()->to_string_tag_symbol());
   11113          40 :         if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() &&
   11114           8 :             to_string_tag.CanAccessMonomorphic() &&
   11115           4 :             (!to_string_tag.IsFound() || to_string_tag.IsData() ||
   11116           4 :              to_string_tag.IsDataConstant()) &&
   11117          12 :             value_of.CanAccessMonomorphic() && value_of.IsDataConstant() &&
   11118          24 :             value_of.constant().is_identical_to(isolate()->object_value_of()) &&
   11119          22 :             to_string.CanAccessMonomorphic() && to_string.IsDataConstant() &&
   11120             :             to_string.constant().is_identical_to(
   11121          14 :                 isolate()->object_to_string())) {
   11122             :           // We depend on the prototype chain to stay the same, because we
   11123             :           // also need to deoptimize when someone installs @@toPrimitive
   11124             :           // or @@toStringTag somewhere in the prototype chain.
   11125             :           Handle<Object> prototype(map->prototype(), isolate());
   11126           2 :           if (prototype->IsJSObject()) {
   11127             :             BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype),
   11128           0 :                                     Handle<JSObject>::null());
   11129             :           }
   11130           2 :           AddCheckMap(left, map);
   11131           2 :           AddCheckMap(right, map);
   11132             :           // The caller expects a branch instruction, so make it happy.
   11133             :           return New<HBranch>(
   11134           4 :               graph()->GetConstantBool(op == Token::LTE || op == Token::GTE));
   11135             :         }
   11136             :       }
   11137             :       Bailout(kUnsupportedNonPrimitiveCompare);
   11138          10 :       return NULL;
   11139             :     }
   11140      439897 :   } else if (combined_type->Is(AstType::InternalizedString()) &&
   11141             :              Token::IsEqualityOp(op)) {
   11142             :     // If we have a constant argument, it should be consistent with the type
   11143             :     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
   11144        9099 :     if ((left->IsConstant() &&
   11145       17716 :          !HConstant::cast(left)->HasInternalizedStringValue()) ||
   11146        4007 :         (right->IsConstant() &&
   11147        4007 :          !HConstant::cast(right)->HasInternalizedStringValue())) {
   11148             :       Add<HDeoptimize>(
   11149             :           DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant,
   11150           2 :           Deoptimizer::SOFT);
   11151             :       // The caller expects a branch instruction, so make it happy.
   11152           2 :       return New<HBranch>(graph()->GetConstantTrue());
   11153             :     }
   11154        8857 :     BuildCheckHeapObject(left);
   11155        8857 :     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11156             :     BuildCheckHeapObject(right);
   11157        8857 :     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11158             :     HCompareObjectEqAndBranch* result =
   11159        8857 :         New<HCompareObjectEqAndBranch>(left, right);
   11160        8857 :     return result;
   11161      422179 :   } else if (combined_type->Is(AstType::String())) {
   11162       15130 :     BuildCheckHeapObject(left);
   11163       15130 :     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
   11164             :     BuildCheckHeapObject(right);
   11165       15130 :     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
   11166             :     HStringCompareAndBranch* result =
   11167       15130 :         New<HStringCompareAndBranch>(left, right, op);
   11168       15130 :     return result;
   11169      407049 :   } else if (combined_type->Is(AstType::Boolean())) {
   11170         637 :     AddCheckMap(left, isolate()->factory()->boolean_map());
   11171         637 :     AddCheckMap(right, isolate()->factory()->boolean_map());
   11172         637 :     if (Token::IsEqualityOp(op)) {
   11173             :       HCompareObjectEqAndBranch* result =
   11174         603 :           New<HCompareObjectEqAndBranch>(left, right);
   11175         603 :       return result;
   11176             :     }
   11177             :     left = Add<HLoadNamedField>(
   11178             :         left, nullptr,
   11179          34 :         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11180             :     right = Add<HLoadNamedField>(
   11181             :         right, nullptr,
   11182          34 :         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11183             :     HCompareNumericAndBranch* result =
   11184          34 :         New<HCompareNumericAndBranch>(left, right, op);
   11185          34 :     return result;
   11186             :   } else {
   11187      406412 :     if (op == Token::EQ) {
   11188       20948 :       if (left->IsConstant() &&
   11189       19477 :           HConstant::cast(left)->GetInstanceType() == ODDBALL_TYPE &&
   11190             :           HConstant::cast(left)->IsUndetectable()) {
   11191           0 :         return New<HIsUndetectableAndBranch>(right);
   11192             :       }
   11193             : 
   11194       32204 :       if (right->IsConstant() &&
   11195       19490 :           HConstant::cast(right)->GetInstanceType() == ODDBALL_TYPE &&
   11196             :           HConstant::cast(right)->IsUndetectable()) {
   11197           1 :         return New<HIsUndetectableAndBranch>(left);
   11198             :       }
   11199             :     }
   11200             : 
   11201      406411 :     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
   11202      326725 :       HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
   11203             :       result->set_observed_input_representation(1, left_rep);
   11204             :       result->set_observed_input_representation(2, right_rep);
   11205      326725 :       if (result->HasObservableSideEffects()) {
   11206      326725 :         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   11207      326645 :           Push(result);
   11208             :           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11209             :           Drop(1);
   11210             :         } else {
   11211             :           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11212             :         }
   11213             :       }
   11214             :       // TODO(jkummerow): Can we make this more efficient?
   11215      326725 :       HBranch* branch = New<HBranch>(result);
   11216      326725 :       return branch;
   11217             :     } else {
   11218             :       HCompareNumericAndBranch* result =
   11219       79686 :           New<HCompareNumericAndBranch>(left, right, op);
   11220             :       result->set_observed_input_representation(left_rep, right_rep);
   11221       79686 :       return result;
   11222             :     }
   11223             :   }
   11224             : }
   11225             : 
   11226             : 
   11227       35158 : void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
   11228             :                                                      Expression* sub_expr,
   11229       35158 :                                                      NilValue nil) {
   11230             :   DCHECK(!HasStackOverflow());
   11231             :   DCHECK(current_block() != NULL);
   11232             :   DCHECK(current_block()->HasPredecessor());
   11233             :   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
   11234       51256 :   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   11235       52737 :   CHECK_ALIVE(VisitForValue(sub_expr));
   11236             :   HValue* value = Pop();
   11237             :   HControlInstruction* instr;
   11238       17579 :   if (expr->op() == Token::EQ_STRICT) {
   11239             :     HConstant* nil_constant = nil == kNullValue
   11240             :         ? graph()->GetConstantNull()
   11241       32196 :         : graph()->GetConstantUndefined();
   11242       16098 :     instr = New<HCompareObjectEqAndBranch>(value, nil_constant);
   11243             :   } else {
   11244             :     DCHECK_EQ(Token::EQ, expr->op());
   11245        1481 :     instr = New<HIsUndetectableAndBranch>(value);
   11246             :   }
   11247       35158 :   return ast_context()->ReturnControl(instr, expr->id());
   11248             : }
   11249             : 
   11250             : 
   11251           0 : void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
   11252             : 
   11253             : 
   11254           0 : void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
   11255           0 :   UNREACHABLE();
   11256             : }
   11257             : 
   11258           0 : void HOptimizedGraphBuilder::VisitGetIterator(GetIterator* expr) {
   11259           0 :   UNREACHABLE();
   11260             : }
   11261             : 
   11262           0 : void HOptimizedGraphBuilder::VisitImportCallExpression(
   11263             :     ImportCallExpression* expr) {
   11264           0 :   UNREACHABLE();
   11265             : }
   11266             : 
   11267       42161 : HValue* HOptimizedGraphBuilder::AddThisFunction() {
   11268       42161 :   return AddInstruction(BuildThisFunction());
   11269             : }
   11270             : 
   11271             : 
   11272       92876 : HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
   11273             :   // If we share optimized code between different closures, the
   11274             :   // this-function is not a constant, except inside an inlined body.
   11275       92876 :   if (function_state()->outer() != NULL) {
   11276             :       return New<HConstant>(
   11277       48562 :           function_state()->compilation_info()->closure());
   11278             :   } else {
   11279       44314 :       return New<HThisFunction>();
   11280             :   }
   11281             : }
   11282             : 
   11283             : 
   11284        7326 : HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
   11285             :     Handle<JSObject> boilerplate_object,
   11286             :     AllocationSiteUsageContext* site_context) {
   11287       60566 :   NoObservableSideEffectsScope no_effects(this);
   11288             :   Handle<Map> initial_map(boilerplate_object->map());
   11289             :   InstanceType instance_type = initial_map->instance_type();
   11290             :   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
   11291             : 
   11292             :   HType type = instance_type == JS_ARRAY_TYPE
   11293        7326 :       ? HType::JSArray() : HType::JSObject();
   11294        7326 :   HValue* object_size_constant = Add<HConstant>(initial_map->instance_size());
   11295             : 
   11296             :   PretenureFlag pretenure_flag = NOT_TENURED;
   11297             :   Handle<AllocationSite> top_site(*site_context->top(), isolate());
   11298        7326 :   if (FLAG_allocation_site_pretenuring) {
   11299        7326 :     pretenure_flag = top_site->GetPretenureMode();
   11300             :   }
   11301             : 
   11302             :   Handle<AllocationSite> current_site(*site_context->current(), isolate());
   11303        7326 :   if (*top_site == *current_site) {
   11304             :     // We install a dependency for pretenuring only on the outermost literal.
   11305        6664 :     top_info()->dependencies()->AssumeTenuringDecision(top_site);
   11306             :   }
   11307        7326 :   top_info()->dependencies()->AssumeTransitionStable(current_site);
   11308             : 
   11309             :   HInstruction* object =
   11310             :       Add<HAllocate>(object_size_constant, type, pretenure_flag, instance_type,
   11311        7326 :                      graph()->GetConstant0(), top_site);
   11312             : 
   11313             :   // If allocation folding reaches kMaxRegularHeapObjectSize the
   11314             :   // elements array may not get folded into the object. Hence, we set the
   11315             :   // elements pointer to empty fixed array and let store elimination remove
   11316             :   // this store in the folding case.
   11317             :   HConstant* empty_fixed_array = Add<HConstant>(
   11318        7326 :       isolate()->factory()->empty_fixed_array());
   11319             :   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11320        7326 :       empty_fixed_array);
   11321             : 
   11322        7326 :   BuildEmitObjectHeader(boilerplate_object, object);
   11323             : 
   11324             :   // Similarly to the elements pointer, there is no guarantee that all
   11325             :   // property allocations can get folded, so pre-initialize all in-object
   11326             :   // properties to a safe value.
   11327        7326 :   BuildInitializeInobjectProperties(object, initial_map);
   11328             : 
   11329             :   // Copy in-object properties.
   11330       11577 :   if (initial_map->NumberOfFields() != 0 ||
   11331             :       initial_map->unused_property_fields() > 0) {
   11332             :     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
   11333        3941 :                                 pretenure_flag);
   11334             :   }
   11335             : 
   11336             :   // Copy elements.
   11337             :   Handle<FixedArrayBase> elements(boilerplate_object->elements());
   11338        2589 :   int elements_size = (elements->length() > 0 &&
   11339        2589 :       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
   11340        9153 :           elements->Size() : 0;
   11341             : 
   11342        7357 :   if (pretenure_flag == TENURED &&
   11343        7357 :       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
   11344             :       isolate()->heap()->InNewSpace(*elements)) {
   11345             :     // If we would like to pretenure a fixed cow array, we must ensure that the
   11346             :     // array is already in old space, otherwise we'll create too many old-to-
   11347             :     // new-space pointers (overflowing the store buffer).
   11348             :     elements = Handle<FixedArrayBase>(
   11349             :         isolate()->factory()->CopyAndTenureFixedCOWArray(
   11350           0 :             Handle<FixedArray>::cast(elements)));
   11351           0 :     boilerplate_object->set_elements(*elements);
   11352             :   }
   11353             : 
   11354             :   HInstruction* object_elements = NULL;
   11355        7326 :   if (elements_size > 0) {
   11356        1827 :     HValue* object_elements_size = Add<HConstant>(elements_size);
   11357        1827 :     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
   11358        1827 :         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
   11359             :     object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
   11360             :                                      pretenure_flag, instance_type,
   11361        1827 :                                      graph()->GetConstant0(), top_site);
   11362             :     BuildEmitElements(boilerplate_object, elements, object_elements,
   11363        1827 :                       site_context);
   11364             :     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11365        1827 :                           object_elements);
   11366             :   } else {
   11367             :     Handle<Object> elements_field =
   11368             :         Handle<Object>(boilerplate_object->elements(), isolate());
   11369        5499 :     HInstruction* object_elements_cow = Add<HConstant>(elements_field);
   11370             :     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11371        5499 :                           object_elements_cow);
   11372             :   }
   11373             : 
   11374        7326 :   return object;
   11375             : }
   11376             : 
   11377             : 
   11378        7326 : void HOptimizedGraphBuilder::BuildEmitObjectHeader(
   11379             :     Handle<JSObject> boilerplate_object,
   11380             :     HInstruction* object) {
   11381             :   DCHECK(boilerplate_object->properties()->length() == 0);
   11382             : 
   11383             :   Handle<Map> boilerplate_object_map(boilerplate_object->map());
   11384       10711 :   AddStoreMapConstant(object, boilerplate_object_map);
   11385             : 
   11386             :   Handle<Object> properties_field =
   11387             :       Handle<Object>(boilerplate_object->properties(), isolate());
   11388             :   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
   11389        7326 :   HInstruction* properties = Add<HConstant>(properties_field);
   11390        7326 :   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
   11391        7326 :   Add<HStoreNamedField>(object, access, properties);
   11392             : 
   11393        7326 :   if (boilerplate_object->IsJSArray()) {
   11394             :     Handle<JSArray> boilerplate_array =
   11395             :         Handle<JSArray>::cast(boilerplate_object);
   11396             :     Handle<Object> length_field =
   11397             :         Handle<Object>(boilerplate_array->length(), isolate());
   11398        3385 :     HInstruction* length = Add<HConstant>(length_field);
   11399             : 
   11400             :     DCHECK(boilerplate_array->length()->IsSmi());
   11401             :     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
   11402        3385 :         boilerplate_array->GetElementsKind()), length);
   11403             :   }
   11404        7326 : }
   11405             : 
   11406             : 
   11407        3941 : void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
   11408             :     Handle<JSObject> boilerplate_object,
   11409             :     HInstruction* object,
   11410             :     AllocationSiteUsageContext* site_context,
   11411             :     PretenureFlag pretenure_flag) {
   11412             :   Handle<Map> boilerplate_map(boilerplate_object->map());
   11413             :   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
   11414             :   int limit = boilerplate_map->NumberOfOwnDescriptors();
   11415             : 
   11416             :   int copied_fields = 0;
   11417       11399 :   for (int i = 0; i < limit; i++) {
   11418        7458 :     PropertyDetails details = descriptors->GetDetails(i);
   11419        7537 :     if (details.location() != kField) continue;
   11420             :     DCHECK_EQ(kData, details.kind());
   11421        7458 :     copied_fields++;
   11422        7458 :     FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);
   11423             : 
   11424             : 
   11425             :     int property_offset = field_index.offset();
   11426             :     Handle<Name> name(descriptors->GetKey(i));
   11427             : 
   11428             :     // The access for the store depends on the type of the boilerplate.
   11429             :     HObjectAccess access = boilerplate_object->IsJSArray() ?
   11430             :         HObjectAccess::ForJSArrayOffset(property_offset) :
   11431        7458 :         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11432             : 
   11433        7458 :     if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
   11434          79 :       CHECK(!boilerplate_object->IsJSArray());
   11435             :       double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
   11436          79 :       access = access.WithRepresentation(Representation::Double());
   11437        9496 :       Add<HStoreNamedField>(object, access, Add<HConstant>(value));
   11438          79 :       continue;
   11439             :     }
   11440             :     Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
   11441        7379 :                          isolate());
   11442             : 
   11443        7379 :     if (value->IsJSObject()) {
   11444         349 :       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11445         349 :       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11446             :       HInstruction* result =
   11447         349 :           BuildFastLiteral(value_object, site_context);
   11448             :       site_context->ExitScope(current_site, value_object);
   11449         349 :       Add<HStoreNamedField>(object, access, result);
   11450             :     } else {
   11451             :       Representation representation = details.representation();
   11452             :       HInstruction* value_instruction;
   11453             : 
   11454        7030 :       if (representation.IsDouble()) {
   11455             :         // Allocate a HeapNumber box and store the value into it.
   11456           0 :         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
   11457             :         HInstruction* double_box = Add<HAllocate>(
   11458             :             heap_number_constant, HType::HeapObject(), pretenure_flag,
   11459           0 :             MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
   11460             :         AddStoreMapConstant(double_box,
   11461           0 :             isolate()->factory()->mutable_heap_number_map());
   11462             :         // Unwrap the mutable heap number from the boilerplate.
   11463             :         HValue* double_value =
   11464           0 :             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
   11465             :         Add<HStoreNamedField>(
   11466           0 :             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
   11467             :         value_instruction = double_box;
   11468        7030 :       } else if (representation.IsSmi()) {
   11469             :         value_instruction = value->IsUninitialized(isolate())
   11470             :                                 ? graph()->GetConstant0()
   11471        3167 :                                 : Add<HConstant>(value);
   11472             :         // Ensure that value is stored as smi.
   11473        2881 :         access = access.WithRepresentation(representation);
   11474             :       } else {
   11475        4149 :         value_instruction = Add<HConstant>(value);
   11476             :       }
   11477             : 
   11478        7030 :       Add<HStoreNamedField>(object, access, value_instruction);
   11479             :     }
   11480             :   }
   11481             : 
   11482             :   int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
   11483             :   HInstruction* value_instruction =
   11484        3941 :       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
   11485        7416 :   for (int i = copied_fields; i < inobject_properties; i++) {
   11486             :     DCHECK(boilerplate_object->IsJSObject());
   11487        3475 :     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
   11488             :     HObjectAccess access =
   11489        3475 :         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11490        3475 :     Add<HStoreNamedField>(object, access, value_instruction);
   11491             :   }
   11492        3941 : }
   11493             : 
   11494             : 
   11495        1827 : void HOptimizedGraphBuilder::BuildEmitElements(
   11496             :     Handle<JSObject> boilerplate_object,
   11497             :     Handle<FixedArrayBase> elements,
   11498             :     HValue* object_elements,
   11499             :     AllocationSiteUsageContext* site_context) {
   11500             :   ElementsKind kind = boilerplate_object->map()->elements_kind();
   11501             :   int elements_length = elements->length();
   11502        1827 :   HValue* object_elements_length = Add<HConstant>(elements_length);
   11503        1827 :   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
   11504             : 
   11505             :   // Copy elements backing store content.
   11506        1827 :   if (elements->IsFixedDoubleArray()) {
   11507         431 :     BuildEmitFixedDoubleArray(elements, kind, object_elements);
   11508        1396 :   } else if (elements->IsFixedArray()) {
   11509             :     BuildEmitFixedArray(elements, kind, object_elements,
   11510        1396 :                         site_context);
   11511             :   } else {
   11512           0 :     UNREACHABLE();
   11513             :   }
   11514        1827 : }
   11515             : 
   11516             : 
   11517         431 : void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
   11518             :     Handle<FixedArrayBase> elements,
   11519             :     ElementsKind kind,
   11520             :     HValue* object_elements) {
   11521         431 :   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11522             :   int elements_length = elements->length();
   11523        6237 :   for (int i = 0; i < elements_length; i++) {
   11524        5806 :     HValue* key_constant = Add<HConstant>(i);
   11525             :     HInstruction* value_instruction =
   11526             :         Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   11527        5806 :                         kind, ALLOW_RETURN_HOLE);
   11528             :     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
   11529        5806 :                                            value_instruction, nullptr, kind);
   11530             :     store->SetFlag(HValue::kTruncatingToNumber);
   11531             :   }
   11532         431 : }
   11533             : 
   11534             : 
   11535        1396 : void HOptimizedGraphBuilder::BuildEmitFixedArray(
   11536             :     Handle<FixedArrayBase> elements,
   11537             :     ElementsKind kind,
   11538             :     HValue* object_elements,
   11539             :     AllocationSiteUsageContext* site_context) {
   11540        8230 :   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11541             :   int elements_length = elements->length();
   11542             :   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   11543        8230 :   for (int i = 0; i < elements_length; i++) {
   11544             :     Handle<Object> value(fast_elements->get(i), isolate());
   11545        6834 :     HValue* key_constant = Add<HConstant>(i);
   11546        6834 :     if (value->IsJSObject()) {
   11547         313 :       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11548         313 :       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11549             :       HInstruction* result =
   11550         313 :           BuildFastLiteral(value_object, site_context);
   11551             :       site_context->ExitScope(current_site, value_object);
   11552         313 :       Add<HStoreKeyed>(object_elements, key_constant, result, nullptr, kind);
   11553             :     } else {
   11554             :       ElementsKind copy_kind =
   11555        6521 :           kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
   11556             :       HInstruction* value_instruction =
   11557             :           Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   11558        6521 :                           copy_kind, ALLOW_RETURN_HOLE);
   11559             :       Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
   11560        6521 :                        nullptr, copy_kind);
   11561             :     }
   11562             :   }
   11563        1396 : }
   11564             : 
   11565             : 
   11566      101430 : void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   11567             :   DCHECK(!HasStackOverflow());
   11568             :   DCHECK(current_block() != NULL);
   11569             :   DCHECK(current_block()->HasPredecessor());
   11570       50715 :   HInstruction* instr = BuildThisFunction();
   11571      101430 :   return ast_context()->ReturnInstruction(instr, expr->id());
   11572             : }
   11573             : 
   11574             : 
   11575           0 : void HOptimizedGraphBuilder::VisitSuperPropertyReference(
   11576             :     SuperPropertyReference* expr) {
   11577             :   DCHECK(!HasStackOverflow());
   11578             :   DCHECK(current_block() != NULL);
   11579             :   DCHECK(current_block()->HasPredecessor());
   11580           0 :   return Bailout(kSuperReference);
   11581             : }
   11582             : 
   11583             : 
   11584           0 : void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
   11585             :   DCHECK(!HasStackOverflow());
   11586             :   DCHECK(current_block() != NULL);
   11587             :   DCHECK(current_block()->HasPredecessor());
   11588           0 :   return Bailout(kSuperReference);
   11589             : }
   11590             : 
   11591      379346 : void HOptimizedGraphBuilder::VisitDeclarations(
   11592             :     Declaration::List* declarations) {
   11593             :   DCHECK(globals_.is_empty());
   11594             :   AstVisitor<HOptimizedGraphBuilder>::VisitDeclarations(declarations);
   11595      933418 :   if (!globals_.is_empty()) {
   11596             :     Handle<FixedArray> array =
   11597       37272 :        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
   11598     1108144 :     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
   11599       12424 :     int flags = current_info()->GetDeclareGlobalsFlags();
   11600             :     Handle<FeedbackVector> vector(current_feedback_vector(), isolate());
   11601       12424 :     Add<HDeclareGlobals>(array, flags, vector);
   11602             :     globals_.Rewind(0);
   11603             :   }
   11604      379346 : }
   11605             : 
   11606             : 
   11607      436396 : void HOptimizedGraphBuilder::VisitVariableDeclaration(
   11608             :     VariableDeclaration* declaration) {
   11609      436396 :   VariableProxy* proxy = declaration->proxy();
   11610      571972 :   Variable* variable = proxy->var();
   11611      436396 :   switch (variable->location()) {
   11612             :     case VariableLocation::UNALLOCATED: {
   11613             :       DCHECK(!variable->binding_needs_init());
   11614      808146 :       globals_.Add(variable->name(), zone());
   11615             :       FeedbackSlot slot = proxy->VariableFeedbackSlot();
   11616             :       DCHECK(!slot.IsInvalid());
   11617      108099 :       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11618      108099 :       globals_.Add(isolate()->factory()->undefined_value(), zone());
   11619      108099 :       globals_.Add(isolate()->factory()->undefined_value(), zone());
   11620             :       return;
   11621             :     }
   11622             :     case VariableLocation::PARAMETER:
   11623             :     case VariableLocation::LOCAL:
   11624      293155 :       if (variable->binding_needs_init()) {
   11625       23976 :         HValue* value = graph()->GetConstantHole();
   11626       23976 :         environment()->Bind(variable, value);
   11627             :       }
   11628             :       break;
   11629             :     case VariableLocation::CONTEXT:
   11630       35142 :       if (variable->binding_needs_init()) {
   11631       27477 :         HValue* value = graph()->GetConstantHole();
   11632             :         HValue* context = environment()->context();
   11633             :         HStoreContextSlot* store = Add<HStoreContextSlot>(
   11634       27477 :             context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11635       27477 :         if (store->HasObservableSideEffects()) {
   11636       27477 :           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11637             :         }
   11638             :       }
   11639             :       break;
   11640             :     case VariableLocation::LOOKUP:
   11641             :       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11642             :     case VariableLocation::MODULE:
   11643           0 :       UNREACHABLE();
   11644             :   }
   11645             : }
   11646             : 
   11647             : 
   11648       34388 : void HOptimizedGraphBuilder::VisitFunctionDeclaration(
   11649       68776 :     FunctionDeclaration* declaration) {
   11650       34388 :   VariableProxy* proxy = declaration->proxy();
   11651       64367 :   Variable* variable = proxy->var();
   11652       34388 :   switch (variable->location()) {
   11653             :     case VariableLocation::UNALLOCATED: {
   11654      198266 :       globals_.Add(variable->name(), zone());
   11655             :       FeedbackSlot slot = proxy->VariableFeedbackSlot();
   11656             :       DCHECK(!slot.IsInvalid());
   11657       27313 :       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11658             : 
   11659             :       // We need the slot where the literals array lives, too.
   11660             :       slot = declaration->fun()->LiteralFeedbackSlot();
   11661             :       DCHECK(!slot.IsInvalid());
   11662       27313 :       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11663             : 
   11664             :       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
   11665       54626 :           declaration->fun(), current_info()->script(), top_info());
   11666             :       // Check for stack-overflow exception.
   11667       27313 :       if (function.is_null()) return SetStackOverflow();
   11668       27313 :       globals_.Add(function, zone());
   11669       27313 :       return;
   11670             :     }
   11671             :     case VariableLocation::PARAMETER:
   11672             :     case VariableLocation::LOCAL: {
   11673       13227 :       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11674             :       HValue* value = Pop();
   11675        4409 :       BindIfLive(variable, value);
   11676        4409 :       break;
   11677             :     }
   11678             :     case VariableLocation::CONTEXT: {
   11679        7998 :       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11680             :       HValue* value = Pop();
   11681             :       HValue* context = environment()->context();
   11682             :       HStoreContextSlot* store = Add<HStoreContextSlot>(
   11683        2666 :           context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11684        2666 :       if (store->HasObservableSideEffects()) {
   11685        2666 :         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11686             :       }
   11687             :       break;
   11688             :     }
   11689             :     case VariableLocation::LOOKUP:
   11690             :       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11691             :     case VariableLocation::MODULE:
   11692           0 :       UNREACHABLE();
   11693             :   }
   11694             : }
   11695             : 
   11696             : 
   11697           8 : void HOptimizedGraphBuilder::VisitRewritableExpression(
   11698           8 :     RewritableExpression* node) {
   11699           8 :   CHECK_ALIVE(Visit(node->expression()));
   11700             : }
   11701             : 
   11702             : 
   11703             : // Generators for inline runtime functions.
   11704             : // Support for types.
   11705        4872 : void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
   11706             :   DCHECK(call->arguments()->length() == 1);
   11707        3248 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11708             :   HValue* value = Pop();
   11709        1624 :   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
   11710        3248 :   return ast_context()->ReturnControl(result, call->id());
   11711             : }
   11712             : 
   11713             : 
   11714        2757 : void HOptimizedGraphBuilder::GenerateIsJSReceiver(CallRuntime* call) {
   11715             :   DCHECK(call->arguments()->length() == 1);
   11716        1838 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11717             :   HValue* value = Pop();
   11718             :   HHasInstanceTypeAndBranch* result =
   11719             :       New<HHasInstanceTypeAndBranch>(value,
   11720             :                                      FIRST_JS_RECEIVER_TYPE,
   11721         919 :                                      LAST_JS_RECEIVER_TYPE);
   11722        1838 :   return ast_context()->ReturnControl(result, call->id());
   11723             : }
   11724             : 
   11725        2346 : void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
   11726             :   DCHECK(call->arguments()->length() == 1);
   11727        1564 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11728             :   HValue* value = Pop();
   11729             :   HHasInstanceTypeAndBranch* result =
   11730         782 :       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
   11731        1564 :   return ast_context()->ReturnControl(result, call->id());
   11732             : }
   11733             : 
   11734             : 
   11735         156 : void HOptimizedGraphBuilder::GenerateIsTypedArray(CallRuntime* call) {
   11736             :   DCHECK(call->arguments()->length() == 1);
   11737         104 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11738             :   HValue* value = Pop();
   11739             :   HHasInstanceTypeAndBranch* result =
   11740          52 :       New<HHasInstanceTypeAndBranch>(value, JS_TYPED_ARRAY_TYPE);
   11741         104 :   return ast_context()->ReturnControl(result, call->id());
   11742             : }
   11743             : 
   11744             : 
   11745         933 : void HOptimizedGraphBuilder::GenerateToInteger(CallRuntime* call) {
   11746             :   DCHECK_EQ(1, call->arguments()->length());
   11747         933 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11748             :   HValue* input = Pop();
   11749         311 :   if (input->type().IsSmi()) {
   11750           0 :     return ast_context()->ReturnValue(input);
   11751             :   } else {
   11752         311 :     Callable callable = CodeFactory::ToInteger(isolate());
   11753         311 :     HValue* stub = Add<HConstant>(callable.code());
   11754         311 :     HValue* values[] = {input};
   11755             :     HInstruction* result = New<HCallWithDescriptor>(
   11756         311 :         stub, 0, callable.descriptor(), ArrayVector(values));
   11757         622 :     return ast_context()->ReturnInstruction(result, call->id());
   11758             :   }
   11759             : }
   11760             : 
   11761             : 
   11762        1143 : void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
   11763             :   DCHECK_EQ(1, call->arguments()->length());
   11764         762 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11765             :   HValue* value = Pop();
   11766         381 :   HValue* result = BuildToObject(value);
   11767         381 :   return ast_context()->ReturnValue(result);
   11768             : }
   11769             : 
   11770             : 
   11771        6411 : void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
   11772             :   DCHECK_EQ(1, call->arguments()->length());
   11773        6358 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11774             :   HValue* input = Pop();
   11775        2137 :   if (input->type().IsString()) {
   11776          53 :     return ast_context()->ReturnValue(input);
   11777             :   } else {
   11778        2084 :     Callable callable = CodeFactory::ToString(isolate());
   11779        2084 :     HValue* stub = Add<HConstant>(callable.code());
   11780        2084 :     HValue* values[] = {input};
   11781             :     HInstruction* result = New<HCallWithDescriptor>(
   11782        2084 :         stub, 0, callable.descriptor(), ArrayVector(values));
   11783        4168 :     return ast_context()->ReturnInstruction(result, call->id());
   11784             :   }
   11785             : }
   11786             : 
   11787             : 
   11788        1032 : void HOptimizedGraphBuilder::GenerateToLength(CallRuntime* call) {
   11789             :   DCHECK_EQ(1, call->arguments()->length());
   11790         688 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11791         344 :   Callable callable = CodeFactory::ToLength(isolate());
   11792             :   HValue* input = Pop();
   11793         344 :   HValue* stub = Add<HConstant>(callable.code());
   11794         344 :   HValue* values[] = {input};
   11795             :   HInstruction* result = New<HCallWithDescriptor>(
   11796         344 :       stub, 0, callable.descriptor(), ArrayVector(values));
   11797         688 :   return ast_context()->ReturnInstruction(result, call->id());
   11798             : }
   11799             : 
   11800             : 
   11801         420 : void HOptimizedGraphBuilder::GenerateToNumber(CallRuntime* call) {
   11802             :   DCHECK_EQ(1, call->arguments()->length());
   11803         168 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11804          84 :   Callable callable = CodeFactory::ToNumber(isolate());
   11805             :   HValue* input = Pop();
   11806          84 :   HValue* result = BuildToNumber(input);
   11807          84 :   if (result->HasObservableSideEffects()) {
   11808          84 :     if (!ast_context()->IsEffect()) Push(result);
   11809          84 :     Add<HSimulate>(call->id(), REMOVABLE_SIMULATE);
   11810          84 :     if (!ast_context()->IsEffect()) result = Pop();
   11811             :   }
   11812          84 :   return ast_context()->ReturnValue(result);
   11813             : }
   11814             : 
   11815             : 
   11816        2529 : void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
   11817             :   DCHECK(call->arguments()->length() == 1);
   11818        1686 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11819             :   HValue* value = Pop();
   11820             :   HIfContinuation continuation;
   11821         843 :   IfBuilder if_proxy(this);
   11822             : 
   11823             :   HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
   11824         843 :   if_proxy.And();
   11825         843 :   HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
   11826             :   HValue* instance_type =
   11827         843 :       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   11828             :   if_proxy.If<HCompareNumericAndBranch>(
   11829         843 :       instance_type, Add<HConstant>(JS_PROXY_TYPE), Token::EQ);
   11830             : 
   11831         843 :   if_proxy.CaptureContinuation(&continuation);
   11832        1686 :   return ast_context()->ReturnContinuation(&continuation, call->id());
   11833             : }
   11834             : 
   11835             : 
   11836          30 : void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
   11837             :   DCHECK(call->arguments()->length() == 1);
   11838          40 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11839             :   HValue* object = Pop();
   11840             :   HIfContinuation continuation(graph()->CreateBasicBlock(),
   11841          20 :                                graph()->CreateBasicBlock());
   11842          10 :   IfBuilder if_not_smi(this);
   11843             :   if_not_smi.IfNot<HIsSmiAndBranch>(object);
   11844          10 :   if_not_smi.Then();
   11845             :   {
   11846             :     NoObservableSideEffectsScope no_effects(this);
   11847             : 
   11848             :     IfBuilder if_fast_packed(this);
   11849          10 :     HValue* elements_kind = BuildGetElementsKind(object);
   11850             :     if_fast_packed.If<HCompareNumericAndBranch>(
   11851          10 :         elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
   11852          10 :     if_fast_packed.Or();
   11853             :     if_fast_packed.If<HCompareNumericAndBranch>(
   11854          10 :         elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
   11855          10 :     if_fast_packed.Or();
   11856             :     if_fast_packed.If<HCompareNumericAndBranch>(
   11857          10 :         elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
   11858          10 :     if_fast_packed.JoinContinuation(&continuation);
   11859             :   }
   11860          10 :   if_not_smi.JoinContinuation(&continuation);
   11861          20 :   return ast_context()->ReturnContinuation(&continuation, call->id());
   11862             : }
   11863             : 
   11864             : 
   11865             : // Fast support for charCodeAt(n).
   11866         600 : void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   11867             :   DCHECK(call->arguments()->length() == 2);
   11868         360 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11869         360 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11870             :   HValue* index = Pop();
   11871             :   HValue* string = Pop();
   11872         120 :   HInstruction* result = BuildStringCharCodeAt(string, index);
   11873         240 :   return ast_context()->ReturnInstruction(result, call->id());
   11874             : }
   11875             : 
   11876             : 
   11877             : // Fast support for SubString.
   11878         414 : void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   11879             :   DCHECK_EQ(3, call->arguments()->length());
   11880         276 :   CHECK_ALIVE(VisitExpressions(call->arguments()));
   11881         138 :   Callable callable = CodeFactory::SubString(isolate());
   11882         138 :   HValue* stub = Add<HConstant>(callable.code());
   11883             :   HValue* to = Pop();
   11884             :   HValue* from = Pop();
   11885             :   HValue* string = Pop();
   11886         138 :   HValue* values[] = {string, from, to};
   11887             :   HInstruction* result = New<HCallWithDescriptor>(
   11888         138 :       stub, 0, callable.descriptor(), ArrayVector(values));
   11889             :   result->set_type(HType::String());
   11890         276 :   return ast_context()->ReturnInstruction(result, call->id());
   11891             : }
   11892             : 
   11893             : 
   11894             : // Fast support for calls.
   11895       35232 : void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
   11896             :   DCHECK_LE(2, call->arguments()->length());
   11897       17616 :   CHECK_ALIVE(VisitExpressions(call->arguments()));
   11898        5872 :   CallTrampolineDescriptor descriptor(isolate());
   11899        5872 :   PushArgumentsFromEnvironment(call->arguments()->length() - 1);
   11900        5872 :   HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
   11901             :   HValue* target = Pop();
   11902       11744 :   HValue* values[] = {target, Add<HConstant>(call->arguments()->length() - 2)};
   11903             :   HInstruction* result =
   11904        5872 :       New<HCallWithDescriptor>(trampoline, call->arguments()->length() - 1,
   11905       11744 :                                descriptor, ArrayVector(values));
   11906       11744 :   return ast_context()->ReturnInstruction(result, call->id());
   11907             : }
   11908             : 
   11909             : 
   11910       39540 : void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
   11911             :   DCHECK(call->arguments()->length() == 2);
   11912       23724 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11913       23724 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11914             :   HValue* index = Pop();
   11915             :   HValue* object = Pop();
   11916             :   HInstruction* result = New<HLoadKeyed>(
   11917        7908 :       object, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
   11918       15816 :   return ast_context()->ReturnInstruction(result, call->id());
   11919             : }
   11920             : 
   11921             : 
   11922       20153 : void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
   11923             :   DCHECK(call->arguments()->length() == 3);
   11924       14395 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11925        8637 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11926        8637 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   11927             :   HValue* value = Pop();
   11928             :   HValue* index = Pop();
   11929             :   HValue* object = Pop();
   11930        2879 :   NoObservableSideEffectsScope no_effects(this);
   11931        2879 :   Add<HStoreKeyed>(object, index, value, nullptr, FAST_HOLEY_ELEMENTS);
   11932        5758 :   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   11933             : }
   11934             : 
   11935             : 
   11936         419 : void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
   11937             :   DCHECK(call->arguments()->length() == 0);
   11938         419 :   return ast_context()->ReturnValue(graph()->GetConstantHole());
   11939             : }
   11940             : 
   11941             : 
   11942          45 : void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
   11943             :   DCHECK_EQ(2, call->arguments()->length());
   11944          27 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11945          27 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11946             :   HValue* done = Pop();
   11947             :   HValue* value = Pop();
   11948           9 :   HValue* result = BuildCreateIterResultObject(value, done);
   11949           9 :   return ast_context()->ReturnValue(result);
   11950             : }
   11951             : 
   11952             : 
   11953        4638 : void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
   11954             :   DCHECK(call->arguments()->length() == 1);
   11955        3092 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11956             :   HValue* receiver = Pop();
   11957             :   HInstruction* result = New<HLoadNamedField>(
   11958        1546 :       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   11959        3092 :   return ast_context()->ReturnInstruction(result, call->id());
   11960             : }
   11961             : 
   11962             : 
   11963        2469 : void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) {
   11964             :   DCHECK(call->arguments()->length() == 1);
   11965        1646 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11966             :   HValue* object = Pop();
   11967             :   HInstruction* result = New<HLoadNamedField>(
   11968         823 :       object, nullptr, HObjectAccess::ForStringHashField());
   11969        1646 :   return ast_context()->ReturnInstruction(result, call->id());
   11970             : }
   11971             : 
   11972             : 
   11973             : template <typename CollectionType>
   11974           3 : HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
   11975             :   static const int kCapacity = CollectionType::kMinCapacity;
   11976             :   static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
   11977             :   static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
   11978             :                                        kBucketCount +
   11979             :                                        (kCapacity * CollectionType::kEntrySize);
   11980             :   static const int kSizeInBytes =
   11981             :       FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);
   11982             : 
   11983             :   // Allocate the table and add the proper map.
   11984             :   HValue* table =
   11985             :       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
   11986          15 :                      NOT_TENURED, FIXED_ARRAY_TYPE, graph()->GetConstant0());
   11987           3 :   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
   11988             : 
   11989             :   // Initialize the FixedArray...
   11990           3 :   HValue* length = Add<HConstant>(kFixedArrayLength);
   11991           3 :   Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);
   11992             : 
   11993             :   // ...and the OrderedHashTable fields.
   11994           3 :   Add<HStoreNamedField>(
   11995             :       table,
   11996             :       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
   11997             :       Add<HConstant>(kBucketCount));
   11998           3 :   Add<HStoreNamedField>(
   11999             :       table,
   12000             :       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
   12001             :       graph()->GetConstant0());
   12002           3 :   Add<HStoreNamedField>(
   12003             :       table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12004             :                  CollectionType>(),
   12005             :       graph()->GetConstant0());
   12006             : 
   12007             :   // Fill the buckets with kNotFound.
   12008           3 :   HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
   12009           9 :   for (int i = 0; i < kBucketCount; ++i) {
   12010           6 :     Add<HStoreNamedField>(
   12011             :         table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
   12012             :         not_found);
   12013             :   }
   12014             : 
   12015             :   // Fill the data table with undefined.
   12016           3 :   HValue* undefined = graph()->GetConstantUndefined();
   12017          31 :   for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
   12018          28 :     Add<HStoreNamedField>(table,
   12019             :                           HObjectAccess::ForOrderedHashTableDataTableIndex<
   12020             :                               CollectionType, kBucketCount>(i),
   12021             :                           undefined);
   12022             :   }
   12023             : 
   12024           3 :   return table;
   12025             : }
   12026             : 
   12027             : 
   12028           0 : void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
   12029             :   DCHECK(call->arguments()->length() == 1);
   12030           0 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12031             :   HValue* receiver = Pop();
   12032             : 
   12033           0 :   NoObservableSideEffectsScope no_effects(this);
   12034           0 :   HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
   12035           0 :   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12036           0 :   return ast_context()->ReturnValue(receiver);
   12037             : }
   12038             : 
   12039             : 
   12040           0 : void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
   12041             :   DCHECK(call->arguments()->length() == 1);
   12042           0 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12043             :   HValue* receiver = Pop();
   12044             : 
   12045           0 :   NoObservableSideEffectsScope no_effects(this);
   12046           0 :   HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
   12047           0 :   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12048           0 :   return ast_context()->ReturnValue(receiver);
   12049             : }
   12050             : 
   12051             : 
   12052             : template <typename CollectionType>
   12053           3 : void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
   12054             :   HValue* old_table = Add<HLoadNamedField>(
   12055           3 :       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   12056           3 :   HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
   12057           3 :   Add<HStoreNamedField>(
   12058             :       old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
   12059             :       new_table);
   12060           3 :   Add<HStoreNamedField>(
   12061             :       old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12062             :                      CollectionType>(),
   12063             :       Add<HConstant>(CollectionType::kClearedTableSentinel));
   12064           3 :   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
   12065           3 :                         new_table);
   12066           3 : }
   12067             : 
   12068             : 
   12069           6 : void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
   12070             :   DCHECK(call->arguments()->length() == 1);
   12071           6 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12072             :   HValue* receiver = Pop();
   12073             : 
   12074           2 :   NoObservableSideEffectsScope no_effects(this);
   12075           2 :   BuildOrderedHashTableClear<OrderedHashSet>(receiver);
   12076           4 :   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12077             : }
   12078             : 
   12079             : 
   12080           3 : void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
   12081             :   DCHECK(call->arguments()->length() == 1);
   12082           3 :   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12083             :   HValue* receiver = Pop();
   12084             : 
   12085           1 :   NoObservableSideEffectsScope no_effects(this);
   12086           1 :   BuildOrderedHashTableClear<OrderedHashMap>(receiver);
   12087           2 :   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12088             : }
   12089             : 
   12090           0 : void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
   12091           0 :     CallRuntime* call) {
   12092           0 :   Add<HDebugBreak>();
   12093           0 :   return ast_context()->ReturnValue(graph()->GetConstant0());
   12094             : }
   12095             : 
   12096             : 
   12097           0 : void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
   12098             :   DCHECK(call->arguments()->length() == 0);
   12099             :   HValue* ref =
   12100           0 :       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
   12101             :   HValue* value =
   12102           0 :       Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
   12103           0 :   return ast_context()->ReturnValue(value);
   12104             : }
   12105             : 
   12106             : #undef CHECK_BAILOUT
   12107             : #undef CHECK_ALIVE
   12108             : 
   12109             : 
   12110      477600 : HEnvironment::HEnvironment(HEnvironment* outer,
   12111             :                            Scope* scope,
   12112             :                            Handle<JSFunction> closure,
   12113             :                            Zone* zone)
   12114             :     : closure_(closure),
   12115             :       values_(0, zone),
   12116             :       frame_type_(JS_FUNCTION),
   12117             :       parameter_count_(0),
   12118             :       specials_count_(1),
   12119             :       local_count_(0),
   12120             :       outer_(outer),
   12121             :       entry_(NULL),
   12122             :       pop_count_(0),
   12123             :       push_count_(0),
   12124             :       ast_id_(BailoutId::None()),
   12125      955199 :       zone_(zone) {
   12126      477599 :   DeclarationScope* declaration_scope = scope->GetDeclarationScope();
   12127             :   Initialize(declaration_scope->num_parameters() + 1,
   12128      955198 :              declaration_scope->num_stack_slots(), 0);
   12129      477598 : }
   12130             : 
   12131             : 
   12132       23483 : HEnvironment::HEnvironment(Zone* zone, int parameter_count)
   12133             :     : values_(0, zone),
   12134             :       frame_type_(STUB),
   12135             :       parameter_count_(parameter_count),
   12136             :       specials_count_(1),
   12137             :       local_count_(0),
   12138             :       outer_(NULL),
   12139             :       entry_(NULL),
   12140             :       pop_count_(0),
   12141             :       push_count_(0),
   12142             :       ast_id_(BailoutId::None()),
   12143       46966 :       zone_(zone) {
   12144       23483 :   Initialize(parameter_count, 0, 0);
   12145       23483 : }
   12146             : 
   12147             : 
   12148    13882160 : HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
   12149             :     : values_(0, zone),
   12150             :       frame_type_(JS_FUNCTION),
   12151             :       parameter_count_(0),
   12152             :       specials_count_(0),
   12153             :       local_count_(0),
   12154             :       outer_(NULL),
   12155             :       entry_(NULL),
   12156             :       pop_count_(0),
   12157             :       push_count_(0),
   12158             :       ast_id_(other->ast_id()),
   12159    27764159 :       zone_(zone) {
   12160    13881999 :   Initialize(other);
   12161    13882355 : }
   12162             : 
   12163             : 
   12164           0 : HEnvironment::HEnvironment(HEnvironment* outer,
   12165             :                            Handle<JSFunction> closure,
   12166             :                            FrameType frame_type,
   12167             :                            int arguments,
   12168             :                            Zone* zone)
   12169             :     : closure_(closure),
   12170             :       values_(arguments, zone),
   12171             :       frame_type_(frame_type),
   12172             :       parameter_count_(arguments),
   12173             :       specials_count_(0),
   12174             :       local_count_(0),
   12175             :       outer_(outer),
   12176             :       entry_(NULL),
   12177             :       pop_count_(0),
   12178             :       push_count_(0),
   12179             :       ast_id_(BailoutId::None()),
   12180      152140 :       zone_(zone) {
   12181           0 : }
   12182             : 
   12183             : 
   12184      501082 : void HEnvironment::Initialize(int parameter_count,
   12185             :                               int local_count,
   12186     2765208 :                               int stack_height) {
   12187      501082 :   parameter_count_ = parameter_count;
   12188      501082 :   local_count_ = local_count;
   12189             : 
   12190             :   // Avoid reallocating the temporaries' backing store on the first Push.
   12191      501082 :   int total = parameter_count + specials_count_ + local_count + stack_height;
   12192      501082 :   values_.Initialize(total + 4, zone());
   12193     2765207 :   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
   12194      501081 : }
   12195             : 
   12196             : 
   12197    41646534 : void HEnvironment::Initialize(const HEnvironment* other) {
   12198    13882200 :   closure_ = other->closure();
   12199             :   values_.AddAll(other->values_, zone());
   12200    13882134 :   assigned_variables_.Union(other->assigned_variables_, zone());
   12201    13882276 :   frame_type_ = other->frame_type_;
   12202    13882276 :   parameter_count_ = other->parameter_count_;
   12203    13882276 :   local_count_ = other->local_count_;
   12204    13882276 :   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
   12205    13882287 :   entry_ = other->entry_;
   12206    13882287 :   pop_count_ = other->pop_count_;
   12207    13882287 :   push_count_ = other->push_count_;
   12208    13882287 :   specials_count_ = other->specials_count_;
   12209    13882287 :   ast_id_ = other->ast_id_;
   12210    13882287 : }
   12211             : 
   12212             : 
   12213      849230 : void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
   12214             :   DCHECK(!block->IsLoopHeader());
   12215             :   DCHECK(values_.length() == other->values_.length());
   12216             : 
   12217    13022968 :   int length = values_.length();
   12218     6705071 :   for (int i = 0; i < length; ++i) {
   12219     6807744 :     HValue* value = values_[i];
   12220    12663585 :     if (value != NULL && value->IsPhi() && value->block() == block) {
   12221             :       // There is already a phi for the i'th value.
   12222             :       HPhi* phi = HPhi::cast(value);
   12223             :       // Assert index is correct and that we haven't missed an incoming edge.
   12224             :       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
   12225             :       DCHECK(phi->OperandCount() == block->predecessors()->length());
   12226     6108973 :       phi->AddInput(other->values_[i]);
   12227    11682210 :     } else if (values_[i] != other->values_[i]) {
   12228             :       // There is a fresh value on the incoming edge, a phi is needed.
   12229             :       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
   12230      238396 :       HPhi* phi = block->AddNewPhi(i);
   12231      238396 :       HValue* old_value = values_[i];
   12232      477534 :       for (int j = 0; j < block->predecessors()->length(); j++) {
   12233      239138 :         phi->AddInput(old_value);
   12234             :       }
   12235      238396 :       phi->AddInput(other->values_[i]);
   12236      238396 :       this->values_[i] = phi;
   12237             :     }
   12238             :   }
   12239      849230 : }
   12240             : 
   12241             : 
   12242     3422921 : void HEnvironment::Bind(int index, HValue* value) {
   12243             :   DCHECK(value != NULL);
   12244     3422921 :   assigned_variables_.Add(index, zone());
   12245     6845862 :   values_[index] = value;
   12246     1459461 : }
   12247             : 
   12248             : 
   12249           0 : bool HEnvironment::HasExpressionAt(int index) const {
   12250           0 :   return index >= parameter_count_ + specials_count_ + local_count_;
   12251             : }
   12252             : 
   12253             : 
   12254           0 : bool HEnvironment::ExpressionStackIsEmpty() const {
   12255             :   DCHECK(length() >= first_expression_index());
   12256           0 :   return length() == first_expression_index();
   12257             : }
   12258             : 
   12259             : 
   12260           0 : void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
   12261           0 :   int count = index_from_top + 1;
   12262      843202 :   int index = values_.length() - count;
   12263             :   DCHECK(HasExpressionAt(index));
   12264             :   // The push count must include at least the element in question or else
   12265             :   // the new value will not be included in this environment's history.
   12266      421601 :   if (push_count_ < count) {
   12267             :     // This is the same effect as popping then re-pushing 'count' elements.
   12268      168186 :     pop_count_ += (count - push_count_);
   12269      168186 :     push_count_ = count;
   12270             :   }
   12271      421601 :   values_[index] = value;
   12272           0 : }
   12273             : 
   12274             : 
   12275        5262 : HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
   12276        5262 :   int count = index_from_top + 1;
   12277        5262 :   int index = values_.length() - count;
   12278             :   DCHECK(HasExpressionAt(index));
   12279             :   // Simulate popping 'count' elements and then
   12280             :   // pushing 'count - 1' elements back.
   12281       10524 :   pop_count_ += Max(count - push_count_, 0);
   12282       10524 :   push_count_ = Max(push_count_ - count, 0) + (count - 1);
   12283        5262 :   return values_.Remove(index);
   12284             : }
   12285             : 
   12286             : 
   12287     4726149 : void HEnvironment::Drop(int count) {
   12288    10177432 :   for (int i = 0; i < count; ++i) {
   12289     5451284 :     Pop();
   12290             :   }
   12291     4726148 : }
   12292             : 
   12293             : 
   12294           0 : void HEnvironment::Print() const {
   12295           0 :   OFStream os(stdout);
   12296           0 :   os << *this << "\n";
   12297           0 : }
   12298             : 
   12299             : 
   12300    13882165 : HEnvironment* HEnvironment::Copy() const {
   12301    13882149 :   return new(zone()) HEnvironment(this, zone());
   12302             : }
   12303             : 
   12304             : 
   12305      526865 : HEnvironment* HEnvironment::CopyWithoutHistory() const {
   12306      526865 :   HEnvironment* result = Copy();
   12307             :   result->ClearHistory();
   12308      526866 :   return result;
   12309             : }
   12310             : 
   12311             : 
   12312       61068 : HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
   12313       61068 :   HEnvironment* new_env = Copy();
   12314      971468 :   for (int i = 0; i < values_.length(); ++i) {
   12315      424666 :     HPhi* phi = loop_header->AddNewPhi(i);
   12316     1335066 :     phi->AddInput(values_[i]);
   12317      849332 :     new_env->values_[i] = phi;
   12318             :   }
   12319             :   new_env->ClearHistory();
   12320       61068 :   return new_env;
   12321             : }
   12322             : 
   12323             : 
   12324       76070 : HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
   12325             :                                                   Handle<JSFunction> target,
   12326             :                                                   FrameType frame_type,
   12327       76070 :                                                   int arguments) const {
   12328             :   HEnvironment* new_env =
   12329             :       new(zone()) HEnvironment(outer, target, frame_type,
   12330      152140 :                                arguments + 1, zone());
   12331      280424 :   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
   12332      204354 :     new_env->Push(ExpressionStackAt(arguments - i));
   12333             :   }
   12334             :   new_env->ClearHistory();
   12335       76070 :   return new_env;
   12336             : }
   12337             : 
   12338           0 : void HEnvironment::MarkAsTailCaller() {
   12339             :   DCHECK_EQ(JS_FUNCTION, frame_type());
   12340         336 :   frame_type_ = TAIL_CALLER_FUNCTION;
   12341           0 : }
   12342             : 
   12343         181 : void HEnvironment::ClearTailCallerMark() {
   12344             :   DCHECK_EQ(TAIL_CALLER_FUNCTION, frame_type());
   12345         372 :   frame_type_ = JS_FUNCTION;
   12346         181 : }
   12347             : 
   12348      214167 : HEnvironment* HEnvironment::CopyForInlining(
   12349      428334 :     Handle<JSFunction> target, int arguments, FunctionLiteral* function,
   12350             :     HConstant* undefined, InliningKind inlining_kind,
   12351      214167 :     TailCallMode syntactic_tail_call_mode) const {
   12352             :   DCHECK_EQ(JS_FUNCTION, frame_type());
   12353             : 
   12354             :   // Outer environment is a copy of this one without the arguments.
   12355             :   int arity = function->scope()->num_parameters();
   12356             : 
   12357      214167 :   HEnvironment* outer = Copy();
   12358             :   outer->Drop(arguments + 1);  // Including receiver.
   12359             :   outer->ClearHistory();
   12360             : 
   12361      214167 :   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
   12362             :     DCHECK_EQ(NORMAL_RETURN, inlining_kind);
   12363             :     outer->MarkAsTailCaller();
   12364             :   }
   12365             : 
   12366      214167 :   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
   12367             :     // Create artificial constructor stub environment.  The receiver should
   12368             :     // actually be the constructor function, but we pass the newly allocated
   12369             :     // object instead, DoComputeConstructStubFrame() relies on that.
   12370        2098 :     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
   12371      212069 :   } else if (inlining_kind == GETTER_CALL_RETURN) {
   12372             :     // We need an additional StackFrame::INTERNAL frame for restoring the
   12373             :     // correct context.
   12374        3617 :     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
   12375      208452 :   } else if (inlining_kind == SETTER_CALL_RETURN) {
   12376             :     // We need an additional StackFrame::INTERNAL frame for temporarily saving
   12377             :     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
   12378         394 :     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
   12379             :   }
   12380             : 
   12381      214167 :   if (arity != arguments) {
   12382             :     // Create artificial arguments adaptation environment.
   12383       69961 :     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
   12384             :   }
   12385             : 
   12386             :   HEnvironment* inner =
   12387      428334 :       new(zone()) HEnvironment(outer, function->scope(), target, zone());
   12388             :   // Get the argument values from the original environment.
   12389      879922 :   for (int i = 0; i <= arity; ++i) {  // Include receiver.
   12390             :     HValue* push = (i <= arguments) ?
   12391      665757 :         ExpressionStackAt(arguments - i) : undefined;
   12392             :     inner->SetValueAt(i, push);
   12393             :   }
   12394      214165 :   inner->SetValueAt(arity + 1, context());
   12395      975554 :   for (int i = arity + 2; i < inner->length(); ++i) {
   12396             :     inner->SetValueAt(i, undefined);
   12397             :   }
   12398             : 
   12399             :   inner->set_ast_id(BailoutId::FunctionEntry());
   12400      214165 :   return inner;
   12401             : }
   12402             : 
   12403             : 
   12404           0 : std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
   12405           0 :   for (int i = 0; i < env.length(); i++) {
   12406           0 :     if (i == 0) os << "parameters\n";
   12407           0 :     if (i == env.parameter_count()) os << "specials\n";
   12408           0 :     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
   12409           0 :     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
   12410           0 :       os << "expressions\n";
   12411             :     }
   12412           0 :     HValue* val = env.values()->at(i);
   12413           0 :     os << i << ": ";
   12414           0 :     if (val != NULL) {
   12415             :       os << val;
   12416             :     } else {
   12417           0 :       os << "NULL";
   12418             :     }
   12419           0 :     os << "\n";
   12420             :   }
   12421           0 :   return os << "\n";
   12422             : }
   12423             : 
   12424             : 
   12425           0 : void HTracer::TraceCompilation(CompilationInfo* info) {
   12426           0 :   Tag tag(this, "compilation");
   12427             :   std::string name;
   12428           0 :   if (info->parse_info()) {
   12429           0 :     Object* source_name = info->script()->name();
   12430           0 :     if (source_name->IsString()) {
   12431             :       String* str = String::cast(source_name);
   12432           0 :       if (str->length() > 0) {
   12433           0 :         name.append(str->ToCString().get());
   12434           0 :         name.append(":");
   12435             :       }
   12436             :     }
   12437             :   }
   12438           0 :   std::unique_ptr<char[]> method_name = info->GetDebugName();
   12439           0 :   name.append(method_name.get());
   12440           0 :   if (info->IsOptimizing()) {
   12441           0 :     PrintStringProperty("name", name.c_str());
   12442             :     PrintIndent();
   12443             :     trace_.Add("method \"%s:%d\"\n", method_name.get(),
   12444           0 :                info->optimization_id());
   12445             :   } else {
   12446           0 :     PrintStringProperty("name", name.c_str());
   12447           0 :     PrintStringProperty("method", "stub");
   12448             :   }
   12449             :   PrintLongProperty("date",
   12450           0 :                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
   12451           0 : }
   12452             : 
   12453             : 
   12454           0 : void HTracer::TraceLithium(const char* name, LChunk* chunk) {
   12455             :   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
   12456             :   AllowHandleDereference allow_deref;
   12457             :   AllowDeferredHandleDereference allow_deferred_deref;
   12458           0 :   Trace(name, chunk->graph(), chunk);
   12459           0 : }
   12460             : 
   12461             : 
   12462           0 : void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
   12463             :   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
   12464             :   AllowHandleDereference allow_deref;
   12465             :   AllowDeferredHandleDereference allow_deferred_deref;
   12466           0 :   Trace(name, graph, NULL);
   12467           0 : }
   12468             : 
   12469             : 
   12470           0 : void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
   12471           0 :   Tag tag(this, "cfg");
   12472           0 :   PrintStringProperty("name", name);
   12473             :   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
   12474           0 :   for (int i = 0; i < blocks->length(); i++) {
   12475           0 :     HBasicBlock* current = blocks->at(i);
   12476           0 :     Tag block_tag(this, "block");
   12477           0 :     PrintBlockProperty("name", current->block_id());
   12478           0 :     PrintIntProperty("from_bci", -1);
   12479           0 :     PrintIntProperty("to_bci", -1);
   12480             : 
   12481           0 :     if (!current->predecessors()->is_empty()) {
   12482             :       PrintIndent();
   12483           0 :       trace_.Add("predecessors");
   12484           0 :       for (int j = 0; j < current->predecessors()->length(); ++j) {
   12485           0 :         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
   12486             :       }
   12487           0 :       trace_.Add("\n");
   12488             :     } else {
   12489           0 :       PrintEmptyProperty("predecessors");
   12490             :     }
   12491             : 
   12492           0 :     if (current->end()->SuccessorCount() == 0) {
   12493           0 :       PrintEmptyProperty("successors");
   12494             :     } else  {
   12495             :       PrintIndent();
   12496           0 :       trace_.Add("successors");
   12497           0 :       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
   12498           0 :         trace_.Add(" \"B%d\"", it.Current()->block_id());
   12499             :       }
   12500           0 :       trace_.Add("\n");
   12501             :     }
   12502             : 
   12503           0 :     PrintEmptyProperty("xhandlers");
   12504             : 
   12505             :     {
   12506             :       PrintIndent();
   12507           0 :       trace_.Add("flags");
   12508           0 :       if (current->IsLoopSuccessorDominator()) {
   12509           0 :         trace_.Add(" \"dom-loop-succ\"");
   12510             :       }
   12511           0 :       if (current->IsUnreachable()) {
   12512           0 :         trace_.Add(" \"dead\"");
   12513             :       }
   12514           0 :       if (current->is_osr_entry()) {
   12515           0 :         trace_.Add(" \"osr\"");
   12516             :       }
   12517           0 :       trace_.Add("\n");
   12518             :     }
   12519             : 
   12520           0 :     if (current->dominator() != NULL) {
   12521           0 :       PrintBlockProperty("dominator", current->dominator()->block_id());
   12522             :     }
   12523             : 
   12524           0 :     PrintIntProperty("loop_depth", current->LoopNestingDepth());
   12525             : 
   12526           0 :     if (chunk != NULL) {
   12527             :       int first_index = current->first_instruction_index();
   12528             :       int last_index = current->last_instruction_index();
   12529             :       PrintIntProperty(
   12530             :           "first_lir_id",
   12531           0 :           LifetimePosition::FromInstructionIndex(first_index).Value());
   12532             :       PrintIntProperty(
   12533             :           "last_lir_id",
   12534           0 :           LifetimePosition::FromInstructionIndex(last_index).Value());
   12535             :     }
   12536             : 
   12537             :     {
   12538           0 :       Tag states_tag(this, "states");
   12539           0 :       Tag locals_tag(this, "locals");
   12540           0 :       int total = current->phis()->length();
   12541           0 :       PrintIntProperty("size", current->phis()->length());
   12542           0 :       PrintStringProperty("method", "None");
   12543           0 :       for (int j = 0; j < total; ++j) {
   12544           0 :         HPhi* phi = current->phis()->at(j);
   12545             :         PrintIndent();
   12546           0 :         std::ostringstream os;
   12547           0 :         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
   12548           0 :         trace_.Add(os.str().c_str());
   12549           0 :       }
   12550             :     }
   12551             : 
   12552             :     {
   12553           0 :       Tag HIR_tag(this, "HIR");
   12554           0 :       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
   12555             :         HInstruction* instruction = it.Current();
   12556           0 :         int uses = instruction->UseCount();
   12557             :         PrintIndent();
   12558           0 :         std::ostringstream os;
   12559           0 :         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
   12560           0 :         if (instruction->has_position()) {
   12561           0 :           const SourcePosition pos = instruction->position();
   12562           0 :           os << " pos:";
   12563           0 :           if (pos.isInlined()) os << "inlining(" << pos.InliningId() << "),";
   12564           0 :           os << pos.ScriptOffset();
   12565             :         }
   12566           0 :         os << " <|@\n";
   12567           0 :         trace_.Add(os.str().c_str());
   12568           0 :       }
   12569             :     }
   12570             : 
   12571             : 
   12572           0 :     if (chunk != NULL) {
   12573           0 :       Tag LIR_tag(this, "LIR");
   12574             :       int first_index = current->first_instruction_index();
   12575             :       int last_index = current->last_instruction_index();
   12576           0 :       if (first_index != -1 && last_index != -1) {
   12577             :         const ZoneList<LInstruction*>* instructions = chunk->instructions();
   12578           0 :         for (int i = first_index; i <= last_index; ++i) {
   12579           0 :           LInstruction* linstr = instructions->at(i);
   12580           0 :           if (linstr != NULL) {
   12581             :             PrintIndent();
   12582             :             trace_.Add("%d ",
   12583           0 :                        LifetimePosition::FromInstructionIndex(i).Value());
   12584           0 :             linstr->PrintTo(&trace_);
   12585           0 :             std::ostringstream os;
   12586           0 :             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
   12587           0 :             trace_.Add(os.str().c_str());
   12588             :           }
   12589             :         }
   12590           0 :       }
   12591             :     }
   12592           0 :   }
   12593           0 : }
   12594             : 
   12595             : 
   12596           0 : void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
   12597           0 :   Tag tag(this, "intervals");
   12598           0 :   PrintStringProperty("name", name);
   12599             : 
   12600           0 :   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
   12601           0 :   for (int i = 0; i < fixed_d->length(); ++i) {
   12602           0 :     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
   12603             :   }
   12604             : 
   12605           0 :   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
   12606           0 :   for (int i = 0; i < fixed->length(); ++i) {
   12607           0 :     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
   12608             :   }
   12609             : 
   12610             :   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
   12611           0 :   for (int i = 0; i < live_ranges->length(); ++i) {
   12612           0 :     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
   12613           0 :   }
   12614           0 : }
   12615             : 
   12616             : 
   12617           0 : void HTracer::TraceLiveRange(LiveRange* range, const char* type,
   12618             :                              Zone* zone) {
   12619           0 :   if (range != NULL && !range->IsEmpty()) {
   12620             :     PrintIndent();
   12621           0 :     trace_.Add("%d %s", range->id(), type);
   12622           0 :     if (range->HasRegisterAssigned()) {
   12623           0 :       LOperand* op = range->CreateAssignedOperand(zone);
   12624             :       int assigned_reg = op->index();
   12625           0 :       if (op->IsDoubleRegister()) {
   12626             :         trace_.Add(" \"%s\"",
   12627           0 :                    GetRegConfig()->GetDoubleRegisterName(assigned_reg));
   12628             :       } else {
   12629             :         DCHECK(op->IsRegister());
   12630             :         trace_.Add(" \"%s\"",
   12631           0 :                    GetRegConfig()->GetGeneralRegisterName(assigned_reg));
   12632             :       }
   12633           0 :     } else if (range->IsSpilled()) {
   12634           0 :       LOperand* op = range->TopLevel()->GetSpillOperand();
   12635           0 :       if (op->IsDoubleStackSlot()) {
   12636           0 :         trace_.Add(" \"double_stack:%d\"", op->index());
   12637             :       } else {
   12638             :         DCHECK(op->IsStackSlot());
   12639           0 :         trace_.Add(" \"stack:%d\"", op->index());
   12640             :       }
   12641             :     }
   12642             :     int parent_index = -1;
   12643           0 :     if (range->IsChild()) {
   12644           0 :       parent_index = range->parent()->id();
   12645             :     } else {
   12646             :       parent_index = range->id();
   12647             :     }
   12648           0 :     LOperand* op = range->FirstHint();
   12649             :     int hint_index = -1;
   12650           0 :     if (op != NULL && op->IsUnallocated()) {
   12651             :       hint_index = LUnallocated::cast(op)->virtual_register();
   12652             :     }
   12653           0 :     trace_.Add(" %d %d", parent_index, hint_index);
   12654           0 :     UseInterval* cur_interval = range->first_interval();
   12655           0 :     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
   12656             :       trace_.Add(" [%d, %d[",
   12657             :                  cur_interval->start().Value(),
   12658           0 :                  cur_interval->end().Value());
   12659             :       cur_interval = cur_interval->next();
   12660             :     }
   12661             : 
   12662           0 :     UsePosition* current_pos = range->first_pos();
   12663           0 :     while (current_pos != NULL) {
   12664           0 :       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
   12665           0 :         trace_.Add(" %d M", current_pos->pos().Value());
   12666             :       }
   12667             :       current_pos = current_pos->next();
   12668             :     }
   12669             : 
   12670           0 :     trace_.Add(" \"\"\n");
   12671             :   }
   12672           0 : }
   12673             : 
   12674             : 
   12675           0 : void HTracer::FlushToFile() {
   12676           0 :   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
   12677           0 :               false);
   12678             :   trace_.Reset();
   12679           0 : }
   12680             : 
   12681             : 
   12682           0 : void HStatistics::Initialize(CompilationInfo* info) {
   12683           0 :   if (!info->has_shared_info()) return;
   12684           0 :   source_size_ += info->shared_info()->SourceSize();
   12685             : }
   12686             : 
   12687             : 
   12688           0 : void HStatistics::Print() {
   12689             :   PrintF(
   12690             :       "\n"
   12691             :       "----------------------------------------"
   12692             :       "----------------------------------------\n"
   12693             :       "--- Hydrogen timing results:\n"
   12694             :       "----------------------------------------"
   12695           0 :       "----------------------------------------\n");
   12696             :   base::TimeDelta sum;
   12697           0 :   for (int i = 0; i < times_.length(); ++i) {
   12698           0 :     sum += times_[i];
   12699             :   }
   12700             : 
   12701           0 :   for (int i = 0; i < names_.length(); ++i) {
   12702           0 :     PrintF("%33s", names_[i]);
   12703           0 :     double ms = times_[i].InMillisecondsF();
   12704             :     double percent = times_[i].PercentOf(sum);
   12705           0 :     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
   12706             : 
   12707           0 :     size_t size = sizes_[i];
   12708           0 :     double size_percent = static_cast<double>(size) * 100 / total_size_;
   12709           0 :     PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
   12710             :   }
   12711             : 
   12712             :   PrintF(
   12713             :       "----------------------------------------"
   12714           0 :       "----------------------------------------\n");
   12715           0 :   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
   12716             :   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
   12717           0 :          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
   12718             :   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
   12719           0 :          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
   12720             :   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
   12721           0 :          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
   12722             :   PrintF(
   12723             :       "----------------------------------------"
   12724           0 :       "----------------------------------------\n");
   12725             :   PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
   12726           0 :          total.InMillisecondsF(), total_size_);
   12727             :   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
   12728           0 :          total.TimesOf(full_code_gen_));
   12729             : 
   12730           0 :   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
   12731             :   double normalized_time =  source_size_in_kb > 0
   12732           0 :       ? total.InMillisecondsF() / source_size_in_kb
   12733           0 :       : 0;
   12734             :   double normalized_size_in_kb =
   12735             :       source_size_in_kb > 0
   12736           0 :           ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
   12737           0 :           : 0;
   12738             :   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
   12739           0 :          "Average per kB source", normalized_time, normalized_size_in_kb);
   12740           0 : }
   12741             : 
   12742             : 
   12743           0 : void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
   12744             :                              size_t size) {
   12745           0 :   total_size_ += size;
   12746           0 :   for (int i = 0; i < names_.length(); ++i) {
   12747           0 :     if (strcmp(names_[i], name) == 0) {
   12748           0 :       times_[i] += time;
   12749           0 :       sizes_[i] += size;
   12750           0 :       return;
   12751             :     }
   12752             :   }
   12753           0 :   names_.Add(name);
   12754           0 :   times_.Add(time);
   12755           0 :   sizes_.Add(size);
   12756             : }
   12757             : 
   12758             : 
   12759    11887319 : HPhase::~HPhase() {
   12760     5943661 :   if (ShouldProduceTraceOutput()) {
   12761           0 :     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
   12762             :   }
   12763             : 
   12764             : #ifdef DEBUG
   12765             :   graph_->Verify(false);  // No full verify.
   12766             : #endif
   12767     5943656 : }
   12768             : 
   12769             : }  // namespace internal
   12770             : }  // namespace v8

Generated by: LCOV version 1.10