// 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/interpreter-assembler.h"

#include <ostream>

#include "src/code-factory.h"
#include "src/compiler/graph.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/linkage.h"
#include "src/compiler/pipeline.h"
#include "src/compiler/raw-machine-assembler.h"
#include "src/compiler/schedule.h"
#include "src/frames.h"
#include "src/interface-descriptors.h"
#include "src/interpreter/bytecodes.h"
#include "src/machine-type.h"
#include "src/macro-assembler.h"
#include "src/zone.h"

namespace v8 {
namespace internal {
namespace compiler {

InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
                                           interpreter::Bytecode bytecode)
    : bytecode_(bytecode),
      raw_assembler_(new RawMachineAssembler(
          isolate, new (zone) Graph(zone),
          Linkage::GetInterpreterDispatchDescriptor(zone),
          MachineType::PointerRepresentation(),
          InstructionSelector::SupportedMachineOperatorFlags())),
      accumulator_(
          raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)),
      context_(
          raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)),
      code_generated_(false) {
  if (FLAG_trace_ignition) {
    TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
  }
}

InterpreterAssembler::~InterpreterAssembler() {}


Handle<Code> InterpreterAssembler::GenerateCode() {
  DCHECK(!code_generated_);

  // Disallow empty handlers that never return.
  DCHECK_NE(0, graph()->end()->InputCount());

  const char* bytecode_name = interpreter::Bytecodes::ToString(bytecode_);
  Schedule* schedule = raw_assembler_->Export();
  Code::Flags flags = Code::ComputeFlags(Code::STUB);
  Handle<Code> code = Pipeline::GenerateCodeForCodeStub(
      isolate(), raw_assembler_->call_descriptor(), graph(), schedule, flags,
      bytecode_name);

#ifdef ENABLE_DISASSEMBLER
  if (FLAG_trace_ignition_codegen) {
    OFStream os(stdout);
    code->Disassemble(bytecode_name, os);
    os << std::flush;
  }
#endif

  code_generated_ = true;
  return code;
}


Node* InterpreterAssembler::GetAccumulator() { return accumulator_; }


void InterpreterAssembler::SetAccumulator(Node* value) { accumulator_ = value; }


Node* InterpreterAssembler::GetContext() { return context_; }


void InterpreterAssembler::SetContext(Node* value) {
  StoreRegister(value, interpreter::Register::current_context());
  context_ = value;
}

Node* InterpreterAssembler::BytecodeOffset() {
  return raw_assembler_->Parameter(
      Linkage::kInterpreterBytecodeOffsetParameter);
}

Node* InterpreterAssembler::RegisterFileRawPointer() {
  return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter);
}


Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
  return raw_assembler_->Parameter(Linkage::kInterpreterBytecodeArrayParameter);
}


Node* InterpreterAssembler::DispatchTableRawPointer() {
  return raw_assembler_->Parameter(Linkage::kInterpreterDispatchTableParameter);
}


Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
  return IntPtrAdd(RegisterFileRawPointer(), RegisterFrameOffset(reg_index));
}


Node* InterpreterAssembler::LoadRegister(int offset) {
  return raw_assembler_->Load(MachineType::AnyTagged(),
                              RegisterFileRawPointer(), Int32Constant(offset));
}


Node* InterpreterAssembler::LoadRegister(interpreter::Register reg) {
  return LoadRegister(reg.ToOperand() << kPointerSizeLog2);
}


Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
  return WordShl(index, kPointerSizeLog2);
}


Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
  return raw_assembler_->Load(MachineType::AnyTagged(),
                              RegisterFileRawPointer(),
                              RegisterFrameOffset(reg_index));
}


Node* InterpreterAssembler::StoreRegister(Node* value, int offset) {
  return raw_assembler_->Store(MachineRepresentation::kTagged,
                               RegisterFileRawPointer(), Int32Constant(offset),
                               value, kNoWriteBarrier);
}


Node* InterpreterAssembler::StoreRegister(Node* value,
                                          interpreter::Register reg) {
  return StoreRegister(value, reg.ToOperand() << kPointerSizeLog2);
}


Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
  return raw_assembler_->Store(
      MachineRepresentation::kTagged, RegisterFileRawPointer(),
      RegisterFrameOffset(reg_index), value, kNoWriteBarrier);
}


