// Copyright 2014 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/js-generic-lowering.h"

#include "src/ast/ast.h"
#include "src/code-factory.h"
#include "src/code-stubs.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/machine-operator.h"
#include "src/compiler/node-matchers.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"

namespace v8 {
namespace internal {
namespace compiler {

namespace {

CallDescriptor::Flags FrameStateFlagForCall(Node* node) {
  return OperatorProperties::HasFrameStateInput(node->op())
             ? CallDescriptor::kNeedsFrameState
             : CallDescriptor::kNoFlags;
}

}  // namespace

JSGenericLowering::JSGenericLowering(JSGraph* jsgraph) : jsgraph_(jsgraph) {}

JSGenericLowering::~JSGenericLowering() {}


Reduction JSGenericLowering::Reduce(Node* node) {
  switch (node->opcode()) {
#define DECLARE_CASE(x)  \
    case IrOpcode::k##x: \
      Lower##x(node);    \
      break;
    JS_OP_LIST(DECLARE_CASE)
#undef DECLARE_CASE
    default:
      // Nothing to see.
      return NoChange();
  }
  return Changed(node);
}

#define REPLACE_STUB_CALL(Name)                                \
  void JSGenericLowering::LowerJS##Name(Node* node) {          \
    CallDescriptor::Flags flags = FrameStateFlagForCall(node); \
    Callable callable = CodeFactory::Name(isolate());          \
    ReplaceWithStubCall(node, callable, flags);                \
  }
REPLACE_STUB_CALL(Add)
REPLACE_STUB_CALL(Subtract)
REPLACE_STUB_CALL(Multiply)
REPLACE_STUB_CALL(Divide)
REPLACE_STUB_CALL(Modulus)
REPLACE_STUB_CALL(BitwiseAnd)
REPLACE_STUB_CALL(BitwiseOr)
REPLACE_STUB_CALL(BitwiseXor)
REPLACE_STUB_CALL(ShiftLeft)
REPLACE_STUB_CALL(ShiftRight)
REPLACE_STUB_CALL(ShiftRightLogical)
REPLACE_STUB_CALL(LessThan)
REPLACE_STUB_CALL(LessThanOrEqual)
REPLACE_STUB_CALL(GreaterThan)
REPLACE_STUB_CALL(GreaterThanOrEqual)
REPLACE_STUB_CALL(HasProperty)
REPLACE_STUB_CALL(Equal)
REPLACE_STUB_CALL(NotEqual)
REPLACE_STUB_CALL(ToInteger)
REPLACE_STUB_CALL(ToLength)
REPLACE_STUB_CALL(ToNumber)
REPLACE_STUB_CALL(ToName)
REPLACE_STUB_CALL(ToObject)
REPLACE_STUB_CALL(ToString)
#undef REPLACE_STUB_CALL

void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
                                            CallDescriptor::Flags flags) {
  ReplaceWithStubCall(node, callable, flags, node->op()->properties());
}

void JSGenericLowering::ReplaceWithStubCall(Node* node, Callable callable,
                                            CallDescriptor::Flags flags,
                                            Operator::Properties properties) {
  const CallInterfaceDescriptor& descriptor = callable.descriptor();
  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
      isolate(), zone(), descriptor, descriptor.GetStackParameterCount(), flags,
      properties);
  Node* stub_code = jsgraph()->HeapConstant(callable.code());
  node->InsertInput(zone(), 0, stub_code);
  NodeProperties::ChangeOp(node, common()->Call(desc));
}


void JSGenericLowering::ReplaceWithRuntimeCall(Node* node,
                                               Runtime::FunctionId f,
                                               int nargs_override) {
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  Operator::Properties properties = node->op()->properties();
  const Runtime::Function* fun = Runtime::FunctionForId(f);
  int nargs = (nargs_override < 0) ? fun->nargs : nargs_override;
  CallDescriptor* desc =
      Linkage::GetRuntimeCallDescriptor(zone(), f, nargs, properties, flags);
  Node* ref = jsgraph()->ExternalConstant(ExternalReference(f, isolate()));
  Node* arity = jsgraph()->Int32Constant(nargs);
  node->InsertInput(zone(), 0, jsgraph()->CEntryStubConstant(fun->result_size));
  node->InsertInput(zone(), nargs + 1, ref);
  node->InsertInput(zone(), nargs + 2, arity);
  NodeProperties::ChangeOp(node, common()->Call(desc));
}

