// 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/linkage.h"
#include "src/compiler/operator-properties.h"
#include "src/interpreter/bytecode-array-iterator.h"

namespace v8 {
namespace internal {
namespace compiler {

// Issues:
// - Need to deal with FrameState / FrameStateBeforeAndAfter / StateValue.
// - 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()) {
  // The layout of values_ is:
  //
  // [receiver] [parameters] [registers]
  //
  // 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_ = undefined_constant;
}


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 {
  int values_index = RegisterToValuesIndex(the_register);
  return values()->at(values_index);
}


void BytecodeGraphBuilder::Environment::BindAccumulator(Node* node) {
  accumulator_ = node;
}


Node* BytecodeGraphBuilder::Environment::LookupAccumulator() const {
  return accumulator_;
}


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


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


BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone,
                                           CompilationInfo* compilation_info,
                                           JSGraph* jsgraph)
    : local_zone_(local_zone),
      info_(compilation_info),
      jsgraph_(jsgraph),
      input_buffer_size_(0),
      input_buffer_(nullptr),
      exit_controls_(local_zone) {
  bytecode_array_ = handle(info()->shared_info()->bytecode_array());
}


Node* BytecodeGraphBuilder::GetFunctionContext() {
  if (!function_context_.is_set()) {
    // Parameter (arity + 1) is special for the outer context of the function
    const Operator* op =
        common()->Parameter(bytecode_array()->parameter_count(), "%context");
    Node* node = NewNode(op, graph()->start());
    function_context_.set(node);
  }
  return function_context_.get();
}


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.

  // The additional count items are for the context and closure.
  int actual_parameter_count = bytecode_array()->parameter_count() + 2;
  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);

  // Build function context only if there are context allocated variables.
  if (info()->num_heap_slots() > 0) {
    UNIMPLEMENTED();  // TODO(oth): Write ast-graph-builder equivalent.
  } else {
    // Simply use the outer function context in building the graph.
    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() {
  interpreter::BytecodeArrayIterator iterator(bytecode_array());
  while (!iterator.done()) {
    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();
  }
}


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::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::VisitLdaGlobalSloppy(
    const interpreter::BytecodeArrayIterator& iterator) {
  UNIMPLEMENTED();
}


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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

  // TODO(oth): Real frame state and environment check pointing.
  int frame_state_count =
      OperatorProperties::GetFrameStateInputCount(node->op());
  for (int i = 0; i < frame_state_count; i++) {
    NodeProperties::ReplaceFrameStateInput(node, i,
                                           jsgraph()->EmptyFrameState());
  }
  environment()->BindAccumulator(node);
}


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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::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;
}


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

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