Node* InterpreterAssembler::NextRegister(Node* reg_index) {
  // Register indexes are negative, so the next index is minus one.
  return IntPtrAdd(reg_index, Int32Constant(-1));
}


Node* InterpreterAssembler::BytecodeOperand(int operand_index) {
  DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
  DCHECK_EQ(interpreter::OperandSize::kByte,
            interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
  return raw_assembler_->Load(
      MachineType::Uint8(), BytecodeArrayTaggedPointer(),
      IntPtrAdd(BytecodeOffset(),
                Int32Constant(interpreter::Bytecodes::GetOperandOffset(
                    bytecode_, operand_index))));
}


Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) {
  DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
  DCHECK_EQ(interpreter::OperandSize::kByte,
            interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
  Node* load = raw_assembler_->Load(
      MachineType::Int8(), BytecodeArrayTaggedPointer(),
      IntPtrAdd(BytecodeOffset(),
                Int32Constant(interpreter::Bytecodes::GetOperandOffset(
                    bytecode_, operand_index))));
  // Ensure that we sign extend to full pointer size
  if (kPointerSize == 8) {
    load = raw_assembler_->ChangeInt32ToInt64(load);
  }
  return load;
}


Node* InterpreterAssembler::BytecodeOperandShort(int operand_index) {
  DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
  DCHECK_EQ(interpreter::OperandSize::kShort,
            interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
  if (TargetSupportsUnalignedAccess()) {
    return raw_assembler_->Load(
        MachineType::Uint16(), BytecodeArrayTaggedPointer(),
        IntPtrAdd(BytecodeOffset(),
                  Int32Constant(interpreter::Bytecodes::GetOperandOffset(
                      bytecode_, operand_index))));
  } else {
    int offset =
        interpreter::Bytecodes::GetOperandOffset(bytecode_, operand_index);
    Node* first_byte = raw_assembler_->Load(
        MachineType::Uint8(), BytecodeArrayTaggedPointer(),
        IntPtrAdd(BytecodeOffset(), Int32Constant(offset)));
    Node* second_byte = raw_assembler_->Load(
        MachineType::Uint8(), BytecodeArrayTaggedPointer(),
        IntPtrAdd(BytecodeOffset(), Int32Constant(offset + 1)));
#if V8_TARGET_LITTLE_ENDIAN
    return raw_assembler_->WordOr(WordShl(second_byte, kBitsPerByte),
                                  first_byte);
#elif V8_TARGET_BIG_ENDIAN
    return raw_assembler_->WordOr(WordShl(first_byte, kBitsPerByte),
                                  second_byte);
#else
#error "Unknown Architecture"
#endif
  }
}


Node* InterpreterAssembler::BytecodeOperandShortSignExtended(
    int operand_index) {
  DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
  DCHECK_EQ(interpreter::OperandSize::kShort,
            interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index));
  int operand_offset =
      interpreter::Bytecodes::GetOperandOffset(bytecode_, operand_index);
  Node* load;
  if (TargetSupportsUnalignedAccess()) {
    load = raw_assembler_->Load(
        MachineType::Int16(), BytecodeArrayTaggedPointer(),
        IntPtrAdd(BytecodeOffset(), Int32Constant(operand_offset)));
  } else {
#if V8_TARGET_LITTLE_ENDIAN
    Node* hi_byte_offset = Int32Constant(operand_offset + 1);
    Node* lo_byte_offset = Int32Constant(operand_offset);
#elif V8_TARGET_BIG_ENDIAN
    Node* hi_byte_offset = Int32Constant(operand_offset);
    Node* lo_byte_offset = Int32Constant(operand_offset + 1);
#else
#error "Unknown Architecture"
#endif
    Node* hi_byte =
        raw_assembler_->Load(MachineType::Int8(), BytecodeArrayTaggedPointer(),
                             IntPtrAdd(BytecodeOffset(), hi_byte_offset));
    Node* lo_byte =
        raw_assembler_->Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(),
                             IntPtrAdd(BytecodeOffset(), lo_byte_offset));
    hi_byte = raw_assembler_->Word32Shl(hi_byte, Int32Constant(kBitsPerByte));
    load = raw_assembler_->Word32Or(hi_byte, lo_byte);
  }

  // Ensure that we sign extend to full pointer size
  if (kPointerSize == 8) {
    load = raw_assembler_->ChangeInt32ToInt64(load);
  }
  return load;
}


Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) {
  switch (interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index)) {
    case interpreter::OperandSize::kByte:
      DCHECK_EQ(
          interpreter::OperandType::kRegCount8,
          interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
      return BytecodeOperand(operand_index);
    case interpreter::OperandSize::kShort:
      DCHECK_EQ(
          interpreter::OperandType::kRegCount16,
          interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
      return BytecodeOperandShort(operand_index);
    case interpreter::OperandSize::kNone:
      UNREACHABLE();
  }
  return nullptr;
}


Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) {
  DCHECK_EQ(interpreter::OperandType::kImm8,
            interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
  return BytecodeOperandSignExtended(operand_index);
}


Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) {
  switch (interpreter::Bytecodes::GetOperandSize(bytecode_, operand_index)) {
    case interpreter::OperandSize::kByte:
      DCHECK_EQ(
          interpreter::OperandType::kIdx8,
          interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
      return BytecodeOperand(operand_index);
    case interpreter::OperandSize::kShort:
      DCHECK_EQ(
          interpreter::OperandType::kIdx16,
          interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
      return BytecodeOperandShort(operand_index);
    case interpreter::OperandSize::kNone:
      UNREACHABLE();
  }
  return nullptr;
}


Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) {
  interpreter::OperandType operand_type =
      interpreter::Bytecodes::GetOperandType(bytecode_, operand_index);
  if (interpreter::Bytecodes::IsRegisterOperandType(operand_type)) {
    interpreter::OperandSize operand_size =
        interpreter::Bytecodes::SizeOfOperand(operand_type);
    if (operand_size == interpreter::OperandSize::kByte) {
      return BytecodeOperandSignExtended(operand_index);
    } else if (operand_size == interpreter::OperandSize::kShort) {
      return BytecodeOperandShortSignExtended(operand_index);
    }
  }
  UNREACHABLE();
  return nullptr;
}


Node* InterpreterAssembler::Int32Constant(int value) {
  return raw_assembler_->Int32Constant(value);
}


Node* InterpreterAssembler::IntPtrConstant(intptr_t value) {
  return raw_assembler_->IntPtrConstant(value);
}


Node* InterpreterAssembler::NumberConstant(double value) {
  return raw_assembler_->NumberConstant(value);
}


Node* InterpreterAssembler::HeapConstant(Handle<HeapObject> object) {
  return raw_assembler_->HeapConstant(object);
}


Node* InterpreterAssembler::BooleanConstant(bool value) {
  return raw_assembler_->BooleanConstant(value);
}


Node* InterpreterAssembler::SmiShiftBitsConstant() {
  return Int32Constant(kSmiShiftSize + kSmiTagSize);
}


Node* InterpreterAssembler::SmiTag(Node* value) {
  return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
}


Node* InterpreterAssembler::SmiUntag(Node* value) {
  return raw_assembler_->WordSar(value, SmiShiftBitsConstant());
}


Node* InterpreterAssembler::IntPtrAdd(Node* a, Node* b) {
  return raw_assembler_->IntPtrAdd(a, b);
}


Node* InterpreterAssembler::IntPtrSub(Node* a, Node* b) {
  return raw_assembler_->IntPtrSub(a, b);
}

Node* InterpreterAssembler::Int32Sub(Node* a, Node* b) {
  return raw_assembler_->Int32Sub(a, b);
}

Node* InterpreterAssembler::WordShl(Node* value, int shift) {
  return raw_assembler_->WordShl(value, Int32Constant(shift));
}


Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
  Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
                                        BytecodeArray::kConstantPoolOffset);
  Node* entry_offset =
      IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
                WordShl(index, kPointerSizeLog2));
  return raw_assembler_->Load(MachineType::AnyTagged(), constant_pool,
                              entry_offset);
}