void JSGenericLowering::LowerJSStrictEqual(Node* node) {
  // The === operator doesn't need the current context.
  NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
  Callable callable = CodeFactory::StrictEqual(isolate());
  node->RemoveInput(4);  // control
  ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
                      Operator::kEliminatable);
}

void JSGenericLowering::LowerJSStrictNotEqual(Node* node) {
  // The !== operator doesn't need the current context.
  NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
  Callable callable = CodeFactory::StrictNotEqual(isolate());
  node->RemoveInput(4);  // control
  ReplaceWithStubCall(node, callable, CallDescriptor::kNoFlags,
                      Operator::kEliminatable);
}

void JSGenericLowering::LowerJSToBoolean(Node* node) {
  // The ToBoolean conversion doesn't need the current context.
  NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
  Callable callable = CodeFactory::ToBoolean(isolate());
  node->AppendInput(zone(), graph()->start());
  ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
                      Operator::kEliminatable);
}

void JSGenericLowering::LowerJSTypeOf(Node* node) {
  // The typeof operator doesn't need the current context.
  NodeProperties::ReplaceContextInput(node, jsgraph()->NoContextConstant());
  Callable callable = CodeFactory::Typeof(isolate());
  node->AppendInput(zone(), graph()->start());
  ReplaceWithStubCall(node, callable, CallDescriptor::kNoAllocate,
                      Operator::kEliminatable);
}


