// Copyright 2015 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/compiler/bytecode-graph-builder.h"

#include "src/compiler/bytecode-branch-analysis.h"
#include "src/compiler/linkage.h"
#include "src/compiler/operator-properties.h"
#include "src/interpreter/bytecodes.h"

namespace v8 {
namespace internal {
namespace compiler {

// Helper for generating frame states for before and after a bytecode.
class BytecodeGraphBuilder::FrameStateBeforeAndAfter {
 public:
  FrameStateBeforeAndAfter(BytecodeGraphBuilder* builder,
                           const interpreter::BytecodeArrayIterator& iterator)
      : builder_(builder), id_after_(BailoutId::None()) {
    BailoutId id_before(iterator.current_offset());
    frame_state_before_ = builder_->environment()->Checkpoint(
        id_before, AccumulatorUpdateMode::kOutputIgnored);
    id_after_ = BailoutId(id_before.ToInt() + iterator.current_bytecode_size());
  }

  ~FrameStateBeforeAndAfter() {
    DCHECK(builder_->environment()->StateValuesAreUpToDate(
        accumulator_update_mode_));
  }

 private:
  friend class Environment;

  void AddToNode(Node* node, AccumulatorUpdateMode update_mode) {
    int count = OperatorProperties::GetFrameStateInputCount(node->op());
    DCHECK_LE(count, 2);
    if (count >= 1) {
      // Add the frame state for after the operation.
      DCHECK_EQ(IrOpcode::kDead,
                NodeProperties::GetFrameStateInput(node, 0)->opcode());
      Node* frame_state_after =
          builder_->environment()->Checkpoint(id_after_, update_mode);
      NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
    }

    if (count >= 2) {
      // Add the frame state for before the operation.
      DCHECK_EQ(IrOpcode::kDead,
                NodeProperties::GetFrameStateInput(node, 1)->opcode());
      NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
    }
    accumulator_update_mode_ = update_mode;
  }

  BytecodeGraphBuilder* builder_;
  Node* frame_state_before_;
  BailoutId id_after_;
  AccumulatorUpdateMode accumulator_update_mode_;
};


// Issues:
// - Scopes - intimately tied to AST. Need to eval what is needed.
// - Need to resolve closure parameter treatment.
BytecodeGraphBuilder::Environment::Environment(BytecodeGraphBuilder* builder,
                                               int register_count,
                                               int parameter_count,
                                               Node* control_dependency,
                                               Node* context)
    : builder_(builder),
      register_count_(register_count),
      parameter_count_(parameter_count),
      context_(context),
      control_dependency_(control_dependency),
      effect_dependency_(control_dependency),
      values_(builder->local_zone()),
      parameters_state_values_(nullptr),
      registers_state_values_(nullptr),
      accumulator_state_values_(nullptr) {
  // The layout of values_ is:
  //
  // [receiver] [parameters] [registers] [accumulator]
  //
  // parameter[0] is the receiver (this), parameters 1..N are the
  // parameters supplied to the method (arg0..argN-1). The accumulator
  // is stored separately.

  // Parameters including the receiver
  for (int i = 0; i < parameter_count; i++) {
    const char* debug_name = (i == 0) ? "%this" : nullptr;
    const Operator* op = common()->Parameter(i, debug_name);
    Node* parameter = builder->graph()->NewNode(op, graph()->start());
    values()->push_back(parameter);
  }

  // Registers
  register_base_ = static_cast<int>(values()->size());
  Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
  values()->insert(values()->end(), register_count, undefined_constant);

  // Accumulator
  accumulator_base_ = static_cast<int>(values()->size());
  values()->push_back(undefined_constant);
}


BytecodeGraphBuilder::Environment::Environment(
    const BytecodeGraphBuilder::Environment* other)
    : builder_(other->builder_),
      register_count_(other->register_count_),
      parameter_count_(other->parameter_count_),
      context_(other->context_),
      control_dependency_(other->control_dependency_),
      effect_dependency_(other->effect_dependency_),
      values_(other->zone()),
      parameters_state_values_(nullptr),
      registers_state_values_(nullptr),
      accumulator_state_values_(nullptr),
      register_base_(other->register_base_),
      accumulator_base_(other->accumulator_base_) {
  values_ = other->values_;
}


int BytecodeGraphBuilder::Environment::RegisterToValuesIndex(
    interpreter::Register the_register) const {
  if (the_register.is_parameter()) {
    return the_register.ToParameterIndex(parameter_count());
  } else {
    return the_register.index() + register_base();
  }
}


void BytecodeGraphBuilder::Environment::BindRegister(
    interpreter::Register the_register, Node* node) {
  int values_index = RegisterToValuesIndex(the_register);
  values()->at(values_index) = node;
}


Node* BytecodeGraphBuilder::Environment::LookupRegister(
    interpreter::Register the_register) const {
  if (the_register.is_function_context()) {
    return builder()->GetFunctionContext();
  } else if (the_register.is_function_closure()) {
    return builder()->GetFunctionClosure();
  } else if (the_register.is_new_target()) {
    return builder()->GetNewTarget();
  } else {
    int values_index = RegisterToValuesIndex(the_register);
    return values()->at(values_index);
  }
}


void BytecodeGraphBuilder::Environment::BindAccumulator(
    Node* node, FrameStateBeforeAndAfter* states) {
  if (states) {
    states->AddToNode(node, AccumulatorUpdateMode::kOutputInAccumulator);
  }
  values()->at(accumulator_base_) = node;
}

void BytecodeGraphBuilder::Environment::RecordAfterState(
    Node* node, FrameStateBeforeAndAfter* states) {
  states->AddToNode(node, AccumulatorUpdateMode::kOutputIgnored);
}


Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
  return values()->at(accumulator_base_);
}


bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const {
  return GetControlDependency()->opcode() == IrOpcode::kDead;
}


void BytecodeGraphBuilder::Environment::MarkAsUnreachable() {
  UpdateControlDependency(builder()->jsgraph()->Dead());
}


BytecodeGraphBuilder::Environment*
BytecodeGraphBuilder::Environment::CopyForLoop() {
  PrepareForLoop();
  return new (zone()) Environment(this);
}


BytecodeGraphBuilder::Environment*
BytecodeGraphBuilder::Environment::CopyForConditional() const {
  return new (zone()) Environment(this);
}


void BytecodeGraphBuilder::Environment::Merge(
    BytecodeGraphBuilder::Environment* other) {
  // Nothing to do if the other environment is dead.
  if (other->IsMarkedAsUnreachable()) {
    return;
  }

  // Create a merge of the control dependencies of both environments and update
  // the current environment's control dependency accordingly.
  Node* control = builder()->MergeControl(GetControlDependency(),
                                          other->GetControlDependency());
  UpdateControlDependency(control);

  // Create a merge of the effect dependencies of both environments and update
  // the current environment's effect dependency accordingly.
  Node* effect = builder()->MergeEffect(GetEffectDependency(),
                                        other->GetEffectDependency(), control);
  UpdateEffectDependency(effect);

  // Introduce Phi nodes for values that have differing input at merge points,
  // potentially extending an existing Phi node if possible.
  context_ = builder()->MergeValue(context_, other->context_, control);
  for (size_t i = 0; i < values_.size(); i++) {
    values_[i] = builder()->MergeValue(values_[i], other->values_[i], control);
  }
}


void BytecodeGraphBuilder::Environment::PrepareForLoop() {
  // Create a control node for the loop header.
  Node* control = builder()->NewLoop();

  // Create a Phi for external effects.
  Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control);
  UpdateEffectDependency(effect);

