// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/crankshaft/hydrogen.h"

#include <sstream>

#include "src/allocation-site-scopes.h"
#include "src/ast/ast-numbering.h"
#include "src/ast/scopeinfo.h"
#include "src/code-factory.h"
#include "src/crankshaft/hydrogen-bce.h"
#include "src/crankshaft/hydrogen-bch.h"
#include "src/crankshaft/hydrogen-canonicalize.h"
#include "src/crankshaft/hydrogen-check-elimination.h"
#include "src/crankshaft/hydrogen-dce.h"
#include "src/crankshaft/hydrogen-dehoist.h"
#include "src/crankshaft/hydrogen-environment-liveness.h"
#include "src/crankshaft/hydrogen-escape-analysis.h"
#include "src/crankshaft/hydrogen-gvn.h"
#include "src/crankshaft/hydrogen-infer-representation.h"
#include "src/crankshaft/hydrogen-infer-types.h"
#include "src/crankshaft/hydrogen-load-elimination.h"
#include "src/crankshaft/hydrogen-mark-deoptimize.h"
#include "src/crankshaft/hydrogen-mark-unreachable.h"
#include "src/crankshaft/hydrogen-osr.h"
#include "src/crankshaft/hydrogen-range-analysis.h"
#include "src/crankshaft/hydrogen-redundant-phi.h"
#include "src/crankshaft/hydrogen-removable-simulates.h"
#include "src/crankshaft/hydrogen-representation-changes.h"
#include "src/crankshaft/hydrogen-sce.h"
#include "src/crankshaft/hydrogen-store-elimination.h"
#include "src/crankshaft/hydrogen-uint32-analysis.h"
#include "src/crankshaft/lithium-allocator.h"
#include "src/crankshaft/typing.h"
#include "src/full-codegen/full-codegen.h"
#include "src/ic/call-optimization.h"
#include "src/ic/ic.h"
// GetRootConstructor
#include "src/ic/ic-inl.h"
#include "src/isolate-inl.h"
#include "src/parsing/parser.h"
#include "src/runtime/runtime.h"

#if V8_TARGET_ARCH_IA32
#include "src/crankshaft/ia32/lithium-codegen-ia32.h"  // NOLINT
#elif V8_TARGET_ARCH_X64
#include "src/crankshaft/x64/lithium-codegen-x64.h"  // NOLINT
#elif V8_TARGET_ARCH_ARM64
#include "src/crankshaft/arm64/lithium-codegen-arm64.h"  // NOLINT
#elif V8_TARGET_ARCH_ARM
#include "src/crankshaft/arm/lithium-codegen-arm.h"  // NOLINT
#elif V8_TARGET_ARCH_PPC
#include "src/crankshaft/ppc/lithium-codegen-ppc.h"  // NOLINT
#elif V8_TARGET_ARCH_MIPS
#include "src/crankshaft/mips/lithium-codegen-mips.h"  // NOLINT
#elif V8_TARGET_ARCH_MIPS64
#include "src/crankshaft/mips64/lithium-codegen-mips64.h"  // NOLINT
#elif V8_TARGET_ARCH_X87
#include "src/crankshaft/x87/lithium-codegen-x87.h"  // NOLINT
#else
#error Unsupported target architecture.
#endif

namespace v8 {
namespace internal {

HBasicBlock::HBasicBlock(HGraph* graph)
    : block_id_(graph->GetNextBlockID()),
      graph_(graph),
      phis_(4, graph->zone()),
      first_(NULL),
      last_(NULL),
      end_(NULL),
      loop_information_(NULL),
      predecessors_(2, graph->zone()),
      dominator_(NULL),
      dominated_blocks_(4, graph->zone()),
      last_environment_(NULL),
      argument_count_(-1),
      first_instruction_index_(-1),
      last_instruction_index_(-1),
      deleted_phis_(4, graph->zone()),
      parent_loop_header_(NULL),
      inlined_entry_block_(NULL),
      is_inline_return_target_(false),
      is_reachable_(true),
      dominates_loop_successors_(false),
      is_osr_entry_(false),
      is_ordered_(false) { }


Isolate* HBasicBlock::isolate() const {
  return graph_->isolate();
}


void HBasicBlock::MarkUnreachable() {
  is_reachable_ = false;
}


void HBasicBlock::AttachLoopInformation() {
  DCHECK(!IsLoopHeader());
  loop_information_ = new(zone()) HLoopInformation(this, zone());
}


void HBasicBlock::DetachLoopInformation() {
  DCHECK(IsLoopHeader());
  loop_information_ = NULL;
}


void HBasicBlock::AddPhi(HPhi* phi) {
  DCHECK(!IsStartBlock());
  phis_.Add(phi, zone());
  phi->SetBlock(this);
}


void HBasicBlock::RemovePhi(HPhi* phi) {
  DCHECK(phi->block() == this);
  DCHECK(phis_.Contains(phi));
  phi->Kill();
  phis_.RemoveElement(phi);
  phi->SetBlock(NULL);
}


void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
  DCHECK(!IsStartBlock() || !IsFinished());
  DCHECK(!instr->IsLinked());
  DCHECK(!IsFinished());

  if (!position.IsUnknown()) {
    instr->set_position(position);
  }
  if (first_ == NULL) {
    DCHECK(last_environment() != NULL);
    DCHECK(!last_environment()->ast_id().IsNone());
    HBlockEntry* entry = new(zone()) HBlockEntry();
    entry->InitializeAsFirst(this);
    if (!position.IsUnknown()) {
      entry->set_position(position);
    } else {
      DCHECK(!FLAG_hydrogen_track_positions ||
             !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
    }
    first_ = last_ = entry;
  }
  instr->InsertAfter(last_);
}


HPhi* HBasicBlock::AddNewPhi(int merged_index) {
  if (graph()->IsInsideNoSideEffectsScope()) {
    merged_index = HPhi::kInvalidMergedIndex;
  }
  HPhi* phi = new(zone()) HPhi(merged_index, zone());
  AddPhi(phi);
  return phi;
}


HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
                                       RemovableSimulate removable) {
  DCHECK(HasEnvironment());
  HEnvironment* environment = last_environment();
  DCHECK(ast_id.IsNone() ||
         ast_id == BailoutId::StubEntry() ||
         environment->closure()->shared()->VerifyBailoutId(ast_id));

  int push_count = environment->push_count();
  int pop_count = environment->pop_count();

  HSimulate* instr =
      new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
#ifdef DEBUG
  instr->set_closure(environment->closure());
#endif
  // Order of pushed values: newest (top of stack) first. This allows
  // HSimulate::MergeWith() to easily append additional pushed values
  // that are older (from further down the stack).
  for (int i = 0; i < push_count; ++i) {
    instr->AddPushedValue(environment->ExpressionStackAt(i));
  }
  for (GrowableBitVector::Iterator it(environment->assigned_variables(),
                                      zone());
       !it.Done();
       it.Advance()) {
    int index = it.Current();
    instr->AddAssignedValue(index, environment->Lookup(index));
  }
  environment->ClearHistory();
  return instr;
}


void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
  DCHECK(!IsFinished());
  AddInstruction(end, position);
  end_ = end;
  for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    it.Current()->RegisterPredecessor(this);
  }
}


void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
                       FunctionState* state, bool add_simulate) {
  bool drop_extra = state != NULL &&
      state->inlining_kind() == NORMAL_RETURN;

  if (block->IsInlineReturnTarget()) {
    HEnvironment* env = last_environment();
    int argument_count = env->arguments_environment()->parameter_count();
    AddInstruction(new(zone())
                   HLeaveInlined(state->entry(), argument_count),
                   position);
    UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
  }

  if (add_simulate) AddNewSimulate(BailoutId::None(), position);
  HGoto* instr = new(zone()) HGoto(block);
  Finish(instr, position);
}


void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
                                  SourcePosition position) {
  HBasicBlock* target = state->function_return();
  bool drop_extra = state->inlining_kind() == NORMAL_RETURN;

  DCHECK(target->IsInlineReturnTarget());
  DCHECK(return_value != NULL);
  HEnvironment* env = last_environment();
  int argument_count = env->arguments_environment()->parameter_count();
  AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
                 position);
  UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
  last_environment()->Push(return_value);
  AddNewSimulate(BailoutId::None(), position);
  HGoto* instr = new(zone()) HGoto(target);
  Finish(instr, position);
}


void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
  DCHECK(!HasEnvironment());
  DCHECK(first() == NULL);
  UpdateEnvironment(env);
}


void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
  last_environment_ = env;
  graph()->update_maximum_environment_size(env->first_expression_index());
}


void HBasicBlock::SetJoinId(BailoutId ast_id) {
  int length = predecessors_.length();
  DCHECK(length > 0);
  for (int i = 0; i < length; i++) {
    HBasicBlock* predecessor = predecessors_[i];
    DCHECK(predecessor->end()->IsGoto());
    HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
    DCHECK(i != 0 ||
           (predecessor->last_environment()->closure().is_null() ||
            predecessor->last_environment()->closure()->shared()
              ->VerifyBailoutId(ast_id)));
    simulate->set_ast_id(ast_id);
    predecessor->last_environment()->set_ast_id(ast_id);
  }
}


bool HBasicBlock::Dominates(HBasicBlock* other) const {
  HBasicBlock* current = other->dominator();
  while (current != NULL) {
    if (current == this) return true;
    current = current->dominator();
  }
  return false;
}


bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
  if (this == other) return true;
  return Dominates(other);
}


int HBasicBlock::LoopNestingDepth() const {
  const HBasicBlock* current = this;
  int result  = (current->IsLoopHeader()) ? 1 : 0;
  while (current->parent_loop_header() != NULL) {
    current = current->parent_loop_header();
    result++;
  }
  return result;
}


void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
  DCHECK(IsLoopHeader());

  SetJoinId(stmt->EntryId());
  if (predecessors()->length() == 1) {
    // This is a degenerated loop.
    DetachLoopInformation();
    return;
  }

  // Only the first entry into the loop is from outside the loop. All other
  // entries must be back edges.
  for (int i = 1; i < predecessors()->length(); ++i) {
    loop_information()->RegisterBackEdge(predecessors()->at(i));
  }
}


void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
  DCHECK(IsFinished());
  HBasicBlock* succ_block = end()->SuccessorAt(succ);

  DCHECK(succ_block->predecessors()->length() == 1);
  succ_block->MarkUnreachable();
}


void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
  if (HasPredecessor()) {
    // Only loop header blocks can have a predecessor added after
    // instructions have been added to the block (they have phis for all
    // values in the environment, these phis may be eliminated later).
    DCHECK(IsLoopHeader() || first_ == NULL);
    HEnvironment* incoming_env = pred->last_environment();
    if (IsLoopHeader()) {
      DCHECK_EQ(phis()->length(), incoming_env->length());
      for (int i = 0; i < phis_.length(); ++i) {
        phis_[i]->AddInput(incoming_env->values()->at(i));
      }
    } else {
      last_environment()->AddIncomingEdge(this, pred->last_environment());
    }
  } else if (!HasEnvironment() && !IsFinished()) {
    DCHECK(!IsLoopHeader());
    SetInitialEnvironment(pred->last_environment()->Copy());
  }

  predecessors_.Add(pred, zone());
}


void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
  DCHECK(!dominated_blocks_.Contains(block));
  // Keep the list of dominated blocks sorted such that if there is two
  // succeeding block in this list, the predecessor is before the successor.
  int index = 0;
  while (index < dominated_blocks_.length() &&
         dominated_blocks_[index]->block_id() < block->block_id()) {
    ++index;
  }
  dominated_blocks_.InsertAt(index, block, zone());
}


void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
  if (dominator_ == NULL) {
    dominator_ = other;
    other->AddDominatedBlock(this);
  } else if (other->dominator() != NULL) {
    HBasicBlock* first = dominator_;
    HBasicBlock* second = other;

    while (first != second) {
      if (first->block_id() > second->block_id()) {
        first = first->dominator();
      } else {
        second = second->dominator();
      }
      DCHECK(first != NULL && second != NULL);
    }

    if (dominator_ != first) {
      DCHECK(dominator_->dominated_blocks_.Contains(this));
      dominator_->dominated_blocks_.RemoveElement(this);
      dominator_ = first;
      first->AddDominatedBlock(this);
    }
  }
}


void HBasicBlock::AssignLoopSuccessorDominators() {
  // Mark blocks that dominate all subsequent reachable blocks inside their
  // loop. Exploit the fact that blocks are sorted in reverse post order. When
  // the loop is visited in increasing block id order, if the number of
  // non-loop-exiting successor edges at the dominator_candidate block doesn't
  // exceed the number of previously encountered predecessor edges, there is no
  // path from the loop header to any block with higher id that doesn't go
  // through the dominator_candidate block. In this case, the
  // dominator_candidate block is guaranteed to dominate all blocks reachable
  // from it with higher ids.
  HBasicBlock* last = loop_information()->GetLastBackEdge();
  int outstanding_successors = 1;  // one edge from the pre-header
  // Header always dominates everything.
  MarkAsLoopSuccessorDominator();
  for (int j = block_id(); j <= last->block_id(); ++j) {
    HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
    for (HPredecessorIterator it(dominator_candidate); !it.Done();
         it.Advance()) {
      HBasicBlock* predecessor = it.Current();
      // Don't count back edges.
      if (predecessor->block_id() < dominator_candidate->block_id()) {
        outstanding_successors--;
      }
    }

    // If more successors than predecessors have been seen in the loop up to
    // now, it's not possible to guarantee that the current block dominates
    // all of the blocks with higher IDs. In this case, assume conservatively
    // that those paths through loop that don't go through the current block
    // contain all of the loop's dependencies. Also be careful to record
    // dominator information about the current loop that's being processed,
    // and not nested loops, which will be processed when
    // AssignLoopSuccessorDominators gets called on their header.
    DCHECK(outstanding_successors >= 0);
    HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
    if (outstanding_successors == 0 &&
        (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
      dominator_candidate->MarkAsLoopSuccessorDominator();
    }
    HControlInstruction* end = dominator_candidate->end();
    for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
      HBasicBlock* successor = it.Current();
      // Only count successors that remain inside the loop and don't loop back
      // to a loop header.
      if (successor->block_id() > dominator_candidate->block_id() &&
          successor->block_id() <= last->block_id()) {
        // Backwards edges must land on loop headers.
        DCHECK(successor->block_id() > dominator_candidate->block_id() ||
               successor->IsLoopHeader());
        outstanding_successors++;
      }
    }
  }
}


int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
  for (int i = 0; i < predecessors_.length(); ++i) {
    if (predecessors_[i] == predecessor) return i;
  }
  UNREACHABLE();
  return -1;
}


#ifdef DEBUG
void HBasicBlock::Verify() {
  // Check that every block is finished.
  DCHECK(IsFinished());
  DCHECK(block_id() >= 0);

  // Check that the incoming edges are in edge split form.
  if (predecessors_.length() > 1) {
    for (int i = 0; i < predecessors_.length(); ++i) {
      DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
    }
  }
}
#endif


void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
  this->back_edges_.Add(block, block->zone());
  AddBlock(block);
}


HBasicBlock* HLoopInformation::GetLastBackEdge() const {
  int max_id = -1;
  HBasicBlock* result = NULL;
  for (int i = 0; i < back_edges_.length(); ++i) {
    HBasicBlock* cur = back_edges_[i];
    if (cur->block_id() > max_id) {
      max_id = cur->block_id();
      result = cur;
    }
  }
  return result;
}


void HLoopInformation::AddBlock(HBasicBlock* block) {
  if (block == loop_header()) return;
  if (block->parent_loop_header() == loop_header()) return;
  if (block->parent_loop_header() != NULL) {
    AddBlock(block->parent_loop_header());
  } else {
    block->set_parent_loop_header(loop_header());
    blocks_.Add(block, block->zone());
    for (int i = 0; i < block->predecessors()->length(); ++i) {
      AddBlock(block->predecessors()->at(i));
    }
  }
}


#ifdef DEBUG

// Checks reachability of the blocks in this graph and stores a bit in
// the BitVector "reachable()" for every block that can be reached
// from the start block of the graph. If "dont_visit" is non-null, the given
// block is treated as if it would not be part of the graph. "visited_count()"
// returns the number of reachable blocks.
class ReachabilityAnalyzer BASE_EMBEDDED {
 public:
  ReachabilityAnalyzer(HBasicBlock* entry_block,
                       int block_count,
                       HBasicBlock* dont_visit)
      : visited_count_(0),
        stack_(16, entry_block->zone()),
        reachable_(block_count, entry_block->zone()),
        dont_visit_(dont_visit) {
    PushBlock(entry_block);
    Analyze();
  }

  int visited_count() const { return visited_count_; }
  const BitVector* reachable() const { return &reachable_; }

 private:
  void PushBlock(HBasicBlock* block) {
    if (block != NULL && block != dont_visit_ &&
        !reachable_.Contains(block->block_id())) {
      reachable_.Add(block->block_id());
      stack_.Add(block, block->zone());
      visited_count_++;
    }
  }

  void Analyze() {
    while (!stack_.is_empty()) {
      HControlInstruction* end = stack_.RemoveLast()->end();
      for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
        PushBlock(it.Current());
      }
    }
  }

  int visited_count_;
  ZoneList<HBasicBlock*> stack_;
  BitVector reachable_;
  HBasicBlock* dont_visit_;
};


void HGraph::Verify(bool do_full_verify) const {
  Heap::RelocationLock relocation_lock(isolate()->heap());
  AllowHandleDereference allow_deref;
  AllowDeferredHandleDereference allow_deferred_deref;
  for (int i = 0; i < blocks_.length(); i++) {
    HBasicBlock* block = blocks_.at(i);

    block->Verify();

    // Check that every block contains at least one node and that only the last
    // node is a control instruction.
    HInstruction* current = block->first();
    DCHECK(current != NULL && current->IsBlockEntry());
    while (current != NULL) {
      DCHECK((current->next() == NULL) == current->IsControlInstruction());
      DCHECK(current->block() == block);
      current->Verify();
      current = current->next();
    }

    // Check that successors are correctly set.
    HBasicBlock* first = block->end()->FirstSuccessor();
    HBasicBlock* second = block->end()->SecondSuccessor();
    DCHECK(second == NULL || first != NULL);

    // Check that the predecessor array is correct.
    if (first != NULL) {
      DCHECK(first->predecessors()->Contains(block));
      if (second != NULL) {
        DCHECK(second->predecessors()->Contains(block));
      }
    }

    // Check that phis have correct arguments.
    for (int j = 0; j < block->phis()->length(); j++) {
      HPhi* phi = block->phis()->at(j);
      phi->Verify();
    }

    // Check that all join blocks have predecessors that end with an
    // unconditional goto and agree on their environment node id.
    if (block->predecessors()->length() >= 2) {
      BailoutId id =
          block->predecessors()->first()->last_environment()->ast_id();
      for (int k = 0; k < block->predecessors()->length(); k++) {
        HBasicBlock* predecessor = block->predecessors()->at(k);
        DCHECK(predecessor->end()->IsGoto() ||
               predecessor->end()->IsDeoptimize());
        DCHECK(predecessor->last_environment()->ast_id() == id);
      }
    }
  }

  // Check special property of first block to have no predecessors.
  DCHECK(blocks_.at(0)->predecessors()->is_empty());

  if (do_full_verify) {
    // Check that the graph is fully connected.
    ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
    DCHECK(analyzer.visited_count() == blocks_.length());

    // Check that entry block dominator is NULL.
    DCHECK(entry_block_->dominator() == NULL);

    // Check dominators.
    for (int i = 0; i < blocks_.length(); ++i) {
      HBasicBlock* block = blocks_.at(i);
      if (block->dominator() == NULL) {
        // Only start block may have no dominator assigned to.
        DCHECK(i == 0);
      } else {
        // Assert that block is unreachable if dominator must not be visited.
        ReachabilityAnalyzer dominator_analyzer(entry_block_,
                                                blocks_.length(),
                                                block->dominator());
        DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
      }
    }
  }
}

#endif


HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
                               int32_t value) {
  if (!pointer->is_set()) {
    // Can't pass GetInvalidContext() to HConstant::New, because that will
    // recursively call GetConstant
    HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
    constant->InsertAfter(entry_block()->first());
    pointer->set(constant);
    return constant;
  }
  return ReinsertConstantIfNecessary(pointer->get());
}


HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
  if (!constant->IsLinked()) {
    // The constant was removed from the graph. Reinsert.
    constant->ClearFlag(HValue::kIsDead);
    constant->InsertAfter(entry_block()->first());
  }
  return constant;
}


HConstant* HGraph::GetConstant0() {
  return GetConstant(&constant_0_, 0);
}


HConstant* HGraph::GetConstant1() {
  return GetConstant(&constant_1_, 1);
}


HConstant* HGraph::GetConstantMinus1() {
  return GetConstant(&constant_minus1_, -1);
}


HConstant* HGraph::GetConstantBool(bool value) {
  return value ? GetConstantTrue() : GetConstantFalse();
}

#define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value,         \
                            undetectable)                                   \
  HConstant* HGraph::GetConstant##Name() {                                  \
    if (!constant_##name##_.is_set()) {                                     \
      HConstant* constant = new (zone()) HConstant(                         \
          Unique<Object>::CreateImmovable(                                  \
              isolate()->factory()->name##_value()),                        \
          Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()), \
          false, Representation::Tagged(), htype, true, boolean_value,      \
          undetectable, ODDBALL_TYPE);                                      \
      constant->InsertAfter(entry_block()->first());                        \
      constant_##name##_.set(constant);                                     \
    }                                                                       \
    return ReinsertConstantIfNecessary(constant_##name##_.get());           \
  }

DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false,
                    true)
DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true, false)
DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false, false)
DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false, false)
DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false, true)

#undef DEFINE_GET_CONSTANT

#define DEFINE_IS_CONSTANT(Name, name)                                         \
bool HGraph::IsConstant##Name(HConstant* constant) {                           \
  return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
}
DEFINE_IS_CONSTANT(Undefined, undefined)
DEFINE_IS_CONSTANT(0, 0)
DEFINE_IS_CONSTANT(1, 1)
DEFINE_IS_CONSTANT(Minus1, minus1)
DEFINE_IS_CONSTANT(True, true)
DEFINE_IS_CONSTANT(False, false)
DEFINE_IS_CONSTANT(Hole, the_hole)
DEFINE_IS_CONSTANT(Null, null)

#undef DEFINE_IS_CONSTANT


HConstant* HGraph::GetInvalidContext() {
  return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
}


bool HGraph::IsStandardConstant(HConstant* constant) {
  if (IsConstantUndefined(constant)) return true;
  if (IsConstant0(constant)) return true;
  if (IsConstant1(constant)) return true;
  if (IsConstantMinus1(constant)) return true;
  if (IsConstantTrue(constant)) return true;
  if (IsConstantFalse(constant)) return true;
  if (IsConstantHole(constant)) return true;
  if (IsConstantNull(constant)) return true;
  return false;
}


HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}


HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
    : needs_compare_(true) {
  Initialize(builder);
}


HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
                                    HIfContinuation* continuation)
    : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
  InitializeDontCreateBlocks(builder);
  continuation->Continue(&first_true_block_, &first_false_block_);
}


void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
    HGraphBuilder* builder) {
  builder_ = builder;
  finished_ = false;
  did_then_ = false;
  did_else_ = false;
  did_else_if_ = false;
  did_and_ = false;
  did_or_ = false;
  captured_ = false;
  pending_merge_block_ = false;
  split_edge_merge_block_ = NULL;
  merge_at_join_blocks_ = NULL;
  normal_merge_at_join_block_count_ = 0;
  deopt_merge_at_join_block_count_ = 0;
}


void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
  InitializeDontCreateBlocks(builder);
  HEnvironment* env = builder->environment();
  first_true_block_ = builder->CreateBasicBlock(env->Copy());
  first_false_block_ = builder->CreateBasicBlock(env->Copy());
}


HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
    HControlInstruction* compare) {
  DCHECK(did_then_ == did_else_);
  if (did_else_) {
    // Handle if-then-elseif
    did_else_if_ = true;
    did_else_ = false;
    did_then_ = false;
    did_and_ = false;
    did_or_ = false;
    pending_merge_block_ = false;
    split_edge_merge_block_ = NULL;
    HEnvironment* env = builder()->environment();
    first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    first_false_block_ = builder()->CreateBasicBlock(env->Copy());
  }
  if (split_edge_merge_block_ != NULL) {
    HEnvironment* env = first_false_block_->last_environment();
    HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
    if (did_or_) {
      compare->SetSuccessorAt(0, split_edge);
      compare->SetSuccessorAt(1, first_false_block_);
    } else {
      compare->SetSuccessorAt(0, first_true_block_);
      compare->SetSuccessorAt(1, split_edge);
    }
    builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
  } else {
    compare->SetSuccessorAt(0, first_true_block_);
    compare->SetSuccessorAt(1, first_false_block_);
  }
  builder()->FinishCurrentBlock(compare);
  needs_compare_ = false;
  return compare;
}


void HGraphBuilder::IfBuilder::Or() {
  DCHECK(!needs_compare_);
  DCHECK(!did_and_);
  did_or_ = true;
  HEnvironment* env = first_false_block_->last_environment();
  if (split_edge_merge_block_ == NULL) {
    split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
    first_true_block_ = split_edge_merge_block_;
  }
  builder()->set_current_block(first_false_block_);
  first_false_block_ = builder()->CreateBasicBlock(env->Copy());
}


void HGraphBuilder::IfBuilder::And() {
  DCHECK(!needs_compare_);
  DCHECK(!did_or_);
  did_and_ = true;
  HEnvironment* env = first_false_block_->last_environment();
  if (split_edge_merge_block_ == NULL) {
    split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
    first_false_block_ = split_edge_merge_block_;
  }
  builder()->set_current_block(first_true_block_);
  first_true_block_ = builder()->CreateBasicBlock(env->Copy());
}


void HGraphBuilder::IfBuilder::CaptureContinuation(
    HIfContinuation* continuation) {
  DCHECK(!did_else_if_);
  DCHECK(!finished_);
  DCHECK(!captured_);

  HBasicBlock* true_block = NULL;
  HBasicBlock* false_block = NULL;
  Finish(&true_block, &false_block);
  DCHECK(true_block != NULL);
  DCHECK(false_block != NULL);
  continuation->Capture(true_block, false_block);
  captured_ = true;
  builder()->set_current_block(NULL);
  End();
}


void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
  DCHECK(!did_else_if_);
  DCHECK(!finished_);
  DCHECK(!captured_);
  HBasicBlock* true_block = NULL;
  HBasicBlock* false_block = NULL;
  Finish(&true_block, &false_block);
  merge_at_join_blocks_ = NULL;
  if (true_block != NULL && !true_block->IsFinished()) {
    DCHECK(continuation->IsTrueReachable());
    builder()->GotoNoSimulate(true_block, continuation->true_branch());
  }
  if (false_block != NULL && !false_block->IsFinished()) {
    DCHECK(continuation->IsFalseReachable());
    builder()->GotoNoSimulate(false_block, continuation->false_branch());
  }
  captured_ = true;
  End();
}


void HGraphBuilder::IfBuilder::Then() {
  DCHECK(!captured_);
  DCHECK(!finished_);
  did_then_ = true;
  if (needs_compare_) {
    // Handle if's without any expressions, they jump directly to the "else"
    // branch. However, we must pretend that the "then" branch is reachable,
    // so that the graph builder visits it and sees any live range extending
    // constructs within it.
    HConstant* constant_false = builder()->graph()->GetConstantFalse();
    ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
    boolean_type.Add(ToBooleanStub::BOOLEAN);
    HBranch* branch = builder()->New<HBranch>(
        constant_false, boolean_type, first_true_block_, first_false_block_);
    builder()->FinishCurrentBlock(branch);
  }
  builder()->set_current_block(first_true_block_);
  pending_merge_block_ = true;
}


void HGraphBuilder::IfBuilder::Else() {
  DCHECK(did_then_);
  DCHECK(!captured_);
  DCHECK(!finished_);
  AddMergeAtJoinBlock(false);
  builder()->set_current_block(first_false_block_);
  pending_merge_block_ = true;
  did_else_ = true;
}


void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) {
  DCHECK(did_then_);
  builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
  AddMergeAtJoinBlock(true);
}


void HGraphBuilder::IfBuilder::Return(HValue* value) {
  HValue* parameter_count = builder()->graph()->GetConstantMinus1();
  builder()->FinishExitCurrentBlock(
      builder()->New<HReturn>(value, parameter_count));
  AddMergeAtJoinBlock(false);
}


void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
  if (!pending_merge_block_) return;
  HBasicBlock* block = builder()->current_block();
  DCHECK(block == NULL || !block->IsFinished());
  MergeAtJoinBlock* record = new (builder()->zone())
      MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
  merge_at_join_blocks_ = record;
  if (block != NULL) {
    DCHECK(block->end() == NULL);
    if (deopt) {
      normal_merge_at_join_block_count_++;
    } else {
      deopt_merge_at_join_block_count_++;
    }
  }
  builder()->set_current_block(NULL);
  pending_merge_block_ = false;
}


void HGraphBuilder::IfBuilder::Finish() {
  DCHECK(!finished_);
  if (!did_then_) {
    Then();
  }
  AddMergeAtJoinBlock(false);
  if (!did_else_) {
    Else();
    AddMergeAtJoinBlock(false);
  }
  finished_ = true;
}


void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
                                      HBasicBlock** else_continuation) {
  Finish();

  MergeAtJoinBlock* else_record = merge_at_join_blocks_;
  if (else_continuation != NULL) {
    *else_continuation = else_record->block_;
  }
  MergeAtJoinBlock* then_record = else_record->next_;
  if (then_continuation != NULL) {
    *then_continuation = then_record->block_;
  }
  DCHECK(then_record->next_ == NULL);
}


void HGraphBuilder::IfBuilder::EndUnreachable() {
  if (captured_) return;
  Finish();
  builder()->set_current_block(nullptr);
}


void HGraphBuilder::IfBuilder::End() {
  if (captured_) return;
  Finish();

  int total_merged_blocks = normal_merge_at_join_block_count_ +
    deopt_merge_at_join_block_count_;
  DCHECK(total_merged_blocks >= 1);
  HBasicBlock* merge_block =
      total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();

  // Merge non-deopt blocks first to ensure environment has right size for
  // padding.
  MergeAtJoinBlock* current = merge_at_join_blocks_;
  while (current != NULL) {
    if (!current->deopt_ && current->block_ != NULL) {
      // If there is only one block that makes it through to the end of the
      // if, then just set it as the current block and continue rather then
      // creating an unnecessary merge block.
      if (total_merged_blocks == 1) {
        builder()->set_current_block(current->block_);
        return;
      }
      builder()->GotoNoSimulate(current->block_, merge_block);
    }
    current = current->next_;
  }

  // Merge deopt blocks, padding when necessary.
  current = merge_at_join_blocks_;
  while (current != NULL) {
    if (current->deopt_ && current->block_ != NULL) {
      current->block_->FinishExit(
          HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
          SourcePosition::Unknown());
    }
    current = current->next_;
  }
  builder()->set_current_block(merge_block);
}


HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
  Initialize(builder, NULL, kWhileTrue, NULL);
}


HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
                                        LoopBuilder::Direction direction) {
  Initialize(builder, context, direction, builder->graph()->GetConstant1());
}


HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
                                        LoopBuilder::Direction direction,
                                        HValue* increment_amount) {
  Initialize(builder, context, direction, increment_amount);
  increment_amount_ = increment_amount;
}


void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
                                            HValue* context,
                                            Direction direction,
                                            HValue* increment_amount) {
  builder_ = builder;
  context_ = context;
  direction_ = direction;
  increment_amount_ = increment_amount;

  finished_ = false;
  header_block_ = builder->CreateLoopHeaderBlock();
  body_block_ = NULL;
  exit_block_ = NULL;
  exit_trampoline_block_ = NULL;
}


HValue* HGraphBuilder::LoopBuilder::BeginBody(
    HValue* initial,
    HValue* terminating,
    Token::Value token) {
  DCHECK(direction_ != kWhileTrue);
  HEnvironment* env = builder_->environment();
  phi_ = header_block_->AddNewPhi(env->values()->length());
  phi_->AddInput(initial);
  env->Push(initial);
  builder_->GotoNoSimulate(header_block_);

  HEnvironment* body_env = env->Copy();
  HEnvironment* exit_env = env->Copy();
  // Remove the phi from the expression stack
  body_env->Pop();
  exit_env->Pop();
  body_block_ = builder_->CreateBasicBlock(body_env);
  exit_block_ = builder_->CreateBasicBlock(exit_env);

  builder_->set_current_block(header_block_);
  env->Pop();
  builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
          phi_, terminating, token, body_block_, exit_block_));

  builder_->set_current_block(body_block_);
  if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
    Isolate* isolate = builder_->isolate();
    HValue* one = builder_->graph()->GetConstant1();
    if (direction_ == kPreIncrement) {
      increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
    } else {
      increment_ = HSub::New(isolate, zone(), context_, phi_, one);
    }
    increment_->ClearFlag(HValue::kCanOverflow);
    builder_->AddInstruction(increment_);
    return increment_;
  } else {
    return phi_;
  }
}


void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
  DCHECK(direction_ == kWhileTrue);
  HEnvironment* env = builder_->environment();
  builder_->GotoNoSimulate(header_block_);
  builder_->set_current_block(header_block_);
  env->Drop(drop_count);
}


void HGraphBuilder::LoopBuilder::Break() {
  if (exit_trampoline_block_ == NULL) {
    // Its the first time we saw a break.
    if (direction_ == kWhileTrue) {
      HEnvironment* env = builder_->environment()->Copy();
      exit_trampoline_block_ = builder_->CreateBasicBlock(env);
    } else {
      HEnvironment* env = exit_block_->last_environment()->Copy();
      exit_trampoline_block_ = builder_->CreateBasicBlock(env);
      builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
    }
  }

  builder_->GotoNoSimulate(exit_trampoline_block_);
  builder_->set_current_block(NULL);
}


void HGraphBuilder::LoopBuilder::EndBody() {
  DCHECK(!finished_);

  if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
    Isolate* isolate = builder_->isolate();
    if (direction_ == kPostIncrement) {
      increment_ =
          HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
    } else {
      increment_ =
          HSub::New(isolate, zone(), context_, phi_, increment_amount_);
    }
    increment_->ClearFlag(HValue::kCanOverflow);
    builder_->AddInstruction(increment_);
  }

  if (direction_ != kWhileTrue) {
    // Push the new increment value on the expression stack to merge into
    // the phi.
    builder_->environment()->Push(increment_);
  }
  HBasicBlock* last_block = builder_->current_block();
  builder_->GotoNoSimulate(last_block, header_block_);
  header_block_->loop_information()->RegisterBackEdge(last_block);

  if (exit_trampoline_block_ != NULL) {
    builder_->set_current_block(exit_trampoline_block_);
  } else {
    builder_->set_current_block(exit_block_);
  }
  finished_ = true;
}


HGraph* HGraphBuilder::CreateGraph() {
  graph_ = new (zone()) HGraph(info_, descriptor_);
  if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
  CompilationPhase phase("H_Block building", info_);
  set_current_block(graph()->entry_block());
  if (!BuildGraph()) return NULL;
  graph()->FinalizeUniqueness();
  return graph_;
}


HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
  DCHECK(current_block() != NULL);
  DCHECK(!FLAG_hydrogen_track_positions ||
         !position_.IsUnknown() ||
         !info_->IsOptimizing());
  current_block()->AddInstruction(instr, source_position());
  if (graph()->IsInsideNoSideEffectsScope()) {
    instr->SetFlag(HValue::kHasNoObservableSideEffects);
  }
  return instr;
}


void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
  DCHECK(!FLAG_hydrogen_track_positions ||
         !info_->IsOptimizing() ||
         !position_.IsUnknown());
  current_block()->Finish(last, source_position());
  if (last->IsReturn() || last->IsAbnormalExit()) {
    set_current_block(NULL);
  }
}


void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
  DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
         !position_.IsUnknown());
  current_block()->FinishExit(instruction, source_position());
  if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
    set_current_block(NULL);
  }
}


void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
  if (FLAG_native_code_counters && counter->Enabled()) {
    HValue* reference = Add<HConstant>(ExternalReference(counter));
    HValue* old_value =
        Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
    HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
    new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
    Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
                          new_value, STORE_TO_INITIALIZED_ENTRY);
  }
}


void HGraphBuilder::AddSimulate(BailoutId id,
                                RemovableSimulate removable) {
  DCHECK(current_block() != NULL);
  DCHECK(!graph()->IsInsideNoSideEffectsScope());
  current_block()->AddNewSimulate(id, source_position(), removable);
}


HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
  HBasicBlock* b = graph()->CreateBasicBlock();
  b->SetInitialEnvironment(env);
  return b;
}


HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
  HBasicBlock* header = graph()->CreateBasicBlock();
  HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
  header->SetInitialEnvironment(entry_env);
  header->AttachLoopInformation();
  return header;
}


HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
  HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());

  HValue* bit_field2 =
      Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
  return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
}


HValue* HGraphBuilder::BuildEnumLength(HValue* map) {
  NoObservableSideEffectsScope scope(this);
  HValue* bit_field3 =
      Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
  return BuildDecodeField<Map::EnumLengthBits>(bit_field3);
}


HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
  if (obj->type().IsHeapObject()) return obj;
  return Add<HCheckHeapObject>(obj);
}


void HGraphBuilder::FinishExitWithHardDeoptimization(
    Deoptimizer::DeoptReason reason) {
  Add<HDeoptimize>(reason, Deoptimizer::EAGER);
  FinishExitCurrentBlock(New<HAbnormalExit>());
}


HValue* HGraphBuilder::BuildCheckString(HValue* string) {
  if (!string->type().IsString()) {
    DCHECK(!string->IsConstant() ||
           !HConstant::cast(string)->HasStringValue());
    BuildCheckHeapObject(string);
    return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
  }
  return string;
}


HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
  if (object->type().IsJSObject()) return object;
  if (function->IsConstant() &&
      HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    Handle<JSFunction> f = Handle<JSFunction>::cast(
        HConstant::cast(function)->handle(isolate()));
    SharedFunctionInfo* shared = f->shared();
    if (is_strict(shared->language_mode()) || shared->native()) return object;
  }
  return Add<HWrapReceiver>(object, function);
}


HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(
    HValue* object, HValue* elements, ElementsKind kind, HValue* length,
    HValue* capacity, HValue* key) {
  HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
  HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
  Add<HBoundsCheck>(key, max_capacity);

  HValue* new_capacity = BuildNewElementsCapacity(key);
  HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, kind,
                                                   length, new_capacity);
  return new_elements;
}


HValue* HGraphBuilder::BuildCheckForCapacityGrow(
    HValue* object,
    HValue* elements,
    ElementsKind kind,
    HValue* length,
    HValue* key,
    bool is_js_array,
    PropertyAccessType access_type) {
  IfBuilder length_checker(this);

  Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
  length_checker.If<HCompareNumericAndBranch>(key, length, token);

  length_checker.Then();

  HValue* current_capacity = AddLoadFixedArrayLength(elements);

  if (top_info()->IsStub()) {
    IfBuilder capacity_checker(this);
    capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
                                                  Token::GTE);
    capacity_checker.Then();
    HValue* new_elements = BuildCheckAndGrowElementsCapacity(
        object, elements, kind, length, current_capacity, key);
    environment()->Push(new_elements);
    capacity_checker.Else();
    environment()->Push(elements);
    capacity_checker.End();
  } else {
    HValue* result = Add<HMaybeGrowElements>(
        object, elements, key, current_capacity, is_js_array, kind);
    environment()->Push(result);
  }

  if (is_js_array) {
    HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
    new_length->ClearFlag(HValue::kCanOverflow);

    Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
                          new_length);
  }

  if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
    HValue* checked_elements = environment()->Top();

    // Write zero to ensure that the new element is initialized with some smi.
    Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), nullptr,
                     kind);
  }

  length_checker.Else();
  Add<HBoundsCheck>(key, length);

  environment()->Push(elements);
  length_checker.End();

  return environment()->Pop();
}


HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
                                                HValue* elements,
                                                ElementsKind kind,
                                                HValue* length) {
  Factory* factory = isolate()->factory();

  IfBuilder cow_checker(this);

  cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
  cow_checker.Then();

  HValue* capacity = AddLoadFixedArrayLength(elements);

  HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
                                                   kind, length, capacity);

  environment()->Push(new_elements);

  cow_checker.Else();

  environment()->Push(elements);

  cow_checker.End();

  return environment()->Pop();
}


void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
                                                HValue* map,
                                                ElementsKind from_kind,
                                                ElementsKind to_kind,
                                                bool is_jsarray) {
  DCHECK(!IsFastHoleyElementsKind(from_kind) ||
         IsFastHoleyElementsKind(to_kind));

  if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
    Add<HTrapAllocationMemento>(object);
  }

  if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
    HInstruction* elements = AddLoadElements(object);

    HInstruction* empty_fixed_array = Add<HConstant>(
        isolate()->factory()->empty_fixed_array());

    IfBuilder if_builder(this);

    if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);

    if_builder.Then();

    HInstruction* elements_length = AddLoadFixedArrayLength(elements);

    HInstruction* array_length =
        is_jsarray
            ? Add<HLoadNamedField>(object, nullptr,
                                   HObjectAccess::ForArrayLength(from_kind))
            : elements_length;

    BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
                              array_length, elements_length);

    if_builder.End();
  }

  Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
}


void HGraphBuilder::BuildJSObjectCheck(HValue* receiver,
                                       int bit_field_mask) {
  // Check that the object isn't a smi.
  Add<HCheckHeapObject>(receiver);

  // Get the map of the receiver.
  HValue* map =
      Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());

  // Check the instance type and if an access check is needed, this can be
  // done with a single load, since both bytes are adjacent in the map.
  HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
  HValue* instance_type_and_bit_field =
      Add<HLoadNamedField>(map, nullptr, access);

  HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
  HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
                                             instance_type_and_bit_field,
                                             mask);
  HValue* sub_result = AddUncasted<HSub>(and_result,
                                         Add<HConstant>(JS_OBJECT_TYPE));
  Add<HBoundsCheck>(sub_result,
                    Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE));
}


void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
                                         HIfContinuation* join_continuation) {
  // The sometimes unintuitively backward ordering of the ifs below is
  // convoluted, but necessary.  All of the paths must guarantee that the
  // if-true of the continuation returns a smi element index and the if-false of
  // the continuation returns either a symbol or a unique string key. All other
  // object types cause a deopt to fall back to the runtime.

  IfBuilder key_smi_if(this);
  key_smi_if.If<HIsSmiAndBranch>(key);
  key_smi_if.Then();
  {
    Push(key);  // Nothing to do, just continue to true of continuation.
  }
  key_smi_if.Else();
  {
    HValue* map = Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForMap());
    HValue* instance_type =
        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());

    // Non-unique string, check for a string with a hash code that is actually
    // an index.
    STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
    IfBuilder not_string_or_name_if(this);
    not_string_or_name_if.If<HCompareNumericAndBranch>(
        instance_type,
        Add<HConstant>(LAST_UNIQUE_NAME_TYPE),
        Token::GT);

    not_string_or_name_if.Then();
    {
      // Non-smi, non-Name, non-String: Try to convert to smi in case of
      // HeapNumber.
      // TODO(danno): This could call some variant of ToString
      Push(AddUncasted<HForceRepresentation>(key, Representation::Smi()));
    }
    not_string_or_name_if.Else();
    {
      // String or Name: check explicitly for Name, they can short-circuit
      // directly to unique non-index key path.
      IfBuilder not_symbol_if(this);
      not_symbol_if.If<HCompareNumericAndBranch>(
          instance_type,
          Add<HConstant>(SYMBOL_TYPE),
          Token::NE);

      not_symbol_if.Then();
      {
        // String: check whether the String is a String of an index. If it is,
        // extract the index value from the hash.
        HValue* hash = Add<HLoadNamedField>(key, nullptr,
                                            HObjectAccess::ForNameHashField());
        HValue* not_index_mask = Add<HConstant>(static_cast<int>(
            String::kContainsCachedArrayIndexMask));

        HValue* not_index_test = AddUncasted<HBitwise>(
            Token::BIT_AND, hash, not_index_mask);

        IfBuilder string_index_if(this);
        string_index_if.If<HCompareNumericAndBranch>(not_index_test,
                                                     graph()->GetConstant0(),
                                                     Token::EQ);
        string_index_if.Then();
        {
          // String with index in hash: extract string and merge to index path.
          Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
        }
        string_index_if.Else();
        {
          // Key is a non-index String, check for uniqueness/internalization.
          // If it's not internalized yet, internalize it now.
          HValue* not_internalized_bit = AddUncasted<HBitwise>(
              Token::BIT_AND,
              instance_type,
              Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));

          IfBuilder internalized(this);
          internalized.If<HCompareNumericAndBranch>(not_internalized_bit,
                                                    graph()->GetConstant0(),
                                                    Token::EQ);
          internalized.Then();
          Push(key);

          internalized.Else();
          Add<HPushArguments>(key);
          HValue* intern_key = Add<HCallRuntime>(
              Runtime::FunctionForId(Runtime::kInternalizeString), 1);
          Push(intern_key);

          internalized.End();
          // Key guaranteed to be a unique string
        }
        string_index_if.JoinContinuation(join_continuation);
      }
      not_symbol_if.Else();
      {
        Push(key);  // Key is symbol
      }
      not_symbol_if.JoinContinuation(join_continuation);
    }
    not_string_or_name_if.JoinContinuation(join_continuation);
  }
  key_smi_if.JoinContinuation(join_continuation);
}


void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) {
  // Get the the instance type of the receiver, and make sure that it is
  // not one of the global object types.
  HValue* map =
      Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
  HValue* instance_type =
      Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
  HValue* global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE);

  IfBuilder if_global_object(this);
  if_global_object.If<HCompareNumericAndBranch>(instance_type, global_type,
                                                Token::EQ);
  if_global_object.ThenDeopt(Deoptimizer::kReceiverWasAGlobalObject);
  if_global_object.End();
}


void HGraphBuilder::BuildTestForDictionaryProperties(
    HValue* object,
    HIfContinuation* continuation) {
  HValue* properties = Add<HLoadNamedField>(
      object, nullptr, HObjectAccess::ForPropertiesPointer());
  HValue* properties_map =
      Add<HLoadNamedField>(properties, nullptr, HObjectAccess::ForMap());
  HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex);
  IfBuilder builder(this);
  builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map);
  builder.CaptureContinuation(continuation);
}


HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object,
                                                 HValue* key) {
  // Load the map of the receiver, compute the keyed lookup cache hash
  // based on 32 bits of the map pointer and the string hash.
  HValue* object_map =
      Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMapAsInteger32());
  HValue* shifted_map = AddUncasted<HShr>(
      object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift));
  HValue* string_hash =
      Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForStringHashField());
  HValue* shifted_hash = AddUncasted<HShr>(
      string_hash, Add<HConstant>(String::kHashShift));
  HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map,
                                             shifted_hash);
  int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
  return AddUncasted<HBitwise>(Token::BIT_AND, xor_result,
                               Add<HConstant>(mask));
}


HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
  int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
  HValue* seed = Add<HConstant>(seed_value);
  HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);

  // hash = ~hash + (hash << 15);
  HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
  HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
                                           graph()->GetConstantMinus1());
  hash = AddUncasted<HAdd>(shifted_hash, not_hash);

  // hash = hash ^ (hash >> 12);
  shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
  hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);

  // hash = hash + (hash << 2);
  shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
  hash = AddUncasted<HAdd>(hash, shifted_hash);

  // hash = hash ^ (hash >> 4);
  shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
  hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);

  // hash = hash * 2057;
  hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
  hash->ClearFlag(HValue::kCanOverflow);

  // hash = hash ^ (hash >> 16);
  shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
  return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
}


HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
    HValue* receiver, HValue* elements, HValue* key, HValue* hash,
    LanguageMode language_mode) {
  HValue* capacity =
      Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
                      nullptr, nullptr, FAST_ELEMENTS);

  HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
  mask->ChangeRepresentation(Representation::Integer32());
  mask->ClearFlag(HValue::kCanOverflow);

  HValue* entry = hash;
  HValue* count = graph()->GetConstant1();
  Push(entry);
  Push(count);

  HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
                                              graph()->CreateBasicBlock());
  HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
                                               graph()->CreateBasicBlock());
  LoopBuilder probe_loop(this);
  probe_loop.BeginBody(2);  // Drop entry, count from last environment to
                            // appease live range building without simulates.

  count = Pop();
  entry = Pop();
  entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
  int entry_size = SeededNumberDictionary::kEntrySize;
  HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
  base_index->ClearFlag(HValue::kCanOverflow);
  int start_offset = SeededNumberDictionary::kElementsStartIndex;
  HValue* key_index =
      AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
  key_index->ClearFlag(HValue::kCanOverflow);

  HValue* candidate_key =
      Add<HLoadKeyed>(elements, key_index, nullptr, nullptr, FAST_ELEMENTS);
  IfBuilder if_undefined(this);
  if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
                                             graph()->GetConstantUndefined());
  if_undefined.Then();
  {
    // element == undefined means "not found". Call the runtime.
    // TODO(jkummerow): walk the prototype chain instead.
    Add<HPushArguments>(receiver, key);
    Push(Add<HCallRuntime>(
        Runtime::FunctionForId(is_strong(language_mode)
                                   ? Runtime::kKeyedGetPropertyStrong
                                   : Runtime::kKeyedGetProperty),
        2));
  }
  if_undefined.Else();
  {
    IfBuilder if_match(this);
    if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
    if_match.Then();
    if_match.Else();

    // Update non-internalized string in the dictionary with internalized key?
    IfBuilder if_update_with_internalized(this);
    HValue* smi_check =
        if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
    if_update_with_internalized.And();
    HValue* map = AddLoadMap(candidate_key, smi_check);
    HValue* instance_type =
        Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
    HValue* not_internalized_bit = AddUncasted<HBitwise>(
        Token::BIT_AND, instance_type,
        Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
    if_update_with_internalized.If<HCompareNumericAndBranch>(
        not_internalized_bit, graph()->GetConstant0(), Token::NE);
    if_update_with_internalized.And();
    if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
        candidate_key, graph()->GetConstantHole());
    if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
                                                               key, Token::EQ);
    if_update_with_internalized.Then();
    // Replace a key that is a non-internalized string by the equivalent
    // internalized string for faster further lookups.
    Add<HStoreKeyed>(elements, key_index, key, nullptr, FAST_ELEMENTS);
    if_update_with_internalized.Else();

    if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
    if_match.JoinContinuation(&found_key_match_continuation);

    IfBuilder found_key_match(this, &found_key_match_continuation);
    found_key_match.Then();
    // Key at current probe matches. Relevant bits in the |details| field must
    // be zero, otherwise the dictionary element requires special handling.
    HValue* details_index =
        AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
    details_index->ClearFlag(HValue::kCanOverflow);
    HValue* details = Add<HLoadKeyed>(elements, details_index, nullptr, nullptr,
                                      FAST_ELEMENTS);
    int details_mask = PropertyDetails::TypeField::kMask;
    details = AddUncasted<HBitwise>(Token::BIT_AND, details,
                                    Add<HConstant>(details_mask));
    IfBuilder details_compare(this);
    details_compare.If<HCompareNumericAndBranch>(
        details, graph()->GetConstant0(), Token::EQ);
    details_compare.Then();
    HValue* result_index =
        AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
    result_index->ClearFlag(HValue::kCanOverflow);
    Push(Add<HLoadKeyed>(elements, result_index, nullptr, nullptr,
                         FAST_ELEMENTS));
    details_compare.Else();
    Add<HPushArguments>(receiver, key);
    Push(Add<HCallRuntime>(
        Runtime::FunctionForId(is_strong(language_mode)
                                   ? Runtime::kKeyedGetPropertyStrong
                                   : Runtime::kKeyedGetProperty),
        2));
    details_compare.End();

    found_key_match.Else();
    found_key_match.JoinContinuation(&return_or_loop_continuation);
  }
  if_undefined.JoinContinuation(&return_or_loop_continuation);

  IfBuilder return_or_loop(this, &return_or_loop_continuation);
  return_or_loop.Then();
  probe_loop.Break();

  return_or_loop.Else();
  entry = AddUncasted<HAdd>(entry, count);
  entry->ClearFlag(HValue::kCanOverflow);
  count = AddUncasted<HAdd>(count, graph()->GetConstant1());
  count->ClearFlag(HValue::kCanOverflow);
  Push(entry);
  Push(count);

  probe_loop.EndBody();

  return_or_loop.End();

  return Pop();
}


HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value,
                                                   HValue* done) {
  NoObservableSideEffectsScope scope(this);

  // Allocate the JSIteratorResult object.
  HValue* result =
      Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
                     NOT_TENURED, JS_OBJECT_TYPE);

  // Initialize the JSIteratorResult object.
  HValue* native_context = BuildGetNativeContext();
  HValue* map = Add<HLoadNamedField>(
      native_context, nullptr,
      HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
  Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
  HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
  Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
                        empty_fixed_array);
  Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
                        empty_fixed_array);
  Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
                                    JSIteratorResult::kValueOffset),
                        value);
  Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
                                    JSIteratorResult::kDoneOffset),
                        done);
  STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
  return result;
}


HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
                                                  HValue* index,
                                                  HValue* input) {
  NoObservableSideEffectsScope scope(this);
  HConstant* max_length = Add<HConstant>(JSArray::kInitialMaxFastElementArray);
  Add<HBoundsCheck>(length, max_length);

  // Generate size calculation code here in order to make it dominate
  // the JSRegExpResult allocation.
  ElementsKind elements_kind = FAST_ELEMENTS;
  HValue* size = BuildCalculateElementsSize(elements_kind, length);

  // Allocate the JSRegExpResult and the FixedArray in one step.
  HValue* result = Add<HAllocate>(
      Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
      NOT_TENURED, JS_ARRAY_TYPE);

  // Initialize the JSRegExpResult header.
  HValue* native_context = Add<HLoadNamedField>(
      context(), nullptr,
      HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
  Add<HStoreNamedField>(
      result, HObjectAccess::ForMap(),
      Add<HLoadNamedField>(
          native_context, nullptr,
          HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
  HConstant* empty_fixed_array =
      Add<HConstant>(isolate()->factory()->empty_fixed_array());
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
      empty_fixed_array);
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
      empty_fixed_array);
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);

  // Initialize the additional fields.
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
      index);
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
      input);

  // Allocate and initialize the elements header.
  HAllocate* elements = BuildAllocateElements(elements_kind, size);
  BuildInitializeElementsHeader(elements, elements_kind, length);

  if (!elements->has_size_upper_bound()) {
    HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
        elements_kind, max_length->Integer32Value());
    elements->set_size_upper_bound(size_in_bytes_upper_bound);
  }

  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
      elements);

  // Initialize the elements contents with undefined.
  BuildFillElementsWithValue(
      elements, elements_kind, graph()->GetConstant0(), length,
      graph()->GetConstantUndefined());

  return result;
}


HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
  NoObservableSideEffectsScope scope(this);

  // Convert constant numbers at compile time.
  if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
    Handle<Object> number = HConstant::cast(object)->handle(isolate());
    Handle<String> result = isolate()->factory()->NumberToString(number);
    return Add<HConstant>(result);
  }

  // Create a joinable continuation.
  HIfContinuation found(graph()->CreateBasicBlock(),
                        graph()->CreateBasicBlock());

  // Load the number string cache.
  HValue* number_string_cache =
      Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);

  // Make the hash mask from the length of the number string cache. It
  // contains two elements (number and string) for each cache entry.
  HValue* mask = AddLoadFixedArrayLength(number_string_cache);
  mask->set_type(HType::Smi());
  mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
  mask = AddUncasted<HSub>(mask, graph()->GetConstant1());

  // Check whether object is a smi.
  IfBuilder if_objectissmi(this);
  if_objectissmi.If<HIsSmiAndBranch>(object);
  if_objectissmi.Then();
  {
    // Compute hash for smi similar to smi_get_hash().
    HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);

    // Load the key.
    HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
    HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
                                  nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE);

    // Check if object == key.
    IfBuilder if_objectiskey(this);
    if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
    if_objectiskey.Then();
    {
      // Make the key_index available.
      Push(key_index);
    }
    if_objectiskey.JoinContinuation(&found);
  }
  if_objectissmi.Else();
  {
    if (type->Is(Type::SignedSmall())) {
      if_objectissmi.Deopt(Deoptimizer::kExpectedSmi);
    } else {
      // Check if the object is a heap number.
      IfBuilder if_objectisnumber(this);
      HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
          object, isolate()->factory()->heap_number_map());
      if_objectisnumber.Then();
      {
        // Compute hash for heap number similar to double_get_hash().
        HValue* low = Add<HLoadNamedField>(
            object, objectisnumber,
            HObjectAccess::ForHeapNumberValueLowestBits());
        HValue* high = Add<HLoadNamedField>(
            object, objectisnumber,
            HObjectAccess::ForHeapNumberValueHighestBits());
        HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
        hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);

        // Load the key.
        HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
        HValue* key =
            Add<HLoadKeyed>(number_string_cache, key_index, nullptr, nullptr,
                            FAST_ELEMENTS, ALLOW_RETURN_HOLE);

        // Check if the key is a heap number and compare it with the object.
        IfBuilder if_keyisnotsmi(this);
        HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
        if_keyisnotsmi.Then();
        {
          IfBuilder if_keyisheapnumber(this);
          if_keyisheapnumber.If<HCompareMap>(
              key, isolate()->factory()->heap_number_map());
          if_keyisheapnumber.Then();
          {
            // Check if values of key and object match.
            IfBuilder if_keyeqobject(this);
            if_keyeqobject.If<HCompareNumericAndBranch>(
                Add<HLoadNamedField>(key, keyisnotsmi,
                                     HObjectAccess::ForHeapNumberValue()),
                Add<HLoadNamedField>(object, objectisnumber,
                                     HObjectAccess::ForHeapNumberValue()),
                Token::EQ);
            if_keyeqobject.Then();
            {
              // Make the key_index available.
              Push(key_index);
            }
            if_keyeqobject.JoinContinuation(&found);
          }
          if_keyisheapnumber.JoinContinuation(&found);
        }
        if_keyisnotsmi.JoinContinuation(&found);
      }
      if_objectisnumber.Else();
      {
        if (type->Is(Type::Number())) {
          if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber);
        }
      }
      if_objectisnumber.JoinContinuation(&found);
    }
  }
  if_objectissmi.JoinContinuation(&found);

  // Check for cache hit.
  IfBuilder if_found(this, &found);
  if_found.Then();
  {
    // Count number to string operation in native code.
    AddIncrementCounter(isolate()->counters()->number_to_string_native());

    // Load the value in case of cache hit.
    HValue* key_index = Pop();
    HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
    Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr, nullptr,
                         FAST_ELEMENTS, ALLOW_RETURN_HOLE));
  }
  if_found.Else();
  {
    // Cache miss, fallback to runtime.
    Add<HPushArguments>(object);
    Push(Add<HCallRuntime>(
            Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
            1));
  }
  if_found.End();

  return Pop();
}


HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
  NoObservableSideEffectsScope scope(this);

  // Create a joinable continuation.
  HIfContinuation wrap(graph()->CreateBasicBlock(),
                       graph()->CreateBasicBlock());

  // Determine the proper global constructor function required to wrap
  // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
  // which case we just return it.  Deopts to Runtime::kToObject if {receiver}
  // is undefined or null.
  IfBuilder receiver_is_smi(this);
  receiver_is_smi.If<HIsSmiAndBranch>(receiver);
  receiver_is_smi.Then();
  {
    // Use global Number function.
    Push(Add<HConstant>(Context::NUMBER_FUNCTION_INDEX));
  }
  receiver_is_smi.Else();
  {
    // Determine {receiver} map and instance type.
    HValue* receiver_map =
        Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
    HValue* receiver_instance_type = Add<HLoadNamedField>(
        receiver_map, nullptr, HObjectAccess::ForMapInstanceType());

    // First check whether {receiver} is already a spec object (fast case).
    IfBuilder receiver_is_not_spec_object(this);
    receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
        receiver_instance_type, Add<HConstant>(FIRST_JS_RECEIVER_TYPE),
        Token::LT);
    receiver_is_not_spec_object.Then();
    {
      // Load the constructor function index from the {receiver} map.
      HValue* constructor_function_index = Add<HLoadNamedField>(
          receiver_map, nullptr,
          HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());

      // Check if {receiver} has a constructor (null and undefined have no
      // constructors, so we deoptimize to the runtime to throw an exception).
      IfBuilder constructor_function_index_is_invalid(this);
      constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
          constructor_function_index,
          Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
      constructor_function_index_is_invalid.ThenDeopt(
          Deoptimizer::kUndefinedOrNullInToObject);
      constructor_function_index_is_invalid.End();

      // Use the global constructor function.
      Push(constructor_function_index);
    }
    receiver_is_not_spec_object.JoinContinuation(&wrap);
  }
  receiver_is_smi.JoinContinuation(&wrap);

  // Wrap the receiver if necessary.
  IfBuilder if_wrap(this, &wrap);
  if_wrap.Then();
  {
    // Grab the constructor function index.
    HValue* constructor_index = Pop();

    // Load native context.
    HValue* native_context = BuildGetNativeContext();

    // Determine the initial map for the global constructor.
    HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
                                          nullptr, nullptr, FAST_ELEMENTS);
    HValue* constructor_initial_map = Add<HLoadNamedField>(
        constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
    // Allocate and initialize a JSValue wrapper.
    HValue* value =
        BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
                      JS_VALUE_TYPE, HAllocationMode());
    Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
                          constructor_initial_map);
    HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
    Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
                          empty_fixed_array);
    Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
                          empty_fixed_array);
    Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
                                     JSValue::kValueOffset),
                          receiver);
    Push(value);
  }
  if_wrap.Else();
  { Push(receiver); }
  if_wrap.End();
  return Pop();
}


HAllocate* HGraphBuilder::BuildAllocate(
    HValue* object_size,
    HType type,
    InstanceType instance_type,
    HAllocationMode allocation_mode) {
  // Compute the effective allocation size.
  HValue* size = object_size;
  if (allocation_mode.CreateAllocationMementos()) {
    size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
    size->ClearFlag(HValue::kCanOverflow);
  }

  // Perform the actual allocation.
  HAllocate* object = Add<HAllocate>(
      size, type, allocation_mode.GetPretenureMode(),
      instance_type, allocation_mode.feedback_site());

  // Setup the allocation memento.
  if (allocation_mode.CreateAllocationMementos()) {
    BuildCreateAllocationMemento(
        object, object_size, allocation_mode.current_site());
  }

  return object;
}


HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
                                             HValue* right_length) {
  // Compute the combined string length and check against max string length.
  HValue* length = AddUncasted<HAdd>(left_length, right_length);
  // Check that length <= kMaxLength <=> length < MaxLength + 1.
  HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
  Add<HBoundsCheck>(length, max_length);
  return length;
}


HValue* HGraphBuilder::BuildCreateConsString(
    HValue* length,
    HValue* left,
    HValue* right,
    HAllocationMode allocation_mode) {
  // Determine the string instance types.
  HInstruction* left_instance_type = AddLoadStringInstanceType(left);
  HInstruction* right_instance_type = AddLoadStringInstanceType(right);

  // Allocate the cons string object. HAllocate does not care whether we
  // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
  // CONS_STRING_TYPE here. Below we decide whether the cons string is
  // one-byte or two-byte and set the appropriate map.
  DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
                                            CONS_ONE_BYTE_STRING_TYPE));
  HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
                                    HType::String(), CONS_STRING_TYPE,
                                    allocation_mode);

  // Compute intersection and difference of instance types.
  HValue* anded_instance_types = AddUncasted<HBitwise>(
      Token::BIT_AND, left_instance_type, right_instance_type);
  HValue* xored_instance_types = AddUncasted<HBitwise>(
      Token::BIT_XOR, left_instance_type, right_instance_type);

  // We create a one-byte cons string if
  // 1. both strings are one-byte, or
  // 2. at least one of the strings is two-byte, but happens to contain only
  //    one-byte characters.
  // To do this, we check
  // 1. if both strings are one-byte, or if the one-byte data hint is set in
  //    both strings, or
  // 2. if one of the strings has the one-byte data hint set and the other
  //    string is one-byte.
  IfBuilder if_onebyte(this);
  STATIC_ASSERT(kOneByteStringTag != 0);
  STATIC_ASSERT(kOneByteDataHintMask != 0);
  if_onebyte.If<HCompareNumericAndBranch>(
      AddUncasted<HBitwise>(
          Token::BIT_AND, anded_instance_types,
          Add<HConstant>(static_cast<int32_t>(
                  kStringEncodingMask | kOneByteDataHintMask))),
      graph()->GetConstant0(), Token::NE);
  if_onebyte.Or();
  STATIC_ASSERT(kOneByteStringTag != 0 &&
                kOneByteDataHintTag != 0 &&
                kOneByteDataHintTag != kOneByteStringTag);
  if_onebyte.If<HCompareNumericAndBranch>(
      AddUncasted<HBitwise>(
          Token::BIT_AND, xored_instance_types,
          Add<HConstant>(static_cast<int32_t>(
                  kOneByteStringTag | kOneByteDataHintTag))),
      Add<HConstant>(static_cast<int32_t>(
              kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
  if_onebyte.Then();
  {
    // We can safely skip the write barrier for storing the map here.
    Add<HStoreNamedField>(
        result, HObjectAccess::ForMap(),
        Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
  }
  if_onebyte.Else();
  {
    // We can safely skip the write barrier for storing the map here.
    Add<HStoreNamedField>(
        result, HObjectAccess::ForMap(),
        Add<HConstant>(isolate()->factory()->cons_string_map()));
  }
  if_onebyte.End();

  // Initialize the cons string fields.
  Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
                        Add<HConstant>(String::kEmptyHashField));
  Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
  Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
  Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);

  // Count the native string addition.
  AddIncrementCounter(isolate()->counters()->string_add_native());

  return result;
}


void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
                                            HValue* src_offset,
                                            String::Encoding src_encoding,
                                            HValue* dst,
                                            HValue* dst_offset,
                                            String::Encoding dst_encoding,
                                            HValue* length) {
  DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
         src_encoding == String::ONE_BYTE_ENCODING);
  LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
  HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
  {
    HValue* src_index = AddUncasted<HAdd>(src_offset, index);
    HValue* value =
        AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
    HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
    Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
  }
  loop.EndBody();
}


HValue* HGraphBuilder::BuildObjectSizeAlignment(
    HValue* unaligned_size, int header_size) {
  DCHECK((header_size & kObjectAlignmentMask) == 0);
  HValue* size = AddUncasted<HAdd>(
      unaligned_size, Add<HConstant>(static_cast<int32_t>(
          header_size + kObjectAlignmentMask)));
  size->ClearFlag(HValue::kCanOverflow);
  return AddUncasted<HBitwise>(
      Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
          ~kObjectAlignmentMask)));
}


HValue* HGraphBuilder::BuildUncheckedStringAdd(
    HValue* left,
    HValue* right,
    HAllocationMode allocation_mode) {
  // Determine the string lengths.
  HValue* left_length = AddLoadStringLength(left);
  HValue* right_length = AddLoadStringLength(right);

  // Compute the combined string length.
  HValue* length = BuildAddStringLengths(left_length, right_length);

  // Do some manual constant folding here.
  if (left_length->IsConstant()) {
    HConstant* c_left_length = HConstant::cast(left_length);
    DCHECK_NE(0, c_left_length->Integer32Value());
    if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
      // The right string contains at least one character.
      return BuildCreateConsString(length, left, right, allocation_mode);
    }
  } else if (right_length->IsConstant()) {
    HConstant* c_right_length = HConstant::cast(right_length);
    DCHECK_NE(0, c_right_length->Integer32Value());
    if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
      // The left string contains at least one character.
      return BuildCreateConsString(length, left, right, allocation_mode);
    }
  }

  // Check if we should create a cons string.
  IfBuilder if_createcons(this);
  if_createcons.If<HCompareNumericAndBranch>(
      length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
  if_createcons.Then();
  {
    // Create a cons string.
    Push(BuildCreateConsString(length, left, right, allocation_mode));
  }
  if_createcons.Else();
  {
    // Determine the string instance types.
    HValue* left_instance_type = AddLoadStringInstanceType(left);
    HValue* right_instance_type = AddLoadStringInstanceType(right);

    // Compute union and difference of instance types.
    HValue* ored_instance_types = AddUncasted<HBitwise>(
        Token::BIT_OR, left_instance_type, right_instance_type);
    HValue* xored_instance_types = AddUncasted<HBitwise>(
        Token::BIT_XOR, left_instance_type, right_instance_type);

    // Check if both strings have the same encoding and both are
    // sequential.
    IfBuilder if_sameencodingandsequential(this);
    if_sameencodingandsequential.If<HCompareNumericAndBranch>(
        AddUncasted<HBitwise>(
            Token::BIT_AND, xored_instance_types,
            Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
        graph()->GetConstant0(), Token::EQ);
    if_sameencodingandsequential.And();
    STATIC_ASSERT(kSeqStringTag == 0);
    if_sameencodingandsequential.If<HCompareNumericAndBranch>(
        AddUncasted<HBitwise>(
            Token::BIT_AND, ored_instance_types,
            Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
        graph()->GetConstant0(), Token::EQ);
    if_sameencodingandsequential.Then();
    {
      HConstant* string_map =
          Add<HConstant>(isolate()->factory()->string_map());
      HConstant* one_byte_string_map =
          Add<HConstant>(isolate()->factory()->one_byte_string_map());

      // Determine map and size depending on whether result is one-byte string.
      IfBuilder if_onebyte(this);
      STATIC_ASSERT(kOneByteStringTag != 0);
      if_onebyte.If<HCompareNumericAndBranch>(
          AddUncasted<HBitwise>(
              Token::BIT_AND, ored_instance_types,
              Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
          graph()->GetConstant0(), Token::NE);
      if_onebyte.Then();
      {
        // Allocate sequential one-byte string object.
        Push(length);
        Push(one_byte_string_map);
      }
      if_onebyte.Else();
      {
        // Allocate sequential two-byte string object.
        HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
        size->ClearFlag(HValue::kCanOverflow);
        size->SetFlag(HValue::kUint32);
        Push(size);
        Push(string_map);
      }
      if_onebyte.End();
      HValue* map = Pop();

      // Calculate the number of bytes needed for the characters in the
      // string while observing object alignment.
      STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
      HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);

      IfBuilder if_size(this);
      if_size.If<HCompareNumericAndBranch>(
          size, Add<HConstant>(Page::kMaxRegularHeapObjectSize), Token::LT);
      if_size.Then();
      {
        // Allocate the string object. HAllocate does not care whether we pass
        // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
        HAllocate* result =
            BuildAllocate(size, HType::String(), STRING_TYPE, allocation_mode);
        Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);

        // Initialize the string fields.
        Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
                              Add<HConstant>(String::kEmptyHashField));
        Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);

        // Copy characters to the result string.
        IfBuilder if_twobyte(this);
        if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
        if_twobyte.Then();
        {
          // Copy characters from the left string.
          BuildCopySeqStringChars(
              left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
              graph()->GetConstant0(), String::TWO_BYTE_ENCODING, left_length);

          // Copy characters from the right string.
          BuildCopySeqStringChars(
              right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
              left_length, String::TWO_BYTE_ENCODING, right_length);
        }
        if_twobyte.Else();
        {
          // Copy characters from the left string.
          BuildCopySeqStringChars(
              left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
              graph()->GetConstant0(), String::ONE_BYTE_ENCODING, left_length);

          // Copy characters from the right string.
          BuildCopySeqStringChars(
              right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
              left_length, String::ONE_BYTE_ENCODING, right_length);
        }
        if_twobyte.End();

        // Count the native string addition.
        AddIncrementCounter(isolate()->counters()->string_add_native());

        // Return the sequential string.
        Push(result);
      }
      if_size.Else();
      {
        // Fallback to the runtime to add the two strings. The string has to be
        // allocated in LO space.
        Add<HPushArguments>(left, right);
        Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
      }
      if_size.End();
    }
    if_sameencodingandsequential.Else();
    {
      // Fallback to the runtime to add the two strings.
      Add<HPushArguments>(left, right);
      Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
    }
    if_sameencodingandsequential.End();
  }
  if_createcons.End();

  return Pop();
}


HValue* HGraphBuilder::BuildStringAdd(
    HValue* left,
    HValue* right,
    HAllocationMode allocation_mode) {
  NoObservableSideEffectsScope no_effects(this);

  // Determine string lengths.
  HValue* left_length = AddLoadStringLength(left);
  HValue* right_length = AddLoadStringLength(right);

  // Check if left string is empty.
  IfBuilder if_leftempty(this);
  if_leftempty.If<HCompareNumericAndBranch>(
      left_length, graph()->GetConstant0(), Token::EQ);
  if_leftempty.Then();
  {
    // Count the native string addition.
    AddIncrementCounter(isolate()->counters()->string_add_native());

    // Just return the right string.
    Push(right);
  }
  if_leftempty.Else();
  {
    // Check if right string is empty.
    IfBuilder if_rightempty(this);
    if_rightempty.If<HCompareNumericAndBranch>(
        right_length, graph()->GetConstant0(), Token::EQ);
    if_rightempty.Then();
    {
      // Count the native string addition.
      AddIncrementCounter(isolate()->counters()->string_add_native());

      // Just return the left string.
      Push(left);
    }
    if_rightempty.Else();
    {
      // Add the two non-empty strings.
      Push(BuildUncheckedStringAdd(left, right, allocation_mode));
    }
    if_rightempty.End();
  }
  if_leftempty.End();

  return Pop();
}


HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
    HValue* checked_object,
    HValue* key,
    HValue* val,
    bool is_js_array,
    ElementsKind elements_kind,
    PropertyAccessType access_type,
    LoadKeyedHoleMode load_mode,
    KeyedAccessStoreMode store_mode) {
  DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
         checked_object->IsCheckMaps());
  DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array);
  // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
  // on a HElementsTransition instruction. The flag can also be removed if the
  // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
  // ElementsKind transitions. Finally, the dependency can be removed for stores
  // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
  // generated store code.
  if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
      (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
    checked_object->ClearDependsOnFlag(kElementsKind);
  }

  bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
  bool fast_elements = IsFastObjectElementsKind(elements_kind);
  HValue* elements = AddLoadElements(checked_object);
  if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
      store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
    HCheckMaps* check_cow_map = Add<HCheckMaps>(
        elements, isolate()->factory()->fixed_array_map());
    check_cow_map->ClearDependsOnFlag(kElementsKind);
  }
  HInstruction* length = NULL;
  if (is_js_array) {
    length = Add<HLoadNamedField>(
        checked_object->ActualValue(), checked_object,
        HObjectAccess::ForArrayLength(elements_kind));
  } else {
    length = AddLoadFixedArrayLength(elements);
  }
  length->set_type(HType::Smi());
  HValue* checked_key = NULL;
  if (IsFixedTypedArrayElementsKind(elements_kind)) {
    checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);

    HValue* external_pointer = Add<HLoadNamedField>(
        elements, nullptr,
        HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
    HValue* base_pointer = Add<HLoadNamedField>(
        elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
    HValue* backing_store = AddUncasted<HAdd>(
        external_pointer, base_pointer, Strength::WEAK, AddOfExternalAndTagged);

    if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
      NoObservableSideEffectsScope no_effects(this);
      IfBuilder length_checker(this);
      length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
      length_checker.Then();
      IfBuilder negative_checker(this);
      HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
          key, graph()->GetConstant0(), Token::GTE);
      negative_checker.Then();
      HInstruction* result = AddElementAccess(
          backing_store, key, val, bounds_check, checked_object->ActualValue(),
          elements_kind, access_type);
      negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered);
      negative_checker.End();
      length_checker.End();
      return result;
    } else {
      DCHECK(store_mode == STANDARD_STORE);
      checked_key = Add<HBoundsCheck>(key, length);
      return AddElementAccess(backing_store, checked_key, val, checked_object,
                              checked_object->ActualValue(), elements_kind,
                              access_type);
    }
  }
  DCHECK(fast_smi_only_elements ||
         fast_elements ||
         IsFastDoubleElementsKind(elements_kind));

  // In case val is stored into a fast smi array, assure that the value is a smi
  // before manipulating the backing store. Otherwise the actual store may
  // deopt, leaving the backing store in an invalid state.
  if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
      !val->type().IsSmi()) {
    val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
  }

  if (IsGrowStoreMode(store_mode)) {
    NoObservableSideEffectsScope no_effects(this);
    Representation representation = HStoreKeyed::RequiredValueRepresentation(
        elements_kind, STORE_TO_INITIALIZED_ENTRY);
    val = AddUncasted<HForceRepresentation>(val, representation);
    elements = BuildCheckForCapacityGrow(checked_object, elements,
                                         elements_kind, length, key,
                                         is_js_array, access_type);
    checked_key = key;
  } else {
    checked_key = Add<HBoundsCheck>(key, length);

    if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
      if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
        NoObservableSideEffectsScope no_effects(this);
        elements = BuildCopyElementsOnWrite(checked_object, elements,
                                            elements_kind, length);
      } else {
        HCheckMaps* check_cow_map = Add<HCheckMaps>(
            elements, isolate()->factory()->fixed_array_map());
        check_cow_map->ClearDependsOnFlag(kElementsKind);
      }
    }
  }
  return AddElementAccess(elements, checked_key, val, checked_object, nullptr,
                          elements_kind, access_type, load_mode);
}


HValue* HGraphBuilder::BuildAllocateArrayFromLength(
    JSArrayBuilder* array_builder,
    HValue* length_argument) {
  if (length_argument->IsConstant() &&
      HConstant::cast(length_argument)->HasSmiValue()) {
    int array_length = HConstant::cast(length_argument)->Integer32Value();
    if (array_length == 0) {
      return array_builder->AllocateEmptyArray();
    } else {
      return array_builder->AllocateArray(length_argument,
                                          array_length,
                                          length_argument);
    }
  }

  HValue* constant_zero = graph()->GetConstant0();
  HConstant* max_alloc_length =
      Add<HConstant>(JSArray::kInitialMaxFastElementArray);
  HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
                                                   max_alloc_length);
  IfBuilder if_builder(this);
  if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
                                          Token::EQ);
  if_builder.Then();
  const int initial_capacity = JSArray::kPreallocatedArrayElements;
  HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
  Push(initial_capacity_node);  // capacity
  Push(constant_zero);          // length
  if_builder.Else();
  if (!(top_info()->IsStub()) &&
      IsFastPackedElementsKind(array_builder->kind())) {
    // We'll come back later with better (holey) feedback.
    if_builder.Deopt(
        Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback);
  } else {
    Push(checked_length);         // capacity
    Push(checked_length);         // length
  }
  if_builder.End();

  // Figure out total size
  HValue* length = Pop();
  HValue* capacity = Pop();
  return array_builder->AllocateArray(capacity, max_alloc_length, length);
}


HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
                                                  HValue* capacity) {
  int elements_size = IsFastDoubleElementsKind(kind)
      ? kDoubleSize
      : kPointerSize;

  HConstant* elements_size_value = Add<HConstant>(elements_size);
  HInstruction* mul =
      HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
                    elements_size_value);
  AddInstruction(mul);
  mul->ClearFlag(HValue::kCanOverflow);

  STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);

  HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
  HValue* total_size = AddUncasted<HAdd>(mul, header_size);
  total_size->ClearFlag(HValue::kCanOverflow);
  return total_size;
}


HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
  int base_size = JSArray::kSize;
  if (mode == TRACK_ALLOCATION_SITE) {
    base_size += AllocationMemento::kSize;
  }
  HConstant* size_in_bytes = Add<HConstant>(base_size);
  return Add<HAllocate>(
      size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
}


HConstant* HGraphBuilder::EstablishElementsAllocationSize(
    ElementsKind kind,
    int capacity) {
  int base_size = IsFastDoubleElementsKind(kind)
      ? FixedDoubleArray::SizeFor(capacity)
      : FixedArray::SizeFor(capacity);

  return Add<HConstant>(base_size);
}


HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
                                                HValue* size_in_bytes) {
  InstanceType instance_type = IsFastDoubleElementsKind(kind)
      ? FIXED_DOUBLE_ARRAY_TYPE
      : FIXED_ARRAY_TYPE;

  return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
                        instance_type);
}


void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
                                                  ElementsKind kind,
                                                  HValue* capacity) {
  Factory* factory = isolate()->factory();
  Handle<Map> map = IsFastDoubleElementsKind(kind)
      ? factory->fixed_double_array_map()
      : factory->fixed_array_map();

  Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
  Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
                        capacity);
}


HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
                                                       HValue* capacity) {
  // The HForceRepresentation is to prevent possible deopt on int-smi
  // conversion after allocation but before the new object fields are set.
  capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
  HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
  HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
  BuildInitializeElementsHeader(new_array, kind, capacity);
  return new_array;
}


void HGraphBuilder::BuildJSArrayHeader(HValue* array,
                                       HValue* array_map,
                                       HValue* elements,
                                       AllocationSiteMode mode,
                                       ElementsKind elements_kind,
                                       HValue* allocation_site_payload,
                                       HValue* length_field) {
  Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);

  HConstant* empty_fixed_array =
    Add<HConstant>(isolate()->factory()->empty_fixed_array());

  Add<HStoreNamedField>(
      array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);

  Add<HStoreNamedField>(
      array, HObjectAccess::ForElementsPointer(),
      elements != NULL ? elements : empty_fixed_array);

  Add<HStoreNamedField>(
      array, HObjectAccess::ForArrayLength(elements_kind), length_field);

  if (mode == TRACK_ALLOCATION_SITE) {
    BuildCreateAllocationMemento(
        array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
  }
}


HInstruction* HGraphBuilder::AddElementAccess(
    HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
    HValue* backing_store_owner, ElementsKind elements_kind,
    PropertyAccessType access_type, LoadKeyedHoleMode load_mode) {
  if (access_type == STORE) {
    DCHECK(val != NULL);
    if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
      val = Add<HClampToUint8>(val);
    }
    return Add<HStoreKeyed>(elements, checked_key, val, backing_store_owner,
                            elements_kind, STORE_TO_INITIALIZED_ENTRY);
  }

  DCHECK(access_type == LOAD);
  DCHECK(val == NULL);
  HLoadKeyed* load =
      Add<HLoadKeyed>(elements, checked_key, dependency, backing_store_owner,
                      elements_kind, load_mode);
  if (elements_kind == UINT32_ELEMENTS) {
    graph()->RecordUint32Instruction(load);
  }
  return load;
}


HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
                                           HValue* dependency) {
  return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
}


HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
                                                HValue* dependency) {
  return Add<HLoadNamedField>(
      object, dependency, HObjectAccess::ForElementsPointer());
}


HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
    HValue* array,
    HValue* dependency) {
  return Add<HLoadNamedField>(
      array, dependency, HObjectAccess::ForFixedArrayLength());
}


HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
                                                   ElementsKind kind,
                                                   HValue* dependency) {
  return Add<HLoadNamedField>(
      array, dependency, HObjectAccess::ForArrayLength(kind));
}


HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
  HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
                                                graph_->GetConstant1());

  HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
  new_capacity->ClearFlag(HValue::kCanOverflow);

  HValue* min_growth = Add<HConstant>(16);

  new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
  new_capacity->ClearFlag(HValue::kCanOverflow);

  return new_capacity;
}


HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
                                                 HValue* elements,
                                                 ElementsKind kind,
                                                 ElementsKind new_kind,
                                                 HValue* length,
                                                 HValue* new_capacity) {
  Add<HBoundsCheck>(new_capacity, Add<HConstant>(
          (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
          ElementsKindToShiftSize(new_kind)));

  HValue* new_elements =
      BuildAllocateAndInitializeArray(new_kind, new_capacity);

  BuildCopyElements(elements, kind, new_elements,
                    new_kind, length, new_capacity);

  Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
                        new_elements);

  return new_elements;
}


void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
                                               ElementsKind elements_kind,
                                               HValue* from,
                                               HValue* to,
                                               HValue* value) {
  if (to == NULL) {
    to = AddLoadFixedArrayLength(elements);
  }

  // Special loop unfolding case
  STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
                kElementLoopUnrollThreshold);
  int initial_capacity = -1;
  if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
    int constant_from = from->GetInteger32Constant();
    int constant_to = to->GetInteger32Constant();

    if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
      initial_capacity = constant_to;
    }
  }

  if (initial_capacity >= 0) {
    for (int i = 0; i < initial_capacity; i++) {
      HInstruction* key = Add<HConstant>(i);
      Add<HStoreKeyed>(elements, key, value, nullptr, elements_kind);
    }
  } else {
    // Carefully loop backwards so that the "from" remains live through the loop
    // rather than the to. This often corresponds to keeping length live rather
    // then capacity, which helps register allocation, since length is used more
    // other than capacity after filling with holes.
    LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);

    HValue* key = builder.BeginBody(to, from, Token::GT);

    HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
    adjusted_key->ClearFlag(HValue::kCanOverflow);

    Add<HStoreKeyed>(elements, adjusted_key, value, nullptr, elements_kind);

    builder.EndBody();
  }
}


void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
                                              ElementsKind elements_kind,
                                              HValue* from,
                                              HValue* to) {
  // Fast elements kinds need to be initialized in case statements below cause a
  // garbage collection.

  HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
                     ? graph()->GetConstantHole()
                     : Add<HConstant>(HConstant::kHoleNaN);

  // Since we're about to store a hole value, the store instruction below must
  // assume an elements kind that supports heap object values.
  if (IsFastSmiOrObjectElementsKind(elements_kind)) {
    elements_kind = FAST_HOLEY_ELEMENTS;
  }

  BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
}


void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
                                        HValue* to_properties, HValue* length,
                                        HValue* capacity) {
  ElementsKind kind = FAST_ELEMENTS;

  BuildFillElementsWithValue(to_properties, kind, length, capacity,
                             graph()->GetConstantUndefined());

  LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);

  HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);

  key = AddUncasted<HSub>(key, graph()->GetConstant1());
  key->ClearFlag(HValue::kCanOverflow);

  HValue* element =
      Add<HLoadKeyed>(from_properties, key, nullptr, nullptr, kind);

  Add<HStoreKeyed>(to_properties, key, element, nullptr, kind);

  builder.EndBody();
}


void HGraphBuilder::BuildCopyElements(HValue* from_elements,
                                      ElementsKind from_elements_kind,
                                      HValue* to_elements,
                                      ElementsKind to_elements_kind,
                                      HValue* length,
                                      HValue* capacity) {
  int constant_capacity = -1;
  if (capacity != NULL &&
      capacity->IsConstant() &&
      HConstant::cast(capacity)->HasInteger32Value()) {
    int constant_candidate = HConstant::cast(capacity)->Integer32Value();
    if (constant_candidate <= kElementLoopUnrollThreshold) {
      constant_capacity = constant_candidate;
    }
  }

  bool pre_fill_with_holes =
    IsFastDoubleElementsKind(from_elements_kind) &&
    IsFastObjectElementsKind(to_elements_kind);
  if (pre_fill_with_holes) {
    // If the copy might trigger a GC, make sure that the FixedArray is
    // pre-initialized with holes to make sure that it's always in a
    // consistent state.
    BuildFillElementsWithHole(to_elements, to_elements_kind,
                              graph()->GetConstant0(), NULL);
  }

  if (constant_capacity != -1) {
    // Unroll the loop for small elements kinds.
    for (int i = 0; i < constant_capacity; i++) {
      HValue* key_constant = Add<HConstant>(i);
      HInstruction* value = Add<HLoadKeyed>(
          from_elements, key_constant, nullptr, nullptr, from_elements_kind);
      Add<HStoreKeyed>(to_elements, key_constant, value, nullptr,
                       to_elements_kind);
    }
  } else {
    if (!pre_fill_with_holes &&
        (capacity == NULL || !length->Equals(capacity))) {
      BuildFillElementsWithHole(to_elements, to_elements_kind,
                                length, NULL);
    }

    LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);

    HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
                                    Token::GT);

    key = AddUncasted<HSub>(key, graph()->GetConstant1());
    key->ClearFlag(HValue::kCanOverflow);

    HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr, nullptr,
                                      from_elements_kind, ALLOW_RETURN_HOLE);

    ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
                         IsFastSmiElementsKind(to_elements_kind))
      ? FAST_HOLEY_ELEMENTS : to_elements_kind;

    if (IsHoleyElementsKind(from_elements_kind) &&
        from_elements_kind != to_elements_kind) {
      IfBuilder if_hole(this);
      if_hole.If<HCompareHoleAndBranch>(element);
      if_hole.Then();
      HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
                                     ? Add<HConstant>(HConstant::kHoleNaN)
                                     : graph()->GetConstantHole();
      Add<HStoreKeyed>(to_elements, key, hole_constant, nullptr, kind);
      if_hole.Else();
      HStoreKeyed* store =
          Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
      store->SetFlag(HValue::kAllowUndefinedAsNaN);
      if_hole.End();
    } else {
      HStoreKeyed* store =
          Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
      store->SetFlag(HValue::kAllowUndefinedAsNaN);
    }

    builder.EndBody();
  }

  Counters* counters = isolate()->counters();
  AddIncrementCounter(counters->inlined_copied_elements());
}


HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate,
                                                 HValue* allocation_site,
                                                 AllocationSiteMode mode,
                                                 ElementsKind kind) {
  HAllocate* array = AllocateJSArrayObject(mode);

  HValue* map = AddLoadMap(boilerplate);
  HValue* elements = AddLoadElements(boilerplate);
  HValue* length = AddLoadArrayLength(boilerplate, kind);

  BuildJSArrayHeader(array,
                     map,
                     elements,
                     mode,
                     FAST_ELEMENTS,
                     allocation_site,
                     length);
  return array;
}


HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate,
                                                   HValue* allocation_site,
                                                   AllocationSiteMode mode) {
  HAllocate* array = AllocateJSArrayObject(mode);

  HValue* map = AddLoadMap(boilerplate);

  BuildJSArrayHeader(array,
                     map,
                     NULL,  // set elements to empty fixed array
                     mode,
                     FAST_ELEMENTS,
                     allocation_site,
                     graph()->GetConstant0());
  return array;
}


HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
                                                      HValue* allocation_site,
                                                      AllocationSiteMode mode,
                                                      ElementsKind kind) {
  HValue* boilerplate_elements = AddLoadElements(boilerplate);
  HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);

  // Generate size calculation code here in order to make it dominate
  // the JSArray allocation.
  HValue* elements_size = BuildCalculateElementsSize(kind, capacity);

  // Create empty JSArray object for now, store elimination should remove
  // redundant initialization of elements and length fields and at the same
  // time the object will be fully prepared for GC if it happens during
  // elements allocation.
  HValue* result = BuildCloneShallowArrayEmpty(
      boilerplate, allocation_site, mode);

  HAllocate* elements = BuildAllocateElements(kind, elements_size);

  // This function implicitly relies on the fact that the
  // FastCloneShallowArrayStub is called only for literals shorter than
  // JSArray::kInitialMaxFastElementArray.
  // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
  HConstant* size_upper_bound = EstablishElementsAllocationSize(
      kind, JSArray::kInitialMaxFastElementArray);
  elements->set_size_upper_bound(size_upper_bound);

  Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);

  // The allocation for the cloned array above causes register pressure on
  // machines with low register counts. Force a reload of the boilerplate
  // elements here to free up a register for the allocation to avoid unnecessary
  // spillage.
  boilerplate_elements = AddLoadElements(boilerplate);
  boilerplate_elements->SetFlag(HValue::kCantBeReplaced);

  // Copy the elements array header.
  for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
    HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
    Add<HStoreNamedField>(
        elements, access,
        Add<HLoadNamedField>(boilerplate_elements, nullptr, access));
  }

  // And the result of the length
  HValue* length = AddLoadArrayLength(boilerplate, kind);
  Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);

  BuildCopyElements(boilerplate_elements, kind, elements,
                    kind, length, NULL);
  return result;
}


void HGraphBuilder::BuildCompareNil(HValue* value, Type* type,
                                    HIfContinuation* continuation,
                                    MapEmbedding map_embedding) {
  IfBuilder if_nil(this);

  if (type->Maybe(Type::Undetectable())) {
    if_nil.If<HIsUndetectableAndBranch>(value);
  } else {
    bool maybe_null = type->Maybe(Type::Null());
    if (maybe_null) {
      if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
    }

    if (type->Maybe(Type::Undefined())) {
      if (maybe_null) if_nil.Or();
      if_nil.If<HCompareObjectEqAndBranch>(value,
                                           graph()->GetConstantUndefined());
    }

    if_nil.Then();
    if_nil.Else();

    if (type->NumClasses() == 1) {
      BuildCheckHeapObject(value);
      // For ICs, the map checked below is a sentinel map that gets replaced by
      // the monomorphic map when the code is used as a template to generate a
      // new IC. For optimized functions, there is no sentinel map, the map
      // emitted below is the actual monomorphic map.
      if (map_embedding == kEmbedMapsViaWeakCells) {
        HValue* cell =
            Add<HConstant>(Map::WeakCellForMap(type->Classes().Current()));
        HValue* expected_map = Add<HLoadNamedField>(
            cell, nullptr, HObjectAccess::ForWeakCellValue());
        HValue* map =
            Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap());
        IfBuilder map_check(this);
        map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
        map_check.ThenDeopt(Deoptimizer::kUnknownMap);
        map_check.End();
      } else {
        DCHECK(map_embedding == kEmbedMapsDirectly);
        Add<HCheckMaps>(value, type->Classes().Current());
      }
    } else {
      if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes);
    }
  }

  if_nil.CaptureContinuation(continuation);
}


void HGraphBuilder::BuildCreateAllocationMemento(
    HValue* previous_object,
    HValue* previous_object_size,
    HValue* allocation_site) {
  DCHECK(allocation_site != NULL);
  HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
      previous_object, previous_object_size, HType::HeapObject());
  AddStoreMapConstant(
      allocation_memento, isolate()->factory()->allocation_memento_map());
  Add<HStoreNamedField>(
      allocation_memento,
      HObjectAccess::ForAllocationMementoSite(),
      allocation_site);
  if (FLAG_allocation_site_pretenuring) {
    HValue* memento_create_count =
        Add<HLoadNamedField>(allocation_site, nullptr,
                             HObjectAccess::ForAllocationSiteOffset(
                                 AllocationSite::kPretenureCreateCountOffset));
    memento_create_count = AddUncasted<HAdd>(
        memento_create_count, graph()->GetConstant1());
    // This smi value is reset to zero after every gc, overflow isn't a problem
    // since the counter is bounded by the new space size.
    memento_create_count->ClearFlag(HValue::kCanOverflow);
    Add<HStoreNamedField>(
        allocation_site, HObjectAccess::ForAllocationSiteOffset(
            AllocationSite::kPretenureCreateCountOffset), memento_create_count);
  }
}


HInstruction* HGraphBuilder::BuildGetNativeContext() {
  return Add<HLoadNamedField>(
      context(), nullptr,
      HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
}


HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
  // Get the global object, then the native context
  HInstruction* context = Add<HLoadNamedField>(
      closure, nullptr, HObjectAccess::ForFunctionContextPointer());
  return Add<HLoadNamedField>(
      context, nullptr,
      HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
}


HInstruction* HGraphBuilder::BuildGetScriptContext(int context_index) {
  HValue* native_context = BuildGetNativeContext();
  HValue* script_context_table = Add<HLoadNamedField>(
      native_context, nullptr,
      HObjectAccess::ForContextSlot(Context::SCRIPT_CONTEXT_TABLE_INDEX));
  return Add<HLoadNamedField>(script_context_table, nullptr,
                              HObjectAccess::ForScriptContext(context_index));
}


HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) {
  HValue* script_context = context();
  if (depth != NULL) {
    HValue* zero = graph()->GetConstant0();

    Push(script_context);
    Push(depth);

    LoopBuilder loop(this);
    loop.BeginBody(2);  // Drop script_context and depth from last environment
                        // to appease live range building without simulates.
    depth = Pop();
    script_context = Pop();

    script_context = Add<HLoadNamedField>(
        script_context, nullptr,
        HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    depth = AddUncasted<HSub>(depth, graph()->GetConstant1());
    depth->ClearFlag(HValue::kCanOverflow);

    IfBuilder if_break(this);
    if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ);
    if_break.Then();
    {
      Push(script_context);  // The result.
      loop.Break();
    }
    if_break.Else();
    {
      Push(script_context);
      Push(depth);
    }
    loop.EndBody();
    if_break.End();

    script_context = Pop();
  } else if (depth_value > 0) {
    // Unroll the above loop.
    for (int i = 0; i < depth_value; i++) {
      script_context = Add<HLoadNamedField>(
          script_context, nullptr,
          HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
    }
  }
  return script_context;
}


HInstruction* HGraphBuilder::BuildGetArrayFunction() {
  HInstruction* native_context = BuildGetNativeContext();
  HInstruction* index =
      Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
  return Add<HLoadKeyed>(native_context, index, nullptr, nullptr,
                         FAST_ELEMENTS);
}


HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
                                                         HValue* checked_object,
                                                         FieldIndex index) {
  NoObservableSideEffectsScope scope(this);
  HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
      index.offset(), Representation::Tagged());
  HInstruction* buffer = Add<HLoadNamedField>(
      object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
  HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);

  HInstruction* flags = Add<HLoadNamedField>(
      buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
  HValue* was_neutered_mask =
      Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
  HValue* was_neutered_test =
      AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);

  IfBuilder if_was_neutered(this);
  if_was_neutered.If<HCompareNumericAndBranch>(
      was_neutered_test, graph()->GetConstant0(), Token::NE);
  if_was_neutered.Then();
  Push(graph()->GetConstant0());
  if_was_neutered.Else();
  Push(field);
  if_was_neutered.End();

  return Pop();
}


HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
    ElementsKind kind,
    HValue* allocation_site_payload,
    HValue* constructor_function,
    AllocationSiteOverrideMode override_mode) :
        builder_(builder),
        kind_(kind),
        allocation_site_payload_(allocation_site_payload),
        constructor_function_(constructor_function) {
  DCHECK(!allocation_site_payload->IsConstant() ||
         HConstant::cast(allocation_site_payload)->handle(
             builder_->isolate())->IsAllocationSite());
  mode_ = override_mode == DISABLE_ALLOCATION_SITES
      ? DONT_TRACK_ALLOCATION_SITE
      : AllocationSite::GetMode(kind);
}


HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
                                              ElementsKind kind,
                                              HValue* constructor_function) :
    builder_(builder),
    kind_(kind),
    mode_(DONT_TRACK_ALLOCATION_SITE),
    allocation_site_payload_(NULL),
    constructor_function_(constructor_function) {
}


HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
  if (!builder()->top_info()->IsStub()) {
    // A constant map is fine.
    Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
                    builder()->isolate());
    return builder()->Add<HConstant>(map);
  }

  if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
    // No need for a context lookup if the kind_ matches the initial
    // map, because we can just load the map in that case.
    HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
    return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
                                           access);
  }

  // TODO(mvstanton): we should always have a constructor function if we
  // are creating a stub.
  HInstruction* native_context = constructor_function_ != NULL
      ? builder()->BuildGetNativeContext(constructor_function_)
      : builder()->BuildGetNativeContext();

  HObjectAccess access =
      HObjectAccess::ForContextSlot(Context::ArrayMapIndex(kind_));
  return builder()->Add<HLoadNamedField>(native_context, nullptr, access);
}


HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
  // Find the map near the constructor function
  HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
  return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
                                         access);
}


HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
  HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
  return AllocateArray(capacity,
                       capacity,
                       builder()->graph()->GetConstant0());
}


HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
    HValue* capacity,
    HConstant* capacity_upper_bound,
    HValue* length_field,
    FillMode fill_mode) {
  return AllocateArray(capacity,
                       capacity_upper_bound->GetInteger32Constant(),
                       length_field,
                       fill_mode);
}


HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
    HValue* capacity,
    int capacity_upper_bound,
    HValue* length_field,
    FillMode fill_mode) {
  HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
      ? HConstant::cast(capacity)
      : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);

  HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
  if (!elements_location_->has_size_upper_bound()) {
    elements_location_->set_size_upper_bound(elememts_size_upper_bound);
  }
  return array;
}


HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
    HValue* capacity,
    HValue* length_field,
    FillMode fill_mode) {
  // These HForceRepresentations are because we store these as fields in the
  // objects we construct, and an int32-to-smi HChange could deopt. Accept
  // the deopt possibility now, before allocation occurs.
  capacity =
      builder()->AddUncasted<HForceRepresentation>(capacity,
                                                   Representation::Smi());
  length_field =
      builder()->AddUncasted<HForceRepresentation>(length_field,
                                                   Representation::Smi());

  // Generate size calculation code here in order to make it dominate
  // the JSArray allocation.
  HValue* elements_size =
      builder()->BuildCalculateElementsSize(kind_, capacity);

  // Bail out for large objects.
  HValue* max_regular_heap_object_size =
      builder()->Add<HConstant>(Page::kMaxRegularHeapObjectSize);
  builder()->Add<HBoundsCheck>(elements_size, max_regular_heap_object_size);

  // Allocate (dealing with failure appropriately)
  HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);

  // Fill in the fields: map, properties, length
  HValue* map;
  if (allocation_site_payload_ == NULL) {
    map = EmitInternalMapCode();
  } else {
    map = EmitMapCode();
  }

  builder()->BuildJSArrayHeader(array_object,
                                map,
                                NULL,  // set elements to empty fixed array
                                mode_,
                                kind_,
                                allocation_site_payload_,
                                length_field);

  // Allocate and initialize the elements
  elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);

  builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);

  // Set the elements
  builder()->Add<HStoreNamedField>(
      array_object, HObjectAccess::ForElementsPointer(), elements_location_);

  if (fill_mode == FILL_WITH_HOLE) {
    builder()->BuildFillElementsWithHole(elements_location_, kind_,
                                         graph()->GetConstant0(), capacity);
  }

  return array_object;
}


HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
  HValue* native_context = BuildGetNativeContext();
  HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
  return Add<HLoadNamedField>(native_context, nullptr, function_access);
}


HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
    : HGraphBuilder(info, CallInterfaceDescriptor()),
      function_state_(NULL),
      initial_function_state_(this, info, NORMAL_RETURN, 0),
      ast_context_(NULL),
      break_scope_(NULL),
      inlined_count_(0),
      globals_(10, info->zone()),
      osr_(new (info->zone()) HOsrBuilder(this)) {
  // This is not initialized in the initializer list because the
  // constructor for the initial state relies on function_state_ == NULL
  // to know it's the initial state.
  function_state_ = &initial_function_state_;
  InitializeAstVisitor(info->isolate());
  if (top_info()->is_tracking_positions()) {
    SetSourcePosition(info->shared_info()->start_position());
  }
}


HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
                                                HBasicBlock* second,
                                                BailoutId join_id) {
  if (first == NULL) {
    return second;
  } else if (second == NULL) {
    return first;
  } else {
    HBasicBlock* join_block = graph()->CreateBasicBlock();
    Goto(first, join_block);
    Goto(second, join_block);
    join_block->SetJoinId(join_id);
    return join_block;
  }
}


HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
                                                  HBasicBlock* exit_block,
                                                  HBasicBlock* continue_block) {
  if (continue_block != NULL) {
    if (exit_block != NULL) Goto(exit_block, continue_block);
    continue_block->SetJoinId(statement->ContinueId());
    return continue_block;
  }
  return exit_block;
}


HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
                                                HBasicBlock* loop_entry,
                                                HBasicBlock* body_exit,
                                                HBasicBlock* loop_successor,
                                                HBasicBlock* break_block) {
  if (body_exit != NULL) Goto(body_exit, loop_entry);
  loop_entry->PostProcessLoopHeader(statement);
  if (break_block != NULL) {
    if (loop_successor != NULL) Goto(loop_successor, break_block);
    break_block->SetJoinId(statement->ExitId());
    return break_block;
  }
  return loop_successor;
}


// Build a new loop header block and set it as the current block.
HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
  HBasicBlock* loop_entry = CreateLoopHeaderBlock();
  Goto(loop_entry);
  set_current_block(loop_entry);
  return loop_entry;
}


HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
    IterationStatement* statement) {
  HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
      ? osr()->BuildOsrLoopEntry(statement)
      : BuildLoopEntry();
  return loop_entry;
}


void HBasicBlock::FinishExit(HControlInstruction* instruction,
                             SourcePosition position) {
  Finish(instruction, position);
  ClearEnvironment();
}


std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
  return os << "B" << b.block_id();
}


HGraph::HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor)
    : isolate_(info->isolate()),
      next_block_id_(0),
      entry_block_(NULL),
      blocks_(8, info->zone()),
      values_(16, info->zone()),
      phi_list_(NULL),
      uint32_instructions_(NULL),
      osr_(NULL),
      info_(info),
      descriptor_(descriptor),
      zone_(info->zone()),
      is_recursive_(false),
      use_optimistic_licm_(false),
      depends_on_empty_array_proto_elements_(false),
      type_change_checksum_(0),
      maximum_environment_size_(0),
      no_side_effects_scope_count_(0),
      disallow_adding_new_values_(false) {
  if (info->IsStub()) {
    start_environment_ =
        new (zone_) HEnvironment(zone_, descriptor.GetRegisterParameterCount());
  } else {
    if (info->is_tracking_positions()) {
      info->TraceInlinedFunction(info->shared_info(), SourcePosition::Unknown(),
                                 InlinedFunctionInfo::kNoParentId);
    }
    start_environment_ =
        new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
  }
  start_environment_->set_ast_id(BailoutId::FunctionContext());
  entry_block_ = CreateBasicBlock();
  entry_block_->SetInitialEnvironment(start_environment_);
}


HBasicBlock* HGraph::CreateBasicBlock() {
  HBasicBlock* result = new(zone()) HBasicBlock(this);
  blocks_.Add(result, zone());
  return result;
}


void HGraph::FinalizeUniqueness() {
  DisallowHeapAllocation no_gc;
  for (int i = 0; i < blocks()->length(); ++i) {
    for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
      it.Current()->FinalizeUniqueness();
    }
  }
}


int HGraph::SourcePositionToScriptPosition(SourcePosition pos) {
  return (FLAG_hydrogen_track_positions && !pos.IsUnknown())
             ? info()->start_position_for(pos.inlining_id()) + pos.position()
             : pos.raw();
}


// Block ordering was implemented with two mutually recursive methods,
// HGraph::Postorder and HGraph::PostorderLoopBlocks.
// The recursion could lead to stack overflow so the algorithm has been
// implemented iteratively.
// At a high level the algorithm looks like this:
//
// Postorder(block, loop_header) : {
//   if (block has already been visited or is of another loop) return;
//   mark block as visited;
//   if (block is a loop header) {
//     VisitLoopMembers(block, loop_header);
//     VisitSuccessorsOfLoopHeader(block);
//   } else {
//     VisitSuccessors(block)
//   }
//   put block in result list;
// }
//
// VisitLoopMembers(block, outer_loop_header) {
//   foreach (block b in block loop members) {
//     VisitSuccessorsOfLoopMember(b, outer_loop_header);
//     if (b is loop header) VisitLoopMembers(b);
//   }
// }
//
// VisitSuccessorsOfLoopMember(block, outer_loop_header) {
//   foreach (block b in block successors) Postorder(b, outer_loop_header)
// }
//
// VisitSuccessorsOfLoopHeader(block) {
//   foreach (block b in block successors) Postorder(b, block)
// }
//
// VisitSuccessors(block, loop_header) {
//   foreach (block b in block successors) Postorder(b, loop_header)
// }
//
// The ordering is started calling Postorder(entry, NULL).
//
// Each instance of PostorderProcessor represents the "stack frame" of the
// recursion, and particularly keeps the state of the loop (iteration) of the
// "Visit..." function it represents.
// To recycle memory we keep all the frames in a double linked list but
// this means that we cannot use constructors to initialize the frames.
//
class PostorderProcessor : public ZoneObject {
 public:
  // Back link (towards the stack bottom).
  PostorderProcessor* parent() {return father_; }
  // Forward link (towards the stack top).
  PostorderProcessor* child() {return child_; }
  HBasicBlock* block() { return block_; }
  HLoopInformation* loop() { return loop_; }
  HBasicBlock* loop_header() { return loop_header_; }

  static PostorderProcessor* CreateEntryProcessor(Zone* zone,
                                                  HBasicBlock* block) {
    PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
    return result->SetupSuccessors(zone, block, NULL);
  }

  PostorderProcessor* PerformStep(Zone* zone,
                                  ZoneList<HBasicBlock*>* order) {
    PostorderProcessor* next =
        PerformNonBacktrackingStep(zone, order);
    if (next != NULL) {
      return next;
    } else {
      return Backtrack(zone, order);
    }
  }

 private:
  explicit PostorderProcessor(PostorderProcessor* father)
      : father_(father), child_(NULL), successor_iterator(NULL) { }

  // Each enum value states the cycle whose state is kept by this instance.
  enum LoopKind {
    NONE,
    SUCCESSORS,
    SUCCESSORS_OF_LOOP_HEADER,
    LOOP_MEMBERS,
    SUCCESSORS_OF_LOOP_MEMBER
  };

  // Each "Setup..." method is like a constructor for a cycle state.
  PostorderProcessor* SetupSuccessors(Zone* zone,
                                      HBasicBlock* block,
                                      HBasicBlock* loop_header) {
    if (block == NULL || block->IsOrdered() ||
        block->parent_loop_header() != loop_header) {
      kind_ = NONE;
      block_ = NULL;
      loop_ = NULL;
      loop_header_ = NULL;
      return this;
    } else {
      block_ = block;
      loop_ = NULL;
      block->MarkAsOrdered();

      if (block->IsLoopHeader()) {
        kind_ = SUCCESSORS_OF_LOOP_HEADER;
        loop_header_ = block;
        InitializeSuccessors();
        PostorderProcessor* result = Push(zone);
        return result->SetupLoopMembers(zone, block, block->loop_information(),
                                        loop_header);
      } else {
        DCHECK(block->IsFinished());
        kind_ = SUCCESSORS;
        loop_header_ = loop_header;
        InitializeSuccessors();
        return this;
      }
    }
  }

  PostorderProcessor* SetupLoopMembers(Zone* zone,
                                       HBasicBlock* block,
                                       HLoopInformation* loop,
                                       HBasicBlock* loop_header) {
    kind_ = LOOP_MEMBERS;
    block_ = block;
    loop_ = loop;
    loop_header_ = loop_header;
    InitializeLoopMembers();
    return this;
  }

  PostorderProcessor* SetupSuccessorsOfLoopMember(
      HBasicBlock* block,
      HLoopInformation* loop,
      HBasicBlock* loop_header) {
    kind_ = SUCCESSORS_OF_LOOP_MEMBER;
    block_ = block;
    loop_ = loop;
    loop_header_ = loop_header;
    InitializeSuccessors();
    return this;
  }

  // This method "allocates" a new stack frame.
  PostorderProcessor* Push(Zone* zone) {
    if (child_ == NULL) {
      child_ = new(zone) PostorderProcessor(this);
    }
    return child_;
  }

  void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
    DCHECK(block_->end()->FirstSuccessor() == NULL ||
           order->Contains(block_->end()->FirstSuccessor()) ||
           block_->end()->FirstSuccessor()->IsLoopHeader());
    DCHECK(block_->end()->SecondSuccessor() == NULL ||
           order->Contains(block_->end()->SecondSuccessor()) ||
           block_->end()->SecondSuccessor()->IsLoopHeader());
    order->Add(block_, zone);
  }

  // This method is the basic block to walk up the stack.
  PostorderProcessor* Pop(Zone* zone,
                          ZoneList<HBasicBlock*>* order) {
    switch (kind_) {
      case SUCCESSORS:
      case SUCCESSORS_OF_LOOP_HEADER:
        ClosePostorder(order, zone);
        return father_;
      case LOOP_MEMBERS:
        return father_;
      case SUCCESSORS_OF_LOOP_MEMBER:
        if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
          // In this case we need to perform a LOOP_MEMBERS cycle so we
          // initialize it and return this instead of father.
          return SetupLoopMembers(zone, block(),
                                  block()->loop_information(), loop_header_);
        } else {
          return father_;
        }
      case NONE:
        return father_;
    }
    UNREACHABLE();
    return NULL;
  }

  // Walks up the stack.
  PostorderProcessor* Backtrack(Zone* zone,
                                ZoneList<HBasicBlock*>* order) {
    PostorderProcessor* parent = Pop(zone, order);
    while (parent != NULL) {
      PostorderProcessor* next =
          parent->PerformNonBacktrackingStep(zone, order);
      if (next != NULL) {
        return next;
      } else {
        parent = parent->Pop(zone, order);
      }
    }
    return NULL;
  }

  PostorderProcessor* PerformNonBacktrackingStep(
      Zone* zone,
      ZoneList<HBasicBlock*>* order) {
    HBasicBlock* next_block;
    switch (kind_) {
      case SUCCESSORS:
        next_block = AdvanceSuccessors();
        if (next_block != NULL) {
          PostorderProcessor* result = Push(zone);
          return result->SetupSuccessors(zone, next_block, loop_header_);
        }
        break;
      case SUCCESSORS_OF_LOOP_HEADER:
        next_block = AdvanceSuccessors();
        if (next_block != NULL) {
          PostorderProcessor* result = Push(zone);
          return result->SetupSuccessors(zone, next_block, block());
        }
        break;
      case LOOP_MEMBERS:
        next_block = AdvanceLoopMembers();
        if (next_block != NULL) {
          PostorderProcessor* result = Push(zone);
          return result->SetupSuccessorsOfLoopMember(next_block,
                                                     loop_, loop_header_);
        }
        break;
      case SUCCESSORS_OF_LOOP_MEMBER:
        next_block = AdvanceSuccessors();
        if (next_block != NULL) {
          PostorderProcessor* result = Push(zone);
          return result->SetupSuccessors(zone, next_block, loop_header_);
        }
        break;
      case NONE:
        return NULL;
    }
    return NULL;
  }

  // The following two methods implement a "foreach b in successors" cycle.
  void InitializeSuccessors() {
    loop_index = 0;
    loop_length = 0;
    successor_iterator = HSuccessorIterator(block_->end());
  }

  HBasicBlock* AdvanceSuccessors() {
    if (!successor_iterator.Done()) {
      HBasicBlock* result = successor_iterator.Current();
      successor_iterator.Advance();
      return result;
    }
    return NULL;
  }

  // The following two methods implement a "foreach b in loop members" cycle.
  void InitializeLoopMembers() {
    loop_index = 0;
    loop_length = loop_->blocks()->length();
  }

  HBasicBlock* AdvanceLoopMembers() {
    if (loop_index < loop_length) {
      HBasicBlock* result = loop_->blocks()->at(loop_index);
      loop_index++;
      return result;
    } else {
      return NULL;
    }
  }

  LoopKind kind_;
  PostorderProcessor* father_;
  PostorderProcessor* child_;
  HLoopInformation* loop_;
  HBasicBlock* block_;
  HBasicBlock* loop_header_;
  int loop_index;
  int loop_length;
  HSuccessorIterator successor_iterator;
};


void HGraph::OrderBlocks() {
  CompilationPhase phase("H_Block ordering", info());

#ifdef DEBUG
  // Initially the blocks must not be ordered.
  for (int i = 0; i < blocks_.length(); ++i) {
    DCHECK(!blocks_[i]->IsOrdered());
  }
#endif

  PostorderProcessor* postorder =
      PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
  blocks_.Rewind(0);
  while (postorder) {
    postorder = postorder->PerformStep(zone(), &blocks_);
  }

#ifdef DEBUG
  // Now all blocks must be marked as ordered.
  for (int i = 0; i < blocks_.length(); ++i) {
    DCHECK(blocks_[i]->IsOrdered());
  }
#endif

  // Reverse block list and assign block IDs.
  for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
    HBasicBlock* bi = blocks_[i];
    HBasicBlock* bj = blocks_[j];
    bi->set_block_id(j);
    bj->set_block_id(i);
    blocks_[i] = bj;
    blocks_[j] = bi;
  }
}


void HGraph::AssignDominators() {
  HPhase phase("H_Assign dominators", this);
  for (int i = 0; i < blocks_.length(); ++i) {
    HBasicBlock* block = blocks_[i];
    if (block->IsLoopHeader()) {
      // Only the first predecessor of a loop header is from outside the loop.
      // All others are back edges, and thus cannot dominate the loop header.
      block->AssignCommonDominator(block->predecessors()->first());
      block->AssignLoopSuccessorDominators();
    } else {
      for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
        blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
      }
    }
  }
}


bool HGraph::CheckArgumentsPhiUses() {
  int block_count = blocks_.length();
  for (int i = 0; i < block_count; ++i) {
    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
      HPhi* phi = blocks_[i]->phis()->at(j);
      // We don't support phi uses of arguments for now.
      if (phi->CheckFlag(HValue::kIsArguments)) return false;
    }
  }
  return true;
}


bool HGraph::CheckConstPhiUses() {
  int block_count = blocks_.length();
  for (int i = 0; i < block_count; ++i) {
    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
      HPhi* phi = blocks_[i]->phis()->at(j);
      // Check for the hole value (from an uninitialized const).
      for (int k = 0; k < phi->OperandCount(); k++) {
        if (phi->OperandAt(k) == GetConstantHole()) return false;
      }
    }
  }
  return true;
}


void HGraph::CollectPhis() {
  int block_count = blocks_.length();
  phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
  for (int i = 0; i < block_count; ++i) {
    for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
      HPhi* phi = blocks_[i]->phis()->at(j);
      phi_list_->Add(phi, zone());
    }
  }
}


// Implementation of utility class to encapsulate the translation state for
// a (possibly inlined) function.
FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
                             CompilationInfo* info, InliningKind inlining_kind,
                             int inlining_id)
    : owner_(owner),
      compilation_info_(info),
      call_context_(NULL),
      inlining_kind_(inlining_kind),
      function_return_(NULL),
      test_context_(NULL),
      entry_(NULL),
      arguments_object_(NULL),
      arguments_elements_(NULL),
      inlining_id_(inlining_id),
      outer_source_position_(SourcePosition::Unknown()),
      outer_(owner->function_state()) {
  if (outer_ != NULL) {
    // State for an inline function.
    if (owner->ast_context()->IsTest()) {
      HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
      HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
      if_true->MarkAsInlineReturnTarget(owner->current_block());
      if_false->MarkAsInlineReturnTarget(owner->current_block());
      TestContext* outer_test_context = TestContext::cast(owner->ast_context());
      Expression* cond = outer_test_context->condition();
      // The AstContext constructor pushed on the context stack.  This newed
      // instance is the reason that AstContext can't be BASE_EMBEDDED.
      test_context_ = new TestContext(owner, cond, if_true, if_false);
    } else {
      function_return_ = owner->graph()->CreateBasicBlock();
      function_return()->MarkAsInlineReturnTarget(owner->current_block());
    }
    // Set this after possibly allocating a new TestContext above.
    call_context_ = owner->ast_context();
  }

  // Push on the state stack.
  owner->set_function_state(this);

  if (compilation_info_->is_tracking_positions()) {
    outer_source_position_ = owner->source_position();
    owner->EnterInlinedSource(
      info->shared_info()->start_position(),
      inlining_id);
    owner->SetSourcePosition(info->shared_info()->start_position());
  }
}


FunctionState::~FunctionState() {
  delete test_context_;
  owner_->set_function_state(outer_);

  if (compilation_info_->is_tracking_positions()) {
    owner_->set_source_position(outer_source_position_);
    owner_->EnterInlinedSource(
      outer_->compilation_info()->shared_info()->start_position(),
      outer_->inlining_id());
  }
}


// Implementation of utility classes to represent an expression's context in
// the AST.
AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
    : owner_(owner),
      kind_(kind),
      outer_(owner->ast_context()),
      typeof_mode_(NOT_INSIDE_TYPEOF) {
  owner->set_ast_context(this);  // Push.
#ifdef DEBUG
  DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
  original_length_ = owner->environment()->length();
#endif
}


AstContext::~AstContext() {
  owner_->set_ast_context(outer_);  // Pop.
}


EffectContext::~EffectContext() {
  DCHECK(owner()->HasStackOverflow() ||
         owner()->current_block() == NULL ||
         (owner()->environment()->length() == original_length_ &&
          owner()->environment()->frame_type() == JS_FUNCTION));
}


ValueContext::~ValueContext() {
  DCHECK(owner()->HasStackOverflow() ||
         owner()->current_block() == NULL ||
         (owner()->environment()->length() == original_length_ + 1 &&
          owner()->environment()->frame_type() == JS_FUNCTION));
}


void EffectContext::ReturnValue(HValue* value) {
  // The value is simply ignored.
}


void ValueContext::ReturnValue(HValue* value) {
  // The value is tracked in the bailout environment, and communicated
  // through the environment as the result of the expression.
  if (value->CheckFlag(HValue::kIsArguments)) {
    if (flag_ == ARGUMENTS_FAKED) {
      value = owner()->graph()->GetConstantUndefined();
    } else if (!arguments_allowed()) {
      owner()->Bailout(kBadValueContextForArgumentsValue);
    }
  }
  owner()->Push(value);
}


void TestContext::ReturnValue(HValue* value) {
  BuildBranch(value);
}


void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
  DCHECK(!instr->IsControlInstruction());
  owner()->AddInstruction(instr);
  if (instr->HasObservableSideEffects()) {
    owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
  }
}


void EffectContext::ReturnControl(HControlInstruction* instr,
                                  BailoutId ast_id) {
  DCHECK(!instr->HasObservableSideEffects());
  HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
  HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
  instr->SetSuccessorAt(0, empty_true);
  instr->SetSuccessorAt(1, empty_false);
  owner()->FinishCurrentBlock(instr);
  HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
  owner()->set_current_block(join);
}


void EffectContext::ReturnContinuation(HIfContinuation* continuation,
                                       BailoutId ast_id) {
  HBasicBlock* true_branch = NULL;
  HBasicBlock* false_branch = NULL;
  continuation->Continue(&true_branch, &false_branch);
  if (!continuation->IsTrueReachable()) {
    owner()->set_current_block(false_branch);
  } else if (!continuation->IsFalseReachable()) {
    owner()->set_current_block(true_branch);
  } else {
    HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
    owner()->set_current_block(join);
  }
}


void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
  DCHECK(!instr->IsControlInstruction());
  if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
    return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
  }
  owner()->AddInstruction(instr);
  owner()->Push(instr);
  if (instr->HasObservableSideEffects()) {
    owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
  }
}


void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
  DCHECK(!instr->HasObservableSideEffects());
  if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
    return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
  }
  HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
  HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
  instr->SetSuccessorAt(0, materialize_true);
  instr->SetSuccessorAt(1, materialize_false);
  owner()->FinishCurrentBlock(instr);
  owner()->set_current_block(materialize_true);
  owner()->Push(owner()->graph()->GetConstantTrue());
  owner()->set_current_block(materialize_false);
  owner()->Push(owner()->graph()->GetConstantFalse());
  HBasicBlock* join =
    owner()->CreateJoin(materialize_true, materialize_false, ast_id);
  owner()->set_current_block(join);
}


void ValueContext::ReturnContinuation(HIfContinuation* continuation,
                                      BailoutId ast_id) {
  HBasicBlock* materialize_true = NULL;
  HBasicBlock* materialize_false = NULL;
  continuation->Continue(&materialize_true, &materialize_false);
  if (continuation->IsTrueReachable()) {
    owner()->set_current_block(materialize_true);
    owner()->Push(owner()->graph()->GetConstantTrue());
    owner()->set_current_block(materialize_true);
  }
  if (continuation->IsFalseReachable()) {
    owner()->set_current_block(materialize_false);
    owner()->Push(owner()->graph()->GetConstantFalse());
    owner()->set_current_block(materialize_false);
  }
  if (continuation->TrueAndFalseReachable()) {
    HBasicBlock* join =
        owner()->CreateJoin(materialize_true, materialize_false, ast_id);
    owner()->set_current_block(join);
  }
}


void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
  DCHECK(!instr->IsControlInstruction());
  HOptimizedGraphBuilder* builder = owner();
  builder->AddInstruction(instr);
  // We expect a simulate after every expression with side effects, though
  // this one isn't actually needed (and wouldn't work if it were targeted).
  if (instr->HasObservableSideEffects()) {
    builder->Push(instr);
    builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    builder->Pop();
  }
  BuildBranch(instr);
}


void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
  DCHECK(!instr->HasObservableSideEffects());
  HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
  HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
  instr->SetSuccessorAt(0, empty_true);
  instr->SetSuccessorAt(1, empty_false);
  owner()->FinishCurrentBlock(instr);
  owner()->Goto(empty_true, if_true(), owner()->function_state());
  owner()->Goto(empty_false, if_false(), owner()->function_state());
  owner()->set_current_block(NULL);
}


void TestContext::ReturnContinuation(HIfContinuation* continuation,
                                     BailoutId ast_id) {
  HBasicBlock* true_branch = NULL;
  HBasicBlock* false_branch = NULL;
  continuation->Continue(&true_branch, &false_branch);
  if (continuation->IsTrueReachable()) {
    owner()->Goto(true_branch, if_true(), owner()->function_state());
  }
  if (continuation->IsFalseReachable()) {
    owner()->Goto(false_branch, if_false(), owner()->function_state());
  }
  owner()->set_current_block(NULL);
}


void TestContext::BuildBranch(HValue* value) {
  // We expect the graph to be in edge-split form: there is no edge that
  // connects a branch node to a join node.  We conservatively ensure that
  // property by always adding an empty block on the outgoing edges of this
  // branch.
  HOptimizedGraphBuilder* builder = owner();
  if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
    builder->Bailout(kArgumentsObjectValueInATestContext);
  }
  ToBooleanStub::Types expected(condition()->to_boolean_types());
  ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
}


// HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
#define CHECK_BAILOUT(call)                     \
  do {                                          \
    call;                                       \
    if (HasStackOverflow()) return;             \
  } while (false)


#define CHECK_ALIVE(call)                                       \
  do {                                                          \
    call;                                                       \
    if (HasStackOverflow() || current_block() == NULL) return;  \
  } while (false)


#define CHECK_ALIVE_OR_RETURN(call, value)                            \
  do {                                                                \
    call;                                                             \
    if (HasStackOverflow() || current_block() == NULL) return value;  \
  } while (false)


void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
  current_info()->AbortOptimization(reason);
  SetStackOverflow();
}


void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
  EffectContext for_effect(this);
  Visit(expr);
}


void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
                                           ArgumentsAllowedFlag flag) {
  ValueContext for_value(this, flag);
  Visit(expr);
}


void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
  ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
  for_value.set_typeof_mode(INSIDE_TYPEOF);
  Visit(expr);
}


void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
                                             HBasicBlock* true_block,
                                             HBasicBlock* false_block) {
  TestContext for_control(this, expr, true_block, false_block);
  Visit(expr);
}


void HOptimizedGraphBuilder::VisitExpressions(
    ZoneList<Expression*>* exprs) {
  for (int i = 0; i < exprs->length(); ++i) {
    CHECK_ALIVE(VisitForValue(exprs->at(i)));
  }
}


void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
                                              ArgumentsAllowedFlag flag) {
  for (int i = 0; i < exprs->length(); ++i) {
    CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
  }
}


bool HOptimizedGraphBuilder::BuildGraph() {
  if (IsSubclassConstructor(current_info()->literal()->kind())) {
    Bailout(kSuperReference);
    return false;
  }

  Scope* scope = current_info()->scope();
  SetUpScope(scope);

  // Add an edge to the body entry.  This is warty: the graph's start
  // environment will be used by the Lithium translation as the initial
  // environment on graph entry, but it has now been mutated by the
  // Hydrogen translation of the instructions in the start block.  This
  // environment uses values which have not been defined yet.  These
  // Hydrogen instructions will then be replayed by the Lithium
  // translation, so they cannot have an environment effect.  The edge to
  // the body's entry block (along with some special logic for the start
  // block in HInstruction::InsertAfter) seals the start block from
  // getting unwanted instructions inserted.
  //
  // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
  // Make the Hydrogen instructions in the initial block into Hydrogen
  // values (but not instructions), present in the initial environment and
  // not replayed by the Lithium translation.
  HEnvironment* initial_env = environment()->CopyWithoutHistory();
  HBasicBlock* body_entry = CreateBasicBlock(initial_env);
  Goto(body_entry);
  body_entry->SetJoinId(BailoutId::FunctionEntry());
  set_current_block(body_entry);

  VisitDeclarations(scope->declarations());
  Add<HSimulate>(BailoutId::Declarations());

  Add<HStackCheck>(HStackCheck::kFunctionEntry);

  VisitStatements(current_info()->literal()->body());
  if (HasStackOverflow()) return false;

  if (current_block() != NULL) {
    Add<HReturn>(graph()->GetConstantUndefined());
    set_current_block(NULL);
  }

  // If the checksum of the number of type info changes is the same as the
  // last time this function was compiled, then this recompile is likely not
  // due to missing/inadequate type feedback, but rather too aggressive
  // optimization. Disable optimistic LICM in that case.
  Handle<Code> unoptimized_code(current_info()->shared_info()->code());
  DCHECK(unoptimized_code->kind() == Code::FUNCTION);
  Handle<TypeFeedbackInfo> type_info(
      TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
  int checksum = type_info->own_type_change_checksum();
  int composite_checksum = graph()->update_type_change_checksum(checksum);
  graph()->set_use_optimistic_licm(
      !type_info->matches_inlined_type_change_checksum(composite_checksum));
  type_info->set_inlined_type_change_checksum(composite_checksum);

  // Perform any necessary OSR-specific cleanups or changes to the graph.
  osr()->FinishGraph();

  return true;
}


bool HGraph::Optimize(BailoutReason* bailout_reason) {
  OrderBlocks();
  AssignDominators();

  // We need to create a HConstant "zero" now so that GVN will fold every
  // zero-valued constant in the graph together.
  // The constant is needed to make idef-based bounds check work: the pass
  // evaluates relations with "zero" and that zero cannot be created after GVN.
  GetConstant0();

#ifdef DEBUG
  // Do a full verify after building the graph and computing dominators.
  Verify(true);
#endif

  if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
    Run<HEnvironmentLivenessAnalysisPhase>();
  }

  if (!CheckConstPhiUses()) {
    *bailout_reason = kUnsupportedPhiUseOfConstVariable;
    return false;
  }
  Run<HRedundantPhiEliminationPhase>();
  if (!CheckArgumentsPhiUses()) {
    *bailout_reason = kUnsupportedPhiUseOfArguments;
    return false;
  }

  // Find and mark unreachable code to simplify optimizations, especially gvn,
  // where unreachable code could unnecessarily defeat LICM.
  Run<HMarkUnreachableBlocksPhase>();

  if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
  if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();

  if (FLAG_load_elimination) Run<HLoadEliminationPhase>();

  CollectPhis();

  if (has_osr()) osr()->FinishOsrValues();

  Run<HInferRepresentationPhase>();

  // Remove HSimulate instructions that have turned out not to be needed
  // after all by folding them into the following HSimulate.
  // This must happen after inferring representations.
  Run<HMergeRemovableSimulatesPhase>();

  Run<HMarkDeoptimizeOnUndefinedPhase>();
  Run<HRepresentationChangesPhase>();

  Run<HInferTypesPhase>();

  // Must be performed before canonicalization to ensure that Canonicalize
  // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
  // zero.
  Run<HUint32AnalysisPhase>();

  if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();

  if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();

  if (FLAG_check_elimination) Run<HCheckEliminationPhase>();

  if (FLAG_store_elimination) Run<HStoreEliminationPhase>();

  Run<HRangeAnalysisPhase>();

  Run<HComputeChangeUndefinedToNaN>();

  // Eliminate redundant stack checks on backwards branches.
  Run<HStackCheckEliminationPhase>();

  if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
  if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
  if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
  if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();

  RestoreActualValues();

  // Find unreachable code a second time, GVN and other optimizations may have
  // made blocks unreachable that were previously reachable.
  Run<HMarkUnreachableBlocksPhase>();

  return true;
}


void HGraph::RestoreActualValues() {
  HPhase phase("H_Restore actual values", this);

  for (int block_index = 0; block_index < blocks()->length(); block_index++) {
    HBasicBlock* block = blocks()->at(block_index);

#ifdef DEBUG
    for (int i = 0; i < block->phis()->length(); i++) {
      HPhi* phi = block->phis()->at(i);
      DCHECK(phi->ActualValue() == phi);
    }
#endif

    for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
      HInstruction* instruction = it.Current();
      if (instruction->ActualValue() == instruction) continue;
      if (instruction->CheckFlag(HValue::kIsDead)) {
        // The instruction was marked as deleted but left in the graph
        // as a control flow dependency point for subsequent
        // instructions.
        instruction->DeleteAndReplaceWith(instruction->ActualValue());
      } else {
        DCHECK(instruction->IsInformativeDefinition());
        if (instruction->IsPurelyInformativeDefinition()) {
          instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
        } else {
          instruction->ReplaceAllUsesWith(instruction->ActualValue());
        }
      }
    }
  }
}


void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
  ZoneList<HValue*> arguments(count, zone());
  for (int i = 0; i < count; ++i) {
    arguments.Add(Pop(), zone());
  }

  HPushArguments* push_args = New<HPushArguments>();
  while (!arguments.is_empty()) {
    push_args->AddInput(arguments.RemoveLast());
  }
  AddInstruction(push_args);
}


template <class Instruction>
HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
  PushArgumentsFromEnvironment(call->argument_count());
  return call;
}


void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
  HEnvironment* prolog_env = environment();
  int parameter_count = environment()->parameter_count();
  ZoneList<HValue*> parameters(parameter_count, zone());
  for (int i = 0; i < parameter_count; ++i) {
    HInstruction* parameter = Add<HParameter>(static_cast<unsigned>(i));
    parameters.Add(parameter, zone());
    environment()->Bind(i, parameter);
  }

  HConstant* undefined_constant = graph()->GetConstantUndefined();
  // Initialize specials and locals to undefined.
  for (int i = parameter_count + 1; i < environment()->length(); ++i) {
    environment()->Bind(i, undefined_constant);
  }
  Add<HPrologue>();

  HEnvironment* initial_env = environment()->CopyWithoutHistory();
  HBasicBlock* body_entry = CreateBasicBlock(initial_env);
  GotoNoSimulate(body_entry);
  set_current_block(body_entry);

  // Initialize context of prolog environment to undefined.
  prolog_env->BindContext(undefined_constant);

  // First special is HContext.
  HInstruction* context = Add<HContext>();
  environment()->BindContext(context);

  // Create an arguments object containing the initial parameters.  Set the
  // initial values of parameters including "this" having parameter index 0.
  DCHECK_EQ(scope->num_parameters() + 1, parameter_count);
  HArgumentsObject* arguments_object = New<HArgumentsObject>(parameter_count);
  for (int i = 0; i < parameter_count; ++i) {
    HValue* parameter = parameters.at(i);
    arguments_object->AddArgument(parameter, zone());
  }

  AddInstruction(arguments_object);
  graph()->SetArgumentsObject(arguments_object);

  // Handle the arguments and arguments shadow variables specially (they do
  // not have declarations).
  if (scope->arguments() != NULL) {
    environment()->Bind(scope->arguments(), graph()->GetArgumentsObject());
  }

  int rest_index;
  Variable* rest = scope->rest_parameter(&rest_index);
  if (rest) {
    return Bailout(kRestParameter);
  }

  if (scope->this_function_var() != nullptr ||
      scope->new_target_var() != nullptr) {
    return Bailout(kSuperReference);
  }

  // Trace the call.
  if (FLAG_trace && top_info()->IsOptimizing()) {
    Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kTraceEnter), 0);
  }
}


void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
  for (int i = 0; i < statements->length(); i++) {
    Statement* stmt = statements->at(i);
    CHECK_ALIVE(Visit(stmt));
    if (stmt->IsJump()) break;
  }
}


void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());

  Scope* outer_scope = scope();
  Scope* scope = stmt->scope();
  BreakAndContinueInfo break_info(stmt, outer_scope);

  { BreakAndContinueScope push(&break_info, this);
    if (scope != NULL) {
      if (scope->NeedsContext()) {
        // Load the function object.
        Scope* declaration_scope = scope->DeclarationScope();
        HInstruction* function;
        HValue* outer_context = environment()->context();
        if (declaration_scope->is_script_scope() ||
            declaration_scope->is_eval_scope()) {
          function = new (zone())
              HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
                               HLoadContextSlot::kNoCheck);
        } else {
          function = New<HThisFunction>();
        }
        AddInstruction(function);
        // Allocate a block context and store it to the stack frame.
        HInstruction* inner_context = Add<HAllocateBlockContext>(
            outer_context, function, scope->GetScopeInfo(isolate()));
        HInstruction* instr = Add<HStoreFrameContext>(inner_context);
        set_scope(scope);
        environment()->BindContext(inner_context);
        if (instr->HasObservableSideEffects()) {
          AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
        }
      }
      VisitDeclarations(scope->declarations());
      AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
    }
    CHECK_BAILOUT(VisitStatements(stmt->statements()));
  }
  set_scope(outer_scope);
  if (scope != NULL && current_block() != NULL &&
      scope->ContextLocalCount() > 0) {
    HValue* inner_context = environment()->context();
    HValue* outer_context = Add<HLoadNamedField>(
        inner_context, nullptr,
        HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));

    HInstruction* instr = Add<HStoreFrameContext>(outer_context);
    environment()->BindContext(outer_context);
    if (instr->HasObservableSideEffects()) {
      AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
    }
  }
  HBasicBlock* break_block = break_info.break_block();
  if (break_block != NULL) {
    if (current_block() != NULL) Goto(break_block);
    break_block->SetJoinId(stmt->ExitId());
    set_current_block(break_block);
  }
}


void HOptimizedGraphBuilder::VisitExpressionStatement(
    ExpressionStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  VisitForEffect(stmt->expression());
}


void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
}


void HOptimizedGraphBuilder::VisitSloppyBlockFunctionStatement(
    SloppyBlockFunctionStatement* stmt) {
  Visit(stmt->statement());
}


void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  if (stmt->condition()->ToBooleanIsTrue()) {
    Add<HSimulate>(stmt->ThenId());
    Visit(stmt->then_statement());
  } else if (stmt->condition()->ToBooleanIsFalse()) {
    Add<HSimulate>(stmt->ElseId());
    Visit(stmt->else_statement());
  } else {
    HBasicBlock* cond_true = graph()->CreateBasicBlock();
    HBasicBlock* cond_false = graph()->CreateBasicBlock();
    CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));

    if (cond_true->HasPredecessor()) {
      cond_true->SetJoinId(stmt->ThenId());
      set_current_block(cond_true);
      CHECK_BAILOUT(Visit(stmt->then_statement()));
      cond_true = current_block();
    } else {
      cond_true = NULL;
    }

    if (cond_false->HasPredecessor()) {
      cond_false->SetJoinId(stmt->ElseId());
      set_current_block(cond_false);
      CHECK_BAILOUT(Visit(stmt->else_statement()));
      cond_false = current_block();
    } else {
      cond_false = NULL;
    }

    HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
    set_current_block(join);
  }
}


HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
    BreakableStatement* stmt,
    BreakType type,
    Scope** scope,
    int* drop_extra) {
  *drop_extra = 0;
  BreakAndContinueScope* current = this;
  while (current != NULL && current->info()->target() != stmt) {
    *drop_extra += current->info()->drop_extra();
    current = current->next();
  }
  DCHECK(current != NULL);  // Always found (unless stack is malformed).
  *scope = current->info()->scope();

  if (type == BREAK) {
    *drop_extra += current->info()->drop_extra();
  }

  HBasicBlock* block = NULL;
  switch (type) {
    case BREAK:
      block = current->info()->break_block();
      if (block == NULL) {
        block = current->owner()->graph()->CreateBasicBlock();
        current->info()->set_break_block(block);
      }
      break;

    case CONTINUE:
      block = current->info()->continue_block();
      if (block == NULL) {
        block = current->owner()->graph()->CreateBasicBlock();
        current->info()->set_continue_block(block);
      }
      break;
  }

  return block;
}


void HOptimizedGraphBuilder::VisitContinueStatement(
    ContinueStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  Scope* outer_scope = NULL;
  Scope* inner_scope = scope();
  int drop_extra = 0;
  HBasicBlock* continue_block = break_scope()->Get(
      stmt->target(), BreakAndContinueScope::CONTINUE,
      &outer_scope, &drop_extra);
  HValue* context = environment()->context();
  Drop(drop_extra);
  int context_pop_count = inner_scope->ContextChainLength(outer_scope);
  if (context_pop_count > 0) {
    while (context_pop_count-- > 0) {
      HInstruction* context_instruction = Add<HLoadNamedField>(
          context, nullptr,
          HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
      context = context_instruction;
    }
    HInstruction* instr = Add<HStoreFrameContext>(context);
    if (instr->HasObservableSideEffects()) {
      AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
    }
    environment()->BindContext(context);
  }

  Goto(continue_block);
  set_current_block(NULL);
}


void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  Scope* outer_scope = NULL;
  Scope* inner_scope = scope();
  int drop_extra = 0;
  HBasicBlock* break_block = break_scope()->Get(
      stmt->target(), BreakAndContinueScope::BREAK,
      &outer_scope, &drop_extra);
  HValue* context = environment()->context();
  Drop(drop_extra);
  int context_pop_count = inner_scope->ContextChainLength(outer_scope);
  if (context_pop_count > 0) {
    while (context_pop_count-- > 0) {
      HInstruction* context_instruction = Add<HLoadNamedField>(
          context, nullptr,
          HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
      context = context_instruction;
    }
    HInstruction* instr = Add<HStoreFrameContext>(context);
    if (instr->HasObservableSideEffects()) {
      AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
    }
    environment()->BindContext(context);
  }
  Goto(break_block);
  set_current_block(NULL);
}


void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  FunctionState* state = function_state();
  AstContext* context = call_context();
  if (context == NULL) {
    // Not an inlined return, so an actual one.
    CHECK_ALIVE(VisitForValue(stmt->expression()));
    HValue* result = environment()->Pop();
    Add<HReturn>(result);
  } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
    // Return from an inlined construct call. In a test context the return value
    // will always evaluate to true, in a value context the return value needs
    // to be a JSObject.
    if (context->IsTest()) {
      TestContext* test = TestContext::cast(context);
      CHECK_ALIVE(VisitForEffect(stmt->expression()));
      Goto(test->if_true(), state);
    } else if (context->IsEffect()) {
      CHECK_ALIVE(VisitForEffect(stmt->expression()));
      Goto(function_return(), state);
    } else {
      DCHECK(context->IsValue());
      CHECK_ALIVE(VisitForValue(stmt->expression()));
      HValue* return_value = Pop();
      HValue* receiver = environment()->arguments_environment()->Lookup(0);
      HHasInstanceTypeAndBranch* typecheck =
          New<HHasInstanceTypeAndBranch>(return_value,
                                         FIRST_JS_RECEIVER_TYPE,
                                         LAST_JS_RECEIVER_TYPE);
      HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
      HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
      typecheck->SetSuccessorAt(0, if_spec_object);
      typecheck->SetSuccessorAt(1, not_spec_object);
      FinishCurrentBlock(typecheck);
      AddLeaveInlined(if_spec_object, return_value, state);
      AddLeaveInlined(not_spec_object, receiver, state);
    }
  } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
    // Return from an inlined setter call. The returned value is never used, the
    // value of an assignment is always the value of the RHS of the assignment.
    CHECK_ALIVE(VisitForEffect(stmt->expression()));
    if (context->IsTest()) {
      HValue* rhs = environment()->arguments_environment()->Lookup(1);
      context->ReturnValue(rhs);
    } else if (context->IsEffect()) {
      Goto(function_return(), state);
    } else {
      DCHECK(context->IsValue());
      HValue* rhs = environment()->arguments_environment()->Lookup(1);
      AddLeaveInlined(rhs, state);
    }
  } else {
    // Return from a normal inlined function. Visit the subexpression in the
    // expression context of the call.
    if (context->IsTest()) {
      TestContext* test = TestContext::cast(context);
      VisitForControl(stmt->expression(), test->if_true(), test->if_false());
    } else if (context->IsEffect()) {
      // Visit in value context and ignore the result. This is needed to keep
      // environment in sync with full-codegen since some visitors (e.g.
      // VisitCountOperation) use the operand stack differently depending on
      // context.
      CHECK_ALIVE(VisitForValue(stmt->expression()));
      Pop();
      Goto(function_return(), state);
    } else {
      DCHECK(context->IsValue());
      CHECK_ALIVE(VisitForValue(stmt->expression()));
      AddLeaveInlined(Pop(), state);
    }
  }
  set_current_block(NULL);
}


void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kWithStatement);
}


void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());

  ZoneList<CaseClause*>* clauses = stmt->cases();
  int clause_count = clauses->length();
  ZoneList<HBasicBlock*> body_blocks(clause_count, zone());

  CHECK_ALIVE(VisitForValue(stmt->tag()));
  Add<HSimulate>(stmt->EntryId());
  HValue* tag_value = Top();
  Type* tag_type = stmt->tag()->bounds().lower;

  // 1. Build all the tests, with dangling true branches
  BailoutId default_id = BailoutId::None();
  for (int i = 0; i < clause_count; ++i) {
    CaseClause* clause = clauses->at(i);
    if (clause->is_default()) {
      body_blocks.Add(NULL, zone());
      if (default_id.IsNone()) default_id = clause->EntryId();
      continue;
    }

    // Generate a compare and branch.
    CHECK_BAILOUT(VisitForValue(clause->label()));
    if (current_block() == NULL) return Bailout(kUnsupportedSwitchStatement);
    HValue* label_value = Pop();

    Type* label_type = clause->label()->bounds().lower;
    Type* combined_type = clause->compare_type();
    HControlInstruction* compare = BuildCompareInstruction(
        Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
        combined_type,
        ScriptPositionToSourcePosition(stmt->tag()->position()),
        ScriptPositionToSourcePosition(clause->label()->position()),
        PUSH_BEFORE_SIMULATE, clause->id());

    HBasicBlock* next_test_block = graph()->CreateBasicBlock();
    HBasicBlock* body_block = graph()->CreateBasicBlock();
    body_blocks.Add(body_block, zone());
    compare->SetSuccessorAt(0, body_block);
    compare->SetSuccessorAt(1, next_test_block);
    FinishCurrentBlock(compare);

    set_current_block(body_block);
    Drop(1);  // tag_value

    set_current_block(next_test_block);
  }

  // Save the current block to use for the default or to join with the
  // exit.
  HBasicBlock* last_block = current_block();
  Drop(1);  // tag_value

  // 2. Loop over the clauses and the linked list of tests in lockstep,
  // translating the clause bodies.
  HBasicBlock* fall_through_block = NULL;

  BreakAndContinueInfo break_info(stmt, scope());
  { BreakAndContinueScope push(&break_info, this);
    for (int i = 0; i < clause_count; ++i) {
      CaseClause* clause = clauses->at(i);

      // Identify the block where normal (non-fall-through) control flow
      // goes to.
      HBasicBlock* normal_block = NULL;
      if (clause->is_default()) {
        if (last_block == NULL) continue;
        normal_block = last_block;
        last_block = NULL;  // Cleared to indicate we've handled it.
      } else {
        normal_block = body_blocks[i];
      }

      if (fall_through_block == NULL) {
        set_current_block(normal_block);
      } else {
        HBasicBlock* join = CreateJoin(fall_through_block,
                                       normal_block,
                                       clause->EntryId());
        set_current_block(join);
      }

      CHECK_BAILOUT(VisitStatements(clause->statements()));
      fall_through_block = current_block();
    }
  }

  // Create an up-to-3-way join.  Use the break block if it exists since
  // it's already a join block.
  HBasicBlock* break_block = break_info.break_block();
  if (break_block == NULL) {
    set_current_block(CreateJoin(fall_through_block,
                                 last_block,
                                 stmt->ExitId()));
  } else {
    if (fall_through_block != NULL) Goto(fall_through_block, break_block);
    if (last_block != NULL) Goto(last_block, break_block);
    break_block->SetJoinId(stmt->ExitId());
    set_current_block(break_block);
  }
}


void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
                                           HBasicBlock* loop_entry) {
  Add<HSimulate>(stmt->StackCheckId());
  HStackCheck* stack_check =
      HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
  DCHECK(loop_entry->IsLoopHeader());
  loop_entry->loop_information()->set_stack_check(stack_check);
  CHECK_BAILOUT(Visit(stmt->body()));
}


void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  DCHECK(current_block() != NULL);
  HBasicBlock* loop_entry = BuildLoopEntry(stmt);

  BreakAndContinueInfo break_info(stmt, scope());
  {
    BreakAndContinueScope push(&break_info, this);
    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
  }
  HBasicBlock* body_exit =
      JoinContinue(stmt, current_block(), break_info.continue_block());
  HBasicBlock* loop_successor = NULL;
  if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
    set_current_block(body_exit);
    loop_successor = graph()->CreateBasicBlock();
    if (stmt->cond()->ToBooleanIsFalse()) {
      loop_entry->loop_information()->stack_check()->Eliminate();
      Goto(loop_successor);
      body_exit = NULL;
    } else {
      // The block for a true condition, the actual predecessor block of the
      // back edge.
      body_exit = graph()->CreateBasicBlock();
      CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
    }
    if (body_exit != NULL && body_exit->HasPredecessor()) {
      body_exit->SetJoinId(stmt->BackEdgeId());
    } else {
      body_exit = NULL;
    }
    if (loop_successor->HasPredecessor()) {
      loop_successor->SetJoinId(stmt->ExitId());
    } else {
      loop_successor = NULL;
    }
  }
  HBasicBlock* loop_exit = CreateLoop(stmt,
                                      loop_entry,
                                      body_exit,
                                      loop_successor,
                                      break_info.break_block());
  set_current_block(loop_exit);
}


void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  DCHECK(current_block() != NULL);
  HBasicBlock* loop_entry = BuildLoopEntry(stmt);

  // If the condition is constant true, do not generate a branch.
  HBasicBlock* loop_successor = NULL;
  if (!stmt->cond()->ToBooleanIsTrue()) {
    HBasicBlock* body_entry = graph()->CreateBasicBlock();
    loop_successor = graph()->CreateBasicBlock();
    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
    if (body_entry->HasPredecessor()) {
      body_entry->SetJoinId(stmt->BodyId());
      set_current_block(body_entry);
    }
    if (loop_successor->HasPredecessor()) {
      loop_successor->SetJoinId(stmt->ExitId());
    } else {
      loop_successor = NULL;
    }
  }

  BreakAndContinueInfo break_info(stmt, scope());
  if (current_block() != NULL) {
    BreakAndContinueScope push(&break_info, this);
    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
  }
  HBasicBlock* body_exit =
      JoinContinue(stmt, current_block(), break_info.continue_block());
  HBasicBlock* loop_exit = CreateLoop(stmt,
                                      loop_entry,
                                      body_exit,
                                      loop_successor,
                                      break_info.break_block());
  set_current_block(loop_exit);
}


void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  if (stmt->init() != NULL) {
    CHECK_ALIVE(Visit(stmt->init()));
  }
  DCHECK(current_block() != NULL);
  HBasicBlock* loop_entry = BuildLoopEntry(stmt);

  HBasicBlock* loop_successor = NULL;
  if (stmt->cond() != NULL) {
    HBasicBlock* body_entry = graph()->CreateBasicBlock();
    loop_successor = graph()->CreateBasicBlock();
    CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
    if (body_entry->HasPredecessor()) {
      body_entry->SetJoinId(stmt->BodyId());
      set_current_block(body_entry);
    }
    if (loop_successor->HasPredecessor()) {
      loop_successor->SetJoinId(stmt->ExitId());
    } else {
      loop_successor = NULL;
    }
  }

  BreakAndContinueInfo break_info(stmt, scope());
  if (current_block() != NULL) {
    BreakAndContinueScope push(&break_info, this);
    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
  }
  HBasicBlock* body_exit =
      JoinContinue(stmt, current_block(), break_info.continue_block());

  if (stmt->next() != NULL && body_exit != NULL) {
    set_current_block(body_exit);
    CHECK_BAILOUT(Visit(stmt->next()));
    body_exit = current_block();
  }

  HBasicBlock* loop_exit = CreateLoop(stmt,
                                      loop_entry,
                                      body_exit,
                                      loop_successor,
                                      break_info.break_block());
  set_current_block(loop_exit);
}


void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());

  if (!stmt->each()->IsVariableProxy() ||
      !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
    return Bailout(kForInStatementWithNonLocalEachVariable);
  }

  Variable* each_var = stmt->each()->AsVariableProxy()->var();

  CHECK_ALIVE(VisitForValue(stmt->enumerable()));
  HValue* enumerable = Top();  // Leave enumerable at the top.

  IfBuilder if_undefined_or_null(this);
  if_undefined_or_null.If<HCompareObjectEqAndBranch>(
      enumerable, graph()->GetConstantUndefined());
  if_undefined_or_null.Or();
  if_undefined_or_null.If<HCompareObjectEqAndBranch>(
      enumerable, graph()->GetConstantNull());
  if_undefined_or_null.ThenDeopt(Deoptimizer::kUndefinedOrNullInForIn);
  if_undefined_or_null.End();
  BuildForInBody(stmt, each_var, enumerable);
}


void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
                                            Variable* each_var,
                                            HValue* enumerable) {
  Handle<Map> meta_map = isolate()->factory()->meta_map();
  bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
  BuildCheckHeapObject(enumerable);
  Add<HCheckInstanceType>(enumerable, HCheckInstanceType::IS_JS_RECEIVER);
  Add<HSimulate>(stmt->ToObjectId());
  if (fast) {
    HForInPrepareMap* map = Add<HForInPrepareMap>(enumerable);
    Push(map);
    Add<HSimulate>(stmt->EnumId());
    Drop(1);
    Add<HCheckMaps>(map, meta_map);

    HForInCacheArray* array = Add<HForInCacheArray>(
        enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
    HValue* enum_length = BuildEnumLength(map);

    HForInCacheArray* index_cache = Add<HForInCacheArray>(
        enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
    array->set_index_cache(index_cache);

    Push(map);
    Push(array);
    Push(enum_length);
    Add<HSimulate>(stmt->PrepareId());
  } else {
    Runtime::FunctionId function_id = Runtime::kForInEnumerate;
    Add<HPushArguments>(enumerable);
    HCallRuntime* array =
        Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
    Push(array);
    Add<HSimulate>(stmt->EnumId());
    Drop(1);

    IfBuilder if_fast(this);
    if_fast.If<HCompareMap>(array, meta_map);
    if_fast.Then();
    {
      HValue* cache_map = array;
      HForInCacheArray* cache = Add<HForInCacheArray>(
          enumerable, cache_map, DescriptorArray::kEnumCacheBridgeCacheIndex);
      HValue* enum_length = BuildEnumLength(cache_map);
      Push(cache_map);
      Push(cache);
      Push(enum_length);
      Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
    }
    if_fast.Else();
    {
      Push(graph()->GetConstant1());
      Push(array);
      Push(AddLoadFixedArrayLength(array));
      Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
    }
  }

  Push(graph()->GetConstant0());

  HBasicBlock* loop_entry = BuildLoopEntry(stmt);

  // Reload the values to ensure we have up-to-date values inside of the loop.
  // This is relevant especially for OSR where the values don't come from the
  // computation above, but from the OSR entry block.
  HValue* index = environment()->ExpressionStackAt(0);
  HValue* limit = environment()->ExpressionStackAt(1);
  HValue* array = environment()->ExpressionStackAt(2);
  HValue* type = environment()->ExpressionStackAt(3);
  enumerable = environment()->ExpressionStackAt(4);

  // Check that we still have more keys.
  HCompareNumericAndBranch* compare_index =
      New<HCompareNumericAndBranch>(index, limit, Token::LT);
  compare_index->set_observed_input_representation(
      Representation::Smi(), Representation::Smi());

  HBasicBlock* loop_body = graph()->CreateBasicBlock();
  HBasicBlock* loop_successor = graph()->CreateBasicBlock();

  compare_index->SetSuccessorAt(0, loop_body);
  compare_index->SetSuccessorAt(1, loop_successor);
  FinishCurrentBlock(compare_index);

  set_current_block(loop_successor);
  Drop(5);

  set_current_block(loop_body);

  // Compute the next enumerated value.
  HValue* key = Add<HLoadKeyed>(array, index, index, nullptr, FAST_ELEMENTS);

  HBasicBlock* continue_block = nullptr;
  if (fast) {
    // Check if expected map still matches that of the enumerable.
    Add<HCheckMapValue>(enumerable, type);
    Add<HSimulate>(stmt->FilterId());
  } else {
    // We need the continue block here to be able to skip over invalidated keys.
    continue_block = graph()->CreateBasicBlock();

    // We cannot use the IfBuilder here, since we need to be able to jump
    // over the loop body in case of undefined result from %ForInFilter,
    // and the poor soul that is the IfBuilder get's really confused about
    // such "advanced control flow requirements".
    HBasicBlock* if_fast = graph()->CreateBasicBlock();
    HBasicBlock* if_slow = graph()->CreateBasicBlock();
    HBasicBlock* if_slow_pass = graph()->CreateBasicBlock();
    HBasicBlock* if_slow_skip = graph()->CreateBasicBlock();
    HBasicBlock* if_join = graph()->CreateBasicBlock();

    // Check if expected map still matches that of the enumerable.
    HValue* enumerable_map =
        Add<HLoadNamedField>(enumerable, nullptr, HObjectAccess::ForMap());
    FinishCurrentBlock(
        New<HCompareObjectEqAndBranch>(enumerable_map, type, if_fast, if_slow));
    set_current_block(if_fast);
    {
      // The enum cache for enumerable is still valid, no need to check key.
      Push(key);
      Goto(if_join);
    }
    set_current_block(if_slow);
    {
      // Check if key is still valid for enumerable.
      Add<HPushArguments>(enumerable, key);
      Runtime::FunctionId function_id = Runtime::kForInFilter;
      Push(Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2));
      Add<HSimulate>(stmt->FilterId());
      FinishCurrentBlock(New<HCompareObjectEqAndBranch>(
          Top(), graph()->GetConstantUndefined(), if_slow_skip, if_slow_pass));
    }
    set_current_block(if_slow_pass);
    { Goto(if_join); }
    set_current_block(if_slow_skip);
    {
      // The key is no longer valid for enumerable, skip it.
      Drop(1);
      Goto(continue_block);
    }
    if_join->SetJoinId(stmt->FilterId());
    set_current_block(if_join);
    key = Pop();
  }

  Bind(each_var, key);
  Add<HSimulate>(stmt->AssignmentId());

  BreakAndContinueInfo break_info(stmt, scope(), 5);
  break_info.set_continue_block(continue_block);
  {
    BreakAndContinueScope push(&break_info, this);
    CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
  }

  HBasicBlock* body_exit =
      JoinContinue(stmt, current_block(), break_info.continue_block());

  if (body_exit != NULL) {
    set_current_block(body_exit);

    HValue* current_index = Pop();
    HValue* increment =
        AddUncasted<HAdd>(current_index, graph()->GetConstant1());
    increment->ClearFlag(HValue::kCanOverflow);
    Push(increment);
    body_exit = current_block();
  }

  HBasicBlock* loop_exit = CreateLoop(stmt,
                                      loop_entry,
                                      body_exit,
                                      loop_successor,
                                      break_info.break_block());

  set_current_block(loop_exit);
}


void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kForOfStatement);
}


void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kTryCatchStatement);
}


void HOptimizedGraphBuilder::VisitTryFinallyStatement(
    TryFinallyStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kTryFinallyStatement);
}


void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kDebuggerStatement);
}


void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
  UNREACHABLE();
}


void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  Handle<SharedFunctionInfo> shared_info = Compiler::GetSharedFunctionInfo(
      expr, current_info()->script(), top_info());
  // We also have a stack overflow if the recursive compilation did.
  if (HasStackOverflow()) return;
  // Use the fast case closure allocation code that allocates in new
  // space for nested functions that don't need literals cloning.
  HConstant* shared_info_value = Add<HConstant>(shared_info);
  HInstruction* instr;
  if (!expr->pretenure() && shared_info->num_literals() == 0) {
    FastNewClosureStub stub(isolate(), shared_info->language_mode(),
                            shared_info->kind());
    FastNewClosureDescriptor descriptor(isolate());
    HValue* values[] = {context(), shared_info_value};
    HConstant* stub_value = Add<HConstant>(stub.GetCode());
    instr = New<HCallWithDescriptor>(stub_value, 0, descriptor,
                                     Vector<HValue*>(values, arraysize(values)),
                                     NORMAL_CALL);
  } else {
    Add<HPushArguments>(shared_info_value);
    Runtime::FunctionId function_id =
        expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
    instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
  }
  return ast_context()->ReturnInstruction(instr, expr->id());
}


void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kClassLiteral);
}


void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
    NativeFunctionLiteral* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kNativeFunctionLiteral);
}


void HOptimizedGraphBuilder::VisitDoExpression(DoExpression* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kDoExpression);
}


void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  HBasicBlock* cond_true = graph()->CreateBasicBlock();
  HBasicBlock* cond_false = graph()->CreateBasicBlock();
  CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));

  // Visit the true and false subexpressions in the same AST context as the
  // whole expression.
  if (cond_true->HasPredecessor()) {
    cond_true->SetJoinId(expr->ThenId());
    set_current_block(cond_true);
    CHECK_BAILOUT(Visit(expr->then_expression()));
    cond_true = current_block();
  } else {
    cond_true = NULL;
  }

  if (cond_false->HasPredecessor()) {
    cond_false->SetJoinId(expr->ElseId());
    set_current_block(cond_false);
    CHECK_BAILOUT(Visit(expr->else_expression()));
    cond_false = current_block();
  } else {
    cond_false = NULL;
  }

  if (!ast_context()->IsTest()) {
    HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
    set_current_block(join);
    if (join != NULL && !ast_context()->IsEffect()) {
      return ast_context()->ReturnValue(Pop());
    }
  }
}


HOptimizedGraphBuilder::GlobalPropertyAccess
HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
                                             PropertyAccessType access_type) {
  if (var->is_this() || !current_info()->has_global_object()) {
    return kUseGeneric;
  }

  switch (it->state()) {
    case LookupIterator::ACCESSOR:
    case LookupIterator::ACCESS_CHECK:
    case LookupIterator::INTERCEPTOR:
    case LookupIterator::INTEGER_INDEXED_EXOTIC:
    case LookupIterator::NOT_FOUND:
      return kUseGeneric;
    case LookupIterator::DATA:
      if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
      return kUseCell;
    case LookupIterator::JSPROXY:
    case LookupIterator::TRANSITION:
      UNREACHABLE();
  }
  UNREACHABLE();
  return kUseGeneric;
}


HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
  DCHECK(var->IsContextSlot());
  HValue* context = environment()->context();
  int length = scope()->ContextChainLength(var->scope());
  while (length-- > 0) {
    context = Add<HLoadNamedField>(
        context, nullptr,
        HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
  }
  return context;
}


void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  Variable* variable = expr->var();
  switch (variable->location()) {
    case VariableLocation::GLOBAL:
    case VariableLocation::UNALLOCATED: {
      if (IsLexicalVariableMode(variable->mode())) {
        // TODO(rossberg): should this be an DCHECK?
        return Bailout(kReferenceToGlobalLexicalVariable);
      }
      // Handle known global constants like 'undefined' specially to avoid a
      // load from a global cell for them.
      Handle<Object> constant_value =
          isolate()->factory()->GlobalConstantFor(variable->name());
      if (!constant_value.is_null()) {
        HConstant* instr = New<HConstant>(constant_value);
        return ast_context()->ReturnInstruction(instr, expr->id());
      }

      Handle<JSGlobalObject> global(current_info()->global_object());

      // Lookup in script contexts.
      {
        Handle<ScriptContextTable> script_contexts(
            global->native_context()->script_context_table());
        ScriptContextTable::LookupResult lookup;
        if (ScriptContextTable::Lookup(script_contexts, variable->name(),
                                       &lookup)) {
          Handle<Context> script_context = ScriptContextTable::GetContext(
              script_contexts, lookup.context_index);
          Handle<Object> current_value =
              FixedArray::get(*script_context, lookup.slot_index, isolate());

          // If the values is not the hole, it will stay initialized,
          // so no need to generate a check.
          if (*current_value == *isolate()->factory()->the_hole_value()) {
            return Bailout(kReferenceToUninitializedVariable);
          }
          HInstruction* result = New<HLoadNamedField>(
              Add<HConstant>(script_context), nullptr,
              HObjectAccess::ForContextSlot(lookup.slot_index));
          return ast_context()->ReturnInstruction(result, expr->id());
        }
      }

      LookupIterator it(global, variable->name(), LookupIterator::OWN);
      GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);

      if (type == kUseCell) {
        Handle<PropertyCell> cell = it.GetPropertyCell();
        top_info()->dependencies()->AssumePropertyCell(cell);
        auto cell_type = it.property_details().cell_type();
        if (cell_type == PropertyCellType::kConstant ||
            cell_type == PropertyCellType::kUndefined) {
          Handle<Object> constant_object(cell->value(), isolate());
          if (constant_object->IsConsString()) {
            constant_object =
                String::Flatten(Handle<String>::cast(constant_object));
          }
          HConstant* constant = New<HConstant>(constant_object);
          return ast_context()->ReturnInstruction(constant, expr->id());
        } else {
          auto access = HObjectAccess::ForPropertyCellValue();
          UniqueSet<Map>* field_maps = nullptr;
          if (cell_type == PropertyCellType::kConstantType) {
            switch (cell->GetConstantType()) {
              case PropertyCellConstantType::kSmi:
                access = access.WithRepresentation(Representation::Smi());
                break;
              case PropertyCellConstantType::kStableMap: {
                // Check that the map really is stable. The heap object could
                // have mutated without the cell updating state. In that case,
                // make no promises about the loaded value except that it's a
                // heap object.
                access =
                    access.WithRepresentation(Representation::HeapObject());
                Handle<Map> map(HeapObject::cast(cell->value())->map());
                if (map->is_stable()) {
                  field_maps = new (zone())
                      UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
                }
                break;
              }
            }
          }
          HConstant* cell_constant = Add<HConstant>(cell);
          HLoadNamedField* instr;
          if (field_maps == nullptr) {
            instr = New<HLoadNamedField>(cell_constant, nullptr, access);
          } else {
            instr = New<HLoadNamedField>(cell_constant, nullptr, access,
                                         field_maps, HType::HeapObject());
          }
          instr->ClearDependsOnFlag(kInobjectFields);
          instr->SetDependsOnFlag(kGlobalVars);
          return ast_context()->ReturnInstruction(instr, expr->id());
        }
      } else {
        HValue* global_object = Add<HLoadNamedField>(
            BuildGetNativeContext(), nullptr,
            HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
        HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>(
            global_object, variable->name(), ast_context()->typeof_mode());
        instr->SetVectorAndSlot(handle(current_feedback_vector(), isolate()),
                                expr->VariableFeedbackSlot());
        return ast_context()->ReturnInstruction(instr, expr->id());
      }
    }

    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL: {
      HValue* value = LookupAndMakeLive(variable);
      if (value == graph()->GetConstantHole()) {
        DCHECK(IsDeclaredVariableMode(variable->mode()) &&
               variable->mode() != VAR);
        return Bailout(kReferenceToUninitializedVariable);
      }
      return ast_context()->ReturnValue(value);
    }

    case VariableLocation::CONTEXT: {
      HValue* context = BuildContextChainWalk(variable);
      HLoadContextSlot::Mode mode;
      switch (variable->mode()) {
        case LET:
        case CONST:
          mode = HLoadContextSlot::kCheckDeoptimize;
          break;
        case CONST_LEGACY:
          mode = HLoadContextSlot::kCheckReturnUndefined;
          break;
        default:
          mode = HLoadContextSlot::kNoCheck;
          break;
      }
      HLoadContextSlot* instr =
          new(zone()) HLoadContextSlot(context, variable->index(), mode);
      return ast_context()->ReturnInstruction(instr, expr->id());
    }

    case VariableLocation::LOOKUP:
      return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
  }
}


void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  HConstant* instr = New<HConstant>(expr->value());
  return ast_context()->ReturnInstruction(instr, expr->id());
}


void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  Callable callable = CodeFactory::FastCloneRegExp(isolate());
  HValue* values[] = {
      context(), AddThisFunction(), Add<HConstant>(expr->literal_index()),
      Add<HConstant>(expr->pattern()), Add<HConstant>(expr->flags())};
  HConstant* stub_value = Add<HConstant>(callable.code());
  HInstruction* instr = New<HCallWithDescriptor>(
      stub_value, 0, callable.descriptor(),
      Vector<HValue*>(values, arraysize(values)), NORMAL_CALL);
  return ast_context()->ReturnInstruction(instr, expr->id());
}


static bool CanInlinePropertyAccess(Handle<Map> map) {
  if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
  if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
  return map->IsJSObjectMap() && !map->is_dictionary_map() &&
         !map->has_named_interceptor() &&
         // TODO(verwaest): Whitelist contexts to which we have access.
         !map->is_access_check_needed();
}


// Determines whether the given array or object literal boilerplate satisfies
// all limits to be considered for fast deep-copying and computes the total
// size of all objects that are part of the graph.
static bool IsFastLiteral(Handle<JSObject> boilerplate,
                          int max_depth,
                          int* max_properties) {
  if (boilerplate->map()->is_deprecated() &&
      !JSObject::TryMigrateInstance(boilerplate)) {
    return false;
  }

  DCHECK(max_depth >= 0 && *max_properties >= 0);
  if (max_depth == 0) return false;

  Isolate* isolate = boilerplate->GetIsolate();
  Handle<FixedArrayBase> elements(boilerplate->elements());
  if (elements->length() > 0 &&
      elements->map() != isolate->heap()->fixed_cow_array_map()) {
    if (boilerplate->HasFastSmiOrObjectElements()) {
      Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
      int length = elements->length();
      for (int i = 0; i < length; i++) {
        if ((*max_properties)-- == 0) return false;
        Handle<Object> value(fast_elements->get(i), isolate);
        if (value->IsJSObject()) {
          Handle<JSObject> value_object = Handle<JSObject>::cast(value);
          if (!IsFastLiteral(value_object,
                             max_depth - 1,
                             max_properties)) {
            return false;
          }
        }
      }
    } else if (!boilerplate->HasFastDoubleElements()) {
      return false;
    }
  }

  Handle<FixedArray> properties(boilerplate->properties());
  if (properties->length() > 0) {
    return false;
  } else {
    Handle<DescriptorArray> descriptors(
        boilerplate->map()->instance_descriptors());
    int limit = boilerplate->map()->NumberOfOwnDescriptors();
    for (int i = 0; i < limit; i++) {
      PropertyDetails details = descriptors->GetDetails(i);
      if (details.type() != DATA) continue;
      if ((*max_properties)-- == 0) return false;
      FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
      if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
      Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
                           isolate);
      if (value->IsJSObject()) {
        Handle<JSObject> value_object = Handle<JSObject>::cast(value);
        if (!IsFastLiteral(value_object,
                           max_depth - 1,
                           max_properties)) {
          return false;
        }
      }
    }
  }
  return true;
}


void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());

  Handle<JSFunction> closure = function_state()->compilation_info()->closure();
  HInstruction* literal;

  // Check whether to use fast or slow deep-copying for boilerplate.
  int max_properties = kMaxFastLiteralProperties;
  Handle<Object> literals_cell(
      closure->literals()->literal(expr->literal_index()), isolate());
  Handle<AllocationSite> site;
  Handle<JSObject> boilerplate;
  if (!literals_cell->IsUndefined()) {
    // Retrieve the boilerplate
    site = Handle<AllocationSite>::cast(literals_cell);
    boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
                                   isolate());
  }

  if (!boilerplate.is_null() &&
      IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
    AllocationSiteUsageContext site_context(isolate(), site, false);
    site_context.EnterNewScope();
    literal = BuildFastLiteral(boilerplate, &site_context);
    site_context.ExitScope(site, boilerplate);
  } else {
    NoObservableSideEffectsScope no_effects(this);
    Handle<FixedArray> constant_properties = expr->constant_properties();
    int literal_index = expr->literal_index();
    int flags = expr->ComputeFlags(true);

    Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
                        Add<HConstant>(constant_properties),
                        Add<HConstant>(flags));

    Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
    literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
  }

  // The object is expected in the bailout environment during computation
  // of the property values and is the value of the entire expression.
  Push(literal);
  for (int i = 0; i < expr->properties()->length(); i++) {
    ObjectLiteral::Property* property = expr->properties()->at(i);
    if (property->is_computed_name()) return Bailout(kComputedPropertyName);
    if (property->IsCompileTimeValue()) continue;

    Literal* key = property->key()->AsLiteral();
    Expression* value = property->value();

    switch (property->kind()) {
      case ObjectLiteral::Property::MATERIALIZED_LITERAL:
        DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
        // Fall through.
      case ObjectLiteral::Property::COMPUTED:
        // It is safe to use [[Put]] here because the boilerplate already
        // contains computed properties with an uninitialized value.
        if (key->value()->IsInternalizedString()) {
          if (property->emit_store()) {
            CHECK_ALIVE(VisitForValue(value));
            HValue* value = Pop();

            Handle<Map> map = property->GetReceiverType();
            Handle<String> name = key->AsPropertyName();
            HValue* store;
            FeedbackVectorSlot slot = property->GetSlot();
            if (map.is_null()) {
              // If we don't know the monomorphic type, do a generic store.
              CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
                                                    name, value));
            } else {
              PropertyAccessInfo info(this, STORE, map, name);
              if (info.CanAccessMonomorphic()) {
                HValue* checked_literal = Add<HCheckMaps>(literal, map);
                DCHECK(!info.IsAccessorConstant());
                store = BuildMonomorphicAccess(
                    &info, literal, checked_literal, value,
                    BailoutId::None(), BailoutId::None());
              } else {
                CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
                                                      literal, name, value));
              }
            }
            if (store->IsInstruction()) {
              AddInstruction(HInstruction::cast(store));
            }
            DCHECK(store->HasObservableSideEffects());
            Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);

            // Add [[HomeObject]] to function literals.
            if (FunctionLiteral::NeedsHomeObject(property->value())) {
              Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
              HInstruction* store_home = BuildNamedGeneric(
                  STORE, NULL, property->GetSlot(1), value, sym, literal);
              AddInstruction(store_home);
              DCHECK(store_home->HasObservableSideEffects());
              Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
            }
          } else {
            CHECK_ALIVE(VisitForEffect(value));
          }
          break;
        }
        // Fall through.
      case ObjectLiteral::Property::PROTOTYPE:
      case ObjectLiteral::Property::SETTER:
      case ObjectLiteral::Property::GETTER:
        return Bailout(kObjectLiteralWithComplexProperty);
      default: UNREACHABLE();
    }
  }

  if (expr->has_function()) {
    // Return the result of the transformation to fast properties
    // instead of the original since this operation changes the map
    // of the object. This makes sure that the original object won't
    // be used by other optimized code before it is transformed
    // (e.g. because of code motion).
    HToFastProperties* result = Add<HToFastProperties>(Pop());
    return ast_context()->ReturnValue(result);
  } else {
    return ast_context()->ReturnValue(Pop());
  }
}


void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  ZoneList<Expression*>* subexprs = expr->values();
  int length = subexprs->length();
  HInstruction* literal;

  Handle<AllocationSite> site;
  Handle<LiteralsArray> literals(environment()->closure()->literals(),
                                 isolate());
  bool uninitialized = false;
  Handle<Object> literals_cell(literals->literal(expr->literal_index()),
                               isolate());
  Handle<JSObject> boilerplate_object;
  if (literals_cell->IsUndefined()) {
    uninitialized = true;
    Handle<Object> raw_boilerplate;
    ASSIGN_RETURN_ON_EXCEPTION_VALUE(
        isolate(), raw_boilerplate,
        Runtime::CreateArrayLiteralBoilerplate(
            isolate(), literals, expr->constant_elements(),
            is_strong(function_language_mode())),
        Bailout(kArrayBoilerplateCreationFailed));

    boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
    AllocationSiteCreationContext creation_context(isolate());
    site = creation_context.EnterNewScope();
    if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
      return Bailout(kArrayBoilerplateCreationFailed);
    }
    creation_context.ExitScope(site, boilerplate_object);
    literals->set_literal(expr->literal_index(), *site);

    if (boilerplate_object->elements()->map() ==
        isolate()->heap()->fixed_cow_array_map()) {
      isolate()->counters()->cow_arrays_created_runtime()->Increment();
    }
  } else {
    DCHECK(literals_cell->IsAllocationSite());
    site = Handle<AllocationSite>::cast(literals_cell);
    boilerplate_object = Handle<JSObject>(
        JSObject::cast(site->transition_info()), isolate());
  }

  DCHECK(!boilerplate_object.is_null());
  DCHECK(site->SitePointsToLiteral());

  ElementsKind boilerplate_elements_kind =
      boilerplate_object->GetElementsKind();

  // Check whether to use fast or slow deep-copying for boilerplate.
  int max_properties = kMaxFastLiteralProperties;
  if (IsFastLiteral(boilerplate_object,
                    kMaxFastLiteralDepth,
                    &max_properties)) {
    AllocationSiteUsageContext site_context(isolate(), site, false);
    site_context.EnterNewScope();
    literal = BuildFastLiteral(boilerplate_object, &site_context);
    site_context.ExitScope(site, boilerplate_object);
  } else {
    NoObservableSideEffectsScope no_effects(this);
    // Boilerplate already exists and constant elements are never accessed,
    // pass an empty fixed array to the runtime function instead.
    Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
    int literal_index = expr->literal_index();
    int flags = expr->ComputeFlags(true);

    Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
                        Add<HConstant>(constants), Add<HConstant>(flags));

    Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
    literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);

    // Register to deopt if the boilerplate ElementsKind changes.
    top_info()->dependencies()->AssumeTransitionStable(site);
  }

  // The array is expected in the bailout environment during computation
  // of the property values and is the value of the entire expression.
  Push(literal);

  HInstruction* elements = NULL;

  for (int i = 0; i < length; i++) {
    Expression* subexpr = subexprs->at(i);
    DCHECK(!subexpr->IsSpread());

    // If the subexpression is a literal or a simple materialized literal it
    // is already set in the cloned array.
    if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;

    CHECK_ALIVE(VisitForValue(subexpr));
    HValue* value = Pop();
    if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);

    elements = AddLoadElements(literal);

    HValue* key = Add<HConstant>(i);

    switch (boilerplate_elements_kind) {
      case FAST_SMI_ELEMENTS:
      case FAST_HOLEY_SMI_ELEMENTS:
      case FAST_ELEMENTS:
      case FAST_HOLEY_ELEMENTS:
      case FAST_DOUBLE_ELEMENTS:
      case FAST_HOLEY_DOUBLE_ELEMENTS: {
        HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, nullptr,
                                              boilerplate_elements_kind);
        instr->SetUninitialized(uninitialized);
        break;
      }
      default:
        UNREACHABLE();
        break;
    }

    Add<HSimulate>(expr->GetIdForElement(i));
  }

  return ast_context()->ReturnValue(Pop());
}


HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
                                                Handle<Map> map) {
  BuildCheckHeapObject(object);
  return Add<HCheckMaps>(object, map);
}


HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
    PropertyAccessInfo* info,
    HValue* checked_object) {
  // See if this is a load for an immutable property
  if (checked_object->ActualValue()->IsConstant()) {
    Handle<Object> object(
        HConstant::cast(checked_object->ActualValue())->handle(isolate()));

    if (object->IsJSObject()) {
      LookupIterator it(object, info->name(),
                        LookupIterator::OWN_SKIP_INTERCEPTOR);
      Handle<Object> value = JSReceiver::GetDataProperty(&it);
      if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
        return New<HConstant>(value);
      }
    }
  }

  HObjectAccess access = info->access();
  if (access.representation().IsDouble() &&
      (!FLAG_unbox_double_fields || !access.IsInobject())) {
    // Load the heap number.
    checked_object = Add<HLoadNamedField>(
        checked_object, nullptr,
        access.WithRepresentation(Representation::Tagged()));
    // Load the double value from it.
    access = HObjectAccess::ForHeapNumberValue();
  }

  SmallMapList* map_list = info->field_maps();
  if (map_list->length() == 0) {
    return New<HLoadNamedField>(checked_object, checked_object, access);
  }

  UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
  for (int i = 0; i < map_list->length(); ++i) {
    maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
  }
  return New<HLoadNamedField>(
      checked_object, checked_object, access, maps, info->field_type());
}


HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
    PropertyAccessInfo* info,
    HValue* checked_object,
    HValue* value) {
  bool transition_to_field = info->IsTransition();
  // TODO(verwaest): Move this logic into PropertyAccessInfo.
  HObjectAccess field_access = info->access();

  HStoreNamedField *instr;
  if (field_access.representation().IsDouble() &&
      (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
    HObjectAccess heap_number_access =
        field_access.WithRepresentation(Representation::Tagged());
    if (transition_to_field) {
      // The store requires a mutable HeapNumber to be allocated.
      NoObservableSideEffectsScope no_side_effects(this);
      HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);

      // TODO(hpayer): Allocation site pretenuring support.
      HInstruction* heap_number = Add<HAllocate>(heap_number_size,
          HType::HeapObject(),
          NOT_TENURED,
          MUTABLE_HEAP_NUMBER_TYPE);
      AddStoreMapConstant(
          heap_number, isolate()->factory()->mutable_heap_number_map());
      Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
                            value);
      instr = New<HStoreNamedField>(checked_object->ActualValue(),
                                    heap_number_access,
                                    heap_number);
    } else {
      // Already holds a HeapNumber; load the box and write its value field.
      HInstruction* heap_number =
          Add<HLoadNamedField>(checked_object, nullptr, heap_number_access);
      instr = New<HStoreNamedField>(heap_number,
                                    HObjectAccess::ForHeapNumberValue(),
                                    value, STORE_TO_INITIALIZED_ENTRY);
    }
  } else {
    if (field_access.representation().IsHeapObject()) {
      BuildCheckHeapObject(value);
    }

    if (!info->field_maps()->is_empty()) {
      DCHECK(field_access.representation().IsHeapObject());
      value = Add<HCheckMaps>(value, info->field_maps());
    }

    // This is a normal store.
    instr = New<HStoreNamedField>(
        checked_object->ActualValue(), field_access, value,
        transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
  }

  if (transition_to_field) {
    Handle<Map> transition(info->transition());
    DCHECK(!transition->is_deprecated());
    instr->SetTransition(Add<HConstant>(transition));
  }
  return instr;
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
    PropertyAccessInfo* info) {
  if (!CanInlinePropertyAccess(map_)) return false;

  // Currently only handle Type::Number as a polymorphic case.
  // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
  // instruction.
  if (IsNumberType()) return false;

  // Values are only compatible for monomorphic load if they all behave the same
  // regarding value wrappers.
  if (IsValueWrapped() != info->IsValueWrapped()) return false;

  if (!LookupDescriptor()) return false;

  if (!IsFound()) {
    return (!info->IsFound() || info->has_holder()) &&
           map()->prototype() == info->map()->prototype();
  }

  // Mismatch if the other access info found the property in the prototype
  // chain.
  if (info->has_holder()) return false;

  if (IsAccessorConstant()) {
    return accessor_.is_identical_to(info->accessor_) &&
        api_holder_.is_identical_to(info->api_holder_);
  }

  if (IsDataConstant()) {
    return constant_.is_identical_to(info->constant_);
  }

  DCHECK(IsData());
  if (!info->IsData()) return false;

  Representation r = access_.representation();
  if (IsLoad()) {
    if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
  } else {
    if (!info->access_.representation().IsCompatibleForStore(r)) return false;
  }
  if (info->access_.offset() != access_.offset()) return false;
  if (info->access_.IsInobject() != access_.IsInobject()) return false;
  if (IsLoad()) {
    if (field_maps_.is_empty()) {
      info->field_maps_.Clear();
    } else if (!info->field_maps_.is_empty()) {
      for (int i = 0; i < field_maps_.length(); ++i) {
        info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
      }
      info->field_maps_.Sort();
    }
  } else {
    // We can only merge stores that agree on their field maps. The comparison
    // below is safe, since we keep the field maps sorted.
    if (field_maps_.length() != info->field_maps_.length()) return false;
    for (int i = 0; i < field_maps_.length(); ++i) {
      if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
        return false;
      }
    }
  }
  info->GeneralizeRepresentation(r);
  info->field_type_ = info->field_type_.Combine(field_type_);
  return true;
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
  if (!map_->IsJSObjectMap()) return true;
  LookupDescriptor(*map_, *name_);
  return LoadResult(map_);
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
  if (!IsLoad() && IsProperty() && IsReadOnly()) {
    return false;
  }

  if (IsData()) {
    // Construct the object field access.
    int index = GetLocalFieldIndexFromMap(map);
    access_ = HObjectAccess::ForField(map, index, representation(), name_);

    // Load field map for heap objects.
    return LoadFieldMaps(map);
  } else if (IsAccessorConstant()) {
    Handle<Object> accessors = GetAccessorsFromMap(map);
    if (!accessors->IsAccessorPair()) return false;
    Object* raw_accessor =
        IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
                 : Handle<AccessorPair>::cast(accessors)->setter();
    if (!raw_accessor->IsJSFunction() &&
        !raw_accessor->IsFunctionTemplateInfo())
      return false;
    Handle<Object> accessor = handle(HeapObject::cast(raw_accessor));
    CallOptimization call_optimization(accessor);
    if (call_optimization.is_simple_api_call()) {
      CallOptimization::HolderLookup holder_lookup;
      api_holder_ =
          call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
    }
    accessor_ = accessor;
  } else if (IsDataConstant()) {
    constant_ = GetConstantFromMap(map);
  }

  return true;
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
    Handle<Map> map) {
  // Clear any previously collected field maps/type.
  field_maps_.Clear();
  field_type_ = HType::Tagged();

  // Figure out the field type from the accessor map.
  Handle<FieldType> field_type = GetFieldTypeFromMap(map);

  // Collect the (stable) maps from the field type.
  if (field_type->IsClass()) {
    DCHECK(access_.representation().IsHeapObject());
    Handle<Map> field_map = field_type->AsClass();
    if (field_map->is_stable()) {
      field_maps_.Add(field_map, zone());
    }
  }

  if (field_maps_.is_empty()) {
    // Store is not safe if the field map was cleared.
    return IsLoad() || !field_type->IsNone();
  }

  // Determine field HType from field type.
  field_type_ = HType::FromFieldType(field_type, zone());
  DCHECK(field_type_.IsHeapObject());

  // Add dependency on the map that introduced the field.
  top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map));
  return true;
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
  Handle<Map> map = this->map();
  if (name_->IsPrivate()) {
    NotFound();
    return !map->has_hidden_prototype();
  }

  while (map->prototype()->IsJSObject()) {
    holder_ = handle(JSObject::cast(map->prototype()));
    if (holder_->map()->is_deprecated()) {
      JSObject::TryMigrateInstance(holder_);
    }
    map = Handle<Map>(holder_->map());
    if (!CanInlinePropertyAccess(map)) {
      NotFound();
      return false;
    }
    LookupDescriptor(*map, *name_);
    if (IsFound()) return LoadResult(map);
  }

  NotFound();
  return !map->prototype()->IsJSReceiver();
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
  InstanceType instance_type = map_->instance_type();
  return instance_type == JS_TYPED_ARRAY_TYPE && name_->IsString() &&
         IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name_));
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
  if (!CanInlinePropertyAccess(map_)) return false;
  if (IsJSObjectFieldAccessor()) return IsLoad();
  if (IsJSArrayBufferViewFieldAccessor()) return IsLoad();
  if (map_->IsJSFunctionMap() && map_->is_constructor() &&
      !map_->has_non_instance_prototype() &&
      name_.is_identical_to(isolate()->factory()->prototype_string())) {
    return IsLoad();
  }
  if (!LookupDescriptor()) return false;
  if (IsFound()) return IsLoad() || !IsReadOnly();
  if (IsIntegerIndexedExotic()) return false;
  if (!LookupInPrototypes()) return false;
  if (IsLoad()) return true;

  if (IsAccessorConstant()) return true;
  LookupTransition(*map_, *name_, NONE);
  if (IsTransitionToData() && map_->unused_property_fields() > 0) {
    // Construct the object field access.
    int descriptor = transition()->LastAdded();
    int index =
        transition()->instance_descriptors()->GetFieldIndex(descriptor) -
        map_->GetInObjectProperties();
    PropertyDetails details =
        transition()->instance_descriptors()->GetDetails(descriptor);
    Representation representation = details.representation();
    access_ = HObjectAccess::ForField(map_, index, representation, name_);

    // Load field map for heap objects.
    return LoadFieldMaps(transition());
  }
  return false;
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
    SmallMapList* maps) {
  DCHECK(map_.is_identical_to(maps->first()));
  if (!CanAccessMonomorphic()) return false;
  STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
  if (maps->length() > kMaxLoadPolymorphism) return false;
  HObjectAccess access = HObjectAccess::ForMap();  // bogus default
  if (GetJSObjectFieldAccess(&access)) {
    for (int i = 1; i < maps->length(); ++i) {
      PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
      HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
      if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
      if (!access.Equals(test_access)) return false;
    }
    return true;
  }
  if (GetJSArrayBufferViewFieldAccess(&access)) {
    for (int i = 1; i < maps->length(); ++i) {
      PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
      HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
      if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) {
        return false;
      }
      if (!access.Equals(test_access)) return false;
    }
    return true;
  }

  // Currently only handle numbers as a polymorphic case.
  // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
  // instruction.
  if (IsNumberType()) return false;

  // Multiple maps cannot transition to the same target map.
  DCHECK(!IsLoad() || !IsTransition());
  if (IsTransition() && maps->length() > 1) return false;

  for (int i = 1; i < maps->length(); ++i) {
    PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
    if (!test_info.IsCompatible(this)) return false;
  }

  return true;
}


Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
  Handle<JSFunction> ctor;
  if (Map::GetConstructorFunction(
          map_, handle(current_info()->closure()->context()->native_context()))
          .ToHandle(&ctor)) {
    return handle(ctor->initial_map());
  }
  return map_;
}


static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
  return !map->IsJSObjectMap() &&
         is_sloppy(target->shared()->language_mode()) &&
         !target->shared()->native();
}


bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
    Handle<JSFunction> target) const {
  return NeedsWrapping(map_, target);
}


HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
    PropertyAccessInfo* info, HValue* object, HValue* checked_object,
    HValue* value, BailoutId ast_id, BailoutId return_id,
    bool can_inline_accessor) {
  HObjectAccess access = HObjectAccess::ForMap();  // bogus default
  if (info->GetJSObjectFieldAccess(&access)) {
    DCHECK(info->IsLoad());
    return New<HLoadNamedField>(object, checked_object, access);
  }

  if (info->GetJSArrayBufferViewFieldAccess(&access)) {
    DCHECK(info->IsLoad());
    checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
    return New<HLoadNamedField>(object, checked_object, access);
  }

  if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
      info->map()->IsJSFunctionMap() && info->map()->is_constructor()) {
    DCHECK(!info->map()->has_non_instance_prototype());
    return New<HLoadFunctionPrototype>(checked_object);
  }

  HValue* checked_holder = checked_object;
  if (info->has_holder()) {
    Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
    checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
  }

  if (!info->IsFound()) {
    DCHECK(info->IsLoad());
    if (is_strong(function_language_mode())) {
      return New<HCallRuntime>(
          Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
          0);
    } else {
      return graph()->GetConstantUndefined();
    }
  }

  if (info->IsData()) {
    if (info->IsLoad()) {
      return BuildLoadNamedField(info, checked_holder);
    } else {
      return BuildStoreNamedField(info, checked_object, value);
    }
  }

  if (info->IsTransition()) {
    DCHECK(!info->IsLoad());
    return BuildStoreNamedField(info, checked_object, value);
  }

  if (info->IsAccessorConstant()) {
    Push(checked_object);
    int argument_count = 1;
    if (!info->IsLoad()) {
      argument_count = 2;
      Push(value);
    }

    if (info->accessor()->IsJSFunction() &&
        info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) {
      HValue* function = Add<HConstant>(info->accessor());
      PushArgumentsFromEnvironment(argument_count);
      return New<HCallFunction>(function, argument_count,
                                ConvertReceiverMode::kNotNullOrUndefined);
    } else if (FLAG_inline_accessors && can_inline_accessor) {
      bool success = info->IsLoad()
          ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
          : TryInlineSetter(
              info->accessor(), info->map(), ast_id, return_id, value);
      if (success || HasStackOverflow()) return NULL;
    }

    PushArgumentsFromEnvironment(argument_count);
    if (!info->accessor()->IsJSFunction()) {
      Bailout(kInliningBailedOut);
      return nullptr;
    }
    return BuildCallConstantFunction(Handle<JSFunction>::cast(info->accessor()),
                                     argument_count);
  }

  DCHECK(info->IsDataConstant());
  if (info->IsLoad()) {
    return New<HConstant>(info->constant());
  } else {
    return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
  }
}


void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
    PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
    BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
    SmallMapList* maps, Handle<Name> name) {
  // Something did not match; must use a polymorphic load.
  int count = 0;
  HBasicBlock* join = NULL;
  HBasicBlock* number_block = NULL;
  bool handled_string = false;

  bool handle_smi = false;
  STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
  int i;
  for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
    PropertyAccessInfo info(this, access_type, maps->at(i), name);
    if (info.IsStringType()) {
      if (handled_string) continue;
      handled_string = true;
    }
    if (info.CanAccessMonomorphic()) {
      count++;
      if (info.IsNumberType()) {
        handle_smi = true;
        break;
      }
    }
  }

  if (i < maps->length()) {
    count = -1;
    maps->Clear();
  } else {
    count = 0;
  }
  HControlInstruction* smi_check = NULL;
  handled_string = false;

  for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
    PropertyAccessInfo info(this, access_type, maps->at(i), name);
    if (info.IsStringType()) {
      if (handled_string) continue;
      handled_string = true;
    }
    if (!info.CanAccessMonomorphic()) continue;

    if (count == 0) {
      join = graph()->CreateBasicBlock();
      if (handle_smi) {
        HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
        HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
        number_block = graph()->CreateBasicBlock();
        smi_check = New<HIsSmiAndBranch>(
            object, empty_smi_block, not_smi_block);
        FinishCurrentBlock(smi_check);
        GotoNoSimulate(empty_smi_block, number_block);
        set_current_block(not_smi_block);
      } else {
        BuildCheckHeapObject(object);
      }
    }
    ++count;
    HBasicBlock* if_true = graph()->CreateBasicBlock();
    HBasicBlock* if_false = graph()->CreateBasicBlock();
    HUnaryControlInstruction* compare;

    HValue* dependency;
    if (info.IsNumberType()) {
      Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
      compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
      dependency = smi_check;
    } else if (info.IsStringType()) {
      compare = New<HIsStringAndBranch>(object, if_true, if_false);
      dependency = compare;
    } else {
      compare = New<HCompareMap>(object, info.map(), if_true, if_false);
      dependency = compare;
    }
    FinishCurrentBlock(compare);

    if (info.IsNumberType()) {
      GotoNoSimulate(if_true, number_block);
      if_true = number_block;
    }

    set_current_block(if_true);

    HValue* access =
        BuildMonomorphicAccess(&info, object, dependency, value, ast_id,
                               return_id, FLAG_polymorphic_inlining);

    HValue* result = NULL;
    switch (access_type) {
      case LOAD:
        result = access;
        break;
      case STORE:
        result = value;
        break;
    }

    if (access == NULL) {
      if (HasStackOverflow()) return;
    } else {
      if (access->IsInstruction()) {
        HInstruction* instr = HInstruction::cast(access);
        if (!instr->IsLinked()) AddInstruction(instr);
      }
      if (!ast_context()->IsEffect()) Push(result);
    }

    if (current_block() != NULL) Goto(join);
    set_current_block(if_false);
  }

  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
  // know about and do not want to handle ones we've never seen.  Otherwise
  // use a generic IC.
  if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
    FinishExitWithHardDeoptimization(
        Deoptimizer::kUnknownMapInPolymorphicAccess);
  } else {
    HInstruction* instr =
        BuildNamedGeneric(access_type, expr, slot, object, name, value);
    AddInstruction(instr);
    if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);

    if (join != NULL) {
      Goto(join);
    } else {
      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
      if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
      return;
    }
  }

  DCHECK(join != NULL);
  if (join->HasPredecessor()) {
    join->SetJoinId(ast_id);
    set_current_block(join);
    if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
  } else {
    set_current_block(NULL);
  }
}


static bool ComputeReceiverTypes(Expression* expr,
                                 HValue* receiver,
                                 SmallMapList** t,
                                 Zone* zone) {
  SmallMapList* maps = expr->GetReceiverTypes();
  *t = maps;
  bool monomorphic = expr->IsMonomorphic();
  if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
    Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
    maps->FilterForPossibleTransitions(root_map);
    monomorphic = maps->length() == 1;
  }
  return monomorphic && CanInlinePropertyAccess(maps->first());
}


static bool AreStringTypes(SmallMapList* maps) {
  for (int i = 0; i < maps->length(); i++) {
    if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
  }
  return true;
}


void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
                                        FeedbackVectorSlot slot,
                                        BailoutId ast_id, BailoutId return_id,
                                        bool is_uninitialized) {
  if (!prop->key()->IsPropertyName()) {
    // Keyed store.
    HValue* value = Pop();
    HValue* key = Pop();
    HValue* object = Pop();
    bool has_side_effects = false;
    HValue* result =
        HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
                                 return_id, STORE, &has_side_effects);
    if (has_side_effects) {
      if (!ast_context()->IsEffect()) Push(value);
      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
      if (!ast_context()->IsEffect()) Drop(1);
    }
    if (result == NULL) return;
    return ast_context()->ReturnValue(value);
  }

  // Named store.
  HValue* value = Pop();
  HValue* object = Pop();

  Literal* key = prop->key()->AsLiteral();
  Handle<String> name = Handle<String>::cast(key->value());
  DCHECK(!name.is_null());

  HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, slot,
                                    object, name, value, is_uninitialized);
  if (access == NULL) return;

  if (!ast_context()->IsEffect()) Push(value);
  if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
  if (access->HasObservableSideEffects()) {
    Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
  }
  if (!ast_context()->IsEffect()) Drop(1);
  return ast_context()->ReturnValue(value);
}


void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
  Property* prop = expr->target()->AsProperty();
  DCHECK(prop != NULL);
  CHECK_ALIVE(VisitForValue(prop->obj()));
  if (!prop->key()->IsPropertyName()) {
    CHECK_ALIVE(VisitForValue(prop->key()));
  }
  CHECK_ALIVE(VisitForValue(expr->value()));
  BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
             expr->AssignmentId(), expr->IsUninitialized());
}


// Because not every expression has a position and there is not common
// superclass of Assignment and CountOperation, we cannot just pass the
// owning expression instead of position and ast_id separately.
void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
    Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) {
  Handle<JSGlobalObject> global(current_info()->global_object());

  // Lookup in script contexts.
  {
    Handle<ScriptContextTable> script_contexts(
        global->native_context()->script_context_table());
    ScriptContextTable::LookupResult lookup;
    if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
      if (lookup.mode == CONST) {
        return Bailout(kNonInitializerAssignmentToConst);
      }
      Handle<Context> script_context =
          ScriptContextTable::GetContext(script_contexts, lookup.context_index);

      Handle<Object> current_value =
          FixedArray::get(*script_context, lookup.slot_index, isolate());

      // If the values is not the hole, it will stay initialized,
      // so no need to generate a check.
      if (*current_value == *isolate()->factory()->the_hole_value()) {
        return Bailout(kReferenceToUninitializedVariable);
      }

      HStoreNamedField* instr = Add<HStoreNamedField>(
          Add<HConstant>(script_context),
          HObjectAccess::ForContextSlot(lookup.slot_index), value);
      USE(instr);
      DCHECK(instr->HasObservableSideEffects());
      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
      return;
    }
  }

  LookupIterator it(global, var->name(), LookupIterator::OWN);
  GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
  if (type == kUseCell) {
    Handle<PropertyCell> cell = it.GetPropertyCell();
    top_info()->dependencies()->AssumePropertyCell(cell);
    auto cell_type = it.property_details().cell_type();
    if (cell_type == PropertyCellType::kConstant ||
        cell_type == PropertyCellType::kUndefined) {
      Handle<Object> constant(cell->value(), isolate());
      if (value->IsConstant()) {
        HConstant* c_value = HConstant::cast(value);
        if (!constant.is_identical_to(c_value->handle(isolate()))) {
          Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
                           Deoptimizer::EAGER);
        }
      } else {
        HValue* c_constant = Add<HConstant>(constant);
        IfBuilder builder(this);
        if (constant->IsNumber()) {
          builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
        } else {
          builder.If<HCompareObjectEqAndBranch>(value, c_constant);
        }
        builder.Then();
        builder.Else();
        Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
                         Deoptimizer::EAGER);
        builder.End();
      }
    }
    HConstant* cell_constant = Add<HConstant>(cell);
    auto access = HObjectAccess::ForPropertyCellValue();
    if (cell_type == PropertyCellType::kConstantType) {
      switch (cell->GetConstantType()) {
        case PropertyCellConstantType::kSmi:
          access = access.WithRepresentation(Representation::Smi());
          break;
        case PropertyCellConstantType::kStableMap: {
          // The map may no longer be stable, deopt if it's ever different from
          // what is currently there, which will allow for restablization.
          Handle<Map> map(HeapObject::cast(cell->value())->map());
          Add<HCheckHeapObject>(value);
          value = Add<HCheckMaps>(value, map);
          access = access.WithRepresentation(Representation::HeapObject());
          break;
        }
      }
    }
    HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value);
    instr->ClearChangesFlag(kInobjectFields);
    instr->SetChangesFlag(kGlobalVars);
    if (instr->HasObservableSideEffects()) {
      Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
    }
  } else {
    HValue* global_object = Add<HLoadNamedField>(
        BuildGetNativeContext(), nullptr,
        HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
    HStoreNamedGeneric* instr =
        Add<HStoreNamedGeneric>(global_object, var->name(), value,
                                function_language_mode(), PREMONOMORPHIC);
    Handle<TypeFeedbackVector> vector =
        handle(current_feedback_vector(), isolate());
    instr->SetVectorAndSlot(vector, slot);
    USE(instr);
    DCHECK(instr->HasObservableSideEffects());
    Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
  }
}


void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
  Expression* target = expr->target();
  VariableProxy* proxy = target->AsVariableProxy();
  Property* prop = target->AsProperty();
  DCHECK(proxy == NULL || prop == NULL);

  // We have a second position recorded in the FullCodeGenerator to have
  // type feedback for the binary operation.
  BinaryOperation* operation = expr->binary_operation();

  if (proxy != NULL) {
    Variable* var = proxy->var();
    if (var->mode() == LET)  {
      return Bailout(kUnsupportedLetCompoundAssignment);
    }

    CHECK_ALIVE(VisitForValue(operation));

    switch (var->location()) {
      case VariableLocation::GLOBAL:
      case VariableLocation::UNALLOCATED:
        HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
                                       expr->AssignmentId());
        break;

      case VariableLocation::PARAMETER:
      case VariableLocation::LOCAL:
        if (var->mode() == CONST_LEGACY)  {
          return Bailout(kUnsupportedConstCompoundAssignment);
        }
        if (var->mode() == CONST) {
          return Bailout(kNonInitializerAssignmentToConst);
        }
        BindIfLive(var, Top());
        break;

      case VariableLocation::CONTEXT: {
        // Bail out if we try to mutate a parameter value in a function
        // using the arguments object.  We do not (yet) correctly handle the
        // arguments property of the function.
        if (current_info()->scope()->arguments() != NULL) {
          // Parameters will be allocated to context slots.  We have no
          // direct way to detect that the variable is a parameter so we do
          // a linear search of the parameter variables.
          int count = current_info()->scope()->num_parameters();
          for (int i = 0; i < count; ++i) {
            if (var == current_info()->scope()->parameter(i)) {
              Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
            }
          }
        }

        HStoreContextSlot::Mode mode;

        switch (var->mode()) {
          case LET:
            mode = HStoreContextSlot::kCheckDeoptimize;
            break;
          case CONST:
            return Bailout(kNonInitializerAssignmentToConst);
          case CONST_LEGACY:
            return ast_context()->ReturnValue(Pop());
          default:
            mode = HStoreContextSlot::kNoCheck;
        }

        HValue* context = BuildContextChainWalk(var);
        HStoreContextSlot* instr = Add<HStoreContextSlot>(
            context, var->index(), mode, Top());
        if (instr->HasObservableSideEffects()) {
          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
        }
        break;
      }

      case VariableLocation::LOOKUP:
        return Bailout(kCompoundAssignmentToLookupSlot);
    }
    return ast_context()->ReturnValue(Pop());

  } else if (prop != NULL) {
    CHECK_ALIVE(VisitForValue(prop->obj()));
    HValue* object = Top();
    HValue* key = NULL;
    if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
      CHECK_ALIVE(VisitForValue(prop->key()));
      key = Top();
    }

    CHECK_ALIVE(PushLoad(prop, object, key));

    CHECK_ALIVE(VisitForValue(expr->value()));
    HValue* right = Pop();
    HValue* left = Pop();

    Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));

    BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
               expr->AssignmentId(), expr->IsUninitialized());
  } else {
    return Bailout(kInvalidLhsInCompoundAssignment);
  }
}


void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());

  VariableProxy* proxy = expr->target()->AsVariableProxy();
  Property* prop = expr->target()->AsProperty();
  DCHECK(proxy == NULL || prop == NULL);

  if (expr->is_compound()) {
    HandleCompoundAssignment(expr);
    return;
  }

  if (prop != NULL) {
    HandlePropertyAssignment(expr);
  } else if (proxy != NULL) {
    Variable* var = proxy->var();

    if (var->mode() == CONST) {
      if (expr->op() != Token::INIT) {
        return Bailout(kNonInitializerAssignmentToConst);
      }
    } else if (var->mode() == CONST_LEGACY) {
      if (expr->op() != Token::INIT) {
        CHECK_ALIVE(VisitForValue(expr->value()));
        return ast_context()->ReturnValue(Pop());
      }

      if (var->IsStackAllocated()) {
        // We insert a use of the old value to detect unsupported uses of const
        // variables (e.g. initialization inside a loop).
        HValue* old_value = environment()->Lookup(var);
        Add<HUseConst>(old_value);
      }
    }

    if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);

    // Handle the assignment.
    switch (var->location()) {
      case VariableLocation::GLOBAL:
      case VariableLocation::UNALLOCATED:
        CHECK_ALIVE(VisitForValue(expr->value()));
        HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
                                       expr->AssignmentId());
        return ast_context()->ReturnValue(Pop());

      case VariableLocation::PARAMETER:
      case VariableLocation::LOCAL: {
        // Perform an initialization check for let declared variables
        // or parameters.
        if (var->mode() == LET && expr->op() == Token::ASSIGN) {
          HValue* env_value = environment()->Lookup(var);
          if (env_value == graph()->GetConstantHole()) {
            return Bailout(kAssignmentToLetVariableBeforeInitialization);
          }
        }
        // We do not allow the arguments object to occur in a context where it
        // may escape, but assignments to stack-allocated locals are
        // permitted.
        CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
        HValue* value = Pop();
        BindIfLive(var, value);
        return ast_context()->ReturnValue(value);
      }

      case VariableLocation::CONTEXT: {
        // Bail out if we try to mutate a parameter value in a function using
        // the arguments object.  We do not (yet) correctly handle the
        // arguments property of the function.
        if (current_info()->scope()->arguments() != NULL) {
          // Parameters will rewrite to context slots.  We have no direct way
          // to detect that the variable is a parameter.
          int count = current_info()->scope()->num_parameters();
          for (int i = 0; i < count; ++i) {
            if (var == current_info()->scope()->parameter(i)) {
              return Bailout(kAssignmentToParameterInArgumentsObject);
            }
          }
        }

        CHECK_ALIVE(VisitForValue(expr->value()));
        HStoreContextSlot::Mode mode;
        if (expr->op() == Token::ASSIGN) {
          switch (var->mode()) {
            case LET:
              mode = HStoreContextSlot::kCheckDeoptimize;
              break;
            case CONST:
              // This case is checked statically so no need to
              // perform checks here
              UNREACHABLE();
            case CONST_LEGACY:
              return ast_context()->ReturnValue(Pop());
            default:
              mode = HStoreContextSlot::kNoCheck;
          }
        } else {
          DCHECK_EQ(Token::INIT, expr->op());
          if (var->mode() == CONST_LEGACY) {
            mode = HStoreContextSlot::kCheckIgnoreAssignment;
          } else {
            mode = HStoreContextSlot::kNoCheck;
          }
        }

        HValue* context = BuildContextChainWalk(var);
        HStoreContextSlot* instr = Add<HStoreContextSlot>(
            context, var->index(), mode, Top());
        if (instr->HasObservableSideEffects()) {
          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
        }
        return ast_context()->ReturnValue(Pop());
      }

      case VariableLocation::LOOKUP:
        return Bailout(kAssignmentToLOOKUPVariable);
    }
  } else {
    return Bailout(kInvalidLeftHandSideInAssignment);
  }
}


void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
  // Generators are not optimized, so we should never get here.
  UNREACHABLE();
}


void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  if (!ast_context()->IsEffect()) {
    // The parser turns invalid left-hand sides in assignments into throw
    // statements, which may not be in effect contexts. We might still try
    // to optimize such functions; bail out now if we do.
    return Bailout(kInvalidLeftHandSideInAssignment);
  }
  CHECK_ALIVE(VisitForValue(expr->exception()));

  HValue* value = environment()->Pop();
  if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
  Add<HPushArguments>(value);
  Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1);
  Add<HSimulate>(expr->id());

  // If the throw definitely exits the function, we can finish with a dummy
  // control flow at this point.  This is not the case if the throw is inside
  // an inlined function which may be replaced.
  if (call_context() == NULL) {
    FinishExitCurrentBlock(New<HAbnormalExit>());
  }
}


HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
  if (string->IsConstant()) {
    HConstant* c_string = HConstant::cast(string);
    if (c_string->HasStringValue()) {
      return Add<HConstant>(c_string->StringValue()->map()->instance_type());
    }
  }
  return Add<HLoadNamedField>(
      Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
      HObjectAccess::ForMapInstanceType());
}


HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
  return AddInstruction(BuildLoadStringLength(string));
}


HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* string) {
  if (string->IsConstant()) {
    HConstant* c_string = HConstant::cast(string);
    if (c_string->HasStringValue()) {
      return New<HConstant>(c_string->StringValue()->length());
    }
  }
  return New<HLoadNamedField>(string, nullptr,
                              HObjectAccess::ForStringLength());
}


HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
    PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
    HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
  if (is_uninitialized) {
    Add<HDeoptimize>(
        Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess,
        Deoptimizer::SOFT);
  }
  if (access_type == LOAD) {
    Handle<TypeFeedbackVector> vector =
        handle(current_feedback_vector(), isolate());

    if (!expr->AsProperty()->key()->IsPropertyName()) {
      // It's possible that a keyed load of a constant string was converted
      // to a named load. Here, at the last minute, we need to make sure to
      // use a generic Keyed Load if we are using the type vector, because
      // it has to share information with full code.
      HConstant* key = Add<HConstant>(name);
      HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
          object, key, function_language_mode(), PREMONOMORPHIC);
      result->SetVectorAndSlot(vector, slot);
      return result;
    }

    HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
        object, name, function_language_mode(), PREMONOMORPHIC);
    result->SetVectorAndSlot(vector, slot);
    return result;
  } else {
    if (current_feedback_vector()->GetKind(slot) ==
        FeedbackVectorSlotKind::KEYED_STORE_IC) {
      // It's possible that a keyed store of a constant string was converted
      // to a named store. Here, at the last minute, we need to make sure to
      // use a generic Keyed Store if we are using the type vector, because
      // it has to share information with full code.
      HConstant* key = Add<HConstant>(name);
      HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
          object, key, value, function_language_mode(), PREMONOMORPHIC);
      Handle<TypeFeedbackVector> vector =
          handle(current_feedback_vector(), isolate());
      result->SetVectorAndSlot(vector, slot);
      return result;
    }

    HStoreNamedGeneric* result = New<HStoreNamedGeneric>(
        object, name, value, function_language_mode(), PREMONOMORPHIC);
    Handle<TypeFeedbackVector> vector =
        handle(current_feedback_vector(), isolate());
    result->SetVectorAndSlot(vector, slot);
    return result;
  }
}


HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
    PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
    HValue* object, HValue* key, HValue* value) {
  if (access_type == LOAD) {
    InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
    HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
        object, key, function_language_mode(), initial_state);
    // HLoadKeyedGeneric with vector ics benefits from being encoded as
    // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
    if (initial_state != MEGAMORPHIC) {
      // We need to pass vector information.
      Handle<TypeFeedbackVector> vector =
          handle(current_feedback_vector(), isolate());
      result->SetVectorAndSlot(vector, slot);
    }
    return result;
  } else {
    HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
        object, key, value, function_language_mode(), PREMONOMORPHIC);
    Handle<TypeFeedbackVector> vector =
        handle(current_feedback_vector(), isolate());
    result->SetVectorAndSlot(vector, slot);
    return result;
  }
}


LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
  // Loads from a "stock" fast holey double arrays can elide the hole check.
  // Loads from a "stock" fast holey array can convert the hole to undefined
  // with impunity.
  LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
  bool holey_double_elements =
      *map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS);
  bool holey_elements =
      *map == isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS);
  if ((holey_double_elements || holey_elements) &&
      isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
    load_mode =
        holey_double_elements ? ALLOW_RETURN_HOLE : CONVERT_HOLE_TO_UNDEFINED;

    Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
    Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
    BuildCheckPrototypeMaps(prototype, object_prototype);
    graph()->MarkDependsOnEmptyArrayProtoElements();
  }
  return load_mode;
}


HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
    HValue* object,
    HValue* key,
    HValue* val,
    HValue* dependency,
    Handle<Map> map,
    PropertyAccessType access_type,
    KeyedAccessStoreMode store_mode) {
  HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);

  if (access_type == STORE && map->prototype()->IsJSObject()) {
    // monomorphic stores need a prototype chain check because shape
    // changes could allow callbacks on elements in the chain that
    // aren't compatible with monomorphic keyed stores.
    PrototypeIterator iter(map);
    JSObject* holder = NULL;
    while (!iter.IsAtEnd()) {
      // JSProxies can't occur here because we wouldn't have installed a
      // non-generic IC if there were any.
      holder = *PrototypeIterator::GetCurrent<JSObject>(iter);
      iter.Advance();
    }
    DCHECK(holder && holder->IsJSObject());

    BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
                            Handle<JSObject>(holder));
  }

  LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
  return BuildUncheckedMonomorphicElementAccess(
      checked_object, key, val,
      map->instance_type() == JS_ARRAY_TYPE,
      map->elements_kind(), access_type,
      load_mode, store_mode);
}


static bool CanInlineElementAccess(Handle<Map> map) {
  return map->IsJSObjectMap() &&
         (map->has_fast_elements() || map->has_fixed_typed_array_elements()) &&
         !map->has_indexed_interceptor() && !map->is_access_check_needed();
}


HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
    HValue* object,
    HValue* key,
    HValue* val,
    SmallMapList* maps) {
  // For polymorphic loads of similar elements kinds (i.e. all tagged or all
  // double), always use the "worst case" code without a transition.  This is
  // much faster than transitioning the elements to the worst case, trading a
  // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
  bool has_double_maps = false;
  bool has_smi_or_object_maps = false;
  bool has_js_array_access = false;
  bool has_non_js_array_access = false;
  bool has_seen_holey_elements = false;
  Handle<Map> most_general_consolidated_map;
  for (int i = 0; i < maps->length(); ++i) {
    Handle<Map> map = maps->at(i);
    if (!CanInlineElementAccess(map)) return NULL;
    // Don't allow mixing of JSArrays with JSObjects.
    if (map->instance_type() == JS_ARRAY_TYPE) {
      if (has_non_js_array_access) return NULL;
      has_js_array_access = true;
    } else if (has_js_array_access) {
      return NULL;
    } else {
      has_non_js_array_access = true;
    }
    // Don't allow mixed, incompatible elements kinds.
    if (map->has_fast_double_elements()) {
      if (has_smi_or_object_maps) return NULL;
      has_double_maps = true;
    } else if (map->has_fast_smi_or_object_elements()) {
      if (has_double_maps) return NULL;
      has_smi_or_object_maps = true;
    } else {
      return NULL;
    }
    // Remember if we've ever seen holey elements.
    if (IsHoleyElementsKind(map->elements_kind())) {
      has_seen_holey_elements = true;
    }
    // Remember the most general elements kind, the code for its load will
    // properly handle all of the more specific cases.
    if ((i == 0) || IsMoreGeneralElementsKindTransition(
            most_general_consolidated_map->elements_kind(),
            map->elements_kind())) {
      most_general_consolidated_map = map;
    }
  }
  if (!has_double_maps && !has_smi_or_object_maps) return NULL;

  HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
  // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
  // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
  ElementsKind consolidated_elements_kind = has_seen_holey_elements
      ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
      : most_general_consolidated_map->elements_kind();
  LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
  if (has_seen_holey_elements) {
    // Make sure that all of the maps we are handling have the initial array
    // prototype.
    bool saw_non_array_prototype = false;
    for (int i = 0; i < maps->length(); ++i) {
      Handle<Map> map = maps->at(i);
      if (map->prototype() != *isolate()->initial_array_prototype()) {
        // We can't guarantee that loading the hole is safe. The prototype may
        // have an element at this position.
        saw_non_array_prototype = true;
        break;
      }
    }

    if (!saw_non_array_prototype) {
      Handle<Map> holey_map = handle(
          isolate()->get_initial_js_array_map(consolidated_elements_kind));
      load_mode = BuildKeyedHoleMode(holey_map);
      if (load_mode != NEVER_RETURN_HOLE) {
        for (int i = 0; i < maps->length(); ++i) {
          Handle<Map> map = maps->at(i);
          // The prototype check was already done for the holey map in
          // BuildKeyedHoleMode.
          if (!map.is_identical_to(holey_map)) {
            Handle<JSObject> prototype(JSObject::cast(map->prototype()),
                                       isolate());
            Handle<JSObject> object_prototype =
                isolate()->initial_object_prototype();
            BuildCheckPrototypeMaps(prototype, object_prototype);
          }
        }
      }
    }
  }
  HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
      checked_object, key, val,
      most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
      consolidated_elements_kind, LOAD, load_mode, STANDARD_STORE);
  return instr;
}


HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
    Expression* expr, FeedbackVectorSlot slot, HValue* object, HValue* key,
    HValue* val, SmallMapList* maps, PropertyAccessType access_type,
    KeyedAccessStoreMode store_mode, bool* has_side_effects) {
  *has_side_effects = false;
  BuildCheckHeapObject(object);

  if (access_type == LOAD) {
    HInstruction* consolidated_load =
        TryBuildConsolidatedElementLoad(object, key, val, maps);
    if (consolidated_load != NULL) {
      *has_side_effects |= consolidated_load->HasObservableSideEffects();
      return consolidated_load;
    }
  }

  // Elements_kind transition support.
  MapHandleList transition_target(maps->length());
  // Collect possible transition targets.
  MapHandleList possible_transitioned_maps(maps->length());
  for (int i = 0; i < maps->length(); ++i) {
    Handle<Map> map = maps->at(i);
    // Loads from strings or loads with a mix of string and non-string maps
    // shouldn't be handled polymorphically.
    DCHECK(access_type != LOAD || !map->IsStringMap());
    ElementsKind elements_kind = map->elements_kind();
    if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
        elements_kind != GetInitialFastElementsKind()) {
      possible_transitioned_maps.Add(map);
    }
    if (IsSloppyArgumentsElements(elements_kind)) {
      HInstruction* result =
          BuildKeyedGeneric(access_type, expr, slot, object, key, val);
      *has_side_effects = result->HasObservableSideEffects();
      return AddInstruction(result);
    }
  }
  // Get transition target for each map (NULL == no transition).
  for (int i = 0; i < maps->length(); ++i) {
    Handle<Map> map = maps->at(i);
    Handle<Map> transitioned_map =
        Map::FindTransitionedMap(map, &possible_transitioned_maps);
    transition_target.Add(transitioned_map);
  }

  MapHandleList untransitionable_maps(maps->length());
  HTransitionElementsKind* transition = NULL;
  for (int i = 0; i < maps->length(); ++i) {
    Handle<Map> map = maps->at(i);
    DCHECK(map->IsMap());
    if (!transition_target.at(i).is_null()) {
      DCHECK(Map::IsValidElementsTransition(
          map->elements_kind(),
          transition_target.at(i)->elements_kind()));
      transition = Add<HTransitionElementsKind>(object, map,
                                                transition_target.at(i));
    } else {
      untransitionable_maps.Add(map);
    }
  }

  // If only one map is left after transitioning, handle this case
  // monomorphically.
  DCHECK(untransitionable_maps.length() >= 1);
  if (untransitionable_maps.length() == 1) {
    Handle<Map> untransitionable_map = untransitionable_maps[0];
    HInstruction* instr = NULL;
    if (!CanInlineElementAccess(untransitionable_map)) {
      instr = AddInstruction(
          BuildKeyedGeneric(access_type, expr, slot, object, key, val));
    } else {
      instr = BuildMonomorphicElementAccess(
          object, key, val, transition, untransitionable_map, access_type,
          store_mode);
    }
    *has_side_effects |= instr->HasObservableSideEffects();
    return access_type == STORE ? val : instr;
  }

  HBasicBlock* join = graph()->CreateBasicBlock();

  for (int i = 0; i < untransitionable_maps.length(); ++i) {
    Handle<Map> map = untransitionable_maps[i];
    ElementsKind elements_kind = map->elements_kind();
    HBasicBlock* this_map = graph()->CreateBasicBlock();
    HBasicBlock* other_map = graph()->CreateBasicBlock();
    HCompareMap* mapcompare =
        New<HCompareMap>(object, map, this_map, other_map);
    FinishCurrentBlock(mapcompare);

    set_current_block(this_map);
    HInstruction* access = NULL;
    if (!CanInlineElementAccess(map)) {
      access = AddInstruction(
          BuildKeyedGeneric(access_type, expr, slot, object, key, val));
    } else {
      DCHECK(IsFastElementsKind(elements_kind) ||
             IsFixedTypedArrayElementsKind(elements_kind));
      LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
      // Happily, mapcompare is a checked object.
      access = BuildUncheckedMonomorphicElementAccess(
          mapcompare, key, val,
          map->instance_type() == JS_ARRAY_TYPE,
          elements_kind, access_type,
          load_mode,
          store_mode);
    }
    *has_side_effects |= access->HasObservableSideEffects();
    // The caller will use has_side_effects and add a correct Simulate.
    access->SetFlag(HValue::kHasNoObservableSideEffects);
    if (access_type == LOAD) {
      Push(access);
    }
    NoObservableSideEffectsScope scope(this);
    GotoNoSimulate(join);
    set_current_block(other_map);
  }

  // Ensure that we visited at least one map above that goes to join. This is
  // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
  // rather than joining the join block. If this becomes an issue, insert a
  // generic access in the case length() == 0.
  DCHECK(join->predecessors()->length() > 0);
  // Deopt if none of the cases matched.
  NoObservableSideEffectsScope scope(this);
  FinishExitWithHardDeoptimization(
      Deoptimizer::kUnknownMapInPolymorphicElementAccess);
  set_current_block(join);
  return access_type == STORE ? val : Pop();
}


HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
    HValue* obj, HValue* key, HValue* val, Expression* expr,
    FeedbackVectorSlot slot, BailoutId ast_id, BailoutId return_id,
    PropertyAccessType access_type, bool* has_side_effects) {
  // A keyed name access with type feedback may contain the name.
  Handle<TypeFeedbackVector> vector =
      handle(current_feedback_vector(), isolate());
  HValue* expected_key = key;
  if (!key->ActualValue()->IsConstant()) {
    Name* name = nullptr;
    if (access_type == LOAD) {
      KeyedLoadICNexus nexus(vector, slot);
      name = nexus.FindFirstName();
    } else {
      KeyedStoreICNexus nexus(vector, slot);
      name = nexus.FindFirstName();
    }
    if (name != nullptr) {
      Handle<Name> handle_name(name);
      expected_key = Add<HConstant>(handle_name);
      // We need a check against the key.
      bool in_new_space = isolate()->heap()->InNewSpace(*handle_name);
      Unique<Name> unique_name = Unique<Name>::CreateUninitialized(handle_name);
      Add<HCheckValue>(key, unique_name, in_new_space);
    }
  }
  if (expected_key->ActualValue()->IsConstant()) {
    Handle<Object> constant =
        HConstant::cast(expected_key->ActualValue())->handle(isolate());
    uint32_t array_index;
    if ((constant->IsString() &&
         !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) ||
        constant->IsSymbol()) {
      if (!constant->IsUniqueName()) {
        constant = isolate()->factory()->InternalizeString(
            Handle<String>::cast(constant));
      }
      HValue* access =
          BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
                           Handle<Name>::cast(constant), val, false);
      if (access == NULL || access->IsPhi() ||
          HInstruction::cast(access)->IsLinked()) {
        *has_side_effects = false;
      } else {
        HInstruction* instr = HInstruction::cast(access);
        AddInstruction(instr);
        *has_side_effects = instr->HasObservableSideEffects();
      }
      return access;
    }
  }

  DCHECK(!expr->IsPropertyName());
  HInstruction* instr = NULL;

  SmallMapList* maps;
  bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());

  bool force_generic = false;
  if (expr->GetKeyType() == PROPERTY) {
    // Non-Generic accesses assume that elements are being accessed, and will
    // deopt for non-index keys, which the IC knows will occur.
    // TODO(jkummerow): Consider adding proper support for property accesses.
    force_generic = true;
    monomorphic = false;
  } else if (access_type == STORE &&
             (monomorphic || (maps != NULL && !maps->is_empty()))) {
    // Stores can't be mono/polymorphic if their prototype chain has dictionary
    // elements. However a receiver map that has dictionary elements itself
    // should be left to normal mono/poly behavior (the other maps may benefit
    // from highly optimized stores).
    for (int i = 0; i < maps->length(); i++) {
      Handle<Map> current_map = maps->at(i);
      if (current_map->DictionaryElementsInPrototypeChainOnly()) {
        force_generic = true;
        monomorphic = false;
        break;
      }
    }
  } else if (access_type == LOAD && !monomorphic &&
             (maps != NULL && !maps->is_empty())) {
    // Polymorphic loads have to go generic if any of the maps are strings.
    // If some, but not all of the maps are strings, we should go generic
    // because polymorphic access wants to key on ElementsKind and isn't
    // compatible with strings.
    for (int i = 0; i < maps->length(); i++) {
      Handle<Map> current_map = maps->at(i);
      if (current_map->IsStringMap()) {
        force_generic = true;
        break;
      }
    }
  }

  if (monomorphic) {
    Handle<Map> map = maps->first();
    if (!CanInlineElementAccess(map)) {
      instr = AddInstruction(
          BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
    } else {
      BuildCheckHeapObject(obj);
      instr = BuildMonomorphicElementAccess(
          obj, key, val, NULL, map, access_type, expr->GetStoreMode());
    }
  } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
    return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
                                          access_type, expr->GetStoreMode(),
                                          has_side_effects);
  } else {
    if (access_type == STORE) {
      if (expr->IsAssignment() &&
          expr->AsAssignment()->HasNoTypeInformation()) {
        Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore,
                         Deoptimizer::SOFT);
      }
    } else {
      if (expr->AsProperty()->HasNoTypeInformation()) {
        Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad,
                         Deoptimizer::SOFT);
      }
    }
    instr = AddInstruction(
        BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
  }
  *has_side_effects = instr->HasObservableSideEffects();
  return instr;
}


void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
  // Outermost function already has arguments on the stack.
  if (function_state()->outer() == NULL) return;

  if (function_state()->arguments_pushed()) return;

  // Push arguments when entering inlined function.
  HEnterInlined* entry = function_state()->entry();
  entry->set_arguments_pushed();

  HArgumentsObject* arguments = entry->arguments_object();
  const ZoneList<HValue*>* arguments_values = arguments->arguments_values();

  HInstruction* insert_after = entry;
  for (int i = 0; i < arguments_values->length(); i++) {
    HValue* argument = arguments_values->at(i);
    HInstruction* push_argument = New<HPushArguments>(argument);
    push_argument->InsertAfter(insert_after);
    insert_after = push_argument;
  }

  HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
  arguments_elements->ClearFlag(HValue::kUseGVN);
  arguments_elements->InsertAfter(insert_after);
  function_state()->set_arguments_elements(arguments_elements);
}


bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
  VariableProxy* proxy = expr->obj()->AsVariableProxy();
  if (proxy == NULL) return false;
  if (!proxy->var()->IsStackAllocated()) return false;
  if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
    return false;
  }

  HInstruction* result = NULL;
  if (expr->key()->IsPropertyName()) {
    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
    if (!String::Equals(name, isolate()->factory()->length_string())) {
      return false;
    }

    if (function_state()->outer() == NULL) {
      HInstruction* elements = Add<HArgumentsElements>(false);
      result = New<HArgumentsLength>(elements);
    } else {
      // Number of arguments without receiver.
      int argument_count = environment()->
          arguments_environment()->parameter_count() - 1;
      result = New<HConstant>(argument_count);
    }
  } else {
    Push(graph()->GetArgumentsObject());
    CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
    HValue* key = Pop();
    Drop(1);  // Arguments object.
    if (function_state()->outer() == NULL) {
      HInstruction* elements = Add<HArgumentsElements>(false);
      HInstruction* length = Add<HArgumentsLength>(elements);
      HInstruction* checked_key = Add<HBoundsCheck>(key, length);
      result = New<HAccessArgumentsAt>(elements, length, checked_key);
    } else {
      EnsureArgumentsArePushedForAccess();

      // Number of arguments without receiver.
      HInstruction* elements = function_state()->arguments_elements();
      int argument_count = environment()->
          arguments_environment()->parameter_count() - 1;
      HInstruction* length = Add<HConstant>(argument_count);
      HInstruction* checked_key = Add<HBoundsCheck>(key, length);
      result = New<HAccessArgumentsAt>(elements, length, checked_key);
    }
  }
  ast_context()->ReturnInstruction(result, expr->id());
  return true;
}


HValue* HOptimizedGraphBuilder::BuildNamedAccess(
    PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
    Expression* expr, FeedbackVectorSlot slot, HValue* object,
    Handle<Name> name, HValue* value, bool is_uninitialized) {
  SmallMapList* maps;
  ComputeReceiverTypes(expr, object, &maps, zone());
  DCHECK(maps != NULL);

  if (maps->length() > 0) {
    PropertyAccessInfo info(this, access, maps->first(), name);
    if (!info.CanAccessAsMonomorphic(maps)) {
      HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
                                        object, value, maps, name);
      return NULL;
    }

    HValue* checked_object;
    // Type::Number() is only supported by polymorphic load/call handling.
    DCHECK(!info.IsNumberType());
    BuildCheckHeapObject(object);
    if (AreStringTypes(maps)) {
      checked_object =
          Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
    } else {
      checked_object = Add<HCheckMaps>(object, maps);
    }
    return BuildMonomorphicAccess(
        &info, object, checked_object, value, ast_id, return_id);
  }

  return BuildNamedGeneric(access, expr, slot, object, name, value,
                           is_uninitialized);
}


void HOptimizedGraphBuilder::PushLoad(Property* expr,
                                      HValue* object,
                                      HValue* key) {
  ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
  Push(object);
  if (key != NULL) Push(key);
  BuildLoad(expr, expr->LoadId());
}


void HOptimizedGraphBuilder::BuildLoad(Property* expr,
                                       BailoutId ast_id) {
  HInstruction* instr = NULL;
  if (expr->IsStringAccess() && expr->GetKeyType() == ELEMENT) {
    HValue* index = Pop();
    HValue* string = Pop();
    HInstruction* char_code = BuildStringCharCodeAt(string, index);
    AddInstruction(char_code);
    instr = NewUncasted<HStringCharFromCode>(char_code);

  } else if (expr->key()->IsPropertyName()) {
    Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
    HValue* object = Pop();

    HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
                                     expr->PropertyFeedbackSlot(), object, name,
                                     NULL, expr->IsUninitialized());
    if (value == NULL) return;
    if (value->IsPhi()) return ast_context()->ReturnValue(value);
    instr = HInstruction::cast(value);
    if (instr->IsLinked()) return ast_context()->ReturnValue(instr);

  } else {
    HValue* key = Pop();
    HValue* obj = Pop();

    bool has_side_effects = false;
    HValue* load = HandleKeyedElementAccess(
        obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
        expr->LoadId(), LOAD, &has_side_effects);
    if (has_side_effects) {
      if (ast_context()->IsEffect()) {
        Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
      } else {
        Push(load);
        Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
        Drop(1);
      }
    }
    if (load == NULL) return;
    return ast_context()->ReturnValue(load);
  }
  return ast_context()->ReturnInstruction(instr, ast_id);
}


void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());

  if (TryArgumentsAccess(expr)) return;

  CHECK_ALIVE(VisitForValue(expr->obj()));
  if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
    CHECK_ALIVE(VisitForValue(expr->key()));
  }

  BuildLoad(expr, expr->id());
}


HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
  HCheckMaps* check = Add<HCheckMaps>(
      Add<HConstant>(constant), handle(constant->map()));
  check->ClearDependsOnFlag(kElementsKind);
  return check;
}


HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
                                                     Handle<JSObject> holder) {
  PrototypeIterator iter(isolate(), prototype,
                         PrototypeIterator::START_AT_RECEIVER);
  while (holder.is_null() ||
         !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
    BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
    iter.Advance();
    if (iter.IsAtEnd()) {
      return NULL;
    }
  }
  return BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
}


void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
                                                   Handle<Map> receiver_map) {
  if (!holder.is_null()) {
    Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
    BuildCheckPrototypeMaps(prototype, holder);
  }
}


HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(HValue* fun,
                                                           int argument_count) {
  return New<HCallJSFunction>(fun, argument_count);
}


HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
    HValue* fun, HValue* context,
    int argument_count, HValue* expected_param_count) {
  HValue* new_target = graph()->GetConstantUndefined();
  HValue* arity = Add<HConstant>(argument_count - 1);

  HValue* op_vals[] = {context, fun, new_target, arity, expected_param_count};

  Callable callable = CodeFactory::ArgumentAdaptor(isolate());
  HConstant* stub = Add<HConstant>(callable.code());

  return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
                                  Vector<HValue*>(op_vals, arraysize(op_vals)));
}


HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
    Handle<JSFunction> jsfun, int argument_count) {
  HValue* target = Add<HConstant>(jsfun);
  // For constant functions, we try to avoid calling the
  // argument adaptor and instead call the function directly
  int formal_parameter_count =
      jsfun->shared()->internal_formal_parameter_count();
  bool dont_adapt_arguments =
      (formal_parameter_count ==
       SharedFunctionInfo::kDontAdaptArgumentsSentinel);
  int arity = argument_count - 1;
  bool can_invoke_directly =
      dont_adapt_arguments || formal_parameter_count == arity;
  if (can_invoke_directly) {
    if (jsfun.is_identical_to(current_info()->closure())) {
      graph()->MarkRecursive();
    }
    return NewPlainFunctionCall(target, argument_count);
  } else {
    HValue* param_count_value = Add<HConstant>(formal_parameter_count);
    HValue* context = Add<HLoadNamedField>(
        target, nullptr, HObjectAccess::ForFunctionContextPointer());
    return NewArgumentAdaptorCall(target, context,
        argument_count, param_count_value);
  }
  UNREACHABLE();
  return NULL;
}


class FunctionSorter {
 public:
  explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
      : index_(index), ticks_(ticks), size_(size) {}

  int index() const { return index_; }
  int ticks() const { return ticks_; }
  int size() const { return size_; }

 private:
  int index_;
  int ticks_;
  int size_;
};


inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
  int diff = lhs.ticks() - rhs.ticks();
  if (diff != 0) return diff > 0;
  return lhs.size() < rhs.size();
}


void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
                                                        HValue* receiver,
                                                        SmallMapList* maps,
                                                        Handle<String> name) {
  int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
  FunctionSorter order[kMaxCallPolymorphism];

  bool handle_smi = false;
  bool handled_string = false;
  int ordered_functions = 0;

  int i;
  for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
       ++i) {
    PropertyAccessInfo info(this, LOAD, maps->at(i), name);
    if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
        info.constant()->IsJSFunction()) {
      if (info.IsStringType()) {
        if (handled_string) continue;
        handled_string = true;
      }
      Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
      if (info.IsNumberType()) {
        handle_smi = true;
      }
      expr->set_target(target);
      order[ordered_functions++] = FunctionSorter(
          i, target->shared()->profiler_ticks(), InliningAstSize(target));
    }
  }

  std::sort(order, order + ordered_functions);

  if (i < maps->length()) {
    maps->Clear();
    ordered_functions = -1;
  }

  HBasicBlock* number_block = NULL;
  HBasicBlock* join = NULL;
  handled_string = false;
  int count = 0;

  for (int fn = 0; fn < ordered_functions; ++fn) {
    int i = order[fn].index();
    PropertyAccessInfo info(this, LOAD, maps->at(i), name);
    if (info.IsStringType()) {
      if (handled_string) continue;
      handled_string = true;
    }
    // Reloads the target.
    info.CanAccessMonomorphic();
    Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());

    expr->set_target(target);
    if (count == 0) {
      // Only needed once.
      join = graph()->CreateBasicBlock();
      if (handle_smi) {
        HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
        HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
        number_block = graph()->CreateBasicBlock();
        FinishCurrentBlock(New<HIsSmiAndBranch>(
                receiver, empty_smi_block, not_smi_block));
        GotoNoSimulate(empty_smi_block, number_block);
        set_current_block(not_smi_block);
      } else {
        BuildCheckHeapObject(receiver);
      }
    }
    ++count;
    HBasicBlock* if_true = graph()->CreateBasicBlock();
    HBasicBlock* if_false = graph()->CreateBasicBlock();
    HUnaryControlInstruction* compare;

    Handle<Map> map = info.map();
    if (info.IsNumberType()) {
      Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
      compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
    } else if (info.IsStringType()) {
      compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
    } else {
      compare = New<HCompareMap>(receiver, map, if_true, if_false);
    }
    FinishCurrentBlock(compare);

    if (info.IsNumberType()) {
      GotoNoSimulate(if_true, number_block);
      if_true = number_block;
    }

    set_current_block(if_true);

    AddCheckPrototypeMaps(info.holder(), map);

    HValue* function = Add<HConstant>(expr->target());
    environment()->SetExpressionStackAt(0, function);
    Push(receiver);
    CHECK_ALIVE(VisitExpressions(expr->arguments()));
    bool needs_wrapping = info.NeedsWrappingFor(target);
    bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
    if (FLAG_trace_inlining && try_inline) {
      Handle<JSFunction> caller = current_info()->closure();
      base::SmartArrayPointer<char> caller_name =
          caller->shared()->DebugName()->ToCString();
      PrintF("Trying to inline the polymorphic call to %s from %s\n",
             name->ToCString().get(),
             caller_name.get());
    }
    if (try_inline && TryInlineCall(expr)) {
      // Trying to inline will signal that we should bailout from the
      // entire compilation by setting stack overflow on the visitor.
      if (HasStackOverflow()) return;
    } else {
      // Since HWrapReceiver currently cannot actually wrap numbers and strings,
      // use the regular CallFunctionStub for method calls to wrap the receiver.
      // TODO(verwaest): Support creation of value wrappers directly in
      // HWrapReceiver.
      HInstruction* call =
          needs_wrapping ? NewUncasted<HCallFunction>(
                               function, argument_count,
                               ConvertReceiverMode::kNotNullOrUndefined)
                         : BuildCallConstantFunction(target, argument_count);
      PushArgumentsFromEnvironment(argument_count);
      AddInstruction(call);
      Drop(1);  // Drop the function.
      if (!ast_context()->IsEffect()) Push(call);
    }

    if (current_block() != NULL) Goto(join);
    set_current_block(if_false);
  }

  // Finish up.  Unconditionally deoptimize if we've handled all the maps we
  // know about and do not want to handle ones we've never seen.  Otherwise
  // use a generic IC.
  if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
    FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
  } else {
    Property* prop = expr->expression()->AsProperty();
    HInstruction* function =
        BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
                          name, NULL, prop->IsUninitialized());
    AddInstruction(function);
    Push(function);
    AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);

    environment()->SetExpressionStackAt(1, function);
    environment()->SetExpressionStackAt(0, receiver);
    CHECK_ALIVE(VisitExpressions(expr->arguments()));

    HInstruction* call = New<HCallFunction>(
        function, argument_count, ConvertReceiverMode::kNotNullOrUndefined);

    PushArgumentsFromEnvironment(argument_count);

    Drop(1);  // Function.

    if (join != NULL) {
      AddInstruction(call);
      if (!ast_context()->IsEffect()) Push(call);
      Goto(join);
    } else {
      return ast_context()->ReturnInstruction(call, expr->id());
    }
  }

  // We assume that control flow is always live after an expression.  So
  // even without predecessors to the join block, we set it as the exit
  // block and continue by adding instructions there.
  DCHECK(join != NULL);
  if (join->HasPredecessor()) {
    set_current_block(join);
    join->SetJoinId(expr->id());
    if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
  } else {
    set_current_block(NULL);
  }
}


void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
                                         Handle<JSFunction> caller,
                                         const char* reason) {
  if (FLAG_trace_inlining) {
    base::SmartArrayPointer<char> target_name =
        target->shared()->DebugName()->ToCString();
    base::SmartArrayPointer<char> caller_name =
        caller->shared()->DebugName()->ToCString();
    if (reason == NULL) {
      PrintF("Inlined %s called from %s.\n", target_name.get(),
             caller_name.get());
    } else {
      PrintF("Did not inline %s called from %s (%s).\n",
             target_name.get(), caller_name.get(), reason);
    }
  }
}


static const int kNotInlinable = 1000000000;


int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
  if (!FLAG_use_inlining) return kNotInlinable;

  // Precondition: call is monomorphic and we have found a target with the
  // appropriate arity.
  Handle<JSFunction> caller = current_info()->closure();
  Handle<SharedFunctionInfo> target_shared(target->shared());

  // Always inline functions that force inlining.
  if (target_shared->force_inline()) {
    return 0;
  }
  if (target->shared()->IsBuiltin()) {
    return kNotInlinable;
  }

  if (target_shared->IsApiFunction()) {
    TraceInline(target, caller, "target is api function");
    return kNotInlinable;
  }

  // Do a quick check on source code length to avoid parsing large
  // inlining candidates.
  if (target_shared->SourceSize() >
      Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
    TraceInline(target, caller, "target text too big");
    return kNotInlinable;
  }

  // Target must be inlineable.
  BailoutReason noopt_reason = target_shared->disable_optimization_reason();
  if (!target_shared->IsInlineable() && noopt_reason != kHydrogenFilter) {
    TraceInline(target, caller, "target not inlineable");
    return kNotInlinable;
  }
  if (noopt_reason != kNoReason && noopt_reason != kHydrogenFilter) {
    TraceInline(target, caller, "target contains unsupported syntax [early]");
    return kNotInlinable;
  }

  int nodes_added = target_shared->ast_node_count();
  return nodes_added;
}


bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
                                       int arguments_count,
                                       HValue* implicit_return_value,
                                       BailoutId ast_id, BailoutId return_id,
                                       InliningKind inlining_kind) {
  if (target->context()->native_context() !=
      top_info()->closure()->context()->native_context()) {
    return false;
  }
  int nodes_added = InliningAstSize(target);
  if (nodes_added == kNotInlinable) return false;

  Handle<JSFunction> caller = current_info()->closure();

  if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
    TraceInline(target, caller, "target AST is too large [early]");
    return false;
  }

  // Don't inline deeper than the maximum number of inlining levels.
  HEnvironment* env = environment();
  int current_level = 1;
  while (env->outer() != NULL) {
    if (current_level == FLAG_max_inlining_levels) {
      TraceInline(target, caller, "inline depth limit reached");
      return false;
    }
    if (env->outer()->frame_type() == JS_FUNCTION) {
      current_level++;
    }
    env = env->outer();
  }

  // Don't inline recursive functions.
  for (FunctionState* state = function_state();
       state != NULL;
       state = state->outer()) {
    if (*state->compilation_info()->closure() == *target) {
      TraceInline(target, caller, "target is recursive");
      return false;
    }
  }

  // We don't want to add more than a certain number of nodes from inlining.
  // Always inline small methods (<= 10 nodes).
  if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
                           kUnlimitedMaxInlinedNodesCumulative)) {
    TraceInline(target, caller, "cumulative AST node limit reached");
    return false;
  }

  // Parse and allocate variables.
  // Use the same AstValueFactory for creating strings in the sub-compilation
  // step, but don't transfer ownership to target_info.
  ParseInfo parse_info(zone(), target);
  parse_info.set_ast_value_factory(
      top_info()->parse_info()->ast_value_factory());
  parse_info.set_ast_value_factory_owned(false);

  CompilationInfo target_info(&parse_info);
  Handle<SharedFunctionInfo> target_shared(target->shared());

  if (inlining_kind != CONSTRUCT_CALL_RETURN &&
      IsClassConstructor(target_shared->kind())) {
    TraceInline(target, caller, "target is classConstructor");
    return false;
  }

  if (target_shared->HasDebugInfo()) {
    TraceInline(target, caller, "target is being debugged");
    return false;
  }
  if (!Compiler::ParseAndAnalyze(target_info.parse_info())) {
    if (target_info.isolate()->has_pending_exception()) {
      // Parse or scope error, never optimize this function.
      SetStackOverflow();
      target_shared->DisableOptimization(kParseScopeError);
    }
    TraceInline(target, caller, "parse failure");
    return false;
  }

  if (target_info.scope()->num_heap_slots() > 0) {
    TraceInline(target, caller, "target has context-allocated variables");
    return false;
  }

  int rest_index;
  Variable* rest = target_info.scope()->rest_parameter(&rest_index);
  if (rest) {
    TraceInline(target, caller, "target uses rest parameters");
    return false;
  }

  FunctionLiteral* function = target_info.literal();

  // The following conditions must be checked again after re-parsing, because
  // earlier the information might not have been complete due to lazy parsing.
  nodes_added = function->ast_node_count();
  if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
    TraceInline(target, caller, "target AST is too large [late]");
    return false;
  }
  if (function->dont_optimize()) {
    TraceInline(target, caller, "target contains unsupported syntax [late]");
    return false;
  }

  // If the function uses the arguments object check that inlining of functions
  // with arguments object is enabled and the arguments-variable is
  // stack allocated.
  if (function->scope()->arguments() != NULL) {
    if (!FLAG_inline_arguments) {
      TraceInline(target, caller, "target uses arguments object");
      return false;
    }
  }

  // Unsupported variable references present.
  if (function->scope()->this_function_var() != nullptr ||
      function->scope()->new_target_var() != nullptr) {
    TraceInline(target, caller, "target uses new target or this function");
    return false;
  }

  // All declarations must be inlineable.
  ZoneList<Declaration*>* decls = target_info.scope()->declarations();
  int decl_count = decls->length();
  for (int i = 0; i < decl_count; ++i) {
    if (!decls->at(i)->IsInlineable()) {
      TraceInline(target, caller, "target has non-trivial declaration");
      return false;
    }
  }

  // In strong mode it is an error to call a function with too few arguments.
  // In that case do not inline because then the arity check would be skipped.
  if (is_strong(function->language_mode()) &&
      arguments_count < function->parameter_count()) {
    TraceInline(target, caller,
                "too few arguments passed to a strong function");
    return false;
  }

  // Generate the deoptimization data for the unoptimized version of
  // the target function if we don't already have it.
  if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
    TraceInline(target, caller, "could not generate deoptimization info");
    return false;
  }
  // Remember that we inlined this function. This needs to be called right
  // after the EnsureDeoptimizationSupport call so that the code flusher
  // does not remove the code with the deoptimization support.
  top_info()->AddInlinedFunction(target_info.shared_info());

  // ----------------------------------------------------------------
  // After this point, we've made a decision to inline this function (so
  // TryInline should always return true).

  // Type-check the inlined function.
  DCHECK(target_shared->has_deoptimization_support());
  AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
           target_info.scope(), target_info.osr_ast_id(), target_info.literal())
      .Run();

  int inlining_id = 0;
  if (top_info()->is_tracking_positions()) {
    inlining_id = top_info()->TraceInlinedFunction(
        target_shared, source_position(), function_state()->inlining_id());
  }

  // Save the pending call context. Set up new one for the inlined function.
  // The function state is new-allocated because we need to delete it
  // in two different places.
  FunctionState* target_state =
      new FunctionState(this, &target_info, inlining_kind, inlining_id);

  HConstant* undefined = graph()->GetConstantUndefined();

  HEnvironment* inner_env =
      environment()->CopyForInlining(target,
                                     arguments_count,
                                     function,
                                     undefined,
                                     function_state()->inlining_kind());

  HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
  inner_env->BindContext(context);

  // Create a dematerialized arguments object for the function, also copy the
  // current arguments values to use them for materialization.
  HEnvironment* arguments_env = inner_env->arguments_environment();
  int parameter_count = arguments_env->parameter_count();
  HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
  for (int i = 0; i < parameter_count; i++) {
    arguments_object->AddArgument(arguments_env->Lookup(i), zone());
  }

  // If the function uses arguments object then bind bind one.
  if (function->scope()->arguments() != NULL) {
    DCHECK(function->scope()->arguments()->IsStackAllocated());
    inner_env->Bind(function->scope()->arguments(), arguments_object);
  }

  // Capture the state before invoking the inlined function for deopt in the
  // inlined function. This simulate has no bailout-id since it's not directly
  // reachable for deopt, and is only used to capture the state. If the simulate
  // becomes reachable by merging, the ast id of the simulate merged into it is
  // adopted.
  Add<HSimulate>(BailoutId::None());

  current_block()->UpdateEnvironment(inner_env);
  Scope* saved_scope = scope();
  set_scope(target_info.scope());
  HEnterInlined* enter_inlined =
      Add<HEnterInlined>(return_id, target, context, arguments_count, function,
                         function_state()->inlining_kind(),
                         function->scope()->arguments(), arguments_object);
  if (top_info()->is_tracking_positions()) {
    enter_inlined->set_inlining_id(inlining_id);
  }
  function_state()->set_entry(enter_inlined);

  VisitDeclarations(target_info.scope()->declarations());
  VisitStatements(function->body());
  set_scope(saved_scope);
  if (HasStackOverflow()) {
    // Bail out if the inline function did, as we cannot residualize a call
    // instead, but do not disable optimization for the outer function.
    TraceInline(target, caller, "inline graph construction failed");
    target_shared->DisableOptimization(kInliningBailedOut);
    current_info()->RetryOptimization(kInliningBailedOut);
    delete target_state;
    return true;
  }

  // Update inlined nodes count.
  inlined_count_ += nodes_added;

  Handle<Code> unoptimized_code(target_shared->code());
  DCHECK(unoptimized_code->kind() == Code::FUNCTION);
  Handle<TypeFeedbackInfo> type_info(
      TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
  graph()->update_type_change_checksum(type_info->own_type_change_checksum());

  TraceInline(target, caller, NULL);

  if (current_block() != NULL) {
    FunctionState* state = function_state();
    if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
      // Falling off the end of an inlined construct call. In a test context the
      // return value will always evaluate to true, in a value context the
      // return value is the newly allocated receiver.
      if (call_context()->IsTest()) {
        Goto(inlined_test_context()->if_true(), state);
      } else if (call_context()->IsEffect()) {
        Goto(function_return(), state);
      } else {
        DCHECK(call_context()->IsValue());
        AddLeaveInlined(implicit_return_value, state);
      }
    } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
      // Falling off the end of an inlined setter call. The returned value is
      // never used, the value of an assignment is always the value of the RHS
      // of the assignment.
      if (call_context()->IsTest()) {
        inlined_test_context()->ReturnValue(implicit_return_value);
      } else if (call_context()->IsEffect()) {
        Goto(function_return(), state);
      } else {
        DCHECK(call_context()->IsValue());
        AddLeaveInlined(implicit_return_value, state);
      }
    } else {
      // Falling off the end of a normal inlined function. This basically means
      // returning undefined.
      if (call_context()->IsTest()) {
        Goto(inlined_test_context()->if_false(), state);
      } else if (call_context()->IsEffect()) {
        Goto(function_return(), state);
      } else {
        DCHECK(call_context()->IsValue());
        AddLeaveInlined(undefined, state);
      }
    }
  }

  // Fix up the function exits.
  if (inlined_test_context() != NULL) {
    HBasicBlock* if_true = inlined_test_context()->if_true();
    HBasicBlock* if_false = inlined_test_context()->if_false();

    HEnterInlined* entry = function_state()->entry();

    // Pop the return test context from the expression context stack.
    DCHECK(ast_context() == inlined_test_context());
    ClearInlinedTestContext();
    delete target_state;

    // Forward to the real test context.
    if (if_true->HasPredecessor()) {
      entry->RegisterReturnTarget(if_true, zone());
      if_true->SetJoinId(ast_id);
      HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
      Goto(if_true, true_target, function_state());
    }
    if (if_false->HasPredecessor()) {
      entry->RegisterReturnTarget(if_false, zone());
      if_false->SetJoinId(ast_id);
      HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
      Goto(if_false, false_target, function_state());
    }
    set_current_block(NULL);
    return true;

  } else if (function_return()->HasPredecessor()) {
    function_state()->entry()->RegisterReturnTarget(function_return(), zone());
    function_return()->SetJoinId(ast_id);
    set_current_block(function_return());
  } else {
    set_current_block(NULL);
  }
  delete target_state;
  return true;
}


bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
  return TryInline(expr->target(), expr->arguments()->length(), NULL,
                   expr->id(), expr->ReturnId(), NORMAL_RETURN);
}


bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
                                                HValue* implicit_return_value) {
  return TryInline(expr->target(), expr->arguments()->length(),
                   implicit_return_value, expr->id(), expr->ReturnId(),
                   CONSTRUCT_CALL_RETURN);
}

bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter,
                                             Handle<Map> receiver_map,
                                             BailoutId ast_id,
                                             BailoutId return_id) {
  if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
  return getter->IsJSFunction() &&
         TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id,
                   GETTER_CALL_RETURN);
}

bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
                                             Handle<Map> receiver_map,
                                             BailoutId id,
                                             BailoutId assignment_id,
                                             HValue* implicit_return_value) {
  if (TryInlineApiSetter(setter, receiver_map, id)) return true;
  return setter->IsJSFunction() &&
         TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value,
                   id, assignment_id, SETTER_CALL_RETURN);
}


bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
                                                   Call* expr,
                                                   int arguments_count) {
  return TryInline(function, arguments_count, NULL, expr->id(),
                   expr->ReturnId(), NORMAL_RETURN);
}


bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
  if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
  BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
  switch (id) {
    case kMathExp:
      if (!FLAG_fast_math) break;
      // Fall through if FLAG_fast_math.
    case kMathRound:
    case kMathFround:
    case kMathFloor:
    case kMathAbs:
    case kMathSqrt:
    case kMathLog:
    case kMathClz32:
      if (expr->arguments()->length() == 1) {
        HValue* argument = Pop();
        Drop(2);  // Receiver and function.
        HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
        ast_context()->ReturnInstruction(op, expr->id());
        return true;
      }
      break;
    case kMathImul:
      if (expr->arguments()->length() == 2) {
        HValue* right = Pop();
        HValue* left = Pop();
        Drop(2);  // Receiver and function.
        HInstruction* op =
            HMul::NewImul(isolate(), zone(), context(), left, right);
        ast_context()->ReturnInstruction(op, expr->id());
        return true;
      }
      break;
    default:
      // Not supported for inlining yet.
      break;
  }
  return false;
}


// static
bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
    Handle<Map> jsarray_map) {
  DCHECK(!jsarray_map->is_dictionary_map());
  Isolate* isolate = jsarray_map->GetIsolate();
  Handle<Name> length_string = isolate->factory()->length_string();
  DescriptorArray* descriptors = jsarray_map->instance_descriptors();
  int number = descriptors->SearchWithCache(*length_string, *jsarray_map);
  DCHECK_NE(DescriptorArray::kNotFound, number);
  return descriptors->GetDetails(number).IsReadOnly();
}


// static
bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
    Handle<Map> receiver_map) {
  return !receiver_map.is_null() && receiver_map->prototype()->IsJSObject() &&
         receiver_map->instance_type() == JS_ARRAY_TYPE &&
         IsFastElementsKind(receiver_map->elements_kind()) &&
         !receiver_map->is_dictionary_map() && !receiver_map->is_observed() &&
         receiver_map->is_extensible() &&
         (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
         !IsReadOnlyLengthDescriptor(receiver_map);
}


bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
    Call* expr, Handle<JSFunction> function, Handle<Map> receiver_map,
    int args_count_no_receiver) {
  if (!function->shared()->HasBuiltinFunctionId()) return false;
  BuiltinFunctionId id = function->shared()->builtin_function_id();
  int argument_count = args_count_no_receiver + 1;  // Plus receiver.

  if (receiver_map.is_null()) {
    HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
    if (receiver->IsConstant() &&
        HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
      receiver_map =
          handle(Handle<HeapObject>::cast(
                     HConstant::cast(receiver)->handle(isolate()))->map());
    }
  }
  // Try to inline calls like Math.* as operations in the calling function.
  switch (id) {
    case kStringCharCodeAt:
    case kStringCharAt:
      if (argument_count == 2) {
        HValue* index = Pop();
        HValue* string = Pop();
        Drop(1);  // Function.
        HInstruction* char_code =
            BuildStringCharCodeAt(string, index);
        if (id == kStringCharCodeAt) {
          ast_context()->ReturnInstruction(char_code, expr->id());
          return true;
        }
        AddInstruction(char_code);
        HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
        ast_context()->ReturnInstruction(result, expr->id());
        return true;
      }
      break;
    case kStringFromCharCode:
      if (argument_count == 2) {
        HValue* argument = Pop();
        Drop(2);  // Receiver and function.
        HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
        ast_context()->ReturnInstruction(result, expr->id());
        return true;
      }
      break;
    case kMathExp:
      if (!FLAG_fast_math) break;
      // Fall through if FLAG_fast_math.
    case kMathRound:
    case kMathFround:
    case kMathFloor:
    case kMathAbs:
    case kMathSqrt:
    case kMathLog:
    case kMathClz32:
      if (argument_count == 2) {
        HValue* argument = Pop();
        Drop(2);  // Receiver and function.
        HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
        ast_context()->ReturnInstruction(op, expr->id());
        return true;
      }
      break;
    case kMathPow:
      if (argument_count == 3) {
        HValue* right = Pop();
        HValue* left = Pop();
        Drop(2);  // Receiver and function.
        HInstruction* result = NULL;
        // Use sqrt() if exponent is 0.5 or -0.5.
        if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
          double exponent = HConstant::cast(right)->DoubleValue();
          if (exponent == 0.5) {
            result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
          } else if (exponent == -0.5) {
            HValue* one = graph()->GetConstant1();
            HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
                left, kMathPowHalf);
            // MathPowHalf doesn't have side effects so there's no need for
            // an environment simulation here.
            DCHECK(!sqrt->HasObservableSideEffects());
            result = NewUncasted<HDiv>(one, sqrt);
          } else if (exponent == 2.0) {
            result = NewUncasted<HMul>(left, left);
          }
        }

        if (result == NULL) {
          result = NewUncasted<HPower>(left, right);
        }
        ast_context()->ReturnInstruction(result, expr->id());
        return true;
      }
      break;
    case kMathMax:
    case kMathMin:
      if (argument_count == 3) {
        HValue* right = Pop();
        HValue* left = Pop();
        Drop(2);  // Receiver and function.
        HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
                                                     : HMathMinMax::kMathMax;
        HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
        ast_context()->ReturnInstruction(result, expr->id());
        return true;
      }
      break;
    case kMathImul:
      if (argument_count == 3) {
        HValue* right = Pop();
        HValue* left = Pop();
        Drop(2);  // Receiver and function.
        HInstruction* result =
            HMul::NewImul(isolate(), zone(), context(), left, right);
        ast_context()->ReturnInstruction(result, expr->id());
        return true;
      }
      break;
    case kArrayPop: {
      if (!CanInlineArrayResizeOperation(receiver_map)) return false;
      ElementsKind elements_kind = receiver_map->elements_kind();

      Drop(args_count_no_receiver);
      HValue* result;
      HValue* reduced_length;
      HValue* receiver = Pop();

      HValue* checked_object = AddCheckMap(receiver, receiver_map);
      HValue* length =
          Add<HLoadNamedField>(checked_object, nullptr,
                               HObjectAccess::ForArrayLength(elements_kind));

      Drop(1);  // Function.

      { NoObservableSideEffectsScope scope(this);
        IfBuilder length_checker(this);

        HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
            length, graph()->GetConstant0(), Token::EQ);
        length_checker.Then();

        if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());

        length_checker.Else();
        HValue* elements = AddLoadElements(checked_object);
        // Ensure that we aren't popping from a copy-on-write array.
        if (IsFastSmiOrObjectElementsKind(elements_kind)) {
          elements = BuildCopyElementsOnWrite(checked_object, elements,
                                              elements_kind, length);
        }
        reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
        result = AddElementAccess(elements, reduced_length, nullptr,
                                  bounds_check, nullptr, elements_kind, LOAD);
        HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
                           ? graph()->GetConstantHole()
                           : Add<HConstant>(HConstant::kHoleNaN);
        if (IsFastSmiOrObjectElementsKind(elements_kind)) {
          elements_kind = FAST_HOLEY_ELEMENTS;
        }
        AddElementAccess(elements, reduced_length, hole, bounds_check, nullptr,
                         elements_kind, STORE);
        Add<HStoreNamedField>(
            checked_object, HObjectAccess::ForArrayLength(elements_kind),
            reduced_length, STORE_TO_INITIALIZED_ENTRY);

        if (!ast_context()->IsEffect()) Push(result);

        length_checker.End();
      }
      result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
      if (!ast_context()->IsEffect()) Drop(1);

      ast_context()->ReturnValue(result);
      return true;
    }
    case kArrayPush: {
      if (!CanInlineArrayResizeOperation(receiver_map)) return false;
      ElementsKind elements_kind = receiver_map->elements_kind();

      // If there may be elements accessors in the prototype chain, the fast
      // inlined version can't be used.
      if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
      // If there currently can be no elements accessors on the prototype chain,
      // it doesn't mean that there won't be any later. Install a full prototype
      // chain check to trap element accessors being installed on the prototype
      // chain, which would cause elements to go to dictionary mode and result
      // in a map change.
      Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
      BuildCheckPrototypeMaps(prototype, Handle<JSObject>());

      // Protect against adding elements to the Array prototype, which needs to
      // route through appropriate bottlenecks.
      if (isolate()->IsFastArrayConstructorPrototypeChainIntact() &&
          !prototype->IsJSArray()) {
        return false;
      }

      const int argc = args_count_no_receiver;
      if (argc != 1) return false;

      HValue* value_to_push = Pop();
      HValue* array = Pop();
      Drop(1);  // Drop function.

      HInstruction* new_size = NULL;
      HValue* length = NULL;

      {
        NoObservableSideEffectsScope scope(this);

        length = Add<HLoadNamedField>(
            array, nullptr, HObjectAccess::ForArrayLength(elements_kind));

        new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());

        bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
        HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
        BuildUncheckedMonomorphicElementAccess(
            checked_array, length, value_to_push, is_array, elements_kind,
            STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);

        if (!ast_context()->IsEffect()) Push(new_size);
        Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
        if (!ast_context()->IsEffect()) Drop(1);
      }

      ast_context()->ReturnValue(new_size);
      return true;
    }
    case kArrayShift: {
      if (!CanInlineArrayResizeOperation(receiver_map)) return false;
      ElementsKind kind = receiver_map->elements_kind();

      // If there may be elements accessors in the prototype chain, the fast
      // inlined version can't be used.
      if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;

      // If there currently can be no elements accessors on the prototype chain,
      // it doesn't mean that there won't be any later. Install a full prototype
      // chain check to trap element accessors being installed on the prototype
      // chain, which would cause elements to go to dictionary mode and result
      // in a map change.
      BuildCheckPrototypeMaps(
          handle(JSObject::cast(receiver_map->prototype()), isolate()),
          Handle<JSObject>::null());

      // Threshold for fast inlined Array.shift().
      HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));

      Drop(args_count_no_receiver);
      HValue* receiver = Pop();
      HValue* function = Pop();
      HValue* result;

      {
        NoObservableSideEffectsScope scope(this);

        HValue* length = Add<HLoadNamedField>(
            receiver, nullptr, HObjectAccess::ForArrayLength(kind));

        IfBuilder if_lengthiszero(this);
        HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
            length, graph()->GetConstant0(), Token::EQ);
        if_lengthiszero.Then();
        {
          if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
        }
        if_lengthiszero.Else();
        {
          HValue* elements = AddLoadElements(receiver);

          // Check if we can use the fast inlined Array.shift().
          IfBuilder if_inline(this);
          if_inline.If<HCompareNumericAndBranch>(
              length, inline_threshold, Token::LTE);
          if (IsFastSmiOrObjectElementsKind(kind)) {
            // We cannot handle copy-on-write backing stores here.
            if_inline.AndIf<HCompareMap>(
                elements, isolate()->factory()->fixed_array_map());
          }
          if_inline.Then();
          {
            // Remember the result.
            if (!ast_context()->IsEffect()) {
              Push(AddElementAccess(elements, graph()->GetConstant0(), nullptr,
                                    lengthiszero, nullptr, kind, LOAD));
            }

            // Compute the new length.
            HValue* new_length = AddUncasted<HSub>(
                length, graph()->GetConstant1());
            new_length->ClearFlag(HValue::kCanOverflow);

            // Copy the remaining elements.
            LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
            {
              HValue* new_key = loop.BeginBody(
                  graph()->GetConstant0(), new_length, Token::LT);
              HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
              key->ClearFlag(HValue::kCanOverflow);
              ElementsKind copy_kind =
                  kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
              HValue* element =
                  AddUncasted<HLoadKeyed>(elements, key, lengthiszero, nullptr,
                                          copy_kind, ALLOW_RETURN_HOLE);
              HStoreKeyed* store = Add<HStoreKeyed>(elements, new_key, element,
                                                    nullptr, copy_kind);
              store->SetFlag(HValue::kAllowUndefinedAsNaN);
            }
            loop.EndBody();

            // Put a hole at the end.
            HValue* hole = IsFastSmiOrObjectElementsKind(kind)
                               ? graph()->GetConstantHole()
                               : Add<HConstant>(HConstant::kHoleNaN);
            if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
            Add<HStoreKeyed>(elements, new_length, hole, nullptr, kind,
                             INITIALIZING_STORE);

            // Remember new length.
            Add<HStoreNamedField>(
                receiver, HObjectAccess::ForArrayLength(kind),
                new_length, STORE_TO_INITIALIZED_ENTRY);
          }
          if_inline.Else();
          {
            Add<HPushArguments>(receiver);
            result = Add<HCallJSFunction>(function, 1);
            if (!ast_context()->IsEffect()) Push(result);
          }
          if_inline.End();
        }
        if_lengthiszero.End();
      }
      result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
      if (!ast_context()->IsEffect()) Drop(1);
      ast_context()->ReturnValue(result);
      return true;
    }
    case kArrayIndexOf:
    case kArrayLastIndexOf: {
      if (receiver_map.is_null()) return false;
      if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
      if (!receiver_map->prototype()->IsJSObject()) return false;
      ElementsKind kind = receiver_map->elements_kind();
      if (!IsFastElementsKind(kind)) return false;
      if (receiver_map->is_observed()) return false;
      if (argument_count != 2) return false;
      if (!receiver_map->is_extensible()) return false;

      // If there may be elements accessors in the prototype chain, the fast
      // inlined version can't be used.
      if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;

      // If there currently can be no elements accessors on the prototype chain,
      // it doesn't mean that there won't be any later. Install a full prototype
      // chain check to trap element accessors being installed on the prototype
      // chain, which would cause elements to go to dictionary mode and result
      // in a map change.
      BuildCheckPrototypeMaps(
          handle(JSObject::cast(receiver_map->prototype()), isolate()),
          Handle<JSObject>::null());

      HValue* search_element = Pop();
      HValue* receiver = Pop();
      Drop(1);  // Drop function.

      ArrayIndexOfMode mode = (id == kArrayIndexOf)
          ? kFirstIndexOf : kLastIndexOf;
      HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);

      if (!ast_context()->IsEffect()) Push(index);
      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
      if (!ast_context()->IsEffect()) Drop(1);
      ast_context()->ReturnValue(index);
      return true;
    }
    default:
      // Not yet supported for inlining.
      break;
  }
  return false;
}


bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
                                                      HValue* receiver) {
  Handle<JSFunction> function = expr->target();
  int argc = expr->arguments()->length();
  SmallMapList receiver_maps;
  return TryInlineApiCall(function,
                          receiver,
                          &receiver_maps,
                          argc,
                          expr->id(),
                          kCallApiFunction);
}


bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
    Call* expr,
    HValue* receiver,
    SmallMapList* receiver_maps) {
  Handle<JSFunction> function = expr->target();
  int argc = expr->arguments()->length();
  return TryInlineApiCall(function,
                          receiver,
                          receiver_maps,
                          argc,
                          expr->id(),
                          kCallApiMethod);
}

bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function,
                                                Handle<Map> receiver_map,
                                                BailoutId ast_id) {
  SmallMapList receiver_maps(1, zone());
  receiver_maps.Add(receiver_map, zone());
  return TryInlineApiCall(function,
                          NULL,  // Receiver is on expression stack.
                          &receiver_maps,
                          0,
                          ast_id,
                          kCallApiGetter);
}

bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function,
                                                Handle<Map> receiver_map,
                                                BailoutId ast_id) {
  SmallMapList receiver_maps(1, zone());
  receiver_maps.Add(receiver_map, zone());
  return TryInlineApiCall(function,
                          NULL,  // Receiver is on expression stack.
                          &receiver_maps,
                          1,
                          ast_id,
                          kCallApiSetter);
}

bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<Object> function,
                                              HValue* receiver,
                                              SmallMapList* receiver_maps,
                                              int argc, BailoutId ast_id,
                                              ApiCallType call_type) {
  if (function->IsJSFunction() &&
      Handle<JSFunction>::cast(function)->context()->native_context() !=
          top_info()->closure()->context()->native_context()) {
    return false;
  }
  CallOptimization optimization(function);
  if (!optimization.is_simple_api_call()) return false;
  Handle<Map> holder_map;
  for (int i = 0; i < receiver_maps->length(); ++i) {
    auto map = receiver_maps->at(i);
    // Don't inline calls to receivers requiring accesschecks.
    if (map->is_access_check_needed()) return false;
  }
  if (call_type == kCallApiFunction) {
    // Cannot embed a direct reference to the global proxy map
    // as it maybe dropped on deserialization.
    CHECK(!isolate()->serializer_enabled());
    DCHECK(function->IsJSFunction());
    DCHECK_EQ(0, receiver_maps->length());
    receiver_maps->Add(
        handle(Handle<JSFunction>::cast(function)->global_proxy()->map()),
        zone());
  }
  CallOptimization::HolderLookup holder_lookup =
      CallOptimization::kHolderNotFound;
  Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
      receiver_maps->first(), &holder_lookup);
  if (holder_lookup == CallOptimization::kHolderNotFound) return false;

  if (FLAG_trace_inlining) {
    PrintF("Inlining api function ");
    function->ShortPrint();
    PrintF("\n");
  }

  bool is_function = false;
  bool is_store = false;
  switch (call_type) {
    case kCallApiFunction:
    case kCallApiMethod:
      // Need to check that none of the receiver maps could have changed.
      Add<HCheckMaps>(receiver, receiver_maps);
      // Need to ensure the chain between receiver and api_holder is intact.
      if (holder_lookup == CallOptimization::kHolderFound) {
        AddCheckPrototypeMaps(api_holder, receiver_maps->first());
      } else {
        DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
      }
      // Includes receiver.
      PushArgumentsFromEnvironment(argc + 1);
      is_function = true;
      break;
    case kCallApiGetter:
      // Receiver and prototype chain cannot have changed.
      DCHECK_EQ(0, argc);
      DCHECK_NULL(receiver);
      // Receiver is on expression stack.
      receiver = Pop();
      Add<HPushArguments>(receiver);
      break;
    case kCallApiSetter:
      {
        is_store = true;
        // Receiver and prototype chain cannot have changed.
        DCHECK_EQ(1, argc);
        DCHECK_NULL(receiver);
        // Receiver and value are on expression stack.
        HValue* value = Pop();
        receiver = Pop();
        Add<HPushArguments>(receiver, value);
        break;
     }
  }

  HValue* holder = NULL;
  switch (holder_lookup) {
    case CallOptimization::kHolderFound:
      holder = Add<HConstant>(api_holder);
      break;
    case CallOptimization::kHolderIsReceiver:
      holder = receiver;
      break;
    case CallOptimization::kHolderNotFound:
      UNREACHABLE();
      break;
  }
  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
  Handle<Object> call_data_obj(api_call_info->data(), isolate());
  bool call_data_undefined = call_data_obj->IsUndefined();
  HValue* call_data = Add<HConstant>(call_data_obj);
  ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
  ExternalReference ref = ExternalReference(&fun,
                                            ExternalReference::DIRECT_API_CALL,
                                            isolate());
  HValue* api_function_address = Add<HConstant>(ExternalReference(ref));

  HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder,
                       api_function_address, nullptr};

  HInstruction* call = nullptr;
  if (!is_function) {
    CallApiAccessorStub stub(isolate(), is_store, call_data_undefined,
                             !optimization.is_constant_call());
    Handle<Code> code = stub.GetCode();
    HConstant* code_value = Add<HConstant>(code);
    ApiAccessorDescriptor descriptor(isolate());
    call = New<HCallWithDescriptor>(
        code_value, argc + 1, descriptor,
        Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
  } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) {
    CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined);
    Handle<Code> code = stub.GetCode();
    HConstant* code_value = Add<HConstant>(code);
    ApiFunctionWithFixedArgsDescriptor descriptor(isolate());
    call = New<HCallWithDescriptor>(
        code_value, argc + 1, descriptor,
        Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
    Drop(1);  // Drop function.
  } else {
    op_vals[arraysize(op_vals) - 1] = Add<HConstant>(argc);
    CallApiFunctionStub stub(isolate(), call_data_undefined);
    Handle<Code> code = stub.GetCode();
    HConstant* code_value = Add<HConstant>(code);
    ApiFunctionDescriptor descriptor(isolate());
    call =
        New<HCallWithDescriptor>(code_value, argc + 1, descriptor,
                                 Vector<HValue*>(op_vals, arraysize(op_vals)));
    Drop(1);  // Drop function.
  }

  ast_context()->ReturnInstruction(call, ast_id);
  return true;
}


void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
                                                int arguments_count) {
  Handle<JSFunction> known_function;
  int args_count_no_receiver = arguments_count - 1;
  if (function->IsConstant() &&
      HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    known_function =
        Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
    if (TryInlineBuiltinMethodCall(expr, known_function, Handle<Map>(),
                                   args_count_no_receiver)) {
      if (FLAG_trace_inlining) {
        PrintF("Inlining builtin ");
        known_function->ShortPrint();
        PrintF("\n");
      }
      return;
    }

    if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
      return;
    }
  }

  PushArgumentsFromEnvironment(arguments_count);
  HInvokeFunction* call =
      New<HInvokeFunction>(function, known_function, arguments_count);
  Drop(1);  // Function
  ast_context()->ReturnInstruction(call, expr->id());
}


bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
  DCHECK(expr->expression()->IsProperty());

  if (!expr->IsMonomorphic()) {
    return false;
  }
  Handle<Map> function_map = expr->GetReceiverTypes()->first();
  if (function_map->instance_type() != JS_FUNCTION_TYPE ||
      !expr->target()->shared()->HasBuiltinFunctionId()) {
    return false;
  }

  switch (expr->target()->shared()->builtin_function_id()) {
    case kFunctionCall: {
      if (expr->arguments()->length() == 0) return false;
      BuildFunctionCall(expr);
      return true;
    }
    case kFunctionApply: {
      // For .apply, only the pattern f.apply(receiver, arguments)
      // is supported.
      if (current_info()->scope()->arguments() == NULL) return false;

      if (!CanBeFunctionApplyArguments(expr)) return false;

      BuildFunctionApply(expr);
      return true;
    }
    default: { return false; }
  }
  UNREACHABLE();
}


// f.apply(...)
void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
  ZoneList<Expression*>* args = expr->arguments();
  CHECK_ALIVE(VisitForValue(args->at(0)));
  HValue* receiver = Pop();  // receiver
  HValue* function = Pop();  // f
  Drop(1);  // apply

  Handle<Map> function_map = expr->GetReceiverTypes()->first();
  HValue* checked_function = AddCheckMap(function, function_map);

  if (function_state()->outer() == NULL) {
    HInstruction* elements = Add<HArgumentsElements>(false);
    HInstruction* length = Add<HArgumentsLength>(elements);
    HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
    HInstruction* result = New<HApplyArguments>(function,
                                                wrapped_receiver,
                                                length,
                                                elements);
    ast_context()->ReturnInstruction(result, expr->id());
  } else {
    // We are inside inlined function and we know exactly what is inside
    // arguments object. But we need to be able to materialize at deopt.
    DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
              function_state()->entry()->arguments_object()->arguments_count());
    HArgumentsObject* args = function_state()->entry()->arguments_object();
    const ZoneList<HValue*>* arguments_values = args->arguments_values();
    int arguments_count = arguments_values->length();
    Push(function);
    Push(BuildWrapReceiver(receiver, checked_function));
    for (int i = 1; i < arguments_count; i++) {
      Push(arguments_values->at(i));
    }
    HandleIndirectCall(expr, function, arguments_count);
  }
}


// f.call(...)
void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
  HValue* function = Top();  // f
  Handle<Map> function_map = expr->GetReceiverTypes()->first();
  HValue* checked_function = AddCheckMap(function, function_map);

  // f and call are on the stack in the unoptimized code
  // during evaluation of the arguments.
  CHECK_ALIVE(VisitExpressions(expr->arguments()));

  int args_length = expr->arguments()->length();
  int receiver_index = args_length - 1;
  // Patch the receiver.
  HValue* receiver = BuildWrapReceiver(
      environment()->ExpressionStackAt(receiver_index), checked_function);
  environment()->SetExpressionStackAt(receiver_index, receiver);

  // Call must not be on the stack from now on.
  int call_index = args_length + 1;
  environment()->RemoveExpressionStackAt(call_index);

  HandleIndirectCall(expr, function, args_length);
}


HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
                                                    Handle<JSFunction> target) {
  SharedFunctionInfo* shared = target->shared();
  if (is_sloppy(shared->language_mode()) && !shared->native()) {
    // Cannot embed a direct reference to the global proxy
    // as is it dropped on deserialization.
    CHECK(!isolate()->serializer_enabled());
    Handle<JSObject> global_proxy(target->context()->global_proxy());
    return Add<HConstant>(global_proxy);
  }
  return graph()->GetConstantUndefined();
}


void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
                                            int arguments_count,
                                            HValue* function,
                                            Handle<AllocationSite> site) {
  Add<HCheckValue>(function, array_function());

  if (IsCallArrayInlineable(arguments_count, site)) {
    BuildInlinedCallArray(expression, arguments_count, site);
    return;
  }

  HInstruction* call = PreProcessCall(New<HCallNewArray>(
      function, arguments_count + 1, site->GetElementsKind(), site));
  if (expression->IsCall()) {
    Drop(1);
  }
  ast_context()->ReturnInstruction(call, expression->id());
}


HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
                                                  HValue* search_element,
                                                  ElementsKind kind,
                                                  ArrayIndexOfMode mode) {
  DCHECK(IsFastElementsKind(kind));

  NoObservableSideEffectsScope no_effects(this);

  HValue* elements = AddLoadElements(receiver);
  HValue* length = AddLoadArrayLength(receiver, kind);

  HValue* initial;
  HValue* terminating;
  Token::Value token;
  LoopBuilder::Direction direction;
  if (mode == kFirstIndexOf) {
    initial = graph()->GetConstant0();
    terminating = length;
    token = Token::LT;
    direction = LoopBuilder::kPostIncrement;
  } else {
    DCHECK_EQ(kLastIndexOf, mode);
    initial = length;
    terminating = graph()->GetConstant0();
    token = Token::GT;
    direction = LoopBuilder::kPreDecrement;
  }

  Push(graph()->GetConstantMinus1());
  if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
    // Make sure that we can actually compare numbers correctly below, see
    // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
    search_element = AddUncasted<HForceRepresentation>(
        search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
                                                    : Representation::Double());

    LoopBuilder loop(this, context(), direction);
    {
      HValue* index = loop.BeginBody(initial, terminating, token);
      HValue* element = AddUncasted<HLoadKeyed>(
          elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
      IfBuilder if_issame(this);
      if_issame.If<HCompareNumericAndBranch>(element, search_element,
                                             Token::EQ_STRICT);
      if_issame.Then();
      {
        Drop(1);
        Push(index);
        loop.Break();
      }
      if_issame.End();
    }
    loop.EndBody();
  } else {
    IfBuilder if_isstring(this);
    if_isstring.If<HIsStringAndBranch>(search_element);
    if_isstring.Then();
    {
      LoopBuilder loop(this, context(), direction);
      {
        HValue* index = loop.BeginBody(initial, terminating, token);
        HValue* element = AddUncasted<HLoadKeyed>(
            elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
        IfBuilder if_issame(this);
        if_issame.If<HIsStringAndBranch>(element);
        if_issame.AndIf<HStringCompareAndBranch>(
            element, search_element, Token::EQ_STRICT);
        if_issame.Then();
        {
          Drop(1);
          Push(index);
          loop.Break();
        }
        if_issame.End();
      }
      loop.EndBody();
    }
    if_isstring.Else();
    {
      IfBuilder if_isnumber(this);
      if_isnumber.If<HIsSmiAndBranch>(search_element);
      if_isnumber.OrIf<HCompareMap>(
          search_element, isolate()->factory()->heap_number_map());
      if_isnumber.Then();
      {
        HValue* search_number =
            AddUncasted<HForceRepresentation>(search_element,
                                              Representation::Double());
        LoopBuilder loop(this, context(), direction);
        {
          HValue* index = loop.BeginBody(initial, terminating, token);
          HValue* element = AddUncasted<HLoadKeyed>(
              elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);

          IfBuilder if_element_isnumber(this);
          if_element_isnumber.If<HIsSmiAndBranch>(element);
          if_element_isnumber.OrIf<HCompareMap>(
              element, isolate()->factory()->heap_number_map());
          if_element_isnumber.Then();
          {
            HValue* number =
                AddUncasted<HForceRepresentation>(element,
                                                  Representation::Double());
            IfBuilder if_issame(this);
            if_issame.If<HCompareNumericAndBranch>(
                number, search_number, Token::EQ_STRICT);
            if_issame.Then();
            {
              Drop(1);
              Push(index);
              loop.Break();
            }
            if_issame.End();
          }
          if_element_isnumber.End();
        }
        loop.EndBody();
      }
      if_isnumber.Else();
      {
        LoopBuilder loop(this, context(), direction);
        {
          HValue* index = loop.BeginBody(initial, terminating, token);
          HValue* element = AddUncasted<HLoadKeyed>(
              elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
          IfBuilder if_issame(this);
          if_issame.If<HCompareObjectEqAndBranch>(
              element, search_element);
          if_issame.Then();
          {
            Drop(1);
            Push(index);
            loop.Break();
          }
          if_issame.End();
        }
        loop.EndBody();
      }
      if_isnumber.End();
    }
    if_isstring.End();
  }

  return Pop();
}


bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
  if (!array_function().is_identical_to(expr->target())) {
    return false;
  }

  Handle<AllocationSite> site = expr->allocation_site();
  if (site.is_null()) return false;

  BuildArrayCall(expr,
                 expr->arguments()->length(),
                 function,
                 site);
  return true;
}


bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
                                                   HValue* function) {
  if (!array_function().is_identical_to(expr->target())) {
    return false;
  }

  Handle<AllocationSite> site = expr->allocation_site();
  if (site.is_null()) return false;

  BuildArrayCall(expr, expr->arguments()->length(), function, site);
  return true;
}


bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
  ZoneList<Expression*>* args = expr->arguments();
  if (args->length() != 2) return false;
  VariableProxy* arg_two = args->at(1)->AsVariableProxy();
  if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
  HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
  if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
  return true;
}


void HOptimizedGraphBuilder::VisitCall(Call* expr) {
  if (expr->tail_call_mode() == TailCallMode::kAllow) {
    return Bailout(kTailCall);
  }
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
  Expression* callee = expr->expression();
  int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
  HInstruction* call = NULL;

  Property* prop = callee->AsProperty();
  if (prop != NULL) {
    CHECK_ALIVE(VisitForValue(prop->obj()));
    HValue* receiver = Top();

    SmallMapList* maps;
    ComputeReceiverTypes(expr, receiver, &maps, zone());

    if (prop->key()->IsPropertyName() && maps->length() > 0) {
      Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
      PropertyAccessInfo info(this, LOAD, maps->first(), name);
      if (!info.CanAccessAsMonomorphic(maps)) {
        HandlePolymorphicCallNamed(expr, receiver, maps, name);
        return;
      }
    }
    HValue* key = NULL;
    if (!prop->key()->IsPropertyName()) {
      CHECK_ALIVE(VisitForValue(prop->key()));
      key = Pop();
    }

    CHECK_ALIVE(PushLoad(prop, receiver, key));
    HValue* function = Pop();

    if (function->IsConstant() &&
        HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
      // Push the function under the receiver.
      environment()->SetExpressionStackAt(0, function);
      Push(receiver);

      Handle<JSFunction> known_function = Handle<JSFunction>::cast(
          HConstant::cast(function)->handle(isolate()));
      expr->set_target(known_function);

      if (TryIndirectCall(expr)) return;
      CHECK_ALIVE(VisitExpressions(expr->arguments()));

      Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
      if (TryInlineBuiltinMethodCall(expr, known_function, map,
                                     expr->arguments()->length())) {
        if (FLAG_trace_inlining) {
          PrintF("Inlining builtin ");
          known_function->ShortPrint();
          PrintF("\n");
        }
        return;
      }
      if (TryInlineApiMethodCall(expr, receiver, maps)) return;

      // Wrap the receiver if necessary.
      if (NeedsWrapping(maps->first(), known_function)) {
        // Since HWrapReceiver currently cannot actually wrap numbers and
        // strings, use the regular CallFunctionStub for method calls to wrap
        // the receiver.
        // TODO(verwaest): Support creation of value wrappers directly in
        // HWrapReceiver.
        call = New<HCallFunction>(function, argument_count,
                                  ConvertReceiverMode::kNotNullOrUndefined);
      } else if (TryInlineCall(expr)) {
        return;
      } else {
        call = BuildCallConstantFunction(known_function, argument_count);
      }

    } else {
      ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
      if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
        // We have to use EAGER deoptimization here because Deoptimizer::SOFT
        // gets ignored by the always-opt flag, which leads to incorrect code.
        Add<HDeoptimize>(
            Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments,
            Deoptimizer::EAGER);
        arguments_flag = ARGUMENTS_FAKED;
      }

      // Push the function under the receiver.
      environment()->SetExpressionStackAt(0, function);
      Push(receiver);

      CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
      call = New<HCallFunction>(function, argument_count,
                                ConvertReceiverMode::kNotNullOrUndefined);
    }
    PushArgumentsFromEnvironment(argument_count);

  } else {
    VariableProxy* proxy = expr->expression()->AsVariableProxy();
    if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
      return Bailout(kPossibleDirectCallToEval);
    }

    // The function is on the stack in the unoptimized code during
    // evaluation of the arguments.
    CHECK_ALIVE(VisitForValue(expr->expression()));
    HValue* function = Top();
    if (function->IsConstant() &&
        HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
      Handle<Object> constant = HConstant::cast(function)->handle(isolate());
      Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
      expr->SetKnownGlobalTarget(target);
    }

    // Placeholder for the receiver.
    Push(graph()->GetConstantUndefined());
    CHECK_ALIVE(VisitExpressions(expr->arguments()));

    if (expr->IsMonomorphic() &&
        !IsClassConstructor(expr->target()->shared()->kind())) {
      Add<HCheckValue>(function, expr->target());

      // Patch the global object on the stack by the expected receiver.
      HValue* receiver = ImplicitReceiverFor(function, expr->target());
      const int receiver_index = argument_count - 1;
      environment()->SetExpressionStackAt(receiver_index, receiver);

      if (TryInlineBuiltinFunctionCall(expr)) {
        if (FLAG_trace_inlining) {
          PrintF("Inlining builtin ");
          expr->target()->ShortPrint();
          PrintF("\n");
        }
        return;
      }
      if (TryInlineApiFunctionCall(expr, receiver)) return;
      if (TryHandleArrayCall(expr, function)) return;
      if (TryInlineCall(expr)) return;

      PushArgumentsFromEnvironment(argument_count);
      call = BuildCallConstantFunction(expr->target(), argument_count);
    } else {
      PushArgumentsFromEnvironment(argument_count);
      HCallFunction* call_function = New<HCallFunction>(
          function, argument_count, ConvertReceiverMode::kNullOrUndefined);
      call = call_function;
      if (expr->is_uninitialized() &&
          expr->IsUsingCallFeedbackICSlot(isolate())) {
        // We've never seen this call before, so let's have Crankshaft learn
        // through the type vector.
        Handle<TypeFeedbackVector> vector =
            handle(current_feedback_vector(), isolate());
        FeedbackVectorSlot slot = expr->CallFeedbackICSlot();
        call_function->SetVectorAndSlot(vector, slot);
      }
    }
  }

  Drop(1);  // Drop the function.
  return ast_context()->ReturnInstruction(call, expr->id());
}


void HOptimizedGraphBuilder::BuildInlinedCallArray(
    Expression* expression,
    int argument_count,
    Handle<AllocationSite> site) {
  DCHECK(!site.is_null());
  DCHECK(argument_count >= 0 && argument_count <= 1);
  NoObservableSideEffectsScope no_effects(this);

  // We should at least have the constructor on the expression stack.
  HValue* constructor = environment()->ExpressionStackAt(argument_count);

  // Register on the site for deoptimization if the transition feedback changes.
  top_info()->dependencies()->AssumeTransitionStable(site);
  ElementsKind kind = site->GetElementsKind();
  HInstruction* site_instruction = Add<HConstant>(site);

  // In the single constant argument case, we may have to adjust elements kind
  // to avoid creating a packed non-empty array.
  if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
    HValue* argument = environment()->Top();
    if (argument->IsConstant()) {
      HConstant* constant_argument = HConstant::cast(argument);
      DCHECK(constant_argument->HasSmiValue());
      int constant_array_size = constant_argument->Integer32Value();
      if (constant_array_size != 0) {
        kind = GetHoleyElementsKind(kind);
      }
    }
  }

  // Build the array.
  JSArrayBuilder array_builder(this,
                               kind,
                               site_instruction,
                               constructor,
                               DISABLE_ALLOCATION_SITES);
  HValue* new_object = argument_count == 0
      ? array_builder.AllocateEmptyArray()
      : BuildAllocateArrayFromLength(&array_builder, Top());

  int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
  Drop(args_to_drop);
  ast_context()->ReturnValue(new_object);
}


// Checks whether allocation using the given constructor can be inlined.
static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
  return constructor->has_initial_map() &&
         !IsSubclassConstructor(constructor->shared()->kind()) &&
         constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
         constructor->initial_map()->instance_size() <
             HAllocate::kMaxInlineSize;
}


bool HOptimizedGraphBuilder::IsCallArrayInlineable(
    int argument_count,
    Handle<AllocationSite> site) {
  Handle<JSFunction> caller = current_info()->closure();
  Handle<JSFunction> target = array_function();
  // We should have the function plus array arguments on the environment stack.
  DCHECK(environment()->length() >= (argument_count + 1));
  DCHECK(!site.is_null());

  bool inline_ok = false;
  if (site->CanInlineCall()) {
    // We also want to avoid inlining in certain 1 argument scenarios.
    if (argument_count == 1) {
      HValue* argument = Top();
      if (argument->IsConstant()) {
        // Do not inline if the constant length argument is not a smi or
        // outside the valid range for unrolled loop initialization.
        HConstant* constant_argument = HConstant::cast(argument);
        if (constant_argument->HasSmiValue()) {
          int value = constant_argument->Integer32Value();
          inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
          if (!inline_ok) {
            TraceInline(target, caller,
                        "Constant length outside of valid inlining range.");
          }
        }
      } else {
        TraceInline(target, caller,
                    "Dont inline [new] Array(n) where n isn't constant.");
      }
    } else if (argument_count == 0) {
      inline_ok = true;
    } else {
      TraceInline(target, caller, "Too many arguments to inline.");
    }
  } else {
    TraceInline(target, caller, "AllocationSite requested no inlining.");
  }

  if (inline_ok) {
    TraceInline(target, caller, NULL);
  }
  return inline_ok;
}


void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
  int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
  Factory* factory = isolate()->factory();

  // The constructor function is on the stack in the unoptimized code
  // during evaluation of the arguments.
  CHECK_ALIVE(VisitForValue(expr->expression()));
  HValue* function = Top();
  CHECK_ALIVE(VisitExpressions(expr->arguments()));

  if (function->IsConstant() &&
      HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
    Handle<Object> constant = HConstant::cast(function)->handle(isolate());
    expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
  }

  if (FLAG_inline_construct &&
      expr->IsMonomorphic() &&
      IsAllocationInlineable(expr->target())) {
    Handle<JSFunction> constructor = expr->target();
    DCHECK(
        constructor->shared()->construct_stub() ==
            isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric) ||
        constructor->shared()->construct_stub() ==
            isolate()->builtins()->builtin(Builtins::kJSConstructStubApi));
    HValue* check = Add<HCheckValue>(function, constructor);

    // Force completion of inobject slack tracking before generating
    // allocation code to finalize instance size.
    constructor->CompleteInobjectSlackTrackingIfActive();

    // Calculate instance size from initial map of constructor.
    DCHECK(constructor->has_initial_map());
    Handle<Map> initial_map(constructor->initial_map());
    int instance_size = initial_map->instance_size();

    // Allocate an instance of the implicit receiver object.
    HValue* size_in_bytes = Add<HConstant>(instance_size);
    HAllocationMode allocation_mode;
    HAllocate* receiver = BuildAllocate(
        size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
    receiver->set_known_initial_map(initial_map);

    // Initialize map and fields of the newly allocated object.
    { NoObservableSideEffectsScope no_effects(this);
      DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
      Add<HStoreNamedField>(receiver,
          HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
          Add<HConstant>(initial_map));
      HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
      Add<HStoreNamedField>(receiver,
          HObjectAccess::ForMapAndOffset(initial_map,
                                         JSObject::kPropertiesOffset),
          empty_fixed_array);
      Add<HStoreNamedField>(receiver,
          HObjectAccess::ForMapAndOffset(initial_map,
                                         JSObject::kElementsOffset),
          empty_fixed_array);
      BuildInitializeInobjectProperties(receiver, initial_map);
    }

    // Replace the constructor function with a newly allocated receiver using
    // the index of the receiver from the top of the expression stack.
    const int receiver_index = argument_count - 1;
    DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
    environment()->SetExpressionStackAt(receiver_index, receiver);

    if (TryInlineConstruct(expr, receiver)) {
      // Inlining worked, add a dependency on the initial map to make sure that
      // this code is deoptimized whenever the initial map of the constructor
      // changes.
      top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
      return;
    }

    // TODO(mstarzinger): For now we remove the previous HAllocate and all
    // corresponding instructions and instead add HPushArguments for the
    // arguments in case inlining failed.  What we actually should do is for
    // inlining to try to build a subgraph without mutating the parent graph.
    HInstruction* instr = current_block()->last();
    do {
      HInstruction* prev_instr = instr->previous();
      instr->DeleteAndReplaceWith(NULL);
      instr = prev_instr;
    } while (instr != check);
    environment()->SetExpressionStackAt(receiver_index, function);
  } else {
    // The constructor function is both an operand to the instruction and an
    // argument to the construct call.
    if (TryHandleArrayCallNew(expr, function)) return;
  }

  HValue* arity = Add<HConstant>(argument_count - 1);
  HValue* op_vals[] = {context(), function, function, arity};
  Callable callable = CodeFactory::Construct(isolate());
  HConstant* stub = Add<HConstant>(callable.code());
  PushArgumentsFromEnvironment(argument_count);
  HInstruction* construct =
      New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
                               Vector<HValue*>(op_vals, arraysize(op_vals)));
  return ast_context()->ReturnInstruction(construct, expr->id());
}


void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
    HValue* receiver, Handle<Map> initial_map) {
  if (initial_map->GetInObjectProperties() != 0) {
    HConstant* undefined = graph()->GetConstantUndefined();
    for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
      int property_offset = initial_map->GetInObjectPropertyOffset(i);
      Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
                                          initial_map, property_offset),
                            undefined);
    }
  }
}


HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
  // We HForceRepresentation here to avoid allocations during an *-to-tagged
  // HChange that could cause GC while the array buffer object is not fully
  // initialized.
  HObjectAccess byte_length_access(HObjectAccess::ForJSArrayBufferByteLength());
  byte_length = AddUncasted<HForceRepresentation>(
      byte_length, byte_length_access.representation());
  HAllocate* result =
      BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
                    HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());

  HValue* native_context = BuildGetNativeContext();
  Add<HStoreNamedField>(
      result, HObjectAccess::ForMap(),
      Add<HLoadNamedField>(
          native_context, nullptr,
          HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));

  HConstant* empty_fixed_array =
      Add<HConstant>(isolate()->factory()->empty_fixed_array());
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
      empty_fixed_array);
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
      empty_fixed_array);
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayBufferBackingStore().WithRepresentation(
                  Representation::Smi()),
      graph()->GetConstant0());
  Add<HStoreNamedField>(result, byte_length_access, byte_length);
  Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
                        graph()->GetConstant0());
  Add<HStoreNamedField>(
      result, HObjectAccess::ForJSArrayBufferBitField(),
      Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
                     (1 << JSArrayBuffer::IsNeuterable::kShift)));

  for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
    Add<HStoreNamedField>(
        result,
        HObjectAccess::ForObservableJSObjectOffset(
            JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
        graph()->GetConstant0());
  }

  return result;
}


template <class ViewClass>
void HGraphBuilder::BuildArrayBufferViewInitialization(
    HValue* obj,
    HValue* buffer,
    HValue* byte_offset,
    HValue* byte_length) {

  for (int offset = ViewClass::kSize;
       offset < ViewClass::kSizeWithInternalFields;
       offset += kPointerSize) {
    Add<HStoreNamedField>(obj,
        HObjectAccess::ForObservableJSObjectOffset(offset),
        graph()->GetConstant0());
  }

  Add<HStoreNamedField>(
      obj,
      HObjectAccess::ForJSArrayBufferViewByteOffset(),
      byte_offset);
  Add<HStoreNamedField>(
      obj,
      HObjectAccess::ForJSArrayBufferViewByteLength(),
      byte_length);
  Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
                        buffer);
}


void HOptimizedGraphBuilder::GenerateDataViewInitialize(
    CallRuntime* expr) {
  ZoneList<Expression*>* arguments = expr->arguments();

  DCHECK(arguments->length()== 4);
  CHECK_ALIVE(VisitForValue(arguments->at(0)));
  HValue* obj = Pop();

  CHECK_ALIVE(VisitForValue(arguments->at(1)));
  HValue* buffer = Pop();

  CHECK_ALIVE(VisitForValue(arguments->at(2)));
  HValue* byte_offset = Pop();

  CHECK_ALIVE(VisitForValue(arguments->at(3)));
  HValue* byte_length = Pop();

  {
    NoObservableSideEffectsScope scope(this);
    BuildArrayBufferViewInitialization<JSDataView>(
        obj, buffer, byte_offset, byte_length);
  }
}


HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
    ExternalArrayType array_type,
    bool is_zero_byte_offset,
    HValue* buffer, HValue* byte_offset, HValue* length) {
  Handle<Map> external_array_map(
      isolate()->heap()->MapForFixedTypedArray(array_type));

  // The HForceRepresentation is to prevent possible deopt on int-smi
  // conversion after allocation but before the new object fields are set.
  length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
  HValue* elements = Add<HAllocate>(
      Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
      NOT_TENURED, external_array_map->instance_type());

  AddStoreMapConstant(elements, external_array_map);
  Add<HStoreNamedField>(elements,
      HObjectAccess::ForFixedArrayLength(), length);

  HValue* backing_store = Add<HLoadNamedField>(
      buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());

  HValue* typed_array_start;
  if (is_zero_byte_offset) {
    typed_array_start = backing_store;
  } else {
    HInstruction* external_pointer =
        AddUncasted<HAdd>(backing_store, byte_offset);
    // Arguments are checked prior to call to TypedArrayInitialize,
    // including byte_offset.
    external_pointer->ClearFlag(HValue::kCanOverflow);
    typed_array_start = external_pointer;
  }

  Add<HStoreNamedField>(elements,
                        HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
                        graph()->GetConstant0());
  Add<HStoreNamedField>(elements,
                        HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
                        typed_array_start);

  return elements;
}


HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
    ExternalArrayType array_type, size_t element_size,
    ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length,
    bool initialize) {
  STATIC_ASSERT(
      (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
  HValue* total_size;

  // if fixed array's elements are not aligned to object's alignment,
  // we need to align the whole array to object alignment.
  if (element_size % kObjectAlignment != 0) {
    total_size = BuildObjectSizeAlignment(
        byte_length, FixedTypedArrayBase::kHeaderSize);
  } else {
    total_size = AddUncasted<HAdd>(byte_length,
        Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
    total_size->ClearFlag(HValue::kCanOverflow);
  }

  // The HForceRepresentation is to prevent possible deopt on int-smi
  // conversion after allocation but before the new object fields are set.
  length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
  Handle<Map> fixed_typed_array_map(
      isolate()->heap()->MapForFixedTypedArray(array_type));
  HAllocate* elements =
      Add<HAllocate>(total_size, HType::HeapObject(), NOT_TENURED,
                     fixed_typed_array_map->instance_type());

#ifndef V8_HOST_ARCH_64_BIT
  if (array_type == kExternalFloat64Array) {
    elements->MakeDoubleAligned();
  }
#endif

  AddStoreMapConstant(elements, fixed_typed_array_map);

  Add<HStoreNamedField>(elements,
      HObjectAccess::ForFixedArrayLength(),
      length);
  Add<HStoreNamedField>(
      elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);

  Add<HStoreNamedField>(
      elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
      Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));

  HValue* filler = Add<HConstant>(static_cast<int32_t>(0));

  if (initialize) {
    LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);

    HValue* backing_store = AddUncasted<HAdd>(
        Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
        elements, Strength::WEAK, AddOfExternalAndTagged);

    HValue* key = builder.BeginBody(
        Add<HConstant>(static_cast<int32_t>(0)),
        length, Token::LT);
    Add<HStoreKeyed>(backing_store, key, filler, elements, fixed_elements_kind);

    builder.EndBody();
  }
  return elements;
}


void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
    CallRuntime* expr) {
  ZoneList<Expression*>* arguments = expr->arguments();

  static const int kObjectArg = 0;
  static const int kArrayIdArg = 1;
  static const int kBufferArg = 2;
  static const int kByteOffsetArg = 3;
  static const int kByteLengthArg = 4;
  static const int kInitializeArg = 5;
  static const int kArgsLength = 6;
  DCHECK(arguments->length() == kArgsLength);


  CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
  HValue* obj = Pop();

  if (!arguments->at(kArrayIdArg)->IsLiteral()) {
    // This should never happen in real use, but can happen when fuzzing.
    // Just bail out.
    Bailout(kNeedSmiLiteral);
    return;
  }
  Handle<Object> value =
      static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
  if (!value->IsSmi()) {
    // This should never happen in real use, but can happen when fuzzing.
    // Just bail out.
    Bailout(kNeedSmiLiteral);
    return;
  }
  int array_id = Smi::cast(*value)->value();

  HValue* buffer;
  if (!arguments->at(kBufferArg)->IsNullLiteral()) {
    CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
    buffer = Pop();
  } else {
    buffer = NULL;
  }

  HValue* byte_offset;
  bool is_zero_byte_offset;

  if (arguments->at(kByteOffsetArg)->IsLiteral()
      && Smi::FromInt(0) ==
      *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
    byte_offset = Add<HConstant>(static_cast<int32_t>(0));
    is_zero_byte_offset = true;
  } else {
    CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
    byte_offset = Pop();
    is_zero_byte_offset = false;
    DCHECK(buffer != NULL);
  }

  CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
  HValue* byte_length = Pop();

  CHECK(arguments->at(kInitializeArg)->IsLiteral());
  bool initialize = static_cast<Literal*>(arguments->at(kInitializeArg))
                        ->value()
                        ->BooleanValue();

  NoObservableSideEffectsScope scope(this);
  IfBuilder byte_offset_smi(this);

  if (!is_zero_byte_offset) {
    byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
    byte_offset_smi.Then();
  }

  ExternalArrayType array_type =
      kExternalInt8Array;  // Bogus initialization.
  size_t element_size = 1;  // Bogus initialization.
  ElementsKind fixed_elements_kind =  // Bogus initialization.
      INT8_ELEMENTS;
  Runtime::ArrayIdToTypeAndSize(array_id,
      &array_type,
      &fixed_elements_kind,
      &element_size);


  { //  byte_offset is Smi.
    HValue* allocated_buffer = buffer;
    if (buffer == NULL) {
      allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
    }
    BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
                                                     byte_offset, byte_length);


    HInstruction* length = AddUncasted<HDiv>(byte_length,
        Add<HConstant>(static_cast<int32_t>(element_size)));

    Add<HStoreNamedField>(obj,
        HObjectAccess::ForJSTypedArrayLength(),
        length);

    HValue* elements;
    if (buffer != NULL) {
      elements = BuildAllocateExternalElements(
          array_type, is_zero_byte_offset, buffer, byte_offset, length);
    } else {
      DCHECK(is_zero_byte_offset);
      elements = BuildAllocateFixedTypedArray(array_type, element_size,
                                              fixed_elements_kind, byte_length,
                                              length, initialize);
    }
    Add<HStoreNamedField>(
        obj, HObjectAccess::ForElementsPointer(), elements);
  }

  if (!is_zero_byte_offset) {
    byte_offset_smi.Else();
    { //  byte_offset is not Smi.
      Push(obj);
      CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
      Push(buffer);
      Push(byte_offset);
      Push(byte_length);
      CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
      PushArgumentsFromEnvironment(kArgsLength);
      Add<HCallRuntime>(expr->function(), kArgsLength);
    }
  }
  byte_offset_smi.End();
}


void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
  DCHECK(expr->arguments()->length() == 0);
  HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
  return ast_context()->ReturnInstruction(max_smi, expr->id());
}


void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
    CallRuntime* expr) {
  DCHECK(expr->arguments()->length() == 0);
  HConstant* result = New<HConstant>(static_cast<int32_t>(
        FLAG_typed_array_max_size_in_heap));
  return ast_context()->ReturnInstruction(result, expr->id());
}


void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
    CallRuntime* expr) {
  DCHECK(expr->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
  HValue* buffer = Pop();
  HInstruction* result = New<HLoadNamedField>(
      buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
  return ast_context()->ReturnInstruction(result, expr->id());
}


void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
    CallRuntime* expr) {
  NoObservableSideEffectsScope scope(this);
  DCHECK(expr->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
  HValue* view = Pop();

  return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
      view, nullptr,
      FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset)));
}


void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
    CallRuntime* expr) {
  NoObservableSideEffectsScope scope(this);
  DCHECK(expr->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
  HValue* view = Pop();

  return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
      view, nullptr,
      FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
}


void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
    CallRuntime* expr) {
  NoObservableSideEffectsScope scope(this);
  DCHECK(expr->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
  HValue* view = Pop();

  return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
      view, nullptr,
      FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset)));
}


void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  if (expr->is_jsruntime()) {
    return Bailout(kCallToAJavaScriptRuntimeFunction);
  }

  const Runtime::Function* function = expr->function();
  DCHECK(function != NULL);
  switch (function->function_id) {
#define CALL_INTRINSIC_GENERATOR(Name) \
  case Runtime::kInline##Name:         \
    return Generate##Name(expr);

    FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
#undef CALL_INTRINSIC_GENERATOR
    default: {
      int argument_count = expr->arguments()->length();
      CHECK_ALIVE(VisitExpressions(expr->arguments()));
      PushArgumentsFromEnvironment(argument_count);
      HCallRuntime* call = New<HCallRuntime>(function, argument_count);
      return ast_context()->ReturnInstruction(call, expr->id());
    }
  }
}


void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  switch (expr->op()) {
    case Token::DELETE: return VisitDelete(expr);
    case Token::VOID: return VisitVoid(expr);
    case Token::TYPEOF: return VisitTypeof(expr);
    case Token::NOT: return VisitNot(expr);
    default: UNREACHABLE();
  }
}


void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
  Property* prop = expr->expression()->AsProperty();
  VariableProxy* proxy = expr->expression()->AsVariableProxy();
  if (prop != NULL) {
    CHECK_ALIVE(VisitForValue(prop->obj()));
    CHECK_ALIVE(VisitForValue(prop->key()));
    HValue* key = Pop();
    HValue* obj = Pop();
    Add<HPushArguments>(obj, key);
    HInstruction* instr = New<HCallRuntime>(
        Runtime::FunctionForId(is_strict(function_language_mode())
                                   ? Runtime::kDeleteProperty_Strict
                                   : Runtime::kDeleteProperty_Sloppy),
        2);
    return ast_context()->ReturnInstruction(instr, expr->id());
  } else if (proxy != NULL) {
    Variable* var = proxy->var();
    if (var->IsUnallocatedOrGlobalSlot()) {
      Bailout(kDeleteWithGlobalVariable);
    } else if (var->IsStackAllocated() || var->IsContextSlot()) {
      // Result of deleting non-global variables is false.  'this' is not really
      // a variable, though we implement it as one.  The subexpression does not
      // have side effects.
      HValue* value = var->HasThisName(isolate()) ? graph()->GetConstantTrue()
                                                  : graph()->GetConstantFalse();
      return ast_context()->ReturnValue(value);
    } else {
      Bailout(kDeleteWithNonGlobalVariable);
    }
  } else {
    // Result of deleting non-property, non-variable reference is true.
    // Evaluate the subexpression for side effects.
    CHECK_ALIVE(VisitForEffect(expr->expression()));
    return ast_context()->ReturnValue(graph()->GetConstantTrue());
  }
}


void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
  CHECK_ALIVE(VisitForEffect(expr->expression()));
  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}


void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
  CHECK_ALIVE(VisitForTypeOf(expr->expression()));
  HValue* value = Pop();
  HInstruction* instr = New<HTypeof>(value);
  return ast_context()->ReturnInstruction(instr, expr->id());
}


void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
  if (ast_context()->IsTest()) {
    TestContext* context = TestContext::cast(ast_context());
    VisitForControl(expr->expression(),
                    context->if_false(),
                    context->if_true());
    return;
  }

  if (ast_context()->IsEffect()) {
    VisitForEffect(expr->expression());
    return;
  }

  DCHECK(ast_context()->IsValue());
  HBasicBlock* materialize_false = graph()->CreateBasicBlock();
  HBasicBlock* materialize_true = graph()->CreateBasicBlock();
  CHECK_BAILOUT(VisitForControl(expr->expression(),
                                materialize_false,
                                materialize_true));

  if (materialize_false->HasPredecessor()) {
    materialize_false->SetJoinId(expr->MaterializeFalseId());
    set_current_block(materialize_false);
    Push(graph()->GetConstantFalse());
  } else {
    materialize_false = NULL;
  }

  if (materialize_true->HasPredecessor()) {
    materialize_true->SetJoinId(expr->MaterializeTrueId());
    set_current_block(materialize_true);
    Push(graph()->GetConstantTrue());
  } else {
    materialize_true = NULL;
  }

  HBasicBlock* join =
    CreateJoin(materialize_false, materialize_true, expr->id());
  set_current_block(join);
  if (join != NULL) return ast_context()->ReturnValue(Pop());
}


static Representation RepresentationFor(Type* type) {
  DisallowHeapAllocation no_allocation;
  if (type->Is(Type::None())) return Representation::None();
  if (type->Is(Type::SignedSmall())) return Representation::Smi();
  if (type->Is(Type::Signed32())) return Representation::Integer32();
  if (type->Is(Type::Number())) return Representation::Double();
  return Representation::Tagged();
}


HInstruction* HOptimizedGraphBuilder::BuildIncrement(
    bool returns_original_input,
    CountOperation* expr) {
  // The input to the count operation is on top of the expression stack.
  Representation rep = RepresentationFor(expr->type());
  if (rep.IsNone() || rep.IsTagged()) {
    rep = Representation::Smi();
  }

  if (returns_original_input && !is_strong(function_language_mode())) {
    // We need an explicit HValue representing ToNumber(input).  The
    // actual HChange instruction we need is (sometimes) added in a later
    // phase, so it is not available now to be used as an input to HAdd and
    // as the return value.
    HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
    if (!rep.IsDouble()) {
      number_input->SetFlag(HInstruction::kFlexibleRepresentation);
      number_input->SetFlag(HInstruction::kCannotBeTagged);
    }
    Push(number_input);
  }

  // The addition has no side effects, so we do not need
  // to simulate the expression stack after this instruction.
  // Any later failures deopt to the load of the input or earlier.
  HConstant* delta = (expr->op() == Token::INC)
      ? graph()->GetConstant1()
      : graph()->GetConstantMinus1();
  HInstruction* instr =
      AddUncasted<HAdd>(Top(), delta, strength(function_language_mode()));
  if (instr->IsAdd()) {
    HAdd* add = HAdd::cast(instr);
    add->set_observed_input_representation(1, rep);
    add->set_observed_input_representation(2, Representation::Smi());
  }
  if (!is_strong(function_language_mode())) {
    instr->ClearAllSideEffects();
  } else {
    Add<HSimulate>(expr->ToNumberId(), REMOVABLE_SIMULATE);
  }
  instr->SetFlag(HInstruction::kCannotBeTagged);
  return instr;
}


void HOptimizedGraphBuilder::BuildStoreForEffect(
    Expression* expr, Property* prop, FeedbackVectorSlot slot, BailoutId ast_id,
    BailoutId return_id, HValue* object, HValue* key, HValue* value) {
  EffectContext for_effect(this);
  Push(object);
  if (key != NULL) Push(key);
  Push(value);
  BuildStore(expr, prop, slot, ast_id, return_id);
}


void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
  Expression* target = expr->expression();
  VariableProxy* proxy = target->AsVariableProxy();
  Property* prop = target->AsProperty();
  if (proxy == NULL && prop == NULL) {
    return Bailout(kInvalidLhsInCountOperation);
  }

  // Match the full code generator stack by simulating an extra stack
  // element for postfix operations in a non-effect context.  The return
  // value is ToNumber(input).
  bool returns_original_input =
      expr->is_postfix() && !ast_context()->IsEffect();
  HValue* input = NULL;  // ToNumber(original_input).
  HValue* after = NULL;  // The result after incrementing or decrementing.

  if (proxy != NULL) {
    Variable* var = proxy->var();
    if (var->mode() == CONST_LEGACY)  {
      return Bailout(kUnsupportedCountOperationWithConst);
    }
    if (var->mode() == CONST) {
      return Bailout(kNonInitializerAssignmentToConst);
    }
    // Argument of the count operation is a variable, not a property.
    DCHECK(prop == NULL);
    CHECK_ALIVE(VisitForValue(target));

    after = BuildIncrement(returns_original_input, expr);
    input = returns_original_input ? Top() : Pop();
    Push(after);

    switch (var->location()) {
      case VariableLocation::GLOBAL:
      case VariableLocation::UNALLOCATED:
        HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
                                       expr->AssignmentId());
        break;

      case VariableLocation::PARAMETER:
      case VariableLocation::LOCAL:
        BindIfLive(var, after);
        break;

      case VariableLocation::CONTEXT: {
        // Bail out if we try to mutate a parameter value in a function
        // using the arguments object.  We do not (yet) correctly handle the
        // arguments property of the function.
        if (current_info()->scope()->arguments() != NULL) {
          // Parameters will rewrite to context slots.  We have no direct
          // way to detect that the variable is a parameter so we use a
          // linear search of the parameter list.
          int count = current_info()->scope()->num_parameters();
          for (int i = 0; i < count; ++i) {
            if (var == current_info()->scope()->parameter(i)) {
              return Bailout(kAssignmentToParameterInArgumentsObject);
            }
          }
        }

        HValue* context = BuildContextChainWalk(var);
        HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
            ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
        HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
                                                          mode, after);
        if (instr->HasObservableSideEffects()) {
          Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
        }
        break;
      }

      case VariableLocation::LOOKUP:
        return Bailout(kLookupVariableInCountOperation);
    }

    Drop(returns_original_input ? 2 : 1);
    return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
  }

  // Argument of the count operation is a property.
  DCHECK(prop != NULL);
  if (returns_original_input) Push(graph()->GetConstantUndefined());

  CHECK_ALIVE(VisitForValue(prop->obj()));
  HValue* object = Top();

  HValue* key = NULL;
  if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
    CHECK_ALIVE(VisitForValue(prop->key()));
    key = Top();
  }

  CHECK_ALIVE(PushLoad(prop, object, key));

  after = BuildIncrement(returns_original_input, expr);

  if (returns_original_input) {
    input = Pop();
    // Drop object and key to push it again in the effect context below.
    Drop(key == NULL ? 1 : 2);
    environment()->SetExpressionStackAt(0, input);
    CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
                                    expr->AssignmentId(), object, key, after));
    return ast_context()->ReturnValue(Pop());
  }

  environment()->SetExpressionStackAt(0, after);
  return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
                    expr->AssignmentId());
}


HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
    HValue* string,
    HValue* index) {
  if (string->IsConstant() && index->IsConstant()) {
    HConstant* c_string = HConstant::cast(string);
    HConstant* c_index = HConstant::cast(index);
    if (c_string->HasStringValue() && c_index->HasNumberValue()) {
      int32_t i = c_index->NumberValueAsInteger32();
      Handle<String> s = c_string->StringValue();
      if (i < 0 || i >= s->length()) {
        return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
      }
      return New<HConstant>(s->Get(i));
    }
  }
  string = BuildCheckString(string);
  index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
  return New<HStringCharCodeAt>(string, index);
}


// Checks if the given shift amounts have following forms:
// (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
                                             HValue* const32_minus_sa) {
  if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
    const HConstant* c1 = HConstant::cast(sa);
    const HConstant* c2 = HConstant::cast(const32_minus_sa);
    return c1->HasInteger32Value() && c2->HasInteger32Value() &&
        (c1->Integer32Value() + c2->Integer32Value() == 32);
  }
  if (!const32_minus_sa->IsSub()) return false;
  HSub* sub = HSub::cast(const32_minus_sa);
  return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
}


// Checks if the left and the right are shift instructions with the oposite
// directions that can be replaced by one rotate right instruction or not.
// Returns the operand and the shift amount for the rotate instruction in the
// former case.
bool HGraphBuilder::MatchRotateRight(HValue* left,
                                     HValue* right,
                                     HValue** operand,
                                     HValue** shift_amount) {
  HShl* shl;
  HShr* shr;
  if (left->IsShl() && right->IsShr()) {
    shl = HShl::cast(left);
    shr = HShr::cast(right);
  } else if (left->IsShr() && right->IsShl()) {
    shl = HShl::cast(right);
    shr = HShr::cast(left);
  } else {
    return false;
  }
  if (shl->left() != shr->left()) return false;

  if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
      !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
    return false;
  }
  *operand = shr->left();
  *shift_amount = shr->right();
  return true;
}


bool CanBeZero(HValue* right) {
  if (right->IsConstant()) {
    HConstant* right_const = HConstant::cast(right);
    if (right_const->HasInteger32Value() &&
       (right_const->Integer32Value() & 0x1f) != 0) {
      return false;
    }
  }
  return true;
}


HValue* HGraphBuilder::EnforceNumberType(HValue* number,
                                         Type* expected) {
  if (expected->Is(Type::SignedSmall())) {
    return AddUncasted<HForceRepresentation>(number, Representation::Smi());
  }
  if (expected->Is(Type::Signed32())) {
    return AddUncasted<HForceRepresentation>(number,
                                             Representation::Integer32());
  }
  return number;
}


HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
  if (value->IsConstant()) {
    HConstant* constant = HConstant::cast(value);
    Maybe<HConstant*> number =
        constant->CopyToTruncatedNumber(isolate(), zone());
    if (number.IsJust()) {
      *expected = Type::Number();
      return AddInstruction(number.FromJust());
    }
  }

  // We put temporary values on the stack, which don't correspond to anything
  // in baseline code. Since nothing is observable we avoid recording those
  // pushes with a NoObservableSideEffectsScope.
  NoObservableSideEffectsScope no_effects(this);

  Type* expected_type = *expected;

  // Separate the number type from the rest.
  Type* expected_obj =
      Type::Intersect(expected_type, Type::NonNumber(), zone());
  Type* expected_number =
      Type::Intersect(expected_type, Type::Number(), zone());

  // We expect to get a number.
  // (We need to check first, since Type::None->Is(Type::Any()) == true.
  if (expected_obj->Is(Type::None())) {
    DCHECK(!expected_number->Is(Type::None()));
    return value;
  }

  if (expected_obj->Is(Type::Undefined())) {
    // This is already done by HChange.
    *expected = Type::Union(expected_number, Type::Number(), zone());
    return value;
  }

  return value;
}


HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
    BinaryOperation* expr,
    HValue* left,
    HValue* right,
    PushBeforeSimulateBehavior push_sim_result) {
  Type* left_type = expr->left()->bounds().lower;
  Type* right_type = expr->right()->bounds().lower;
  Type* result_type = expr->bounds().lower;
  Maybe<int> fixed_right_arg = expr->fixed_right_arg();
  Handle<AllocationSite> allocation_site = expr->allocation_site();

  HAllocationMode allocation_mode;
  if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
    allocation_mode = HAllocationMode(allocation_site);
  }
  HValue* result = HGraphBuilder::BuildBinaryOperation(
      expr->op(), left, right, left_type, right_type, result_type,
      fixed_right_arg, allocation_mode, strength(function_language_mode()),
      expr->id());
  // Add a simulate after instructions with observable side effects, and
  // after phis, which are the result of BuildBinaryOperation when we
  // inlined some complex subgraph.
  if (result->HasObservableSideEffects() || result->IsPhi()) {
    if (push_sim_result == PUSH_BEFORE_SIMULATE) {
      Push(result);
      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
      Drop(1);
    } else {
      Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
    }
  }
  return result;
}


HValue* HGraphBuilder::BuildBinaryOperation(
    Token::Value op, HValue* left, HValue* right, Type* left_type,
    Type* right_type, Type* result_type, Maybe<int> fixed_right_arg,
    HAllocationMode allocation_mode, Strength strength, BailoutId opt_id) {
  bool maybe_string_add = false;
  if (op == Token::ADD) {
    // If we are adding constant string with something for which we don't have
    // a feedback yet, assume that it's also going to be a string and don't
    // generate deopt instructions.
    if (!left_type->IsInhabited() && right->IsConstant() &&
        HConstant::cast(right)->HasStringValue()) {
      left_type = Type::String();
    }

    if (!right_type->IsInhabited() && left->IsConstant() &&
        HConstant::cast(left)->HasStringValue()) {
      right_type = Type::String();
    }

    maybe_string_add = (left_type->Maybe(Type::String()) ||
                        left_type->Maybe(Type::Receiver()) ||
                        right_type->Maybe(Type::String()) ||
                        right_type->Maybe(Type::Receiver()));
  }

  Representation left_rep = RepresentationFor(left_type);
  Representation right_rep = RepresentationFor(right_type);

  if (!left_type->IsInhabited()) {
    Add<HDeoptimize>(
        Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
        Deoptimizer::SOFT);
    left_type = Type::Any();
    left_rep = RepresentationFor(left_type);
    maybe_string_add = op == Token::ADD;
  }

  if (!right_type->IsInhabited()) {
    Add<HDeoptimize>(
        Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
        Deoptimizer::SOFT);
    right_type = Type::Any();
    right_rep = RepresentationFor(right_type);
    maybe_string_add = op == Token::ADD;
  }

  if (!maybe_string_add && !is_strong(strength)) {
    left = TruncateToNumber(left, &left_type);
    right = TruncateToNumber(right, &right_type);
  }

  // Special case for string addition here.
  if (op == Token::ADD &&
      (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
    if (is_strong(strength)) {
      // In strong mode, if the one side of an addition is a string,
      // the other side must be a string too.
      left = BuildCheckString(left);
      right = BuildCheckString(right);
    } else {
      // Validate type feedback for left argument.
      if (left_type->Is(Type::String())) {
        left = BuildCheckString(left);
      }

      // Validate type feedback for right argument.
      if (right_type->Is(Type::String())) {
        right = BuildCheckString(right);
      }

      // Convert left argument as necessary.
      if (left_type->Is(Type::Number())) {
        DCHECK(right_type->Is(Type::String()));
        left = BuildNumberToString(left, left_type);
      } else if (!left_type->Is(Type::String())) {
        DCHECK(right_type->Is(Type::String()));
        return AddUncasted<HStringAdd>(
            left, right, allocation_mode.GetPretenureMode(),
            STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
      }

      // Convert right argument as necessary.
      if (right_type->Is(Type::Number())) {
        DCHECK(left_type->Is(Type::String()));
        right = BuildNumberToString(right, right_type);
      } else if (!right_type->Is(Type::String())) {
        DCHECK(left_type->Is(Type::String()));
        return AddUncasted<HStringAdd>(
            left, right, allocation_mode.GetPretenureMode(),
            STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
      }
    }

    // Fast paths for empty constant strings.
    Handle<String> left_string =
        left->IsConstant() && HConstant::cast(left)->HasStringValue()
            ? HConstant::cast(left)->StringValue()
            : Handle<String>();
    Handle<String> right_string =
        right->IsConstant() && HConstant::cast(right)->HasStringValue()
            ? HConstant::cast(right)->StringValue()
            : Handle<String>();
    if (!left_string.is_null() && left_string->length() == 0) return right;
    if (!right_string.is_null() && right_string->length() == 0) return left;
    if (!left_string.is_null() && !right_string.is_null()) {
      return AddUncasted<HStringAdd>(
          left, right, allocation_mode.GetPretenureMode(),
          STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
    }

    // Register the dependent code with the allocation site.
    if (!allocation_mode.feedback_site().is_null()) {
      DCHECK(!graph()->info()->IsStub());
      Handle<AllocationSite> site(allocation_mode.feedback_site());
      top_info()->dependencies()->AssumeTenuringDecision(site);
    }

    // Inline the string addition into the stub when creating allocation
    // mementos to gather allocation site feedback, or if we can statically
    // infer that we're going to create a cons string.
    if ((graph()->info()->IsStub() &&
         allocation_mode.CreateAllocationMementos()) ||
        (left->IsConstant() &&
         HConstant::cast(left)->HasStringValue() &&
         HConstant::cast(left)->StringValue()->length() + 1 >=
           ConsString::kMinLength) ||
        (right->IsConstant() &&
         HConstant::cast(right)->HasStringValue() &&
         HConstant::cast(right)->StringValue()->length() + 1 >=
           ConsString::kMinLength)) {
      return BuildStringAdd(left, right, allocation_mode);
    }

    // Fallback to using the string add stub.
    return AddUncasted<HStringAdd>(
        left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE,
        allocation_mode.feedback_site());
  }

  if (graph()->info()->IsStub()) {
    left = EnforceNumberType(left, left_type);
    right = EnforceNumberType(right, right_type);
  }

  Representation result_rep = RepresentationFor(result_type);

  bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
                          (right_rep.IsTagged() && !right_rep.IsSmi());

  HInstruction* instr = NULL;
  // Only the stub is allowed to call into the runtime, since otherwise we would
  // inline several instructions (including the two pushes) for every tagged
  // operation in optimized code, which is more expensive, than a stub call.
  if (graph()->info()->IsStub() && is_non_primitive) {
    Runtime::FunctionId function_id;
    switch (op) {
      default:
        UNREACHABLE();
      case Token::ADD:
        function_id =
            is_strong(strength) ? Runtime::kAdd_Strong : Runtime::kAdd;
        break;
      case Token::SUB:
        function_id = is_strong(strength) ? Runtime::kSubtract_Strong
                                          : Runtime::kSubtract;
        break;
      case Token::MUL:
        function_id = is_strong(strength) ? Runtime::kMultiply_Strong
                                          : Runtime::kMultiply;
        break;
      case Token::DIV:
        function_id =
            is_strong(strength) ? Runtime::kDivide_Strong : Runtime::kDivide;
        break;
      case Token::MOD:
        function_id =
            is_strong(strength) ? Runtime::kModulus_Strong : Runtime::kModulus;
        break;
      case Token::BIT_OR:
        function_id = is_strong(strength) ? Runtime::kBitwiseOr_Strong
                                          : Runtime::kBitwiseOr;
        break;
      case Token::BIT_AND:
        function_id = is_strong(strength) ? Runtime::kBitwiseAnd_Strong
                                          : Runtime::kBitwiseAnd;
        break;
      case Token::BIT_XOR:
        function_id = is_strong(strength) ? Runtime::kBitwiseXor_Strong
                                          : Runtime::kBitwiseXor;
        break;
      case Token::SAR:
        function_id = is_strong(strength) ? Runtime::kShiftRight_Strong
                                          : Runtime::kShiftRight;
        break;
      case Token::SHR:
        function_id = is_strong(strength) ? Runtime::kShiftRightLogical_Strong
                                          : Runtime::kShiftRightLogical;
        break;
      case Token::SHL:
        function_id = is_strong(strength) ? Runtime::kShiftLeft_Strong
                                          : Runtime::kShiftLeft;
        break;
    }
    Add<HPushArguments>(left, right);
    instr = AddUncasted<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
  } else {
    if (is_strong(strength) && Token::IsBitOp(op)) {
      // TODO(conradw): This is not efficient, but is necessary to prevent
      // conversion of oddball values to numbers in strong mode. It would be
      // better to prevent the conversion rather than adding a runtime check.
      IfBuilder if_builder(this);
      if_builder.If<HHasInstanceTypeAndBranch>(left, ODDBALL_TYPE);
      if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE);
      if_builder.Then();
      Add<HCallRuntime>(
          Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
          0);
      if (!graph()->info()->IsStub()) {
        Add<HSimulate>(opt_id, REMOVABLE_SIMULATE);
      }
      if_builder.End();
    }
    switch (op) {
      case Token::ADD:
        instr = AddUncasted<HAdd>(left, right, strength);
        break;
      case Token::SUB:
        instr = AddUncasted<HSub>(left, right, strength);
        break;
      case Token::MUL:
        instr = AddUncasted<HMul>(left, right, strength);
        break;
      case Token::MOD: {
        if (fixed_right_arg.IsJust() &&
            !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
          HConstant* fixed_right =
              Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
          IfBuilder if_same(this);
          if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
          if_same.Then();
          if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation);
          right = fixed_right;
        }
        instr = AddUncasted<HMod>(left, right, strength);
        break;
      }
      case Token::DIV:
        instr = AddUncasted<HDiv>(left, right, strength);
        break;
      case Token::BIT_XOR:
      case Token::BIT_AND:
        instr = AddUncasted<HBitwise>(op, left, right, strength);
        break;
      case Token::BIT_OR: {
        HValue *operand, *shift_amount;
        if (left_type->Is(Type::Signed32()) &&
            right_type->Is(Type::Signed32()) &&
            MatchRotateRight(left, right, &operand, &shift_amount)) {
          instr = AddUncasted<HRor>(operand, shift_amount, strength);
        } else {
          instr = AddUncasted<HBitwise>(op, left, right, strength);
        }
        break;
      }
      case Token::SAR:
        instr = AddUncasted<HSar>(left, right, strength);
        break;
      case Token::SHR:
        instr = AddUncasted<HShr>(left, right, strength);
        if (instr->IsShr() && CanBeZero(right)) {
          graph()->RecordUint32Instruction(instr);
        }
        break;
      case Token::SHL:
        instr = AddUncasted<HShl>(left, right, strength);
        break;
      default:
        UNREACHABLE();
    }
  }

  if (instr->IsBinaryOperation()) {
    HBinaryOperation* binop = HBinaryOperation::cast(instr);
    binop->set_observed_input_representation(1, left_rep);
    binop->set_observed_input_representation(2, right_rep);
    binop->initialize_output_representation(result_rep);
    if (graph()->info()->IsStub()) {
      // Stub should not call into stub.
      instr->SetFlag(HValue::kCannotBeTagged);
      // And should truncate on HForceRepresentation already.
      if (left->IsForceRepresentation()) {
        left->CopyFlag(HValue::kTruncatingToSmi, instr);
        left->CopyFlag(HValue::kTruncatingToInt32, instr);
      }
      if (right->IsForceRepresentation()) {
        right->CopyFlag(HValue::kTruncatingToSmi, instr);
        right->CopyFlag(HValue::kTruncatingToInt32, instr);
      }
    }
  }
  return instr;
}


// Check for the form (%_ClassOf(foo) === 'BarClass').
static bool IsClassOfTest(CompareOperation* expr) {
  if (expr->op() != Token::EQ_STRICT) return false;
  CallRuntime* call = expr->left()->AsCallRuntime();
  if (call == NULL) return false;
  Literal* literal = expr->right()->AsLiteral();
  if (literal == NULL) return false;
  if (!literal->value()->IsString()) return false;
  if (!call->is_jsruntime() &&
      call->function()->function_id != Runtime::kInlineClassOf) {
    return false;
  }
  DCHECK(call->arguments()->length() == 1);
  return true;
}


void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  switch (expr->op()) {
    case Token::COMMA:
      return VisitComma(expr);
    case Token::OR:
    case Token::AND:
      return VisitLogicalExpression(expr);
    default:
      return VisitArithmeticExpression(expr);
  }
}


void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
  CHECK_ALIVE(VisitForEffect(expr->left()));
  // Visit the right subexpression in the same AST context as the entire
  // expression.
  Visit(expr->right());
}


void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
  bool is_logical_and = expr->op() == Token::AND;
  if (ast_context()->IsTest()) {
    TestContext* context = TestContext::cast(ast_context());
    // Translate left subexpression.
    HBasicBlock* eval_right = graph()->CreateBasicBlock();
    if (is_logical_and) {
      CHECK_BAILOUT(VisitForControl(expr->left(),
                                    eval_right,
                                    context->if_false()));
    } else {
      CHECK_BAILOUT(VisitForControl(expr->left(),
                                    context->if_true(),
                                    eval_right));
    }

    // Translate right subexpression by visiting it in the same AST
    // context as the entire expression.
    if (eval_right->HasPredecessor()) {
      eval_right->SetJoinId(expr->RightId());
      set_current_block(eval_right);
      Visit(expr->right());
    }

  } else if (ast_context()->IsValue()) {
    CHECK_ALIVE(VisitForValue(expr->left()));
    DCHECK(current_block() != NULL);
    HValue* left_value = Top();

    // Short-circuit left values that always evaluate to the same boolean value.
    if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
      // l (evals true)  && r -> r
      // l (evals true)  || r -> l
      // l (evals false) && r -> l
      // l (evals false) || r -> r
      if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
        Drop(1);
        CHECK_ALIVE(VisitForValue(expr->right()));
      }
      return ast_context()->ReturnValue(Pop());
    }

    // We need an extra block to maintain edge-split form.
    HBasicBlock* empty_block = graph()->CreateBasicBlock();
    HBasicBlock* eval_right = graph()->CreateBasicBlock();
    ToBooleanStub::Types expected(expr->left()->to_boolean_types());
    HBranch* test = is_logical_and
        ? New<HBranch>(left_value, expected, eval_right, empty_block)
        : New<HBranch>(left_value, expected, empty_block, eval_right);
    FinishCurrentBlock(test);

    set_current_block(eval_right);
    Drop(1);  // Value of the left subexpression.
    CHECK_BAILOUT(VisitForValue(expr->right()));

    HBasicBlock* join_block =
      CreateJoin(empty_block, current_block(), expr->id());
    set_current_block(join_block);
    return ast_context()->ReturnValue(Pop());

  } else {
    DCHECK(ast_context()->IsEffect());
    // In an effect context, we don't need the value of the left subexpression,
    // only its control flow and side effects.  We need an extra block to
    // maintain edge-split form.
    HBasicBlock* empty_block = graph()->CreateBasicBlock();
    HBasicBlock* right_block = graph()->CreateBasicBlock();
    if (is_logical_and) {
      CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
    } else {
      CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
    }

    // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
    // actually two empty blocks (one here and one inserted by
    // TestContext::BuildBranch, and that they both have an HSimulate though the
    // second one is not a merge node, and that we really have no good AST ID to
    // put on that first HSimulate.

    if (empty_block->HasPredecessor()) {
      empty_block->SetJoinId(expr->id());
    } else {
      empty_block = NULL;
    }

    if (right_block->HasPredecessor()) {
      right_block->SetJoinId(expr->RightId());
      set_current_block(right_block);
      CHECK_BAILOUT(VisitForEffect(expr->right()));
      right_block = current_block();
    } else {
      right_block = NULL;
    }

    HBasicBlock* join_block =
      CreateJoin(empty_block, right_block, expr->id());
    set_current_block(join_block);
    // We did not materialize any value in the predecessor environments,
    // so there is no need to handle it here.
  }
}


void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
  CHECK_ALIVE(VisitForValue(expr->left()));
  CHECK_ALIVE(VisitForValue(expr->right()));
  SetSourcePosition(expr->position());
  HValue* right = Pop();
  HValue* left = Pop();
  HValue* result =
      BuildBinaryOperation(expr, left, right,
          ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
                                    : PUSH_BEFORE_SIMULATE);
  if (top_info()->is_tracking_positions() && result->IsBinaryOperation()) {
    HBinaryOperation::cast(result)->SetOperandPositions(
        zone(),
        ScriptPositionToSourcePosition(expr->left()->position()),
        ScriptPositionToSourcePosition(expr->right()->position()));
  }
  return ast_context()->ReturnValue(result);
}


void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
                                                        Expression* sub_expr,
                                                        Handle<String> check) {
  CHECK_ALIVE(VisitForTypeOf(sub_expr));
  SetSourcePosition(expr->position());
  HValue* value = Pop();
  HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
  return ast_context()->ReturnControl(instr, expr->id());
}


static bool IsLiteralCompareBool(Isolate* isolate,
                                 HValue* left,
                                 Token::Value op,
                                 HValue* right) {
  return op == Token::EQ_STRICT &&
      ((left->IsConstant() &&
          HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
       (right->IsConstant() &&
           HConstant::cast(right)->handle(isolate)->IsBoolean()));
}


void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());

  if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());

  // Check for a few fast cases. The AST visiting behavior must be in sync
  // with the full codegen: We don't push both left and right values onto
  // the expression stack when one side is a special-case literal.
  Expression* sub_expr = NULL;
  Handle<String> check;
  if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
    return HandleLiteralCompareTypeof(expr, sub_expr, check);
  }
  if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
    return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
  }
  if (expr->IsLiteralCompareNull(&sub_expr)) {
    return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
  }

  if (IsClassOfTest(expr)) {
    CallRuntime* call = expr->left()->AsCallRuntime();
    DCHECK(call->arguments()->length() == 1);
    CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
    HValue* value = Pop();
    Literal* literal = expr->right()->AsLiteral();
    Handle<String> rhs = Handle<String>::cast(literal->value());
    HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
    return ast_context()->ReturnControl(instr, expr->id());
  }

  Type* left_type = expr->left()->bounds().lower;
  Type* right_type = expr->right()->bounds().lower;
  Type* combined_type = expr->combined_type();

  CHECK_ALIVE(VisitForValue(expr->left()));
  CHECK_ALIVE(VisitForValue(expr->right()));

  HValue* right = Pop();
  HValue* left = Pop();
  Token::Value op = expr->op();

  if (IsLiteralCompareBool(isolate(), left, op, right)) {
    HCompareObjectEqAndBranch* result =
        New<HCompareObjectEqAndBranch>(left, right);
    return ast_context()->ReturnControl(result, expr->id());
  }

  if (op == Token::INSTANCEOF) {
    // Check to see if the rhs of the instanceof is a known function.
    if (right->IsConstant() &&
        HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
      Handle<JSFunction> constructor =
          Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
      if (constructor->IsConstructor() &&
          !constructor->map()->has_non_instance_prototype()) {
        JSFunction::EnsureHasInitialMap(constructor);
        DCHECK(constructor->has_initial_map());
        Handle<Map> initial_map(constructor->initial_map(), isolate());
        top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
        HInstruction* prototype =
            Add<HConstant>(handle(initial_map->prototype(), isolate()));
        HHasInPrototypeChainAndBranch* result =
            New<HHasInPrototypeChainAndBranch>(left, prototype);
        return ast_context()->ReturnControl(result, expr->id());
      }
    }

    HInstanceOf* result = New<HInstanceOf>(left, right);
    return ast_context()->ReturnInstruction(result, expr->id());

  } else if (op == Token::IN) {
    Add<HPushArguments>(left, right);
    HInstruction* result =
        New<HCallRuntime>(Runtime::FunctionForId(Runtime::kHasProperty), 2);
    return ast_context()->ReturnInstruction(result, expr->id());
  }

  PushBeforeSimulateBehavior push_behavior =
    ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
                              : PUSH_BEFORE_SIMULATE;
  HControlInstruction* compare = BuildCompareInstruction(
      op, left, right, left_type, right_type, combined_type,
      ScriptPositionToSourcePosition(expr->left()->position()),
      ScriptPositionToSourcePosition(expr->right()->position()),
      push_behavior, expr->id());
  if (compare == NULL) return;  // Bailed out.
  return ast_context()->ReturnControl(compare, expr->id());
}


HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
    Token::Value op, HValue* left, HValue* right, Type* left_type,
    Type* right_type, Type* combined_type, SourcePosition left_position,
    SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
    BailoutId bailout_id) {
  // Cases handled below depend on collected type feedback. They should
  // soft deoptimize when there is no type feedback.
  if (!combined_type->IsInhabited()) {
    Add<HDeoptimize>(
        Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
        Deoptimizer::SOFT);
    combined_type = left_type = right_type = Type::Any();
  }

  Representation left_rep = RepresentationFor(left_type);
  Representation right_rep = RepresentationFor(right_type);
  Representation combined_rep = RepresentationFor(combined_type);

  if (combined_type->Is(Type::Receiver())) {
    if (Token::IsEqualityOp(op)) {
      // HCompareObjectEqAndBranch can only deal with object, so
      // exclude numbers.
      if ((left->IsConstant() &&
           HConstant::cast(left)->HasNumberValue()) ||
          (right->IsConstant() &&
           HConstant::cast(right)->HasNumberValue())) {
        Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
                         Deoptimizer::SOFT);
        // The caller expects a branch instruction, so make it happy.
        return New<HBranch>(graph()->GetConstantTrue());
      }
      // Can we get away with map check and not instance type check?
      HValue* operand_to_check =
          left->block()->block_id() < right->block()->block_id() ? left : right;
      if (combined_type->IsClass()) {
        Handle<Map> map = combined_type->AsClass()->Map();
        AddCheckMap(operand_to_check, map);
        HCompareObjectEqAndBranch* result =
            New<HCompareObjectEqAndBranch>(left, right);
        if (top_info()->is_tracking_positions()) {
          result->set_operand_position(zone(), 0, left_position);
          result->set_operand_position(zone(), 1, right_position);
        }
        return result;
      } else {
        BuildCheckHeapObject(operand_to_check);
        Add<HCheckInstanceType>(operand_to_check,
                                HCheckInstanceType::IS_JS_RECEIVER);
        HCompareObjectEqAndBranch* result =
            New<HCompareObjectEqAndBranch>(left, right);
        return result;
      }
    } else {
      if (combined_type->IsClass()) {
        // TODO(bmeurer): This is an optimized version of an x < y, x > y,
        // x <= y or x >= y, where both x and y are spec objects with the
        // same map. The CompareIC collects this map for us. So if we know
        // that there's no @@toPrimitive on the map (including the prototype
        // chain), and both valueOf and toString are the default initial
        // implementations (on the %ObjectPrototype%), then we can reduce
        // the comparison to map checks on x and y, because the comparison
        // will turn into a comparison of "[object CLASS]" to itself (the
        // default outcome of toString, since valueOf returns a spec object).
        // This is pretty much adhoc, so in TurboFan we could do a lot better
        // and inline the interesting parts of ToPrimitive (actually we could
        // even do that in Crankshaft but we don't want to waste too much
        // time on this now).
        DCHECK(Token::IsOrderedRelationalCompareOp(op));
        Handle<Map> map = combined_type->AsClass()->Map();
        PropertyAccessInfo value_of(this, LOAD, map,
                                    isolate()->factory()->valueOf_string());
        PropertyAccessInfo to_primitive(
            this, LOAD, map, isolate()->factory()->to_primitive_symbol());
        PropertyAccessInfo to_string(this, LOAD, map,
                                     isolate()->factory()->toString_string());
        PropertyAccessInfo to_string_tag(
            this, LOAD, map, isolate()->factory()->to_string_tag_symbol());
        if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() &&
            to_string_tag.CanAccessMonomorphic() &&
            (!to_string_tag.IsFound() || to_string_tag.IsData() ||
             to_string_tag.IsDataConstant()) &&
            value_of.CanAccessMonomorphic() && value_of.IsDataConstant() &&
            value_of.constant().is_identical_to(isolate()->object_value_of()) &&
            to_string.CanAccessMonomorphic() && to_string.IsDataConstant() &&
            to_string.constant().is_identical_to(
                isolate()->object_to_string())) {
          // We depend on the prototype chain to stay the same, because we
          // also need to deoptimize when someone installs @@toPrimitive
          // or @@toStringTag somewhere in the prototype chain.
          BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
                                  Handle<JSObject>::null());
          AddCheckMap(left, map);
          AddCheckMap(right, map);
          // The caller expects a branch instruction, so make it happy.
          return New<HBranch>(
              graph()->GetConstantBool(op == Token::LTE || op == Token::GTE));
        }
      }
      Bailout(kUnsupportedNonPrimitiveCompare);
      return NULL;
    }
  } else if (combined_type->Is(Type::InternalizedString()) &&
             Token::IsEqualityOp(op)) {
    // If we have a constant argument, it should be consistent with the type
    // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
    if ((left->IsConstant() &&
         !HConstant::cast(left)->HasInternalizedStringValue()) ||
        (right->IsConstant() &&
         !HConstant::cast(right)->HasInternalizedStringValue())) {
      Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
                       Deoptimizer::SOFT);
      // The caller expects a branch instruction, so make it happy.
      return New<HBranch>(graph()->GetConstantTrue());
    }
    BuildCheckHeapObject(left);
    Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
    BuildCheckHeapObject(right);
    Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
    HCompareObjectEqAndBranch* result =
        New<HCompareObjectEqAndBranch>(left, right);
    return result;
  } else if (combined_type->Is(Type::String())) {
    BuildCheckHeapObject(left);
    Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
    BuildCheckHeapObject(right);
    Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
    HStringCompareAndBranch* result =
        New<HStringCompareAndBranch>(left, right, op);
    return result;
  } else if (combined_type->Is(Type::Boolean())) {
    AddCheckMap(left, isolate()->factory()->boolean_map());
    AddCheckMap(right, isolate()->factory()->boolean_map());
    if (Token::IsEqualityOp(op)) {
      HCompareObjectEqAndBranch* result =
          New<HCompareObjectEqAndBranch>(left, right);
      return result;
    }
    left = Add<HLoadNamedField>(
        left, nullptr,
        HObjectAccess::ForOddballToNumber(Representation::Smi()));
    right = Add<HLoadNamedField>(
        right, nullptr,
        HObjectAccess::ForOddballToNumber(Representation::Smi()));
    HCompareNumericAndBranch* result =
        New<HCompareNumericAndBranch>(left, right, op);
    return result;
  } else {
    if (combined_rep.IsTagged() || combined_rep.IsNone()) {
      HCompareGeneric* result = Add<HCompareGeneric>(
          left, right, op, strength(function_language_mode()));
      result->set_observed_input_representation(1, left_rep);
      result->set_observed_input_representation(2, right_rep);
      if (result->HasObservableSideEffects()) {
        if (push_sim_result == PUSH_BEFORE_SIMULATE) {
          Push(result);
          AddSimulate(bailout_id, REMOVABLE_SIMULATE);
          Drop(1);
        } else {
          AddSimulate(bailout_id, REMOVABLE_SIMULATE);
        }
      }
      // TODO(jkummerow): Can we make this more efficient?
      HBranch* branch = New<HBranch>(result);
      return branch;
    } else {
      HCompareNumericAndBranch* result = New<HCompareNumericAndBranch>(
          left, right, op, strength(function_language_mode()));
      result->set_observed_input_representation(left_rep, right_rep);
      if (top_info()->is_tracking_positions()) {
        result->SetOperandPositions(zone(), left_position, right_position);
      }
      return result;
    }
  }
}


void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
                                                     Expression* sub_expr,
                                                     NilValue nil) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
  if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
  CHECK_ALIVE(VisitForValue(sub_expr));
  HValue* value = Pop();
  if (expr->op() == Token::EQ_STRICT) {
    HConstant* nil_constant = nil == kNullValue
        ? graph()->GetConstantNull()
        : graph()->GetConstantUndefined();
    HCompareObjectEqAndBranch* instr =
        New<HCompareObjectEqAndBranch>(value, nil_constant);
    return ast_context()->ReturnControl(instr, expr->id());
  } else {
    DCHECK_EQ(Token::EQ, expr->op());
    Type* type = expr->combined_type()->Is(Type::None())
                     ? Type::Any()
                     : expr->combined_type();
    HIfContinuation continuation;
    BuildCompareNil(value, type, &continuation);
    return ast_context()->ReturnContinuation(&continuation, expr->id());
  }
}


void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }


void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
  UNREACHABLE();
}


HValue* HOptimizedGraphBuilder::AddThisFunction() {
  return AddInstruction(BuildThisFunction());
}


HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
  // If we share optimized code between different closures, the
  // this-function is not a constant, except inside an inlined body.
  if (function_state()->outer() != NULL) {
      return New<HConstant>(
          function_state()->compilation_info()->closure());
  } else {
      return New<HThisFunction>();
  }
}


HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
    Handle<JSObject> boilerplate_object,
    AllocationSiteUsageContext* site_context) {
  NoObservableSideEffectsScope no_effects(this);
  Handle<Map> initial_map(boilerplate_object->map());
  InstanceType instance_type = initial_map->instance_type();
  DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);

  HType type = instance_type == JS_ARRAY_TYPE
      ? HType::JSArray() : HType::JSObject();
  HValue* object_size_constant = Add<HConstant>(initial_map->instance_size());

  PretenureFlag pretenure_flag = NOT_TENURED;
  Handle<AllocationSite> top_site(*site_context->top(), isolate());
  if (FLAG_allocation_site_pretenuring) {
    pretenure_flag = top_site->GetPretenureMode();
  }

  Handle<AllocationSite> current_site(*site_context->current(), isolate());
  if (*top_site == *current_site) {
    // We install a dependency for pretenuring only on the outermost literal.
    top_info()->dependencies()->AssumeTenuringDecision(top_site);
  }
  top_info()->dependencies()->AssumeTransitionStable(current_site);

  HInstruction* object = Add<HAllocate>(
      object_size_constant, type, pretenure_flag, instance_type, top_site);

  // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
  // elements array may not get folded into the object. Hence, we set the
  // elements pointer to empty fixed array and let store elimination remove
  // this store in the folding case.
  HConstant* empty_fixed_array = Add<HConstant>(
      isolate()->factory()->empty_fixed_array());
  Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
      empty_fixed_array);

  BuildEmitObjectHeader(boilerplate_object, object);

  // Similarly to the elements pointer, there is no guarantee that all
  // property allocations can get folded, so pre-initialize all in-object
  // properties to a safe value.
  BuildInitializeInobjectProperties(object, initial_map);

  Handle<FixedArrayBase> elements(boilerplate_object->elements());
  int elements_size = (elements->length() > 0 &&
      elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
          elements->Size() : 0;

  if (pretenure_flag == TENURED &&
      elements->map() == isolate()->heap()->fixed_cow_array_map() &&
      isolate()->heap()->InNewSpace(*elements)) {
    // If we would like to pretenure a fixed cow array, we must ensure that the
    // array is already in old space, otherwise we'll create too many old-to-
    // new-space pointers (overflowing the store buffer).
    elements = Handle<FixedArrayBase>(
        isolate()->factory()->CopyAndTenureFixedCOWArray(
            Handle<FixedArray>::cast(elements)));
    boilerplate_object->set_elements(*elements);
  }

  HInstruction* object_elements = NULL;
  if (elements_size > 0) {
    HValue* object_elements_size = Add<HConstant>(elements_size);
    InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
        ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
    object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
                                     pretenure_flag, instance_type, top_site);
    BuildEmitElements(boilerplate_object, elements, object_elements,
                      site_context);
    Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
                          object_elements);
  } else {
    Handle<Object> elements_field =
        Handle<Object>(boilerplate_object->elements(), isolate());
    HInstruction* object_elements_cow = Add<HConstant>(elements_field);
    Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
                          object_elements_cow);
  }

  // Copy in-object properties.
  if (initial_map->NumberOfFields() != 0 ||
      initial_map->unused_property_fields() > 0) {
    BuildEmitInObjectProperties(boilerplate_object, object, site_context,
                                pretenure_flag);
  }
  return object;
}


void HOptimizedGraphBuilder::BuildEmitObjectHeader(
    Handle<JSObject> boilerplate_object,
    HInstruction* object) {
  DCHECK(boilerplate_object->properties()->length() == 0);

  Handle<Map> boilerplate_object_map(boilerplate_object->map());
  AddStoreMapConstant(object, boilerplate_object_map);

  Handle<Object> properties_field =
      Handle<Object>(boilerplate_object->properties(), isolate());
  DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
  HInstruction* properties = Add<HConstant>(properties_field);
  HObjectAccess access = HObjectAccess::ForPropertiesPointer();
  Add<HStoreNamedField>(object, access, properties);

  if (boilerplate_object->IsJSArray()) {
    Handle<JSArray> boilerplate_array =
        Handle<JSArray>::cast(boilerplate_object);
    Handle<Object> length_field =
        Handle<Object>(boilerplate_array->length(), isolate());
    HInstruction* length = Add<HConstant>(length_field);

    DCHECK(boilerplate_array->length()->IsSmi());
    Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
        boilerplate_array->GetElementsKind()), length);
  }
}


void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
    Handle<JSObject> boilerplate_object,
    HInstruction* object,
    AllocationSiteUsageContext* site_context,
    PretenureFlag pretenure_flag) {
  Handle<Map> boilerplate_map(boilerplate_object->map());
  Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
  int limit = boilerplate_map->NumberOfOwnDescriptors();

  int copied_fields = 0;
  for (int i = 0; i < limit; i++) {
    PropertyDetails details = descriptors->GetDetails(i);
    if (details.type() != DATA) continue;
    copied_fields++;
    FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);


    int property_offset = field_index.offset();
    Handle<Name> name(descriptors->GetKey(i));

    // The access for the store depends on the type of the boilerplate.
    HObjectAccess access = boilerplate_object->IsJSArray() ?
        HObjectAccess::ForJSArrayOffset(property_offset) :
        HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);

    if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
      CHECK(!boilerplate_object->IsJSArray());
      double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
      access = access.WithRepresentation(Representation::Double());
      Add<HStoreNamedField>(object, access, Add<HConstant>(value));
      continue;
    }
    Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
                         isolate());

    if (value->IsJSObject()) {
      Handle<JSObject> value_object = Handle<JSObject>::cast(value);
      Handle<AllocationSite> current_site = site_context->EnterNewScope();
      HInstruction* result =
          BuildFastLiteral(value_object, site_context);
      site_context->ExitScope(current_site, value_object);
      Add<HStoreNamedField>(object, access, result);
    } else {
      Representation representation = details.representation();
      HInstruction* value_instruction;

      if (representation.IsDouble()) {
        // Allocate a HeapNumber box and store the value into it.
        HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
        HInstruction* double_box =
            Add<HAllocate>(heap_number_constant, HType::HeapObject(),
                pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
        AddStoreMapConstant(double_box,
            isolate()->factory()->mutable_heap_number_map());
        // Unwrap the mutable heap number from the boilerplate.
        HValue* double_value =
            Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
        Add<HStoreNamedField>(
            double_box, HObjectAccess::ForHeapNumberValue(), double_value);
        value_instruction = double_box;
      } else if (representation.IsSmi()) {
        value_instruction = value->IsUninitialized()
            ? graph()->GetConstant0()
            : Add<HConstant>(value);
        // Ensure that value is stored as smi.
        access = access.WithRepresentation(representation);
      } else {
        value_instruction = Add<HConstant>(value);
      }

      Add<HStoreNamedField>(object, access, value_instruction);
    }
  }

  int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
  HInstruction* value_instruction =
      Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
  for (int i = copied_fields; i < inobject_properties; i++) {
    DCHECK(boilerplate_object->IsJSObject());
    int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
    HObjectAccess access =
        HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
    Add<HStoreNamedField>(object, access, value_instruction);
  }
}


void HOptimizedGraphBuilder::BuildEmitElements(
    Handle<JSObject> boilerplate_object,
    Handle<FixedArrayBase> elements,
    HValue* object_elements,
    AllocationSiteUsageContext* site_context) {
  ElementsKind kind = boilerplate_object->map()->elements_kind();
  int elements_length = elements->length();
  HValue* object_elements_length = Add<HConstant>(elements_length);
  BuildInitializeElementsHeader(object_elements, kind, object_elements_length);

  // Copy elements backing store content.
  if (elements->IsFixedDoubleArray()) {
    BuildEmitFixedDoubleArray(elements, kind, object_elements);
  } else if (elements->IsFixedArray()) {
    BuildEmitFixedArray(elements, kind, object_elements,
                        site_context);
  } else {
    UNREACHABLE();
  }
}


void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
    Handle<FixedArrayBase> elements,
    ElementsKind kind,
    HValue* object_elements) {
  HInstruction* boilerplate_elements = Add<HConstant>(elements);
  int elements_length = elements->length();
  for (int i = 0; i < elements_length; i++) {
    HValue* key_constant = Add<HConstant>(i);
    HInstruction* value_instruction =
        Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
                        kind, ALLOW_RETURN_HOLE);
    HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
                                           value_instruction, nullptr, kind);
    store->SetFlag(HValue::kAllowUndefinedAsNaN);
  }
}


void HOptimizedGraphBuilder::BuildEmitFixedArray(
    Handle<FixedArrayBase> elements,
    ElementsKind kind,
    HValue* object_elements,
    AllocationSiteUsageContext* site_context) {
  HInstruction* boilerplate_elements = Add<HConstant>(elements);
  int elements_length = elements->length();
  Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
  for (int i = 0; i < elements_length; i++) {
    Handle<Object> value(fast_elements->get(i), isolate());
    HValue* key_constant = Add<HConstant>(i);
    if (value->IsJSObject()) {
      Handle<JSObject> value_object = Handle<JSObject>::cast(value);
      Handle<AllocationSite> current_site = site_context->EnterNewScope();
      HInstruction* result =
          BuildFastLiteral(value_object, site_context);
      site_context->ExitScope(current_site, value_object);
      Add<HStoreKeyed>(object_elements, key_constant, result, nullptr, kind);
    } else {
      ElementsKind copy_kind =
          kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
      HInstruction* value_instruction =
          Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
                          copy_kind, ALLOW_RETURN_HOLE);
      Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
                       nullptr, copy_kind);
    }
  }
}


void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  HInstruction* instr = BuildThisFunction();
  return ast_context()->ReturnInstruction(instr, expr->id());
}


void HOptimizedGraphBuilder::VisitSuperPropertyReference(
    SuperPropertyReference* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kSuperReference);
}


void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
  DCHECK(!HasStackOverflow());
  DCHECK(current_block() != NULL);
  DCHECK(current_block()->HasPredecessor());
  return Bailout(kSuperReference);
}


void HOptimizedGraphBuilder::VisitDeclarations(
    ZoneList<Declaration*>* declarations) {
  DCHECK(globals_.is_empty());
  AstVisitor::VisitDeclarations(declarations);
  if (!globals_.is_empty()) {
    Handle<FixedArray> array =
       isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
    for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
    int flags =
        DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
        DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
        DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
    Add<HDeclareGlobals>(array, flags);
    globals_.Rewind(0);
  }
}


void HOptimizedGraphBuilder::VisitVariableDeclaration(
    VariableDeclaration* declaration) {
  VariableProxy* proxy = declaration->proxy();
  VariableMode mode = declaration->mode();
  Variable* variable = proxy->var();
  bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
  switch (variable->location()) {
    case VariableLocation::GLOBAL:
    case VariableLocation::UNALLOCATED:
      globals_.Add(variable->name(), zone());
      globals_.Add(variable->binding_needs_init()
                       ? isolate()->factory()->the_hole_value()
                       : isolate()->factory()->undefined_value(), zone());
      return;
    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL:
      if (hole_init) {
        HValue* value = graph()->GetConstantHole();
        environment()->Bind(variable, value);
      }
      break;
    case VariableLocation::CONTEXT:
      if (hole_init) {
        HValue* value = graph()->GetConstantHole();
        HValue* context = environment()->context();
        HStoreContextSlot* store = Add<HStoreContextSlot>(
            context, variable->index(), HStoreContextSlot::kNoCheck, value);
        if (store->HasObservableSideEffects()) {
          Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
        }
      }
      break;
    case VariableLocation::LOOKUP:
      return Bailout(kUnsupportedLookupSlotInDeclaration);
  }
}


void HOptimizedGraphBuilder::VisitFunctionDeclaration(
    FunctionDeclaration* declaration) {
  VariableProxy* proxy = declaration->proxy();
  Variable* variable = proxy->var();
  switch (variable->location()) {
    case VariableLocation::GLOBAL:
    case VariableLocation::UNALLOCATED: {
      globals_.Add(variable->name(), zone());
      Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
          declaration->fun(), current_info()->script(), top_info());
      // Check for stack-overflow exception.
      if (function.is_null()) return SetStackOverflow();
      globals_.Add(function, zone());
      return;
    }
    case VariableLocation::PARAMETER:
    case VariableLocation::LOCAL: {
      CHECK_ALIVE(VisitForValue(declaration->fun()));
      HValue* value = Pop();
      BindIfLive(variable, value);
      break;
    }
    case VariableLocation::CONTEXT: {
      CHECK_ALIVE(VisitForValue(declaration->fun()));
      HValue* value = Pop();
      HValue* context = environment()->context();
      HStoreContextSlot* store = Add<HStoreContextSlot>(
          context, variable->index(), HStoreContextSlot::kNoCheck, value);
      if (store->HasObservableSideEffects()) {
        Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
      }
      break;
    }
    case VariableLocation::LOOKUP:
      return Bailout(kUnsupportedLookupSlotInDeclaration);
  }
}


void HOptimizedGraphBuilder::VisitImportDeclaration(
    ImportDeclaration* declaration) {
  UNREACHABLE();
}


void HOptimizedGraphBuilder::VisitExportDeclaration(
    ExportDeclaration* declaration) {
  UNREACHABLE();
}


void HOptimizedGraphBuilder::VisitRewritableAssignmentExpression(
    RewritableAssignmentExpression* node) {
  CHECK_ALIVE(Visit(node->expression()));
}


// Generators for inline runtime functions.
// Support for types.
void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
  return ast_context()->ReturnControl(result, call->id());
}


void HOptimizedGraphBuilder::GenerateIsJSReceiver(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HHasInstanceTypeAndBranch* result =
      New<HHasInstanceTypeAndBranch>(value,
                                     FIRST_JS_RECEIVER_TYPE,
                                     LAST_JS_RECEIVER_TYPE);
  return ast_context()->ReturnControl(result, call->id());
}


void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HHasCachedArrayIndexAndBranch* result =
      New<HHasCachedArrayIndexAndBranch>(value);
  return ast_context()->ReturnControl(result, call->id());
}


void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HHasInstanceTypeAndBranch* result =
      New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
  return ast_context()->ReturnControl(result, call->id());
}


void HOptimizedGraphBuilder::GenerateIsTypedArray(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HHasInstanceTypeAndBranch* result =
      New<HHasInstanceTypeAndBranch>(value, JS_TYPED_ARRAY_TYPE);
  return ast_context()->ReturnControl(result, call->id());
}


void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HHasInstanceTypeAndBranch* result =
      New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
  return ast_context()->ReturnControl(result, call->id());
}


void HOptimizedGraphBuilder::GenerateToInteger(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* input = Pop();
  if (input->type().IsSmi()) {
    return ast_context()->ReturnValue(input);
  } else {
    IfBuilder if_inputissmi(this);
    if_inputissmi.If<HIsSmiAndBranch>(input);
    if_inputissmi.Then();
    {
      // Return the input value.
      Push(input);
      Add<HSimulate>(call->id(), FIXED_SIMULATE);
    }
    if_inputissmi.Else();
    {
      Add<HPushArguments>(input);
      Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToInteger), 1));
      Add<HSimulate>(call->id(), FIXED_SIMULATE);
    }
    if_inputissmi.End();
    return ast_context()->ReturnValue(Pop());
  }
}


void HOptimizedGraphBuilder::GenerateToName(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* input = Pop();
  if (input->type().IsSmi()) {
    HValue* result = BuildNumberToString(input, Type::SignedSmall());
    return ast_context()->ReturnValue(result);
  } else if (input->type().IsTaggedNumber()) {
    HValue* result = BuildNumberToString(input, Type::Number());
    return ast_context()->ReturnValue(result);
  } else if (input->type().IsString()) {
    return ast_context()->ReturnValue(input);
  } else {
    Callable callable = CodeFactory::ToName(isolate());
    HValue* stub = Add<HConstant>(callable.code());
    HValue* values[] = {context(), input};
    HInstruction* result =
        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
                                 Vector<HValue*>(values, arraysize(values)));
    return ast_context()->ReturnInstruction(result, call->id());
  }
}


void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HValue* result = BuildToObject(value);
  return ast_context()->ReturnValue(result);
}


void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* input = Pop();
  if (input->type().IsString()) {
    return ast_context()->ReturnValue(input);
  } else {
    Callable callable = CodeFactory::ToString(isolate());
    HValue* stub = Add<HConstant>(callable.code());
    HValue* values[] = {context(), input};
    HInstruction* result =
        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
                                 Vector<HValue*>(values, arraysize(values)));
    return ast_context()->ReturnInstruction(result, call->id());
  }
}


void HOptimizedGraphBuilder::GenerateToLength(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  Callable callable = CodeFactory::ToLength(isolate());
  HValue* input = Pop();
  HValue* stub = Add<HConstant>(callable.code());
  HValue* values[] = {context(), input};
  HInstruction* result =
      New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
                               Vector<HValue*>(values, arraysize(values)));
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateToNumber(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  Callable callable = CodeFactory::ToNumber(isolate());
  HValue* input = Pop();
  if (input->type().IsTaggedNumber()) {
    return ast_context()->ReturnValue(input);
  } else {
    HValue* stub = Add<HConstant>(callable.code());
    HValue* values[] = {context(), input};
    HInstruction* result =
        New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
                                 Vector<HValue*>(values, arraysize(values)));
    return ast_context()->ReturnInstruction(result, call->id());
  }
}


void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HIfContinuation continuation;
  IfBuilder if_proxy(this);

  HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
  if_proxy.And();
  HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
  HValue* instance_type =
      Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
  if_proxy.If<HCompareNumericAndBranch>(
      instance_type, Add<HConstant>(JS_PROXY_TYPE), Token::EQ);

  if_proxy.CaptureContinuation(&continuation);
  return ast_context()->ReturnContinuation(&continuation, call->id());
}


void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* object = Pop();
  HIfContinuation continuation(graph()->CreateBasicBlock(),
                               graph()->CreateBasicBlock());
  IfBuilder if_not_smi(this);
  if_not_smi.IfNot<HIsSmiAndBranch>(object);
  if_not_smi.Then();
  {
    NoObservableSideEffectsScope no_effects(this);

    IfBuilder if_fast_packed(this);
    HValue* elements_kind = BuildGetElementsKind(object);
    if_fast_packed.If<HCompareNumericAndBranch>(
        elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
    if_fast_packed.Or();
    if_fast_packed.If<HCompareNumericAndBranch>(
        elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
    if_fast_packed.Or();
    if_fast_packed.If<HCompareNumericAndBranch>(
        elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
    if_fast_packed.JoinContinuation(&continuation);
  }
  if_not_smi.JoinContinuation(&continuation);
  return ast_context()->ReturnContinuation(&continuation, call->id());
}


// Support for arguments.length and arguments[?].
void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 0);
  HInstruction* result = NULL;
  if (function_state()->outer() == NULL) {
    HInstruction* elements = Add<HArgumentsElements>(false);
    result = New<HArgumentsLength>(elements);
  } else {
    // Number of arguments without receiver.
    int argument_count = environment()->
        arguments_environment()->parameter_count() - 1;
    result = New<HConstant>(argument_count);
  }
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* index = Pop();
  HInstruction* result = NULL;
  if (function_state()->outer() == NULL) {
    HInstruction* elements = Add<HArgumentsElements>(false);
    HInstruction* length = Add<HArgumentsLength>(elements);
    HInstruction* checked_index = Add<HBoundsCheck>(index, length);
    result = New<HAccessArgumentsAt>(elements, length, checked_index);
  } else {
    EnsureArgumentsArePushedForAccess();

    // Number of arguments without receiver.
    HInstruction* elements = function_state()->arguments_elements();
    int argument_count = environment()->
        arguments_environment()->parameter_count() - 1;
    HInstruction* length = Add<HConstant>(argument_count);
    HInstruction* checked_key = Add<HBoundsCheck>(index, length);
    result = New<HAccessArgumentsAt>(elements, length, checked_key);
  }
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* object = Pop();

  IfBuilder if_objectisvalue(this);
  HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
      object, JS_VALUE_TYPE);
  if_objectisvalue.Then();
  {
    // Return the actual value.
    Push(Add<HLoadNamedField>(
            object, objectisvalue,
            HObjectAccess::ForObservableJSObjectOffset(
                JSValue::kValueOffset)));
    Add<HSimulate>(call->id(), FIXED_SIMULATE);
  }
  if_objectisvalue.Else();
  {
    // If the object is not a value return the object.
    Push(object);
    Add<HSimulate>(call->id(), FIXED_SIMULATE);
  }
  if_objectisvalue.End();
  return ast_context()->ReturnValue(Pop());
}


void HOptimizedGraphBuilder::GenerateJSValueGetValue(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HInstruction* result = Add<HLoadNamedField>(
      value, nullptr,
      HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset));
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateIsDate(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HHasInstanceTypeAndBranch* result =
      New<HHasInstanceTypeAndBranch>(value, JS_DATE_TYPE);
  return ast_context()->ReturnControl(result, call->id());
}


void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
    CallRuntime* call) {
  DCHECK(call->arguments()->length() == 3);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
  HValue* string = Pop();
  HValue* value = Pop();
  HValue* index = Pop();
  Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
                         index, value);
  Add<HSimulate>(call->id(), FIXED_SIMULATE);
  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}


void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
    CallRuntime* call) {
  DCHECK(call->arguments()->length() == 3);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
  HValue* string = Pop();
  HValue* value = Pop();
  HValue* index = Pop();
  Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
                         index, value);
  Add<HSimulate>(call->id(), FIXED_SIMULATE);
  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}


void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 2);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* value = Pop();
  HValue* object = Pop();

  // Check if object is a JSValue.
  IfBuilder if_objectisvalue(this);
  if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
  if_objectisvalue.Then();
  {
    // Create in-object property store to kValueOffset.
    Add<HStoreNamedField>(object,
        HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
        value);
    if (!ast_context()->IsEffect()) {
      Push(value);
    }
    Add<HSimulate>(call->id(), FIXED_SIMULATE);
  }
  if_objectisvalue.Else();
  {
    // Nothing to do in this case.
    if (!ast_context()->IsEffect()) {
      Push(value);
    }
    Add<HSimulate>(call->id(), FIXED_SIMULATE);
  }
  if_objectisvalue.End();
  if (!ast_context()->IsEffect()) {
    Drop(1);
  }
  return ast_context()->ReturnValue(value);
}


// Fast support for charCodeAt(n).
void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 2);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* index = Pop();
  HValue* string = Pop();
  HInstruction* result = BuildStringCharCodeAt(string, index);
  return ast_context()->ReturnInstruction(result, call->id());
}


// Fast support for string.charAt(n) and string[n].
void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* char_code = Pop();
  HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
  return ast_context()->ReturnInstruction(result, call->id());
}


// Fast support for string.charAt(n) and string[n].
void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 2);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* index = Pop();
  HValue* string = Pop();
  HInstruction* char_code = BuildStringCharCodeAt(string, index);
  AddInstruction(char_code);
  HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
  return ast_context()->ReturnInstruction(result, call->id());
}


// Fast support for object equality testing.
void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 2);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* right = Pop();
  HValue* left = Pop();
  HCompareObjectEqAndBranch* result =
      New<HCompareObjectEqAndBranch>(left, right);
  return ast_context()->ReturnControl(result, call->id());
}


// Fast support for SubString.
void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
  DCHECK_EQ(3, call->arguments()->length());
  CHECK_ALIVE(VisitExpressions(call->arguments()));
  PushArgumentsFromEnvironment(call->arguments()->length());
  HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
  return ast_context()->ReturnInstruction(result, call->id());
}


// Support for direct calls from JavaScript to native RegExp code.
void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
  DCHECK_EQ(4, call->arguments()->length());
  CHECK_ALIVE(VisitExpressions(call->arguments()));
  PushArgumentsFromEnvironment(call->arguments()->length());
  HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateRegExpFlags(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitExpressions(call->arguments()));
  HValue* regexp = Pop();
  HInstruction* result =
      New<HLoadNamedField>(regexp, nullptr, HObjectAccess::ForJSRegExpFlags());
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateRegExpSource(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitExpressions(call->arguments()));
  HValue* regexp = Pop();
  HInstruction* result =
      New<HLoadNamedField>(regexp, nullptr, HObjectAccess::ForJSRegExpSource());
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
  DCHECK_EQ(2, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* lo = Pop();
  HValue* hi = Pop();
  HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
  return ast_context()->ReturnInstruction(result, call->id());
}


// Construct a RegExp exec result with two in-object properties.
void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
  DCHECK_EQ(3, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
  HValue* input = Pop();
  HValue* index = Pop();
  HValue* length = Pop();
  HValue* result = BuildRegExpConstructResult(length, index, input);
  return ast_context()->ReturnValue(result);
}


// Fast support for number to string.
void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
  DCHECK_EQ(1, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* number = Pop();
  HValue* result = BuildNumberToString(number, Type::Any());
  return ast_context()->ReturnValue(result);
}


// Fast support for calls.
void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
  DCHECK_LE(2, call->arguments()->length());
  CHECK_ALIVE(VisitExpressions(call->arguments()));
  CallTrampolineDescriptor descriptor(isolate());
  PushArgumentsFromEnvironment(call->arguments()->length() - 1);
  HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
  HValue* target = Pop();
  HValue* values[] = {context(), target,
                      Add<HConstant>(call->arguments()->length() - 2)};
  HInstruction* result = New<HCallWithDescriptor>(
      trampoline, call->arguments()->length() - 1, descriptor,
      Vector<HValue*>(values, arraysize(values)));
  return ast_context()->ReturnInstruction(result, call->id());
}


// Fast call to math functions.
void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
  DCHECK_EQ(2, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* right = Pop();
  HValue* left = Pop();
  HInstruction* result = NewUncasted<HPower>(left, right);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateMathClz32(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathClz32);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateMathFloor(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathFloor);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 2);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* index = Pop();
  HValue* object = Pop();
  HInstruction* result = New<HLoadKeyed>(
      object, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 3);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
  HValue* value = Pop();
  HValue* index = Pop();
  HValue* object = Pop();
  NoObservableSideEffectsScope no_effects(this);
  Add<HStoreKeyed>(object, index, value, nullptr, FAST_HOLEY_ELEMENTS);
  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}


void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 0);
  return ast_context()->ReturnValue(graph()->GetConstantHole());
}


void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
  DCHECK_EQ(2, call->arguments()->length());
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
  HValue* done = Pop();
  HValue* value = Pop();
  HValue* result = BuildCreateIterResultObject(value, done);
  return ast_context()->ReturnValue(result);
}


void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* receiver = Pop();
  HInstruction* result = New<HLoadNamedField>(
      receiver, nullptr, HObjectAccess::ForJSCollectionTable());
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* object = Pop();
  HInstruction* result = New<HLoadNamedField>(
      object, nullptr, HObjectAccess::ForStringHashField());
  return ast_context()->ReturnInstruction(result, call->id());
}


template <typename CollectionType>
HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
  static const int kCapacity = CollectionType::kMinCapacity;
  static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
  static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
                                       kBucketCount +
                                       (kCapacity * CollectionType::kEntrySize);
  static const int kSizeInBytes =
      FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);

  // Allocate the table and add the proper map.
  HValue* table =
      Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
                     NOT_TENURED, FIXED_ARRAY_TYPE);
  AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());

  // Initialize the FixedArray...
  HValue* length = Add<HConstant>(kFixedArrayLength);
  Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);

  // ...and the OrderedHashTable fields.
  Add<HStoreNamedField>(
      table,
      HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
      Add<HConstant>(kBucketCount));
  Add<HStoreNamedField>(
      table,
      HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
      graph()->GetConstant0());
  Add<HStoreNamedField>(
      table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
                 CollectionType>(),
      graph()->GetConstant0());

  // Fill the buckets with kNotFound.
  HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
  for (int i = 0; i < kBucketCount; ++i) {
    Add<HStoreNamedField>(
        table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
        not_found);
  }

  // Fill the data table with undefined.
  HValue* undefined = graph()->GetConstantUndefined();
  for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
    Add<HStoreNamedField>(table,
                          HObjectAccess::ForOrderedHashTableDataTableIndex<
                              CollectionType, kBucketCount>(i),
                          undefined);
  }

  return table;
}


void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* receiver = Pop();

  NoObservableSideEffectsScope no_effects(this);
  HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
  Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
  return ast_context()->ReturnValue(receiver);
}


void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* receiver = Pop();

  NoObservableSideEffectsScope no_effects(this);
  HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
  Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
  return ast_context()->ReturnValue(receiver);
}


template <typename CollectionType>
void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
  HValue* old_table = Add<HLoadNamedField>(
      receiver, nullptr, HObjectAccess::ForJSCollectionTable());
  HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
  Add<HStoreNamedField>(
      old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
      new_table);
  Add<HStoreNamedField>(
      old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
                     CollectionType>(),
      Add<HConstant>(CollectionType::kClearedTableSentinel));
  Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
                        new_table);
}


void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* receiver = Pop();

  NoObservableSideEffectsScope no_effects(this);
  BuildOrderedHashTableClear<OrderedHashSet>(receiver);
  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}


void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* receiver = Pop();

  NoObservableSideEffectsScope no_effects(this);
  BuildOrderedHashTableClear<OrderedHashMap>(receiver);
  return ast_context()->ReturnValue(graph()->GetConstantUndefined());
}


void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 1);
  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
  HValue* value = Pop();
  HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
  return ast_context()->ReturnInstruction(result, call->id());
}


void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
  // Simply returning undefined here would be semantically correct and even
  // avoid the bailout. Nevertheless, some ancient benchmarks like SunSpider's
  // string-fasta would tank, because fullcode contains an optimized version.
  // Obviously the fullcode => Crankshaft => bailout => fullcode dance is
  // faster... *sigh*
  return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
}


void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
    CallRuntime* call) {
  Add<HDebugBreak>();
  return ast_context()->ReturnValue(graph()->GetConstant0());
}


void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
  DCHECK(call->arguments()->length() == 0);
  HValue* ref =
      Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
  HValue* value =
      Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
  return ast_context()->ReturnValue(value);
}


#undef CHECK_BAILOUT
#undef CHECK_ALIVE


HEnvironment::HEnvironment(HEnvironment* outer,
                           Scope* scope,
                           Handle<JSFunction> closure,
                           Zone* zone)
    : closure_(closure),
      values_(0, zone),
      frame_type_(JS_FUNCTION),
      parameter_count_(0),
      specials_count_(1),
      local_count_(0),
      outer_(outer),
      entry_(NULL),
      pop_count_(0),
      push_count_(0),
      ast_id_(BailoutId::None()),
      zone_(zone) {
  Scope* declaration_scope = scope->DeclarationScope();
  Initialize(declaration_scope->num_parameters() + 1,
             declaration_scope->num_stack_slots(), 0);
}


HEnvironment::HEnvironment(Zone* zone, int parameter_count)
    : values_(0, zone),
      frame_type_(STUB),
      parameter_count_(parameter_count),
      specials_count_(1),
      local_count_(0),
      outer_(NULL),
      entry_(NULL),
      pop_count_(0),
      push_count_(0),
      ast_id_(BailoutId::None()),
      zone_(zone) {
  Initialize(parameter_count, 0, 0);
}


HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
    : values_(0, zone),
      frame_type_(JS_FUNCTION),
      parameter_count_(0),
      specials_count_(0),
      local_count_(0),
      outer_(NULL),
      entry_(NULL),
      pop_count_(0),
      push_count_(0),
      ast_id_(other->ast_id()),
      zone_(zone) {
  Initialize(other);
}


HEnvironment::HEnvironment(HEnvironment* outer,
                           Handle<JSFunction> closure,
                           FrameType frame_type,
                           int arguments,
                           Zone* zone)
    : closure_(closure),
      values_(arguments, zone),
      frame_type_(frame_type),
      parameter_count_(arguments),
      specials_count_(0),
      local_count_(0),
      outer_(outer),
      entry_(NULL),
      pop_count_(0),
      push_count_(0),
      ast_id_(BailoutId::None()),
      zone_(zone) {
}


void HEnvironment::Initialize(int parameter_count,
                              int local_count,
                              int stack_height) {
  parameter_count_ = parameter_count;
  local_count_ = local_count;

  // Avoid reallocating the temporaries' backing store on the first Push.
  int total = parameter_count + specials_count_ + local_count + stack_height;
  values_.Initialize(total + 4, zone());
  for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
}


void HEnvironment::Initialize(const HEnvironment* other) {
  closure_ = other->closure();
  values_.AddAll(other->values_, zone());
  assigned_variables_.Union(other->assigned_variables_, zone());
  frame_type_ = other->frame_type_;
  parameter_count_ = other->parameter_count_;
  local_count_ = other->local_count_;
  if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
  entry_ = other->entry_;
  pop_count_ = other->pop_count_;
  push_count_ = other->push_count_;
  specials_count_ = other->specials_count_;
  ast_id_ = other->ast_id_;
}


void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
  DCHECK(!block->IsLoopHeader());
  DCHECK(values_.length() == other->values_.length());

  int length = values_.length();
  for (int i = 0; i < length; ++i) {
    HValue* value = values_[i];
    if (value != NULL && value->IsPhi() && value->block() == block) {
      // There is already a phi for the i'th value.
      HPhi* phi = HPhi::cast(value);
      // Assert index is correct and that we haven't missed an incoming edge.
      DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
      DCHECK(phi->OperandCount() == block->predecessors()->length());
      phi->AddInput(other->values_[i]);
    } else if (values_[i] != other->values_[i]) {
      // There is a fresh value on the incoming edge, a phi is needed.
      DCHECK(values_[i] != NULL && other->values_[i] != NULL);
      HPhi* phi = block->AddNewPhi(i);
      HValue* old_value = values_[i];
      for (int j = 0; j < block->predecessors()->length(); j++) {
        phi->AddInput(old_value);
      }
      phi->AddInput(other->values_[i]);
      this->values_[i] = phi;
    }
  }
}


void HEnvironment::Bind(int index, HValue* value) {
  DCHECK(value != NULL);
  assigned_variables_.Add(index, zone());
  values_[index] = value;
}


bool HEnvironment::HasExpressionAt(int index) const {
  return index >= parameter_count_ + specials_count_ + local_count_;
}


bool HEnvironment::ExpressionStackIsEmpty() const {
  DCHECK(length() >= first_expression_index());
  return length() == first_expression_index();
}


void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
  int count = index_from_top + 1;
  int index = values_.length() - count;
  DCHECK(HasExpressionAt(index));
  // The push count must include at least the element in question or else
  // the new value will not be included in this environment's history.
  if (push_count_ < count) {
    // This is the same effect as popping then re-pushing 'count' elements.
    pop_count_ += (count - push_count_);
    push_count_ = count;
  }
  values_[index] = value;
}


HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
  int count = index_from_top + 1;
  int index = values_.length() - count;
  DCHECK(HasExpressionAt(index));
  // Simulate popping 'count' elements and then
  // pushing 'count - 1' elements back.
  pop_count_ += Max(count - push_count_, 0);
  push_count_ = Max(push_count_ - count, 0) + (count - 1);
  return values_.Remove(index);
}


void HEnvironment::Drop(int count) {
  for (int i = 0; i < count; ++i) {
    Pop();
  }
}


void HEnvironment::Print() const {
  OFStream os(stdout);
  os << *this << "\n";
}


HEnvironment* HEnvironment::Copy() const {
  return new(zone()) HEnvironment(this, zone());
}


HEnvironment* HEnvironment::CopyWithoutHistory() const {
  HEnvironment* result = Copy();
  result->ClearHistory();
  return result;
}


HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
  HEnvironment* new_env = Copy();
  for (int i = 0; i < values_.length(); ++i) {
    HPhi* phi = loop_header->AddNewPhi(i);
    phi->AddInput(values_[i]);
    new_env->values_[i] = phi;
  }
  new_env->ClearHistory();
  return new_env;
}


HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
                                                  Handle<JSFunction> target,
                                                  FrameType frame_type,
                                                  int arguments) const {
  HEnvironment* new_env =
      new(zone()) HEnvironment(outer, target, frame_type,
                               arguments + 1, zone());
  for (int i = 0; i <= arguments; ++i) {  // Include receiver.
    new_env->Push(ExpressionStackAt(arguments - i));
  }
  new_env->ClearHistory();
  return new_env;
}


HEnvironment* HEnvironment::CopyForInlining(
    Handle<JSFunction> target,
    int arguments,
    FunctionLiteral* function,
    HConstant* undefined,
    InliningKind inlining_kind) const {
  DCHECK(frame_type() == JS_FUNCTION);

  // Outer environment is a copy of this one without the arguments.
  int arity = function->scope()->num_parameters();

  HEnvironment* outer = Copy();
  outer->Drop(arguments + 1);  // Including receiver.
  outer->ClearHistory();

  if (inlining_kind == CONSTRUCT_CALL_RETURN) {
    // Create artificial constructor stub environment.  The receiver should
    // actually be the constructor function, but we pass the newly allocated
    // object instead, DoComputeConstructStubFrame() relies on that.
    outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
  } else if (inlining_kind == GETTER_CALL_RETURN) {
    // We need an additional StackFrame::INTERNAL frame for restoring the
    // correct context.
    outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
  } else if (inlining_kind == SETTER_CALL_RETURN) {
    // We need an additional StackFrame::INTERNAL frame for temporarily saving
    // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
    outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
  }

  if (arity != arguments) {
    // Create artificial arguments adaptation environment.
    outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
  }

  HEnvironment* inner =
      new(zone()) HEnvironment(outer, function->scope(), target, zone());
  // Get the argument values from the original environment.
  for (int i = 0; i <= arity; ++i) {  // Include receiver.
    HValue* push = (i <= arguments) ?
        ExpressionStackAt(arguments - i) : undefined;
    inner->SetValueAt(i, push);
  }
  inner->SetValueAt(arity + 1, context());
  for (int i = arity + 2; i < inner->length(); ++i) {
    inner->SetValueAt(i, undefined);
  }

  inner->set_ast_id(BailoutId::FunctionEntry());
  return inner;
}


std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
  for (int i = 0; i < env.length(); i++) {
    if (i == 0) os << "parameters\n";
    if (i == env.parameter_count()) os << "specials\n";
    if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
    if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
      os << "expressions\n";
    }
    HValue* val = env.values()->at(i);
    os << i << ": ";
    if (val != NULL) {
      os << val;
    } else {
      os << "NULL";
    }
    os << "\n";
  }
  return os << "\n";
}


void HTracer::TraceCompilation(CompilationInfo* info) {
  Tag tag(this, "compilation");
  base::SmartArrayPointer<char> name = info->GetDebugName();
  if (info->IsOptimizing()) {
    PrintStringProperty("name", name.get());
    PrintIndent();
    trace_.Add("method \"%s:%d\"\n", name.get(), info->optimization_id());
  } else {
    PrintStringProperty("name", name.get());
    PrintStringProperty("method", "stub");
  }
  PrintLongProperty("date",
                    static_cast<int64_t>(base::OS::TimeCurrentMillis()));
}


void HTracer::TraceLithium(const char* name, LChunk* chunk) {
  DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
  AllowHandleDereference allow_deref;
  AllowDeferredHandleDereference allow_deferred_deref;
  Trace(name, chunk->graph(), chunk);
}


void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
  DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
  AllowHandleDereference allow_deref;
  AllowDeferredHandleDereference allow_deferred_deref;
  Trace(name, graph, NULL);
}


void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
  Tag tag(this, "cfg");
  PrintStringProperty("name", name);
  const ZoneList<HBasicBlock*>* blocks = graph->blocks();
  for (int i = 0; i < blocks->length(); i++) {
    HBasicBlock* current = blocks->at(i);
    Tag block_tag(this, "block");
    PrintBlockProperty("name", current->block_id());
    PrintIntProperty("from_bci", -1);
    PrintIntProperty("to_bci", -1);

    if (!current->predecessors()->is_empty()) {
      PrintIndent();
      trace_.Add("predecessors");
      for (int j = 0; j < current->predecessors()->length(); ++j) {
        trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
      }
      trace_.Add("\n");
    } else {
      PrintEmptyProperty("predecessors");
    }

    if (current->end()->SuccessorCount() == 0) {
      PrintEmptyProperty("successors");
    } else  {
      PrintIndent();
      trace_.Add("successors");
      for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
        trace_.Add(" \"B%d\"", it.Current()->block_id());
      }
      trace_.Add("\n");
    }

    PrintEmptyProperty("xhandlers");

    {
      PrintIndent();
      trace_.Add("flags");
      if (current->IsLoopSuccessorDominator()) {
        trace_.Add(" \"dom-loop-succ\"");
      }
      if (current->IsUnreachable()) {
        trace_.Add(" \"dead\"");
      }
      if (current->is_osr_entry()) {
        trace_.Add(" \"osr\"");
      }
      trace_.Add("\n");
    }

    if (current->dominator() != NULL) {
      PrintBlockProperty("dominator", current->dominator()->block_id());
    }

    PrintIntProperty("loop_depth", current->LoopNestingDepth());

    if (chunk != NULL) {
      int first_index = current->first_instruction_index();
      int last_index = current->last_instruction_index();
      PrintIntProperty(
          "first_lir_id",
          LifetimePosition::FromInstructionIndex(first_index).Value());
      PrintIntProperty(
          "last_lir_id",
          LifetimePosition::FromInstructionIndex(last_index).Value());
    }

    {
      Tag states_tag(this, "states");
      Tag locals_tag(this, "locals");
      int total = current->phis()->length();
      PrintIntProperty("size", current->phis()->length());
      PrintStringProperty("method", "None");
      for (int j = 0; j < total; ++j) {
        HPhi* phi = current->phis()->at(j);
        PrintIndent();
        std::ostringstream os;
        os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
        trace_.Add(os.str().c_str());
      }
    }

    {
      Tag HIR_tag(this, "HIR");
      for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
        HInstruction* instruction = it.Current();
        int uses = instruction->UseCount();
        PrintIndent();
        std::ostringstream os;
        os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
        if (graph->info()->is_tracking_positions() &&
            instruction->has_position() && instruction->position().raw() != 0) {
          const SourcePosition pos = instruction->position();
          os << " pos:";
          if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
          os << pos.position();
        }
        os << " <|@\n";
        trace_.Add(os.str().c_str());
      }
    }


    if (chunk != NULL) {
      Tag LIR_tag(this, "LIR");
      int first_index = current->first_instruction_index();
      int last_index = current->last_instruction_index();
      if (first_index != -1 && last_index != -1) {
        const ZoneList<LInstruction*>* instructions = chunk->instructions();
        for (int i = first_index; i <= last_index; ++i) {
          LInstruction* linstr = instructions->at(i);
          if (linstr != NULL) {
            PrintIndent();
            trace_.Add("%d ",
                       LifetimePosition::FromInstructionIndex(i).Value());
            linstr->PrintTo(&trace_);
            std::ostringstream os;
            os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
            trace_.Add(os.str().c_str());
          }
        }
      }
    }
  }
}


void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
  Tag tag(this, "intervals");
  PrintStringProperty("name", name);

  const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
  for (int i = 0; i < fixed_d->length(); ++i) {
    TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
  }

  const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
  for (int i = 0; i < fixed->length(); ++i) {
    TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
  }

  const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
  for (int i = 0; i < live_ranges->length(); ++i) {
    TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
  }
}


void HTracer::TraceLiveRange(LiveRange* range, const char* type,
                             Zone* zone) {
  if (range != NULL && !range->IsEmpty()) {
    PrintIndent();
    trace_.Add("%d %s", range->id(), type);
    if (range->HasRegisterAssigned()) {
      LOperand* op = range->CreateAssignedOperand(zone);
      int assigned_reg = op->index();
      if (op->IsDoubleRegister()) {
        trace_.Add(" \"%s\"",
                   DoubleRegister::from_code(assigned_reg).ToString());
      } else {
        DCHECK(op->IsRegister());
        trace_.Add(" \"%s\"", Register::from_code(assigned_reg).ToString());
      }
    } else if (range->IsSpilled()) {
      LOperand* op = range->TopLevel()->GetSpillOperand();
      if (op->IsDoubleStackSlot()) {
        trace_.Add(" \"double_stack:%d\"", op->index());
      } else {
        DCHECK(op->IsStackSlot());
        trace_.Add(" \"stack:%d\"", op->index());
      }
    }
    int parent_index = -1;
    if (range->IsChild()) {
      parent_index = range->parent()->id();
    } else {
      parent_index = range->id();
    }
    LOperand* op = range->FirstHint();
    int hint_index = -1;
    if (op != NULL && op->IsUnallocated()) {
      hint_index = LUnallocated::cast(op)->virtual_register();
    }
    trace_.Add(" %d %d", parent_index, hint_index);
    UseInterval* cur_interval = range->first_interval();
    while (cur_interval != NULL && range->Covers(cur_interval->start())) {
      trace_.Add(" [%d, %d[",
                 cur_interval->start().Value(),
                 cur_interval->end().Value());
      cur_interval = cur_interval->next();
    }

    UsePosition* current_pos = range->first_pos();
    while (current_pos != NULL) {
      if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
        trace_.Add(" %d M", current_pos->pos().Value());
      }
      current_pos = current_pos->next();
    }

    trace_.Add(" \"\"\n");
  }
}


void HTracer::FlushToFile() {
  AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
              false);
  trace_.Reset();
}


void HStatistics::Initialize(CompilationInfo* info) {
  if (!info->has_shared_info()) return;
  source_size_ += info->shared_info()->SourceSize();
}


void HStatistics::Print() {
  PrintF(
      "\n"
      "----------------------------------------"
      "----------------------------------------\n"
      "--- Hydrogen timing results:\n"
      "----------------------------------------"
      "----------------------------------------\n");
  base::TimeDelta sum;
  for (int i = 0; i < times_.length(); ++i) {
    sum += times_[i];
  }

  for (int i = 0; i < names_.length(); ++i) {
    PrintF("%33s", names_[i]);
    double ms = times_[i].InMillisecondsF();
    double percent = times_[i].PercentOf(sum);
    PrintF(" %8.3f ms / %4.1f %% ", ms, percent);

    size_t size = sizes_[i];
    double size_percent = static_cast<double>(size) * 100 / total_size_;
    PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
  }

  PrintF(
      "----------------------------------------"
      "----------------------------------------\n");
  base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
  PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
         create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
  PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
         optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
  PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
         generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
  PrintF(
      "----------------------------------------"
      "----------------------------------------\n");
  PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
         total.InMillisecondsF(), total_size_);
  PrintF("%33s     (%.1f times slower than full code gen)\n", "",
         total.TimesOf(full_code_gen_));

  double source_size_in_kb = static_cast<double>(source_size_) / 1024;
  double normalized_time =  source_size_in_kb > 0
      ? total.InMillisecondsF() / source_size_in_kb
      : 0;
  double normalized_size_in_kb =
      source_size_in_kb > 0
          ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
          : 0;
  PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
         "Average per kB source", normalized_time, normalized_size_in_kb);
}


void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
                             size_t size) {
  total_size_ += size;
  for (int i = 0; i < names_.length(); ++i) {
    if (strcmp(names_[i], name) == 0) {
      times_[i] += time;
      sizes_[i] += size;
      return;
    }
  }
  names_.Add(name);
  times_.Add(time);
  sizes_.Add(size);
}


HPhase::~HPhase() {
  if (ShouldProduceTraceOutput()) {
    isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
  }

#ifdef DEBUG
  graph_->Verify(false);  // No full verify.
#endif
}

}  // namespace internal
}  // namespace v8