Node* InterpreterAssembler::LoadFixedArrayElement(Node* fixed_array,
                                                  int index) {
  Node* entry_offset =
      IntPtrAdd(IntPtrConstant(FixedArray::kHeaderSize - kHeapObjectTag),
                WordShl(Int32Constant(index), kPointerSizeLog2));
  return raw_assembler_->Load(MachineType::AnyTagged(), fixed_array,
                              entry_offset);
}


Node* InterpreterAssembler::LoadObjectField(Node* object, int offset) {
  return raw_assembler_->Load(MachineType::AnyTagged(), object,
                              IntPtrConstant(offset - kHeapObjectTag));
}


Node* InterpreterAssembler::LoadContextSlot(Node* context, int slot_index) {
  return raw_assembler_->Load(MachineType::AnyTagged(), context,
                              IntPtrConstant(Context::SlotOffset(slot_index)));
}


Node* InterpreterAssembler::LoadContextSlot(Node* context, Node* slot_index) {
  Node* offset =
      IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
                Int32Constant(Context::kHeaderSize - kHeapObjectTag));
  return raw_assembler_->Load(MachineType::AnyTagged(), context, offset);
}


Node* InterpreterAssembler::StoreContextSlot(Node* context, Node* slot_index,
                                             Node* value) {
  Node* offset =
      IntPtrAdd(WordShl(slot_index, kPointerSizeLog2),
                Int32Constant(Context::kHeaderSize - kHeapObjectTag));
  return raw_assembler_->Store(MachineRepresentation::kTagged, context, offset,
                               value, kFullWriteBarrier);
}