  // Assume everything in the loop is updated.
  context_ = builder()->NewPhi(1, context_, control);
  int size = static_cast<int>(values()->size());
  for (int i = 0; i < size; i++) {
    values()->at(i) = builder()->NewPhi(1, values()->at(i), control);
  }

  // Connect to the loop end.
  Node* terminate = builder()->graph()->NewNode(
      builder()->common()->Terminate(), effect, control);
  builder()->exit_controls_.push_back(terminate);
}


bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate(
    Node** state_values, int offset, int count) {
  Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
  if (*state_values == nullptr) {
    return true;
  } else {
    DCHECK_EQ((*state_values)->InputCount(), count);
    DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
    for (int i = 0; i < count; i++) {
      if ((*state_values)->InputAt(i) != env_values[i]) {
        return true;
      }
    }
  }
  return false;
}


void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
                                                          int offset,
                                                          int count) {
  if (StateValuesRequireUpdate(state_values, offset, count)) {
    const Operator* op = common()->StateValues(count);
    (*state_values) = graph()->NewNode(op, count, &values()->at(offset));
  }
}


Node* BytecodeGraphBuilder::Environment::Checkpoint(
    BailoutId bailout_id, AccumulatorUpdateMode update_mode) {
  if (!builder()->info()->is_deoptimization_enabled()) {
    return builder()->jsgraph()->EmptyFrameState();
  }

  // TODO(rmcilroy): Consider using StateValuesCache for some state values.
  UpdateStateValues(&parameters_state_values_, 0, parameter_count());
  UpdateStateValues(&registers_state_values_, register_base(),
                    register_count());
  UpdateStateValues(&accumulator_state_values_, accumulator_base(), 1);

  OutputFrameStateCombine combine =
      update_mode == AccumulatorUpdateMode::kOutputIgnored
          ? OutputFrameStateCombine::Ignore()
          : OutputFrameStateCombine::PokeAt(0);
  const Operator* op = common()->FrameState(
      bailout_id, combine, builder()->frame_state_function_info());

  Node* result = graph()->NewNode(
      op, parameters_state_values_, registers_state_values_,
      accumulator_state_values_, Context(), builder()->GetFunctionClosure(),
      builder()->graph()->start());

  return result;
}


bool BytecodeGraphBuilder::Environment::StateValuesAreUpToDate(
    AccumulatorUpdateMode update_mode) {
  return !StateValuesRequireUpdate(&parameters_state_values_, 0,
                                   parameter_count()) &&
         !StateValuesRequireUpdate(&registers_state_values_, register_base(),
                                   register_count()) &&
         (update_mode == AccumulatorUpdateMode::kOutputInAccumulator ||
          !StateValuesRequireUpdate(&accumulator_state_values_,
                                    accumulator_base(), 1));
}


BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
                                           CompilationInfo* compilation_info,
                                           JSGraph* jsgraph)
    : local_zone_(local_zone),
      info_(compilation_info),
      jsgraph_(jsgraph),
      bytecode_array_(handle(info()->shared_info()->bytecode_array())),
      frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
          FrameStateType::kInterpretedFunction,
          bytecode_array()->parameter_count(),
          bytecode_array()->register_count(), info()->shared_info(),
          CALL_MAINTAINS_NATIVE_CONTEXT)),
      merge_environments_(local_zone),
      loop_header_environments_(local_zone),
      input_buffer_size_(0),
      input_buffer_(nullptr),
      exit_controls_(local_zone) {}