void JSGenericLowering::LowerJSLoadProperty(Node* node) {
  Node* closure = NodeProperties::GetValueInput(node, 2);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  const PropertyAccess& p = PropertyAccessOf(node->op());
  Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
  // Load the type feedback vector from the closure.
  Node* literals = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), closure,
      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
      effect, control);
  Node* vector = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), literals,
      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                kHeapObjectTag),
      effect, control);
  node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
  node->ReplaceInput(3, vector);
  node->ReplaceInput(6, effect);
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSLoadNamed(Node* node) {
  Node* closure = NodeProperties::GetValueInput(node, 1);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  NamedAccess const& p = NamedAccessOf(node->op());
  Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
  // Load the type feedback vector from the closure.
  Node* literals = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), closure,
      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
      effect, control);
  Node* vector = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), literals,
      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                kHeapObjectTag),
      effect, control);
  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(p.name()));
  node->InsertInput(zone(), 2, jsgraph()->SmiConstant(p.feedback().index()));
  node->ReplaceInput(3, vector);
  node->ReplaceInput(6, effect);
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSLoadGlobal(Node* node) {
  Node* closure = NodeProperties::GetValueInput(node, 0);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  const LoadGlobalParameters& p = LoadGlobalParametersOf(node->op());
  Callable callable =
      CodeFactory::LoadGlobalICInOptimizedCode(isolate(), p.typeof_mode());
  // Load the type feedback vector from the closure.
  Node* literals = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), closure,
      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
      effect, control);
  Node* vector = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), literals,
      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                kHeapObjectTag),
      effect, control);
  node->InsertInput(zone(), 0, jsgraph()->SmiConstant(p.feedback().index()));
  node->ReplaceInput(1, vector);
  node->ReplaceInput(4, effect);
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSStoreProperty(Node* node) {
  Node* receiver = NodeProperties::GetValueInput(node, 0);
  Node* key = NodeProperties::GetValueInput(node, 1);
  Node* value = NodeProperties::GetValueInput(node, 2);
  Node* closure = NodeProperties::GetValueInput(node, 3);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  PropertyAccess const& p = PropertyAccessOf(node->op());
  LanguageMode language_mode = p.language_mode();
  Callable callable =
      CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode);
  // Load the type feedback vector from the closure.
  Node* literals = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), closure,
      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
      effect, control);
  Node* vector = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), literals,
      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                kHeapObjectTag),
      effect, control);
  typedef StoreWithVectorDescriptor Descriptor;
  node->InsertInputs(zone(), 0, 1);
  node->ReplaceInput(Descriptor::kReceiver, receiver);
  node->ReplaceInput(Descriptor::kName, key);
  node->ReplaceInput(Descriptor::kValue, value);
  node->ReplaceInput(Descriptor::kSlot,
                     jsgraph()->SmiConstant(p.feedback().index()));
  node->ReplaceInput(Descriptor::kVector, vector);
  node->ReplaceInput(7, effect);
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSStoreNamed(Node* node) {
  Node* receiver = NodeProperties::GetValueInput(node, 0);
  Node* value = NodeProperties::GetValueInput(node, 1);
  Node* closure = NodeProperties::GetValueInput(node, 2);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  NamedAccess const& p = NamedAccessOf(node->op());
  Callable callable =
      CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
  // Load the type feedback vector from the closure.
  Node* literals = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), closure,
      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
      effect, control);
  Node* vector = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), literals,
      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                kHeapObjectTag),
      effect, control);
  typedef StoreWithVectorDescriptor Descriptor;
  node->InsertInputs(zone(), 0, 2);
  node->ReplaceInput(Descriptor::kReceiver, receiver);
  node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name()));
  node->ReplaceInput(Descriptor::kValue, value);
  node->ReplaceInput(Descriptor::kSlot,
                     jsgraph()->SmiConstant(p.feedback().index()));
  node->ReplaceInput(Descriptor::kVector, vector);
  node->ReplaceInput(7, effect);
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSStoreGlobal(Node* node) {
  Node* value = NodeProperties::GetValueInput(node, 0);
  Node* closure = NodeProperties::GetValueInput(node, 1);
  Node* context = NodeProperties::GetContextInput(node);
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  const StoreGlobalParameters& p = StoreGlobalParametersOf(node->op());
  Callable callable =
      CodeFactory::StoreICInOptimizedCode(isolate(), p.language_mode());
  // Load the type feedback vector from the closure.
  Node* literals = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), closure,
      jsgraph()->IntPtrConstant(JSFunction::kLiteralsOffset - kHeapObjectTag),
      effect, control);
  Node* vector = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), literals,
      jsgraph()->IntPtrConstant(LiteralsArray::kFeedbackVectorOffset -
                                kHeapObjectTag),
      effect, control);
  // Load global object from the context.
  Node* native_context = effect =
      graph()->NewNode(machine()->Load(MachineType::AnyTagged()), context,
                       jsgraph()->IntPtrConstant(
                           Context::SlotOffset(Context::NATIVE_CONTEXT_INDEX)),
                       effect, control);
  Node* global = effect = graph()->NewNode(
      machine()->Load(MachineType::AnyTagged()), native_context,
      jsgraph()->IntPtrConstant(Context::SlotOffset(Context::EXTENSION_INDEX)),
      effect, control);
  typedef StoreWithVectorDescriptor Descriptor;
  node->InsertInputs(zone(), 0, 3);
  node->ReplaceInput(Descriptor::kReceiver, global);
  node->ReplaceInput(Descriptor::kName, jsgraph()->HeapConstant(p.name()));
  node->ReplaceInput(Descriptor::kValue, value);
  node->ReplaceInput(Descriptor::kSlot,
                     jsgraph()->SmiConstant(p.feedback().index()));
  node->ReplaceInput(Descriptor::kVector, vector);
  node->ReplaceInput(7, effect);
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSDeleteProperty(Node* node) {
  LanguageMode language_mode = OpParameter<LanguageMode>(node);
  ReplaceWithRuntimeCall(node, is_strict(language_mode)
                                   ? Runtime::kDeleteProperty_Strict
                                   : Runtime::kDeleteProperty_Sloppy);
}


void JSGenericLowering::LowerJSInstanceOf(Node* node) {
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  Callable callable = CodeFactory::InstanceOf(isolate());
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSLoadContext(Node* node) {
  const ContextAccess& access = ContextAccessOf(node->op());
  for (size_t i = 0; i < access.depth(); ++i) {
    node->ReplaceInput(
        0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
                            NodeProperties::GetValueInput(node, 0),
                            jsgraph()->Int32Constant(
                                Context::SlotOffset(Context::PREVIOUS_INDEX)),
                            NodeProperties::GetEffectInput(node),
                            graph()->start()));
  }
  node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
                            static_cast<int>(access.index()))));
  node->AppendInput(zone(), graph()->start());
  NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
}