Node* InterpreterAssembler::LoadTypeFeedbackVector() {
  Node* function = raw_assembler_->Load(
      MachineType::AnyTagged(), RegisterFileRawPointer(),
      IntPtrConstant(InterpreterFrameConstants::kFunctionFromRegisterPointer));
  Node* shared_info =
      LoadObjectField(function, JSFunction::kSharedFunctionInfoOffset);
  Node* vector =
      LoadObjectField(shared_info, SharedFunctionInfo::kFeedbackVectorOffset);
  return vector;
}


Node* InterpreterAssembler::Projection(int index, Node* node) {
  return raw_assembler_->Projection(index, node);
}


Node* InterpreterAssembler::CallConstruct(Node* new_target, Node* constructor,
                                          Node* first_arg, Node* arg_count) {
  Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(isolate());
  CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
      isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags);

  Node* code_target = HeapConstant(callable.code());

  Node** args = zone()->NewArray<Node*>(5);
  args[0] = arg_count;
  args[1] = new_target;
  args[2] = constructor;
  args[3] = first_arg;
  args[4] = GetContext();

  return CallN(descriptor, code_target, args);
}


void InterpreterAssembler::CallPrologue() {
  StoreRegister(SmiTag(BytecodeOffset()),
                InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer);
}


Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
                                  Node** args) {
  CallPrologue();

  Node* stack_pointer_before_call = nullptr;
  if (FLAG_debug_code) {
    stack_pointer_before_call = raw_assembler_->LoadStackPointer();
  }
  Node* return_val = raw_assembler_->CallN(descriptor, code_target, args);
  if (FLAG_debug_code) {
    Node* stack_pointer_after_call = raw_assembler_->LoadStackPointer();
    AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
                        kUnexpectedStackPointer);
  }

  return return_val;
}


Node* InterpreterAssembler::CallJS(Node* function, Node* first_arg,
                                   Node* arg_count) {
  Callable callable = CodeFactory::InterpreterPushArgsAndCall(isolate());
  CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
      isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags);

  Node* code_target = HeapConstant(callable.code());

  Node** args = zone()->NewArray<Node*>(4);
  args[0] = arg_count;
  args[1] = first_arg;
  args[2] = function;
  args[3] = GetContext();

  return CallN(descriptor, code_target, args);
}


Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
                                   Node* target, Node** args) {
  CallDescriptor* call_descriptor = Linkage::GetStubCallDescriptor(
      isolate(), zone(), descriptor, 0, CallDescriptor::kNoFlags);
  return CallN(call_descriptor, target, args);
}


Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
                                   Node* target, Node* arg1, Node* arg2,
                                   Node* arg3) {
  Node** args = zone()->NewArray<Node*>(4);
  args[0] = arg1;
  args[1] = arg2;
  args[2] = arg3;
  args[3] = GetContext();
  return CallIC(descriptor, target, args);
}


Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
                                   Node* target, Node* arg1, Node* arg2,
                                   Node* arg3, Node* arg4) {
  Node** args = zone()->NewArray<Node*>(5);
  args[0] = arg1;
  args[1] = arg2;
  args[2] = arg3;
  args[3] = arg4;
  args[4] = GetContext();
  return CallIC(descriptor, target, args);
}