Node* BytecodeGraphBuilder::GetNewTarget() {
  if (!new_target_.is_set()) {
    int params = bytecode_array()->parameter_count();
    int index = Linkage::GetJSCallNewTargetParamIndex(params);
    const Operator* op = common()->Parameter(index, "%new.target");
    Node* node = NewNode(op, graph()->start());
    new_target_.set(node);
  }
  return new_target_.get();
}


Node* BytecodeGraphBuilder::GetFunctionContext() {
  if (!function_context_.is_set()) {
    int params = bytecode_array()->parameter_count();
    int index = Linkage::GetJSCallContextParamIndex(params);
    const Operator* op = common()->Parameter(index, "%context");
    Node* node = NewNode(op, graph()->start());
    function_context_.set(node);
  }
  return function_context_.get();
}


Node* BytecodeGraphBuilder::GetFunctionClosure() {
  if (!function_closure_.is_set()) {
    int index = Linkage::kJSCallClosureParamIndex;
    const Operator* op = common()->Parameter(index, "%closure");
    Node* node = NewNode(op, graph()->start());
    function_closure_.set(node);
  }
  return function_closure_.get();
}


Node* BytecodeGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
  return NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()), object,
                 jsgraph()->IntPtrConstant(offset - kHeapObjectTag));
}


Node* BytecodeGraphBuilder::BuildLoadImmutableObjectField(Node* object,
                                                          int offset) {
  return graph()->NewNode(jsgraph()->machine()->Load(MachineType::AnyTagged()),
                          object,
                          jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
                          graph()->start(), graph()->start());
}


Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
  const Operator* op =
      javascript()->LoadContext(0, Context::NATIVE_CONTEXT_INDEX, true);
  Node* native_context = NewNode(op, environment()->Context());
  return NewNode(javascript()->LoadContext(0, index, true), native_context);
}


Node* BytecodeGraphBuilder::BuildLoadFeedbackVector() {
  if (!feedback_vector_.is_set()) {
    Node* closure = GetFunctionClosure();
    Node* shared = BuildLoadImmutableObjectField(
        closure, JSFunction::kSharedFunctionInfoOffset);
    Node* vector = BuildLoadImmutableObjectField(
        shared, SharedFunctionInfo::kFeedbackVectorOffset);
    feedback_vector_.set(vector);
  }
  return feedback_vector_.get();
}


VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
  Handle<TypeFeedbackVector> feedback_vector = info()->feedback_vector();
  FeedbackVectorSlot slot = feedback_vector->ToSlot(slot_id);
  return VectorSlotPair(feedback_vector, slot);
}


bool BytecodeGraphBuilder::CreateGraph(bool stack_check) {
  // Set up the basic structure of the graph. Outputs for {Start} are
  // the formal parameters (including the receiver) plus context and
  // closure.

  // Set up the basic structure of the graph. Outputs for {Start} are the formal
  // parameters (including the receiver) plus new target, number of arguments,
  // context and closure.
  int actual_parameter_count = bytecode_array()->parameter_count() + 4;
  graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));

  Environment env(this, bytecode_array()->register_count(),
                  bytecode_array()->parameter_count(), graph()->start(),
                  GetFunctionContext());
  set_environment(&env);

  CreateGraphBody(stack_check);

  // Finish the basic structure of the graph.
  DCHECK_NE(0u, exit_controls_.size());
  int const input_count = static_cast<int>(exit_controls_.size());
  Node** const inputs = &exit_controls_.front();
  Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
  graph()->SetEnd(end);

  return true;
}


void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) {
  // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments
  // object setup, this function variable if used, tracing hooks.
  VisitBytecodes();
}


void BytecodeGraphBuilder::VisitBytecodes() {
  BytecodeBranchAnalysis analysis(bytecode_array(), local_zone());
  analysis.Analyze();
  set_branch_analysis(&analysis);
  interpreter::BytecodeArrayIterator iterator(bytecode_array());
  set_bytecode_iterator(&iterator);
  while (!iterator.done()) {
    int current_offset = iterator.current_offset();
    if (analysis.is_reachable(current_offset)) {
      MergeEnvironmentsOfForwardBranches(current_offset);
      BuildLoopHeaderForBackwardBranches(current_offset);

      switch (iterator.current_bytecode()) {
#define BYTECODE_CASE(name, ...)       \
  case interpreter::Bytecode::k##name: \
    Visit##name(iterator);             \
    break;
        BYTECODE_LIST(BYTECODE_CASE)
#undef BYTECODE_CODE
      }
    }
    iterator.Advance();
  }
  set_branch_analysis(nullptr);
  set_bytecode_iterator(nullptr);
}


void BytecodeGraphBuilder::VisitLdaZero(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->ZeroConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaSmi8(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->Constant(iterator.GetImmediateOperand(0));
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaConstantWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->Constant(iterator.GetConstantForIndexOperand(0));
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaUndefined(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->UndefinedConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaNull(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->NullConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaTheHole(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->TheHoleConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaTrue(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->TrueConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdaFalse(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node = jsgraph()->FalseConstant();
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitLdar(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  environment()->BindAccumulator(value);
}


void BytecodeGraphBuilder::VisitStar(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* value = environment()->LookupAccumulator();
  environment()->BindRegister(iterator.GetRegisterOperand(0), value);
}


void BytecodeGraphBuilder::VisitMov(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* value = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  environment()->BindRegister(iterator.GetRegisterOperand(1), value);
}


void BytecodeGraphBuilder::BuildLoadGlobal(
    const interpreter::BytecodeArrayIterator& iterator,
    TypeofMode typeof_mode) {
  FrameStateBeforeAndAfter states(this, iterator);
  Handle<Name> name =
      Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
  VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));

  const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode);
  Node* node = NewNode(op, BuildLoadFeedbackVector());
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitLdaGlobalSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::VisitLdaGlobalStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::VisitLdaGlobalSloppyWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::VisitLdaGlobalStrictWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::NOT_INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofSloppyWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::VisitLdaGlobalInsideTypeofStrictWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildLoadGlobal(iterator, TypeofMode::INSIDE_TYPEOF);
}


void BytecodeGraphBuilder::BuildStoreGlobal(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Handle<Name> name =
      Handle<Name>::cast(iterator.GetConstantForIndexOperand(0));
  VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));
  Node* value = environment()->LookupAccumulator();

  const Operator* op =
      javascript()->StoreGlobal(language_mode(), name, feedback);
  Node* node = NewNode(op, value, BuildLoadFeedbackVector());
  environment()->RecordAfterState(node, &states);
}


void BytecodeGraphBuilder::VisitStaGlobalSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildStoreGlobal(iterator);
}


void BytecodeGraphBuilder::VisitStaGlobalStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildStoreGlobal(iterator);
}