void JSGenericLowering::LowerJSStoreContext(Node* node) {
  const ContextAccess& access = ContextAccessOf(node->op());
  for (size_t i = 0; i < access.depth(); ++i) {
    node->ReplaceInput(
        0, graph()->NewNode(machine()->Load(MachineType::AnyTagged()),
                            NodeProperties::GetValueInput(node, 0),
                            jsgraph()->Int32Constant(
                                Context::SlotOffset(Context::PREVIOUS_INDEX)),
                            NodeProperties::GetEffectInput(node),
                            graph()->start()));
  }
  node->ReplaceInput(2, NodeProperties::GetValueInput(node, 1));
  node->ReplaceInput(1, jsgraph()->Int32Constant(Context::SlotOffset(
                            static_cast<int>(access.index()))));
  NodeProperties::ChangeOp(
      node, machine()->Store(StoreRepresentation(MachineRepresentation::kTagged,
                                                 kFullWriteBarrier)));
}


void JSGenericLowering::LowerJSCreate(Node* node) {
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  Callable callable = CodeFactory::FastNewObject(isolate());
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSCreateArguments(Node* node) {
  CreateArgumentsType const type = CreateArgumentsTypeOf(node->op());
  switch (type) {
    case CreateArgumentsType::kMappedArguments:
      ReplaceWithRuntimeCall(node, Runtime::kNewSloppyArguments_Generic);
      break;
    case CreateArgumentsType::kUnmappedArguments:
      ReplaceWithRuntimeCall(node, Runtime::kNewStrictArguments);
      break;
    case CreateArgumentsType::kRestParameter:
      ReplaceWithRuntimeCall(node, Runtime::kNewRestParameter);
      break;
  }
}


void JSGenericLowering::LowerJSCreateArray(Node* node) {
  CreateArrayParameters const& p = CreateArrayParametersOf(node->op());
  int const arity = static_cast<int>(p.arity());
  Handle<AllocationSite> const site = p.site();
  Node* new_target = node->InputAt(1);
  Node* type_info = site.is_null() ? jsgraph()->UndefinedConstant()
                                   : jsgraph()->HeapConstant(site);
  node->RemoveInput(1);
  node->InsertInput(zone(), 1 + arity, new_target);
  node->InsertInput(zone(), 2 + arity, type_info);
  ReplaceWithRuntimeCall(node, Runtime::kNewArray, arity + 3);
}


void JSGenericLowering::LowerJSCreateClosure(Node* node) {
  CreateClosureParameters const& p = CreateClosureParametersOf(node->op());
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  Handle<SharedFunctionInfo> const shared_info = p.shared_info();
  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(shared_info));

  // Use the FastNewClosureStub only for functions allocated in new space.
  if (p.pretenure() == NOT_TENURED) {
    Callable callable = CodeFactory::FastNewClosure(isolate());
    ReplaceWithStubCall(node, callable, flags);
  } else {
    ReplaceWithRuntimeCall(node, (p.pretenure() == TENURED)
                                     ? Runtime::kNewClosure_Tenured
                                     : Runtime::kNewClosure);
  }
}


void JSGenericLowering::LowerJSCreateFunctionContext(Node* node) {
  int const slot_count = OpParameter<int>(node->op());
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);

  if (slot_count <= FastNewFunctionContextStub::kMaximumSlots) {
    Callable callable = CodeFactory::FastNewFunctionContext(isolate());
    node->InsertInput(zone(), 1, jsgraph()->Int32Constant(slot_count));
    ReplaceWithStubCall(node, callable, flags);
  } else {
    ReplaceWithRuntimeCall(node, Runtime::kNewFunctionContext);
  }
}


void JSGenericLowering::LowerJSCreateIterResultObject(Node* node) {
  ReplaceWithRuntimeCall(node, Runtime::kCreateIterResultObject);
}


void JSGenericLowering::LowerJSCreateLiteralArray(Node* node) {
  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
  node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));

  // Use the FastCloneShallowArrayStub only for shallow boilerplates up to the
  // initial length limit for arrays with "fast" elements kind.
  if ((p.flags() & ArrayLiteral::kShallowElements) != 0 &&
      p.length() < JSArray::kInitialMaxFastElementArray) {
    Callable callable = CodeFactory::FastCloneShallowArray(isolate());
    ReplaceWithStubCall(node, callable, flags);
  } else {
    node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));
    ReplaceWithRuntimeCall(node, Runtime::kCreateArrayLiteral);
  }
}