Node* InterpreterAssembler::CallIC(CallInterfaceDescriptor descriptor,
                                   Node* target, Node* arg1, Node* arg2,
                                   Node* arg3, Node* arg4, Node* arg5) {
  Node** args = zone()->NewArray<Node*>(6);
  args[0] = arg1;
  args[1] = arg2;
  args[2] = arg3;
  args[3] = arg4;
  args[4] = arg5;
  args[5] = GetContext();
  return CallIC(descriptor, target, args);
}


Node* InterpreterAssembler::CallRuntime(Node* function_id, Node* first_arg,
                                        Node* arg_count, int result_size) {
  Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size);
  CallDescriptor* descriptor = Linkage::GetStubCallDescriptor(
      isolate(), zone(), callable.descriptor(), 0, CallDescriptor::kNoFlags,
      Operator::kNoProperties, MachineType::AnyTagged(), result_size);
  Node* code_target = HeapConstant(callable.code());

  // Get the function entry from the function id.
  Node* function_table = raw_assembler_->ExternalConstant(
      ExternalReference::runtime_function_table_address(isolate()));
  Node* function_offset = raw_assembler_->Int32Mul(
      function_id, Int32Constant(sizeof(Runtime::Function)));
  Node* function = IntPtrAdd(function_table, function_offset);
  Node* function_entry =
      raw_assembler_->Load(MachineType::Pointer(), function,
                           Int32Constant(offsetof(Runtime::Function, entry)));

  Node** args = zone()->NewArray<Node*>(4);
  args[0] = arg_count;
  args[1] = first_arg;
  args[2] = function_entry;
  args[3] = GetContext();

  return CallN(descriptor, code_target, args);
}

Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id) {
  CallPrologue();
  Node* return_val = raw_assembler_->CallRuntime0(function_id, GetContext());
  return return_val;
}

Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
                                        Node* arg1) {
  CallPrologue();
  Node* return_val =
      raw_assembler_->CallRuntime1(function_id, arg1, GetContext());
  return return_val;
}


Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
                                        Node* arg1, Node* arg2) {
  CallPrologue();
  Node* return_val =
      raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext());
  return return_val;
}

Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
                                        Node* arg1, Node* arg2, Node* arg3) {
  CallPrologue();
  Node* return_val =
      raw_assembler_->CallRuntime3(function_id, arg1, arg2, arg3, GetContext());
  return return_val;
}

Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
                                        Node* arg1, Node* arg2, Node* arg3,
                                        Node* arg4) {
  CallPrologue();
  Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3,
                                                  arg4, GetContext());
  return return_val;
}


void InterpreterAssembler::Return() {
  if (FLAG_trace_ignition) {
    TraceBytecode(Runtime::kInterpreterTraceBytecodeExit);
  }

  Node* exit_trampoline_code_object =
      HeapConstant(isolate()->builtins()->InterpreterExitTrampoline());
  // If the order of the parameters you need to change the call signature below.
  STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
  STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
  STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
  STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
  STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
  STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
  Node* args[] = { GetAccumulator(),
                   RegisterFileRawPointer(),
                   BytecodeOffset(),
                   BytecodeArrayTaggedPointer(),
                   DispatchTableRawPointer(),
                   GetContext() };
  raw_assembler_->TailCallN(call_descriptor(), exit_trampoline_code_object,
                            args);
}


Node* InterpreterAssembler::Advance(int delta) {
  return IntPtrAdd(BytecodeOffset(), Int32Constant(delta));
}


Node* InterpreterAssembler::Advance(Node* delta) {
  return raw_assembler_->IntPtrAdd(BytecodeOffset(), delta);
}

void InterpreterAssembler::Jump(Node* delta) { DispatchTo(Advance(delta)); }