void BytecodeGraphBuilder::VisitStaGlobalSloppyWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildStoreGlobal(iterator);
}


void BytecodeGraphBuilder::VisitStaGlobalStrictWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildStoreGlobal(iterator);
}


void BytecodeGraphBuilder::VisitLdaContextSlot(
    const interpreter::BytecodeArrayIterator& iterator) {
  // TODO(mythria): LoadContextSlots are unrolled by the required depth when
  // generating bytecode. Hence the value of depth is always 0. Update this
  // code, when the implementation changes.
  // TODO(mythria): immutable flag is also set to false. This information is not
  // available in bytecode array. update this code when the implementation
  // changes.
  const Operator* op =
      javascript()->LoadContext(0, iterator.GetIndexOperand(1), false);
  Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* node = NewNode(op, context);
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitStaContextSlot(
    const interpreter::BytecodeArrayIterator& iterator) {
  // TODO(mythria): LoadContextSlots are unrolled by the required depth when
  // generating bytecode. Hence the value of depth is always 0. Update this
  // code, when the implementation changes.
  const Operator* op =
      javascript()->StoreContext(0, iterator.GetIndexOperand(1));
  Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* value = environment()->LookupAccumulator();
  NewNode(op, context, value);
}


void BytecodeGraphBuilder::VisitLdaLookupSlot(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitStaLookupSlotSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitStaLookupSlotStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::BuildNamedLoad(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Handle<Name> name =
      Handle<Name>::cast(iterator.GetConstantForIndexOperand(1));
  VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));

  const Operator* op = javascript()->LoadNamed(language_mode(), name, feedback);
  Node* node = NewNode(op, object, BuildLoadFeedbackVector());
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitLoadICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildNamedLoad(iterator);
}


void BytecodeGraphBuilder::VisitLoadICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildNamedLoad(iterator);
}


void BytecodeGraphBuilder::VisitLoadICSloppyWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildNamedLoad(iterator);
}


void BytecodeGraphBuilder::VisitLoadICStrictWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildNamedLoad(iterator);
}


void BytecodeGraphBuilder::BuildKeyedLoad(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* key = environment()->LookupAccumulator();
  Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(1));

  const Operator* op = javascript()->LoadProperty(language_mode(), feedback);
  Node* node = NewNode(op, object, key, BuildLoadFeedbackVector());
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitKeyedLoadICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildKeyedLoad(iterator);
}


void BytecodeGraphBuilder::VisitKeyedLoadICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildKeyedLoad(iterator);
}


void BytecodeGraphBuilder::VisitKeyedLoadICSloppyWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildKeyedLoad(iterator);
}


void BytecodeGraphBuilder::VisitKeyedLoadICStrictWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildKeyedLoad(iterator);
}


void BytecodeGraphBuilder::BuildNamedStore(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* value = environment()->LookupAccumulator();
  Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Handle<Name> name =
      Handle<Name>::cast(iterator.GetConstantForIndexOperand(1));
  VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));

  const Operator* op =
      javascript()->StoreNamed(language_mode(), name, feedback);
  Node* node = NewNode(op, object, value, BuildLoadFeedbackVector());
  environment()->RecordAfterState(node, &states);
}


void BytecodeGraphBuilder::VisitStoreICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildNamedStore(iterator);
}


void BytecodeGraphBuilder::VisitStoreICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildNamedStore(iterator);
}


void BytecodeGraphBuilder::VisitStoreICSloppyWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildNamedStore(iterator);
}


void BytecodeGraphBuilder::VisitStoreICStrictWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildNamedStore(iterator);
}


void BytecodeGraphBuilder::BuildKeyedStore(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* value = environment()->LookupAccumulator();
  Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* key = environment()->LookupRegister(iterator.GetRegisterOperand(1));
  VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(2));

  const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
  Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector());
  environment()->RecordAfterState(node, &states);
}


void BytecodeGraphBuilder::VisitKeyedStoreICSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildKeyedStore(iterator);
}


void BytecodeGraphBuilder::VisitKeyedStoreICStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildKeyedStore(iterator);
}


void BytecodeGraphBuilder::VisitKeyedStoreICSloppyWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildKeyedStore(iterator);
}


void BytecodeGraphBuilder::VisitKeyedStoreICStrictWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildKeyedStore(iterator);
}


void BytecodeGraphBuilder::VisitPushContext(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* context = environment()->LookupAccumulator();
  environment()->BindRegister(iterator.GetRegisterOperand(0), context);
  environment()->SetContext(context);
}


void BytecodeGraphBuilder::VisitPopContext(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* context = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  environment()->SetContext(context);
}