void JSGenericLowering::LowerJSCreateLiteralObject(Node* node) {
  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  node->InsertInput(zone(), 1, jsgraph()->SmiConstant(p.index()));
  node->InsertInput(zone(), 2, jsgraph()->HeapConstant(p.constant()));
  node->InsertInput(zone(), 3, jsgraph()->SmiConstant(p.flags()));

  // Use the FastCloneShallowObjectStub only for shallow boilerplates without
  // elements up to the number of properties that the stubs can handle.
  if ((p.flags() & ObjectLiteral::kShallowProperties) != 0 &&
      p.length() <= FastCloneShallowObjectStub::kMaximumClonedProperties) {
    Callable callable =
        CodeFactory::FastCloneShallowObject(isolate(), p.length());
    ReplaceWithStubCall(node, callable, flags);
  } else {
    ReplaceWithRuntimeCall(node, Runtime::kCreateObjectLiteral);
  }
}


void JSGenericLowering::LowerJSCreateLiteralRegExp(Node* node) {
  CreateLiteralParameters const& p = CreateLiteralParametersOf(node->op());
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  Callable callable = CodeFactory::FastCloneRegExp(isolate());
  Node* literal_index = jsgraph()->SmiConstant(p.index());
  Node* literal_flags = jsgraph()->SmiConstant(p.flags());
  Node* pattern = jsgraph()->HeapConstant(p.constant());
  node->InsertInput(graph()->zone(), 1, literal_index);
  node->InsertInput(graph()->zone(), 2, pattern);
  node->InsertInput(graph()->zone(), 3, literal_flags);
  ReplaceWithStubCall(node, callable, flags);
}


void JSGenericLowering::LowerJSCreateCatchContext(Node* node) {
  const CreateCatchContextParameters& parameters =
      CreateCatchContextParametersOf(node->op());
  node->InsertInput(zone(), 0,
                    jsgraph()->HeapConstant(parameters.catch_name()));
  node->InsertInput(zone(), 2,
                    jsgraph()->HeapConstant(parameters.scope_info()));
  ReplaceWithRuntimeCall(node, Runtime::kPushCatchContext);
}

void JSGenericLowering::LowerJSCreateWithContext(Node* node) {
  Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
  ReplaceWithRuntimeCall(node, Runtime::kPushWithContext);
}

void JSGenericLowering::LowerJSCreateBlockContext(Node* node) {
  Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(scope_info));
  ReplaceWithRuntimeCall(node, Runtime::kPushBlockContext);
}


void JSGenericLowering::LowerJSCreateScriptContext(Node* node) {
  Handle<ScopeInfo> scope_info = OpParameter<Handle<ScopeInfo>>(node);
  node->InsertInput(zone(), 1, jsgraph()->HeapConstant(scope_info));
  ReplaceWithRuntimeCall(node, Runtime::kNewScriptContext);
}


void JSGenericLowering::LowerJSCallConstruct(Node* node) {
  CallConstructParameters const& p = CallConstructParametersOf(node->op());
  int const arg_count = static_cast<int>(p.arity() - 2);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  Callable callable = CodeFactory::Construct(isolate());
  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
      isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
  Node* stub_code = jsgraph()->HeapConstant(callable.code());
  Node* stub_arity = jsgraph()->Int32Constant(arg_count);
  Node* new_target = node->InputAt(arg_count + 1);
  Node* receiver = jsgraph()->UndefinedConstant();
  node->RemoveInput(arg_count + 1);  // Drop new target.
  node->InsertInput(zone(), 0, stub_code);
  node->InsertInput(zone(), 2, new_target);
  node->InsertInput(zone(), 3, stub_arity);
  node->InsertInput(zone(), 4, receiver);
  NodeProperties::ChangeOp(node, common()->Call(desc));
}


void JSGenericLowering::LowerJSCallFunction(Node* node) {
  CallFunctionParameters const& p = CallFunctionParametersOf(node->op());
  int const arg_count = static_cast<int>(p.arity() - 2);
  ConvertReceiverMode const mode = p.convert_mode();
  Callable callable = CodeFactory::Call(isolate(), mode);
  CallDescriptor::Flags flags = FrameStateFlagForCall(node);
  if (p.tail_call_mode() == TailCallMode::kAllow) {
    flags |= CallDescriptor::kSupportsTailCalls;
  }
  CallDescriptor* desc = Linkage::GetStubCallDescriptor(
      isolate(), zone(), callable.descriptor(), arg_count + 1, flags);
  Node* stub_code = jsgraph()->HeapConstant(callable.code());
  Node* stub_arity = jsgraph()->Int32Constant(arg_count);
  node->InsertInput(zone(), 0, stub_code);
  node->InsertInput(zone(), 2, stub_arity);
  NodeProperties::ChangeOp(node, common()->Call(desc));
}