void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) {
  RawMachineLabel match, no_match;
  raw_assembler_->Branch(condition, &match, &no_match);
  raw_assembler_->Bind(&match);
  DispatchTo(Advance(delta));
  raw_assembler_->Bind(&no_match);
  Dispatch();
}

void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) {
  JumpConditional(raw_assembler_->WordEqual(lhs, rhs), delta);
}

void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs,
                                              Node* delta) {
  JumpConditional(raw_assembler_->WordNotEqual(lhs, rhs), delta);
}

void InterpreterAssembler::Dispatch() {
  DispatchTo(Advance(interpreter::Bytecodes::Size(bytecode_)));
}


void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
  if (FLAG_trace_ignition) {
    TraceBytecode(Runtime::kInterpreterTraceBytecodeExit);
  }
  Node* target_bytecode = raw_assembler_->Load(
      MachineType::Uint8(), BytecodeArrayTaggedPointer(), new_bytecode_offset);

  // TODO(rmcilroy): Create a code target dispatch table to avoid conversion
  // from code object on every dispatch.
  Node* target_code_object = raw_assembler_->Load(
      MachineType::Pointer(), DispatchTableRawPointer(),
      raw_assembler_->Word32Shl(target_bytecode,
                                Int32Constant(kPointerSizeLog2)));

  // If the order of the parameters you need to change the call signature below.
  STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
  STATIC_ASSERT(1 == Linkage::kInterpreterRegisterFileParameter);
  STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
  STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
  STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
  STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
  Node* args[] = { GetAccumulator(),
                   RegisterFileRawPointer(),
                   new_bytecode_offset,
                   BytecodeArrayTaggedPointer(),
                   DispatchTableRawPointer(),
                   GetContext() };
  raw_assembler_->TailCallN(call_descriptor(), target_code_object, args);
}

void InterpreterAssembler::StackCheck() {
  RawMachineLabel end, ok, stack_guard;
  Node* sp = raw_assembler_->LoadStackPointer();
  Node* stack_limit = raw_assembler_->Load(
      MachineType::Pointer(),
      raw_assembler_->ExternalConstant(
          ExternalReference::address_of_stack_limit(isolate())));
  Node* condition = raw_assembler_->UintPtrGreaterThanOrEqual(sp, stack_limit);
  raw_assembler_->Branch(condition, &ok, &stack_guard);
  raw_assembler_->Bind(&stack_guard);
  CallRuntime(Runtime::kStackGuard);
  raw_assembler_->Goto(&end);
  raw_assembler_->Bind(&ok);
  raw_assembler_->Goto(&end);
  raw_assembler_->Bind(&end);
}

void InterpreterAssembler::Abort(BailoutReason bailout_reason) {
  Node* abort_id = SmiTag(Int32Constant(bailout_reason));
  Node* ret_value = CallRuntime(Runtime::kAbort, abort_id);
  // Unreached, but keeps turbofan happy.
  raw_assembler_->Return(ret_value);
}


void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs,
                                               BailoutReason bailout_reason) {
  RawMachineLabel match, no_match;
  Node* condition = raw_assembler_->WordEqual(lhs, rhs);
  raw_assembler_->Branch(condition, &match, &no_match);
  raw_assembler_->Bind(&no_match);
  Abort(bailout_reason);
  raw_assembler_->Bind(&match);
}

void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) {
  CallRuntime(function_id, BytecodeArrayTaggedPointer(),
              SmiTag(BytecodeOffset()), GetAccumulator());
}

// static
bool InterpreterAssembler::TargetSupportsUnalignedAccess() {
#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
  return false;
#elif V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC
  return CpuFeatures::IsSupported(UNALIGNED_ACCESSES);
#elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87
  return true;
#else
#error "Unknown Architecture"
#endif
}


// RawMachineAssembler delegate helpers:
Isolate* InterpreterAssembler::isolate() { return raw_assembler_->isolate(); }


Graph* InterpreterAssembler::graph() { return raw_assembler_->graph(); }


CallDescriptor* InterpreterAssembler::call_descriptor() const {
  return raw_assembler_->call_descriptor();
}


Zone* InterpreterAssembler::zone() { return raw_assembler_->zone(); }


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