void BytecodeGraphBuilder::VisitCreateClosure(
    const interpreter::BytecodeArrayIterator& iterator) {
  Handle<SharedFunctionInfo> shared_info =
      Handle<SharedFunctionInfo>::cast(iterator.GetConstantForIndexOperand(0));
  PretenureFlag tenured =
      iterator.GetImmediateOperand(1) ? TENURED : NOT_TENURED;
  const Operator* op = javascript()->CreateClosure(shared_info, tenured);
  Node* closure = NewNode(op);
  environment()->BindAccumulator(closure);
}


void BytecodeGraphBuilder::VisitCreateClosureWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  VisitCreateClosure(iterator);
}


void BytecodeGraphBuilder::VisitCreateMappedArguments(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::VisitCreateUnmappedArguments(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


void BytecodeGraphBuilder::BuildCreateLiteral(
    const Operator* op, const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* literal = NewNode(op, GetFunctionClosure());
  environment()->BindAccumulator(literal, &states);
}


void BytecodeGraphBuilder::BuildCreateRegExpLiteral(
    const interpreter::BytecodeArrayIterator& iterator) {
  Handle<String> constant_pattern =
      Handle<String>::cast(iterator.GetConstantForIndexOperand(0));
  int literal_index = iterator.GetIndexOperand(1);
  int literal_flags = iterator.GetImmediateOperand(2);
  const Operator* op = javascript()->CreateLiteralRegExp(
      constant_pattern, literal_flags, literal_index);
  BuildCreateLiteral(op, iterator);
}


void BytecodeGraphBuilder::VisitCreateRegExpLiteral(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCreateRegExpLiteral(iterator);
}


void BytecodeGraphBuilder::VisitCreateRegExpLiteralWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCreateRegExpLiteral(iterator);
}


void BytecodeGraphBuilder::BuildCreateArrayLiteral(
    const interpreter::BytecodeArrayIterator& iterator) {
  Handle<FixedArray> constant_elements =
      Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
  int literal_index = iterator.GetIndexOperand(1);
  int literal_flags = iterator.GetImmediateOperand(2);
  const Operator* op = javascript()->CreateLiteralArray(
      constant_elements, literal_flags, literal_index);
  BuildCreateLiteral(op, iterator);
}


void BytecodeGraphBuilder::VisitCreateArrayLiteral(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCreateArrayLiteral(iterator);
}


void BytecodeGraphBuilder::VisitCreateArrayLiteralWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCreateArrayLiteral(iterator);
}


void BytecodeGraphBuilder::BuildCreateObjectLiteral(
    const interpreter::BytecodeArrayIterator& iterator) {
  Handle<FixedArray> constant_properties =
      Handle<FixedArray>::cast(iterator.GetConstantForIndexOperand(0));
  int literal_index = iterator.GetIndexOperand(1);
  int literal_flags = iterator.GetImmediateOperand(2);
  const Operator* op = javascript()->CreateLiteralObject(
      constant_properties, literal_flags, literal_index);
  BuildCreateLiteral(op, iterator);
}


void BytecodeGraphBuilder::VisitCreateObjectLiteral(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCreateObjectLiteral(iterator);
}


void BytecodeGraphBuilder::VisitCreateObjectLiteralWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCreateObjectLiteral(iterator);
}


Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
                                                 Node* callee,
                                                 interpreter::Register receiver,
                                                 size_t arity) {
  Node** all = info()->zone()->NewArray<Node*>(static_cast<int>(arity));
  all[0] = callee;
  all[1] = environment()->LookupRegister(receiver);
  int receiver_index = receiver.index();
  for (int i = 2; i < static_cast<int>(arity); ++i) {
    all[i] = environment()->LookupRegister(
        interpreter::Register(receiver_index + i - 1));
  }
  Node* value = MakeNode(call_op, static_cast<int>(arity), all, false);
  return value;
}


void BytecodeGraphBuilder::BuildCall(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  // TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver
  // register has been loaded with null / undefined explicitly or we are sure it
  // is not null / undefined.
  ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
  Node* callee = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  interpreter::Register receiver = iterator.GetRegisterOperand(1);
  size_t arg_count = iterator.GetCountOperand(2);
  VectorSlotPair feedback = CreateVectorSlotPair(iterator.GetIndexOperand(3));

  const Operator* call = javascript()->CallFunction(
      arg_count + 2, language_mode(), feedback, receiver_hint);
  Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
  environment()->BindAccumulator(value, &states);
}


void BytecodeGraphBuilder::VisitCall(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCall(iterator);
}


void BytecodeGraphBuilder::VisitCallWide(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCall(iterator);
}


void BytecodeGraphBuilder::VisitCallJSRuntime(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* callee = BuildLoadNativeContextField(iterator.GetIndexOperand(0));
  interpreter::Register receiver = iterator.GetRegisterOperand(1);
  size_t arg_count = iterator.GetCountOperand(2);

  // Create node to perform the JS runtime call.
  const Operator* call =
      javascript()->CallFunction(arg_count + 2, language_mode());
  Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 2);
  environment()->BindAccumulator(value, &states);
}


Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
    const Operator* call_runtime_op, interpreter::Register first_arg,
    size_t arity) {
  Node** all = info()->zone()->NewArray<Node*>(arity);
  int first_arg_index = first_arg.index();
  for (int i = 0; i < static_cast<int>(arity); ++i) {
    all[i] = environment()->LookupRegister(
        interpreter::Register(first_arg_index + i));
  }
  Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false);
  return value;
}