void JSGenericLowering::LowerJSCallRuntime(Node* node) {
  const CallRuntimeParameters& p = CallRuntimeParametersOf(node->op());
  ReplaceWithRuntimeCall(node, p.id(), static_cast<int>(p.arity()));
}

void JSGenericLowering::LowerJSConvertReceiver(Node* node) {
  ReplaceWithRuntimeCall(node, Runtime::kConvertReceiver);
}

void JSGenericLowering::LowerJSForInNext(Node* node) {
  ReplaceWithRuntimeCall(node, Runtime::kForInNext);
}


void JSGenericLowering::LowerJSForInPrepare(Node* node) {
  ReplaceWithRuntimeCall(node, Runtime::kForInPrepare);
}

void JSGenericLowering::LowerJSLoadMessage(Node* node) {
  ExternalReference message_address =
      ExternalReference::address_of_pending_message_obj(isolate());
  node->RemoveInput(NodeProperties::FirstContextIndex(node));
  node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
  node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
  NodeProperties::ChangeOp(node, machine()->Load(MachineType::AnyTagged()));
}


void JSGenericLowering::LowerJSStoreMessage(Node* node) {
  ExternalReference message_address =
      ExternalReference::address_of_pending_message_obj(isolate());
  node->RemoveInput(NodeProperties::FirstContextIndex(node));
  node->InsertInput(zone(), 0, jsgraph()->ExternalConstant(message_address));
  node->InsertInput(zone(), 1, jsgraph()->IntPtrConstant(0));
  StoreRepresentation representation(MachineRepresentation::kTagged,
                                     kNoWriteBarrier);
  NodeProperties::ChangeOp(node, machine()->Store(representation));
}

void JSGenericLowering::LowerJSLoadModule(Node* node) {
  UNREACHABLE();  // Eliminated in typed lowering.
}

void JSGenericLowering::LowerJSStoreModule(Node* node) {
  UNREACHABLE();  // Eliminated in typed lowering.
}

void JSGenericLowering::LowerJSGeneratorStore(Node* node) {
  UNREACHABLE();  // Eliminated in typed lowering.
}

void JSGenericLowering::LowerJSGeneratorRestoreContinuation(Node* node) {
  UNREACHABLE();  // Eliminated in typed lowering.
}

void JSGenericLowering::LowerJSGeneratorRestoreRegister(Node* node) {
  UNREACHABLE();  // Eliminated in typed lowering.
}

void JSGenericLowering::LowerJSStackCheck(Node* node) {
  Node* effect = NodeProperties::GetEffectInput(node);
  Node* control = NodeProperties::GetControlInput(node);

  Node* limit = graph()->NewNode(
      machine()->Load(MachineType::Pointer()),
      jsgraph()->ExternalConstant(
          ExternalReference::address_of_stack_limit(isolate())),
      jsgraph()->IntPtrConstant(0), effect, control);
  Node* pointer = graph()->NewNode(machine()->LoadStackPointer());

  Node* check = graph()->NewNode(machine()->UintLessThan(), limit, pointer);
  Node* branch =
      graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);

  Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
  Node* etrue = effect;

  Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
  NodeProperties::ReplaceControlInput(node, if_false);
  Node* efalse = node;

  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
  Node* ephi = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, merge);

  // Wire the new diamond into the graph, {node} can still throw.
  NodeProperties::ReplaceUses(node, node, ephi, node, node);
  NodeProperties::ReplaceEffectInput(ephi, efalse, 1);

  // TODO(mstarzinger): This iteration cuts out the IfSuccess projection from
  // the node and places it inside the diamond. Come up with a helper method!
  for (Node* use : node->uses()) {
    if (use->opcode() == IrOpcode::kIfSuccess) {
      use->ReplaceUses(merge);
      merge->ReplaceInput(1, use);
    }
  }

  // Turn the stack check into a runtime call.
  ReplaceWithRuntimeCall(node, Runtime::kStackGuard);
}


Zone* JSGenericLowering::zone() const { return graph()->zone(); }


Isolate* JSGenericLowering::isolate() const { return jsgraph()->isolate(); }


Graph* JSGenericLowering::graph() const { return jsgraph()->graph(); }


CommonOperatorBuilder* JSGenericLowering::common() const {
  return jsgraph()->common();
}


MachineOperatorBuilder* JSGenericLowering::machine() const {
  return jsgraph()->machine();
}

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