void BytecodeGraphBuilder::VisitCallRuntime(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Runtime::FunctionId functionId =
      static_cast<Runtime::FunctionId>(iterator.GetIndexOperand(0));
  interpreter::Register first_arg = iterator.GetRegisterOperand(1);
  size_t arg_count = iterator.GetCountOperand(2);

  // Create node to perform the runtime call.
  const Operator* call = javascript()->CallRuntime(functionId, arg_count);
  Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
  environment()->BindAccumulator(value, &states);
}


Node* BytecodeGraphBuilder::ProcessCallNewArguments(
    const Operator* call_new_op, interpreter::Register callee,
    interpreter::Register first_arg, size_t arity) {
  Node** all = info()->zone()->NewArray<Node*>(arity);
  all[0] = environment()->LookupRegister(callee);
  int first_arg_index = first_arg.index();
  for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
    all[i] = environment()->LookupRegister(
        interpreter::Register(first_arg_index + i - 1));
  }
  // Original constructor is the same as the callee.
  all[arity - 1] = environment()->LookupRegister(callee);
  Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
  return value;
}


void BytecodeGraphBuilder::VisitNew(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  interpreter::Register callee = iterator.GetRegisterOperand(0);
  interpreter::Register first_arg = iterator.GetRegisterOperand(1);
  size_t arg_count = iterator.GetCountOperand(2);

  // TODO(turbofan): Pass the feedback here.
  const Operator* call = javascript()->CallConstruct(
      static_cast<int>(arg_count) + 2, VectorSlotPair());
  Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2);
  environment()->BindAccumulator(value, &states);
}


void BytecodeGraphBuilder::VisitThrow(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* value = environment()->LookupAccumulator();
  // TODO(mythria): Change to Runtime::kThrow when we have deoptimization
  // information support in the interpreter.
  NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), value);
  Node* control = NewNode(common()->Throw(), value);
  environment()->RecordAfterState(control, &states);
  UpdateControlDependencyToLeaveFunction(control);
}


void BytecodeGraphBuilder::BuildBinaryOp(
    const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* right = environment()->LookupAccumulator();
  Node* node = NewNode(js_op, left, right);
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitAdd(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->Add(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitSub(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->Subtract(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitMul(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->Multiply(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitDiv(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->Divide(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitMod(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->Modulus(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitBitwiseOr(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->BitwiseOr(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitBitwiseXor(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->BitwiseXor(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitBitwiseAnd(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->BitwiseAnd(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitShiftLeft(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->ShiftLeft(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitShiftRight(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->ShiftRight(language_mode(), hints), iterator);
}


void BytecodeGraphBuilder::VisitShiftRightLogical(
    const interpreter::BytecodeArrayIterator& iterator) {
  BinaryOperationHints hints = BinaryOperationHints::Any();
  BuildBinaryOp(javascript()->ShiftRightLogical(language_mode(), hints),
                iterator);
}


void BytecodeGraphBuilder::VisitInc(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  const Operator* js_op =
      javascript()->Add(language_mode(), BinaryOperationHints::Any());
  Node* node = NewNode(js_op, environment()->LookupAccumulator(),
                       jsgraph()->OneConstant());
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitDec(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  const Operator* js_op =
      javascript()->Subtract(language_mode(), BinaryOperationHints::Any());
  Node* node = NewNode(js_op, environment()->LookupAccumulator(),
                       jsgraph()->OneConstant());
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitLogicalNot(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* value = NewNode(javascript()->ToBoolean(ToBooleanHint::kAny),
                        environment()->LookupAccumulator());
  Node* node = NewNode(common()->Select(MachineRepresentation::kTagged), value,
                       jsgraph()->FalseConstant(), jsgraph()->TrueConstant());
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::VisitTypeOf(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* node =
      NewNode(javascript()->TypeOf(), environment()->LookupAccumulator());
  environment()->BindAccumulator(node);
}


void BytecodeGraphBuilder::BuildDelete(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* key = environment()->LookupAccumulator();
  Node* object = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* node =
      NewNode(javascript()->DeleteProperty(language_mode()), object, key);
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitDeletePropertyStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_strict(language_mode()));
  BuildDelete(iterator);
}


void BytecodeGraphBuilder::VisitDeletePropertySloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  DCHECK(is_sloppy(language_mode()));
  BuildDelete(iterator);
}


void BytecodeGraphBuilder::BuildCompareOp(
    const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* left = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* right = environment()->LookupAccumulator();
  Node* node = NewNode(js_op, left, right);
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitTestEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->Equal(), iterator);
}


void BytecodeGraphBuilder::VisitTestNotEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->NotEqual(), iterator);
}


void BytecodeGraphBuilder::VisitTestEqualStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->StrictEqual(), iterator);
}


void BytecodeGraphBuilder::VisitTestNotEqualStrict(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->StrictNotEqual(), iterator);
}


void BytecodeGraphBuilder::VisitTestLessThan(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->LessThan(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitTestGreaterThan(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->GreaterThan(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitTestLessThanOrEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->LessThanOrEqual(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitTestGreaterThanOrEqual(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->GreaterThanOrEqual(language_mode()), iterator);
}


void BytecodeGraphBuilder::VisitTestIn(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->HasProperty(), iterator);
}


void BytecodeGraphBuilder::VisitTestInstanceOf(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCompareOp(javascript()->InstanceOf(), iterator);
}


void BytecodeGraphBuilder::BuildCastOperator(
    const Operator* js_op, const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* node = NewNode(js_op, environment()->LookupAccumulator());
  environment()->BindAccumulator(node, &states);
}


void BytecodeGraphBuilder::VisitToName(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCastOperator(javascript()->ToName(), iterator);
}


void BytecodeGraphBuilder::VisitToObject(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCastOperator(javascript()->ToObject(), iterator);
}


void BytecodeGraphBuilder::VisitToNumber(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildCastOperator(javascript()->ToNumber(), iterator);
}


void BytecodeGraphBuilder::VisitJump(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildJump();
}


void BytecodeGraphBuilder::VisitJumpConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  BuildJump();
}


void BytecodeGraphBuilder::VisitJumpIfTrue(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->TrueConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfTrueConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->TrueConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfFalse(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->FalseConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfFalseConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->FalseConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildToBooleanCondition(jsgraph()->TrueConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildToBooleanCondition(jsgraph()->TrueConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildToBooleanCondition(jsgraph()->FalseConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildToBooleanCondition(jsgraph()->FalseConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfNull(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->NullConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfNullConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->NullConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfUndefined(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->UndefinedConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* condition = BuildCondition(jsgraph()->UndefinedConstant());
  BuildConditionalJump(condition);
}


void BytecodeGraphBuilder::VisitReturn(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* control =
      NewNode(common()->Return(), environment()->LookupAccumulator());
  UpdateControlDependencyToLeaveFunction(control);
  set_environment(nullptr);
}


void BytecodeGraphBuilder::VisitForInPrepare(
    const interpreter::BytecodeArrayIterator& iterator) {
  Node* prepare = nullptr;
  {
    FrameStateBeforeAndAfter states(this, iterator);
    Node* receiver = environment()->LookupAccumulator();
    prepare = NewNode(javascript()->ForInPrepare(), receiver);
    environment()->RecordAfterState(prepare, &states);
  }
  // Project cache_type, cache_array, cache_length into register
  // operands 1, 2, 3.
  for (int i = 0; i < 3; i++) {
    environment()->BindRegister(iterator.GetRegisterOperand(i),
                                NewNode(common()->Projection(i), prepare));
  }
}


void BytecodeGraphBuilder::VisitForInDone(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* cache_length =
      environment()->LookupRegister(iterator.GetRegisterOperand(1));
  Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
  environment()->BindAccumulator(exit_cond, &states);
}


void BytecodeGraphBuilder::VisitForInNext(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* receiver =
      environment()->LookupRegister(iterator.GetRegisterOperand(0));
  Node* cache_type =
      environment()->LookupRegister(iterator.GetRegisterOperand(1));
  Node* cache_array =
      environment()->LookupRegister(iterator.GetRegisterOperand(2));
  Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(3));
  Node* value = NewNode(javascript()->ForInNext(), receiver, cache_array,
                        cache_type, index);
  environment()->BindAccumulator(value, &states);
}


void BytecodeGraphBuilder::VisitForInStep(
    const interpreter::BytecodeArrayIterator& iterator) {
  FrameStateBeforeAndAfter states(this, iterator);
  Node* index = environment()->LookupRegister(iterator.GetRegisterOperand(0));
  index = NewNode(javascript()->ForInStep(), index);
  environment()->BindAccumulator(index, &states);
}


void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches(
    int source_offset, int target_offset) {
  DCHECK_GE(source_offset, target_offset);
  const ZoneVector<int>* branch_sites =
      branch_analysis()->BackwardBranchesTargetting(target_offset);
  if (branch_sites->back() == source_offset) {
    // The set of back branches is complete, merge them.
    DCHECK_GE(branch_sites->at(0), target_offset);
    Environment* merged = merge_environments_[branch_sites->at(0)];
    for (size_t i = 1; i < branch_sites->size(); i++) {
      DCHECK_GE(branch_sites->at(i), target_offset);
      merged->Merge(merge_environments_[branch_sites->at(i)]);
    }
    // And now merge with loop header environment created when loop
    // header was visited.
    loop_header_environments_[target_offset]->Merge(merged);
  }
}


void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches(
    int source_offset) {
  if (branch_analysis()->forward_branches_target(source_offset)) {
    // Merge environments of branches that reach this bytecode.
    auto branch_sites =
        branch_analysis()->ForwardBranchesTargetting(source_offset);
    DCHECK_LT(branch_sites->at(0), source_offset);
    Environment* merged = merge_environments_[branch_sites->at(0)];
    for (size_t i = 1; i < branch_sites->size(); i++) {
      DCHECK_LT(branch_sites->at(i), source_offset);
      merged->Merge(merge_environments_[branch_sites->at(i)]);
    }
    if (environment()) {
      merged->Merge(environment());
    }
    set_environment(merged);
  }
}


void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches(
    int source_offset) {
  if (branch_analysis()->backward_branches_target(source_offset)) {
    // Add loop header and store a copy so we can connect merged back
    // edge inputs to the loop header.
    loop_header_environments_[source_offset] = environment()->CopyForLoop();
  }
}


void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) {
  DCHECK_NULL(merge_environments_[source_offset]);
  merge_environments_[source_offset] = environment();
  if (source_offset >= target_offset) {
    MergeEnvironmentsOfBackwardBranches(source_offset, target_offset);
  }
  set_environment(nullptr);
}


void BytecodeGraphBuilder::BuildJump() {
  int source_offset = bytecode_iterator()->current_offset();
  int target_offset = bytecode_iterator()->GetJumpTargetOffset();
  BuildJump(source_offset, target_offset);
}


void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) {
  int source_offset = bytecode_iterator()->current_offset();
  NewBranch(condition);
  Environment* if_false_environment = environment()->CopyForConditional();
  NewIfTrue();
  BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset());
  set_environment(if_false_environment);
  NewIfFalse();
}


Node* BytecodeGraphBuilder::BuildCondition(Node* comperand) {
  Node* accumulator = environment()->LookupAccumulator();
  return NewNode(javascript()->StrictEqual(), accumulator, comperand);
}


Node* BytecodeGraphBuilder::BuildToBooleanCondition(Node* comperand) {
  Node* accumulator = environment()->LookupAccumulator();
  Node* to_boolean =
      NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator);
  return NewNode(javascript()->StrictEqual(), to_boolean, comperand);
}


Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) {
  if (size > input_buffer_size_) {
    size = size + kInputBufferSizeIncrement + input_buffer_size_;
    input_buffer_ = local_zone()->NewArray<Node*>(size);
    input_buffer_size_ = size;
  }
  return input_buffer_;
}


Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count,
                                     Node** value_inputs, bool incomplete) {
  DCHECK_EQ(op->ValueInputCount(), value_input_count);

  bool has_context = OperatorProperties::HasContextInput(op);
  int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
  bool has_control = op->ControlInputCount() == 1;
  bool has_effect = op->EffectInputCount() == 1;

  DCHECK_LT(op->ControlInputCount(), 2);
  DCHECK_LT(op->EffectInputCount(), 2);

  Node* result = NULL;
  if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
    result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
  } else {
    int input_count_with_deps = value_input_count;
    if (has_context) ++input_count_with_deps;
    input_count_with_deps += frame_state_count;
    if (has_control) ++input_count_with_deps;
    if (has_effect) ++input_count_with_deps;
    Node** buffer = EnsureInputBufferSize(input_count_with_deps);
    memcpy(buffer, value_inputs, kPointerSize * value_input_count);
    Node** current_input = buffer + value_input_count;
    if (has_context) {
      *current_input++ = environment()->Context();
    }
    for (int i = 0; i < frame_state_count; i++) {
      // The frame state will be inserted later. Here we misuse
      // the {Dead} node as a sentinel to be later overwritten
      // with the real frame state.
      *current_input++ = jsgraph()->Dead();
    }
    if (has_effect) {
      *current_input++ = environment()->GetEffectDependency();
    }
    if (has_control) {
      *current_input++ = environment()->GetControlDependency();
    }
    result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
    if (!environment()->IsMarkedAsUnreachable()) {
      // Update the current control dependency for control-producing nodes.
      if (NodeProperties::IsControl(result)) {
        environment()->UpdateControlDependency(result);
      }
      // Update the current effect dependency for effect-producing nodes.
      if (result->op()->EffectOutputCount() > 0) {
        environment()->UpdateEffectDependency(result);
      }
      // Add implicit success continuation for throwing nodes.
      if (!result->op()->HasProperty(Operator::kNoThrow)) {
        const Operator* if_success = common()->IfSuccess();
        Node* on_success = graph()->NewNode(if_success, result);
        environment_->UpdateControlDependency(on_success);
      }
    }
  }

  return result;
}


Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) {
  const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count);
  Node** buffer = EnsureInputBufferSize(count + 1);
  MemsetPointer(buffer, input, count);
  buffer[count] = control;
  return graph()->NewNode(phi_op, count + 1, buffer, true);
}


Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input,
                                         Node* control) {
  const Operator* phi_op = common()->EffectPhi(count);
  Node** buffer = EnsureInputBufferSize(count + 1);
  MemsetPointer(buffer, input, count);
  buffer[count] = control;
  return graph()->NewNode(phi_op, count + 1, buffer, true);
}


Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) {
  int inputs = control->op()->ControlInputCount() + 1;
  if (control->opcode() == IrOpcode::kLoop) {
    // Control node for loop exists, add input.
    const Operator* op = common()->Loop(inputs);
    control->AppendInput(graph_zone(), other);
    NodeProperties::ChangeOp(control, op);
  } else if (control->opcode() == IrOpcode::kMerge) {
    // Control node for merge exists, add input.
    const Operator* op = common()->Merge(inputs);
    control->AppendInput(graph_zone(), other);
    NodeProperties::ChangeOp(control, op);
  } else {
    // Control node is a singleton, introduce a merge.
    const Operator* op = common()->Merge(inputs);
    Node* merge_inputs[] = {control, other};
    control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true);
  }
  return control;
}


Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other,
                                        Node* control) {
  int inputs = control->op()->ControlInputCount();
  if (value->opcode() == IrOpcode::kEffectPhi &&
      NodeProperties::GetControlInput(value) == control) {
    // Phi already exists, add input.
    value->InsertInput(graph_zone(), inputs - 1, other);
    NodeProperties::ChangeOp(value, common()->EffectPhi(inputs));
  } else if (value != other) {
    // Phi does not exist yet, introduce one.
    value = NewEffectPhi(inputs, value, control);
    value->ReplaceInput(inputs - 1, other);
  }
  return value;
}


Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other,
                                       Node* control) {
  int inputs = control->op()->ControlInputCount();
  if (value->opcode() == IrOpcode::kPhi &&
      NodeProperties::GetControlInput(value) == control) {
    // Phi already exists, add input.
    value->InsertInput(graph_zone(), inputs - 1, other);
    NodeProperties::ChangeOp(
        value, common()->Phi(MachineRepresentation::kTagged, inputs));
  } else if (value != other) {
    // Phi does not exist yet, introduce one.
    value = NewPhi(inputs, value, control);
    value->ReplaceInput(inputs - 1, other);
  }
  return value;
}


void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
  if (environment()->IsMarkedAsUnreachable()) return;
  environment()->MarkAsUnreachable();
  exit_controls_.push_back(exit);
}

}  // namespace compiler
}  // namespace internal
}  // namespace v8
