// 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/interpreter/bytecode-array-builder.h"

namespace v8 {
namespace internal {
namespace interpreter {

class BytecodeArrayBuilder::PreviousBytecodeHelper BASE_EMBEDDED {
 public:
  explicit PreviousBytecodeHelper(const BytecodeArrayBuilder& array_builder)
      : array_builder_(array_builder),
        previous_bytecode_start_(array_builder_.last_bytecode_start_) {
    // This helper is expected to be instantiated only when the last bytecode is
    // in the same basic block.
    DCHECK(array_builder_.LastBytecodeInSameBlock());
  }

  // Returns the previous bytecode in the same basic block.
  MUST_USE_RESULT Bytecode GetBytecode() const {
    DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
    return Bytecodes::FromByte(
        array_builder_.bytecodes()->at(previous_bytecode_start_));
  }

  // Returns the operand at operand_index for the previous bytecode in the
  // same basic block.
  MUST_USE_RESULT uint32_t GetOperand(int operand_index) const {
    DCHECK_EQ(array_builder_.last_bytecode_start_, previous_bytecode_start_);
    Bytecode bytecode = GetBytecode();
    DCHECK_GE(operand_index, 0);
    DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode));
    size_t operand_offset =
        previous_bytecode_start_ +
        Bytecodes::GetOperandOffset(bytecode, operand_index);
    OperandSize size = Bytecodes::GetOperandSize(bytecode, operand_index);
    switch (size) {
      case OperandSize::kNone:
        UNREACHABLE();
        break;
      case OperandSize::kByte:
        return static_cast<uint32_t>(
            array_builder_.bytecodes()->at(operand_offset));
      case OperandSize::kShort:
        uint16_t operand =
            (array_builder_.bytecodes()->at(operand_offset) << 8) +
            array_builder_.bytecodes()->at(operand_offset + 1);
        return static_cast<uint32_t>(operand);
    }
    return 0;
  }

  Handle<Object> GetConstantForIndexOperand(int operand_index) const {
    return array_builder_.constant_array_builder()->At(
        GetOperand(operand_index));
  }

 private:
  const BytecodeArrayBuilder& array_builder_;
  size_t previous_bytecode_start_;

  DISALLOW_COPY_AND_ASSIGN(PreviousBytecodeHelper);
};

BytecodeArrayBuilder::BytecodeArrayBuilder(Isolate* isolate, Zone* zone)
    : isolate_(isolate),
      zone_(zone),
      bytecodes_(zone),
      bytecode_generated_(false),
      constant_array_builder_(isolate, zone),
      handler_table_builder_(isolate, zone),
      last_block_end_(0),
      last_bytecode_start_(~0),
      exit_seen_in_block_(false),
      unbound_jumps_(0),
      parameter_count_(-1),
      local_register_count_(-1),
      context_register_count_(-1),
      temporary_register_count_(0),
      free_temporaries_(zone),
      register_translator_(this) {}

BytecodeArrayBuilder::~BytecodeArrayBuilder() { DCHECK_EQ(0, unbound_jumps_); }


void BytecodeArrayBuilder::set_locals_count(int number_of_locals) {
  local_register_count_ = number_of_locals;
  DCHECK_LE(context_register_count_, 0);
}


void BytecodeArrayBuilder::set_parameter_count(int number_of_parameters) {
  parameter_count_ = number_of_parameters;
}


void BytecodeArrayBuilder::set_context_count(int number_of_contexts) {
  context_register_count_ = number_of_contexts;
  DCHECK_GE(local_register_count_, 0);
}


Register BytecodeArrayBuilder::first_context_register() const {
  DCHECK_GT(context_register_count_, 0);
  return Register(local_register_count_);
}


Register BytecodeArrayBuilder::last_context_register() const {
  DCHECK_GT(context_register_count_, 0);
  return Register(local_register_count_ + context_register_count_ - 1);
}


Register BytecodeArrayBuilder::first_temporary_register() const {
  DCHECK_GT(temporary_register_count_, 0);
  return Register(fixed_register_count());
}


Register BytecodeArrayBuilder::last_temporary_register() const {
  DCHECK_GT(temporary_register_count_, 0);
  return Register(fixed_register_count() + temporary_register_count_ - 1);
}


Register BytecodeArrayBuilder::Parameter(int parameter_index) const {
  DCHECK_GE(parameter_index, 0);
  return Register::FromParameterIndex(parameter_index, parameter_count());
}


bool BytecodeArrayBuilder::RegisterIsParameterOrLocal(Register reg) const {
  return reg.is_parameter() || reg.index() < locals_count();
}


bool BytecodeArrayBuilder::RegisterIsTemporary(Register reg) const {
  return temporary_register_count_ > 0 && first_temporary_register() <= reg &&
         reg <= last_temporary_register();
}


Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
  DCHECK_EQ(bytecode_generated_, false);
  EnsureReturn();

  int bytecode_size = static_cast<int>(bytecodes_.size());
  int register_count =
      fixed_and_temporary_register_count() + translation_register_count();
  int frame_size = register_count * kPointerSize;
  Handle<FixedArray> constant_pool = constant_array_builder()->ToFixedArray();
  Handle<FixedArray> handler_table = handler_table_builder()->ToHandlerTable();
  Handle<BytecodeArray> output = isolate_->factory()->NewBytecodeArray(
      bytecode_size, &bytecodes_.front(), frame_size, parameter_count(),
      constant_pool);
  output->set_handler_table(*handler_table);
  bytecode_generated_ = true;
  return output;
}


template <size_t N>
void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t(&operands)[N]) {
  // Don't output dead code.
  if (exit_seen_in_block_) return;

  int operand_count = static_cast<int>(N);
  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count);

  int register_operand_count = Bytecodes::NumberOfRegisterOperands(bytecode);
  if (register_operand_count > 0) {
    register_translator()->TranslateInputRegisters(bytecode, operands,
                                                   operand_count);
  }

  last_bytecode_start_ = bytecodes()->size();
  bytecodes()->push_back(Bytecodes::ToByte(bytecode));
  for (int i = 0; i < operand_count; i++) {
    DCHECK(OperandIsValid(bytecode, i, operands[i]));
    switch (Bytecodes::GetOperandSize(bytecode, i)) {
      case OperandSize::kNone:
        UNREACHABLE();
        break;
      case OperandSize::kByte:
        bytecodes()->push_back(static_cast<uint8_t>(operands[i]));
        break;
      case OperandSize::kShort: {
        uint8_t operand_bytes[2];
        WriteUnalignedUInt16(operand_bytes, operands[i]);
        bytecodes()->insert(bytecodes()->end(), operand_bytes,
                            operand_bytes + 2);
        break;
      }
    }
  }

  if (register_operand_count > 0) {
    register_translator()->TranslateOutputRegisters();
  }
}


void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
                                  uint32_t operand1, uint32_t operand2,
                                  uint32_t operand3) {
  uint32_t operands[] = {operand0, operand1, operand2, operand3};
  Output(bytecode, operands);
}


void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
                                  uint32_t operand1, uint32_t operand2) {
  uint32_t operands[] = {operand0, operand1, operand2};
  Output(bytecode, operands);
}


void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0,
                                  uint32_t operand1) {
  uint32_t operands[] = {operand0, operand1};
  Output(bytecode, operands);
}


void BytecodeArrayBuilder::Output(Bytecode bytecode, uint32_t operand0) {
  uint32_t operands[] = {operand0};
  Output(bytecode, operands);
}


void BytecodeArrayBuilder::Output(Bytecode bytecode) {
  // Don't output dead code.
  if (exit_seen_in_block_) return;

  DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
  last_bytecode_start_ = bytecodes()->size();
  bytecodes()->push_back(Bytecodes::ToByte(bytecode));
}


BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value op,
                                                            Register reg,
                                                            Strength strength) {
  if (is_strong(strength)) {
    UNIMPLEMENTED();
  }

  Output(BytecodeForBinaryOperation(op), reg.ToRawOperand());
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CountOperation(Token::Value op,
                                                           Strength strength) {
  if (is_strong(strength)) {
    UNIMPLEMENTED();
  }

  Output(BytecodeForCountOperation(op));
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LogicalNot() {
  Output(Bytecode::kLogicalNot);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::TypeOf() {
  Output(Bytecode::kTypeOf);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CompareOperation(
    Token::Value op, Register reg, Strength strength) {
  if (is_strong(strength)) {
    UNIMPLEMENTED();
  }

  Output(BytecodeForCompareOperation(op), reg.ToRawOperand());
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(
    v8::internal::Smi* smi) {
  int32_t raw_smi = smi->value();
  if (raw_smi == 0) {
    Output(Bytecode::kLdaZero);
  } else if (raw_smi >= -128 && raw_smi <= 127) {
    Output(Bytecode::kLdaSmi8, static_cast<uint8_t>(raw_smi));
  } else {
    LoadLiteral(Handle<Object>(smi, isolate_));
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLiteral(Handle<Object> object) {
  size_t entry = GetConstantPoolEntry(object);
  if (FitsInIdx8Operand(entry)) {
    Output(Bytecode::kLdaConstant, static_cast<uint8_t>(entry));
  } else if (FitsInIdx16Operand(entry)) {
    Output(Bytecode::kLdaConstantWide, static_cast<uint16_t>(entry));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadUndefined() {
  Output(Bytecode::kLdaUndefined);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNull() {
  Output(Bytecode::kLdaNull);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTheHole() {
  Output(Bytecode::kLdaTheHole);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadTrue() {
  Output(Bytecode::kLdaTrue);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
  Output(Bytecode::kLdaFalse);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadBooleanConstant(bool value) {
  if (value) {
    LoadTrue();
  } else {
    LoadFalse();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
    Register reg) {
  if (!IsRegisterInAccumulator(reg)) {
    Output(Bytecode::kLdar, reg.ToRawOperand());
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
    Register reg) {
  if (!IsRegisterInAccumulator(reg)) {
    Output(Bytecode::kStar, reg.ToRawOperand());
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::MoveRegister(Register from,
                                                         Register to) {
  DCHECK(from != to);
  if (FitsInReg8Operand(from) && FitsInReg8Operand(to)) {
    Output(Bytecode::kMov, from.ToRawOperand(), to.ToRawOperand());
  } else if (FitsInReg16Operand(from) && FitsInReg16Operand(to)) {
    Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand());
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}

void BytecodeArrayBuilder::MoveRegisterUntranslated(Register from,
                                                    Register to) {
  // Move bytecodes modify the stack. Checking validity is an
  // essential mitigation against corrupting the stack.
  if (FitsInReg8OperandUntranslated(from)) {
    CHECK(RegisterIsValid(from, OperandType::kReg8) &&
          RegisterIsValid(to, OperandType::kReg16));
  } else if (FitsInReg8OperandUntranslated(to)) {
    CHECK(RegisterIsValid(from, OperandType::kReg16) &&
          RegisterIsValid(to, OperandType::kReg8));
  } else {
    UNIMPLEMENTED();
  }
  Output(Bytecode::kMovWide, from.ToRawOperand(), to.ToRawOperand());
}

bool BytecodeArrayBuilder::RegisterOperandIsMovable(Bytecode bytecode,
                                                    int operand_index) {
  // By design, we only support moving individual registers. There
  // should be wide variants of such bytecodes instead to avoid the
  // need for a large translation window.
  OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
  if (operand_type != OperandType::kReg8 &&
      operand_type != OperandType::kReg16) {
    return false;
  } else if (operand_index + 1 == Bytecodes::NumberOfOperands(bytecode)) {
    return true;
  } else {
    OperandType next_operand_type =
        Bytecodes::GetOperandType(bytecode, operand_index + 1);
    return (next_operand_type != OperandType::kRegCount8 &&
            next_operand_type != OperandType::kRegCount16);
  }
}

BytecodeArrayBuilder& BytecodeArrayBuilder::LoadGlobal(
    const Handle<String> name, int feedback_slot, LanguageMode language_mode,
    TypeofMode typeof_mode) {
  // TODO(rmcilroy): Potentially store language and typeof information in an
  // operand rather than having extra bytecodes.
  Bytecode bytecode = BytecodeForLoadGlobal(language_mode, typeof_mode);
  size_t name_index = GetConstantPoolEntry(name);
  if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    Output(bytecode, static_cast<uint8_t>(name_index),
           static_cast<uint8_t>(feedback_slot));
  } else if (FitsInIdx16Operand(name_index) &&
             FitsInIdx16Operand(feedback_slot)) {
    Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index),
           static_cast<uint16_t>(feedback_slot));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::StoreGlobal(
    const Handle<String> name, int feedback_slot, LanguageMode language_mode) {
  Bytecode bytecode = BytecodeForStoreGlobal(language_mode);
  size_t name_index = GetConstantPoolEntry(name);
  if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    Output(bytecode, static_cast<uint8_t>(name_index),
           static_cast<uint8_t>(feedback_slot));
  } else if (FitsInIdx16Operand(name_index) &&
             FitsInIdx16Operand(feedback_slot)) {
    Output(BytecodeForWideOperands(bytecode), static_cast<uint16_t>(name_index),
           static_cast<uint16_t>(feedback_slot));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadContextSlot(Register context,
                                                            int slot_index) {
  DCHECK(slot_index >= 0);
  if (FitsInIdx8Operand(slot_index)) {
    Output(Bytecode::kLdaContextSlot, context.ToRawOperand(),
           static_cast<uint8_t>(slot_index));
  } else if (FitsInIdx16Operand(slot_index)) {
    Output(Bytecode::kLdaContextSlotWide, context.ToRawOperand(),
           static_cast<uint16_t>(slot_index));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::StoreContextSlot(Register context,
                                                             int slot_index) {
  DCHECK(slot_index >= 0);
  if (FitsInIdx8Operand(slot_index)) {
    Output(Bytecode::kStaContextSlot, context.ToRawOperand(),
           static_cast<uint8_t>(slot_index));
  } else if (FitsInIdx16Operand(slot_index)) {
    Output(Bytecode::kStaContextSlotWide, context.ToRawOperand(),
           static_cast<uint16_t>(slot_index));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadLookupSlot(
    const Handle<String> name, TypeofMode typeof_mode) {
  Bytecode bytecode = (typeof_mode == INSIDE_TYPEOF)
                          ? Bytecode::kLdaLookupSlotInsideTypeof
                          : Bytecode::kLdaLookupSlot;
  size_t name_index = GetConstantPoolEntry(name);
  if (FitsInIdx8Operand(name_index)) {
    Output(bytecode, static_cast<uint8_t>(name_index));
  } else if (FitsInIdx16Operand(name_index)) {
    Output(BytecodeForWideOperands(bytecode),
           static_cast<uint16_t>(name_index));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::StoreLookupSlot(
    const Handle<String> name, LanguageMode language_mode) {
  Bytecode bytecode = BytecodeForStoreLookupSlot(language_mode);
  size_t name_index = GetConstantPoolEntry(name);
  if (FitsInIdx8Operand(name_index)) {
    Output(bytecode, static_cast<uint8_t>(name_index));
  } else if (FitsInIdx16Operand(name_index)) {
    Output(BytecodeForWideOperands(bytecode),
           static_cast<uint16_t>(name_index));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadNamedProperty(
    Register object, const Handle<String> name, int feedback_slot,
    LanguageMode language_mode) {
  Bytecode bytecode = BytecodeForLoadIC(language_mode);
  size_t name_index = GetConstantPoolEntry(name);
  if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index),
           static_cast<uint8_t>(feedback_slot));
  } else if (FitsInIdx16Operand(name_index) &&
             FitsInIdx16Operand(feedback_slot)) {
    Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(),
           static_cast<uint16_t>(name_index),
           static_cast<uint16_t>(feedback_slot));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::LoadKeyedProperty(
    Register object, int feedback_slot, LanguageMode language_mode) {
  Bytecode bytecode = BytecodeForKeyedLoadIC(language_mode);
  if (FitsInIdx8Operand(feedback_slot)) {
    Output(bytecode, object.ToRawOperand(),
           static_cast<uint8_t>(feedback_slot));
  } else if (FitsInIdx16Operand(feedback_slot)) {
    Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(),
           static_cast<uint16_t>(feedback_slot));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::StoreNamedProperty(
    Register object, const Handle<String> name, int feedback_slot,
    LanguageMode language_mode) {
  Bytecode bytecode = BytecodeForStoreIC(language_mode);
  size_t name_index = GetConstantPoolEntry(name);
  if (FitsInIdx8Operand(name_index) && FitsInIdx8Operand(feedback_slot)) {
    Output(bytecode, object.ToRawOperand(), static_cast<uint8_t>(name_index),
           static_cast<uint8_t>(feedback_slot));
  } else if (FitsInIdx16Operand(name_index) &&
             FitsInIdx16Operand(feedback_slot)) {
    Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(),
           static_cast<uint16_t>(name_index),
           static_cast<uint16_t>(feedback_slot));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::StoreKeyedProperty(
    Register object, Register key, int feedback_slot,
    LanguageMode language_mode) {
  Bytecode bytecode = BytecodeForKeyedStoreIC(language_mode);
  if (FitsInIdx8Operand(feedback_slot)) {
    Output(bytecode, object.ToRawOperand(), key.ToRawOperand(),
           static_cast<uint8_t>(feedback_slot));
  } else if (FitsInIdx16Operand(feedback_slot)) {
    Output(BytecodeForWideOperands(bytecode), object.ToRawOperand(),
           key.ToRawOperand(), static_cast<uint16_t>(feedback_slot));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CreateClosure(
    Handle<SharedFunctionInfo> shared_info, PretenureFlag tenured) {
  size_t entry = GetConstantPoolEntry(shared_info);
  DCHECK(FitsInImm8Operand(tenured));
  if (FitsInIdx8Operand(entry)) {
    Output(Bytecode::kCreateClosure, static_cast<uint8_t>(entry),
           static_cast<uint8_t>(tenured));
  } else if (FitsInIdx16Operand(entry)) {
    Output(Bytecode::kCreateClosureWide, static_cast<uint16_t>(entry),
           static_cast<uint8_t>(tenured));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArguments(
    CreateArgumentsType type) {
  // TODO(rmcilroy): Consider passing the type as a bytecode operand rather
  // than having two different bytecodes once we have better support for
  // branches in the InterpreterAssembler.
  Bytecode bytecode = BytecodeForCreateArguments(type);
  Output(bytecode);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CreateRegExpLiteral(
    Handle<String> pattern, int literal_index, int flags) {
  DCHECK(FitsInImm8Operand(flags));  // Flags should fit in 8 bits.
  size_t pattern_entry = GetConstantPoolEntry(pattern);
  if (FitsInIdx8Operand(literal_index) && FitsInIdx8Operand(pattern_entry)) {
    Output(Bytecode::kCreateRegExpLiteral, static_cast<uint8_t>(pattern_entry),
           static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
  } else if (FitsInIdx16Operand(literal_index) &&
             FitsInIdx16Operand(pattern_entry)) {
    Output(Bytecode::kCreateRegExpLiteralWide,
           static_cast<uint16_t>(pattern_entry),
           static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CreateArrayLiteral(
    Handle<FixedArray> constant_elements, int literal_index, int flags) {
  DCHECK(FitsInImm8Operand(flags));  // Flags should fit in 8 bits.
  size_t constant_elements_entry = GetConstantPoolEntry(constant_elements);
  if (FitsInIdx8Operand(literal_index) &&
      FitsInIdx8Operand(constant_elements_entry)) {
    Output(Bytecode::kCreateArrayLiteral,
           static_cast<uint8_t>(constant_elements_entry),
           static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
  } else if (FitsInIdx16Operand(literal_index) &&
             FitsInIdx16Operand(constant_elements_entry)) {
    Output(Bytecode::kCreateArrayLiteralWide,
           static_cast<uint16_t>(constant_elements_entry),
           static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CreateObjectLiteral(
    Handle<FixedArray> constant_properties, int literal_index, int flags) {
  DCHECK(FitsInImm8Operand(flags));  // Flags should fit in 8 bits.
  size_t constant_properties_entry = GetConstantPoolEntry(constant_properties);
  if (FitsInIdx8Operand(literal_index) &&
      FitsInIdx8Operand(constant_properties_entry)) {
    Output(Bytecode::kCreateObjectLiteral,
           static_cast<uint8_t>(constant_properties_entry),
           static_cast<uint8_t>(literal_index), static_cast<uint8_t>(flags));
  } else if (FitsInIdx16Operand(literal_index) &&
             FitsInIdx16Operand(constant_properties_entry)) {
    Output(Bytecode::kCreateObjectLiteralWide,
           static_cast<uint16_t>(constant_properties_entry),
           static_cast<uint16_t>(literal_index), static_cast<uint8_t>(flags));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::PushContext(Register context) {
  Output(Bytecode::kPushContext, context.ToRawOperand());
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::PopContext(Register context) {
  Output(Bytecode::kPopContext, context.ToRawOperand());
  return *this;
}


bool BytecodeArrayBuilder::NeedToBooleanCast() {
  if (!LastBytecodeInSameBlock()) {
    return true;
  }
  PreviousBytecodeHelper previous_bytecode(*this);
  switch (previous_bytecode.GetBytecode()) {
    // If the previous bytecode puts a boolean in the accumulator return true.
    case Bytecode::kLdaTrue:
    case Bytecode::kLdaFalse:
    case Bytecode::kLogicalNot:
    case Bytecode::kTestEqual:
    case Bytecode::kTestNotEqual:
    case Bytecode::kTestEqualStrict:
    case Bytecode::kTestNotEqualStrict:
    case Bytecode::kTestLessThan:
    case Bytecode::kTestLessThanOrEqual:
    case Bytecode::kTestGreaterThan:
    case Bytecode::kTestGreaterThanOrEqual:
    case Bytecode::kTestInstanceOf:
    case Bytecode::kTestIn:
    case Bytecode::kForInDone:
      return false;
    default:
      return true;
  }
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToJSObject() {
  Output(Bytecode::kToObject);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToName() {
  if (LastBytecodeInSameBlock()) {
    PreviousBytecodeHelper previous_bytecode(*this);
    switch (previous_bytecode.GetBytecode()) {
      case Bytecode::kToName:
      case Bytecode::kTypeOf:
        return *this;
      case Bytecode::kLdaConstantWide:
      case Bytecode::kLdaConstant: {
        Handle<Object> object = previous_bytecode.GetConstantForIndexOperand(0);
        if (object->IsName()) return *this;
        break;
      }
      default:
        break;
    }
  }
  Output(Bytecode::kToName);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CastAccumulatorToNumber() {
  // TODO(rmcilroy): consider omitting if the preceeding bytecode always returns
  // a number.
  Output(Bytecode::kToNumber);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(BytecodeLabel* label) {
  if (label->is_forward_target()) {
    // An earlier jump instruction refers to this label. Update it's location.
    PatchJump(bytecodes()->end(), bytecodes()->begin() + label->offset());
    // Now treat as if the label will only be back referred to.
  }
  label->bind_to(bytecodes()->size());
  LeaveBasicBlock();
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::Bind(const BytecodeLabel& target,
                                                 BytecodeLabel* label) {
  DCHECK(!label->is_bound());
  DCHECK(target.is_bound());
  PatchJump(bytecodes()->begin() + target.offset(),
            bytecodes()->begin() + label->offset());
  label->bind_to(target.offset());
  LeaveBasicBlock();
  return *this;
}


// static
Bytecode BytecodeArrayBuilder::GetJumpWithConstantOperand(
    Bytecode jump_bytecode) {
  switch (jump_bytecode) {
    case Bytecode::kJump:
      return Bytecode::kJumpConstant;
    case Bytecode::kJumpIfTrue:
      return Bytecode::kJumpIfTrueConstant;
    case Bytecode::kJumpIfFalse:
      return Bytecode::kJumpIfFalseConstant;
    case Bytecode::kJumpIfToBooleanTrue:
      return Bytecode::kJumpIfToBooleanTrueConstant;
    case Bytecode::kJumpIfToBooleanFalse:
      return Bytecode::kJumpIfToBooleanFalseConstant;
    case Bytecode::kJumpIfNull:
      return Bytecode::kJumpIfNullConstant;
    case Bytecode::kJumpIfUndefined:
      return Bytecode::kJumpIfUndefinedConstant;
    default:
      UNREACHABLE();
      return static_cast<Bytecode>(-1);
  }
}


// static
Bytecode BytecodeArrayBuilder::GetJumpWithConstantWideOperand(
    Bytecode jump_bytecode) {
  switch (jump_bytecode) {
    case Bytecode::kJump:
      return Bytecode::kJumpConstantWide;
    case Bytecode::kJumpIfTrue:
      return Bytecode::kJumpIfTrueConstantWide;
    case Bytecode::kJumpIfFalse:
      return Bytecode::kJumpIfFalseConstantWide;
    case Bytecode::kJumpIfToBooleanTrue:
      return Bytecode::kJumpIfToBooleanTrueConstantWide;
    case Bytecode::kJumpIfToBooleanFalse:
      return Bytecode::kJumpIfToBooleanFalseConstantWide;
    case Bytecode::kJumpIfNull:
      return Bytecode::kJumpIfNullConstantWide;
    case Bytecode::kJumpIfUndefined:
      return Bytecode::kJumpIfUndefinedConstantWide;
    default:
      UNREACHABLE();
      return static_cast<Bytecode>(-1);
  }
}


// static
Bytecode BytecodeArrayBuilder::GetJumpWithToBoolean(Bytecode jump_bytecode) {
  switch (jump_bytecode) {
    case Bytecode::kJump:
    case Bytecode::kJumpIfNull:
    case Bytecode::kJumpIfUndefined:
      return jump_bytecode;
    case Bytecode::kJumpIfTrue:
      return Bytecode::kJumpIfToBooleanTrue;
    case Bytecode::kJumpIfFalse:
      return Bytecode::kJumpIfToBooleanFalse;
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


void BytecodeArrayBuilder::PatchIndirectJumpWith8BitOperand(
    const ZoneVector<uint8_t>::iterator& jump_location, int delta) {
  Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
  DCHECK(Bytecodes::IsJumpImmediate(jump_bytecode));
  ZoneVector<uint8_t>::iterator operand_location = jump_location + 1;
  DCHECK_EQ(*operand_location, 0);
  if (FitsInImm8Operand(delta)) {
    // The jump fits within the range of an Imm8 operand, so cancel
    // the reservation and jump directly.
    constant_array_builder()->DiscardReservedEntry(OperandSize::kByte);
    *operand_location = static_cast<uint8_t>(delta);
  } else {
    // The jump does not fit within the range of an Imm8 operand, so
    // commit reservation putting the offset into the constant pool,
    // and update the jump instruction and operand.
    size_t entry = constant_array_builder()->CommitReservedEntry(
        OperandSize::kByte, handle(Smi::FromInt(delta), isolate()));
    DCHECK(FitsInIdx8Operand(entry));
    jump_bytecode = GetJumpWithConstantOperand(jump_bytecode);
    *jump_location = Bytecodes::ToByte(jump_bytecode);
    *operand_location = static_cast<uint8_t>(entry);
  }
}


void BytecodeArrayBuilder::PatchIndirectJumpWith16BitOperand(
    const ZoneVector<uint8_t>::iterator& jump_location, int delta) {
  DCHECK(Bytecodes::IsJumpConstantWide(Bytecodes::FromByte(*jump_location)));
  ZoneVector<uint8_t>::iterator operand_location = jump_location + 1;
  size_t entry = constant_array_builder()->CommitReservedEntry(
      OperandSize::kShort, handle(Smi::FromInt(delta), isolate()));
  DCHECK(FitsInIdx16Operand(entry));
  uint8_t operand_bytes[2];
  WriteUnalignedUInt16(operand_bytes, static_cast<uint16_t>(entry));
  DCHECK(*operand_location == 0 && *(operand_location + 1) == 0);
  *operand_location++ = operand_bytes[0];
  *operand_location = operand_bytes[1];
}


void BytecodeArrayBuilder::PatchJump(
    const ZoneVector<uint8_t>::iterator& jump_target,
    const ZoneVector<uint8_t>::iterator& jump_location) {
  Bytecode jump_bytecode = Bytecodes::FromByte(*jump_location);
  int delta = static_cast<int>(jump_target - jump_location);
  DCHECK(Bytecodes::IsJump(jump_bytecode));
  switch (Bytecodes::GetOperandSize(jump_bytecode, 0)) {
    case OperandSize::kByte:
      PatchIndirectJumpWith8BitOperand(jump_location, delta);
      break;
    case OperandSize::kShort:
      PatchIndirectJumpWith16BitOperand(jump_location, delta);
      break;
    case OperandSize::kNone:
      UNREACHABLE();
  }
  unbound_jumps_--;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::OutputJump(Bytecode jump_bytecode,
                                                       BytecodeLabel* label) {
  // Don't emit dead code.
  if (exit_seen_in_block_) return *this;

  // Check if the value in accumulator is boolean, if not choose an
  // appropriate JumpIfToBoolean bytecode.
  if (NeedToBooleanCast()) {
    jump_bytecode = GetJumpWithToBoolean(jump_bytecode);
  }

  if (label->is_bound()) {
    // Label has been bound already so this is a backwards jump.
    CHECK_GE(bytecodes()->size(), label->offset());
    CHECK_LE(bytecodes()->size(), static_cast<size_t>(kMaxInt));
    size_t abs_delta = bytecodes()->size() - label->offset();
    int delta = -static_cast<int>(abs_delta);

    if (FitsInImm8Operand(delta)) {
      Output(jump_bytecode, static_cast<uint8_t>(delta));
    } else {
      size_t entry =
          GetConstantPoolEntry(handle(Smi::FromInt(delta), isolate()));
      if (FitsInIdx8Operand(entry)) {
        Output(GetJumpWithConstantOperand(jump_bytecode),
               static_cast<uint8_t>(entry));
      } else if (FitsInIdx16Operand(entry)) {
        Output(GetJumpWithConstantWideOperand(jump_bytecode),
               static_cast<uint16_t>(entry));
      } else {
        UNREACHABLE();
      }
    }
  } else {
    // The label has not yet been bound so this is a forward reference
    // that will be patched when the label is bound. We create a
    // reservation in the constant pool so the jump can be patched
    // when the label is bound. The reservation means the maximum size
    // of the operand for the constant is known and the jump can
    // be emitted into the bytecode stream with space for the operand.
    label->set_referrer(bytecodes()->size());
    unbound_jumps_++;
    OperandSize reserved_operand_size =
        constant_array_builder()->CreateReservedEntry();
    switch (reserved_operand_size) {
      case OperandSize::kByte:
        Output(jump_bytecode, 0);
        break;
      case OperandSize::kShort:
        Output(GetJumpWithConstantWideOperand(jump_bytecode), 0);
        break;
      case OperandSize::kNone:
        UNREACHABLE();
    }
  }
  LeaveBasicBlock();
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::Jump(BytecodeLabel* label) {
  return OutputJump(Bytecode::kJump, label);
}


BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfTrue(BytecodeLabel* label) {
  return OutputJump(Bytecode::kJumpIfTrue, label);
}


BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfFalse(BytecodeLabel* label) {
  return OutputJump(Bytecode::kJumpIfFalse, label);
}


BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfNull(BytecodeLabel* label) {
  return OutputJump(Bytecode::kJumpIfNull, label);
}


BytecodeArrayBuilder& BytecodeArrayBuilder::JumpIfUndefined(
    BytecodeLabel* label) {
  return OutputJump(Bytecode::kJumpIfUndefined, label);
}


BytecodeArrayBuilder& BytecodeArrayBuilder::Throw() {
  Output(Bytecode::kThrow);
  exit_seen_in_block_ = true;
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::ReThrow() {
  Output(Bytecode::kReThrow);
  exit_seen_in_block_ = true;
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
  Output(Bytecode::kReturn);
  exit_seen_in_block_ = true;
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::ForInPrepare(
    Register cache_info_triple) {
  if (FitsInReg8Operand(cache_info_triple)) {
    Output(Bytecode::kForInPrepare, cache_info_triple.ToRawOperand());
  } else if (FitsInReg16Operand(cache_info_triple)) {
    Output(Bytecode::kForInPrepareWide, cache_info_triple.ToRawOperand());
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::ForInDone(Register index,
                                                      Register cache_length) {
  Output(Bytecode::kForInDone, index.ToRawOperand(),
         cache_length.ToRawOperand());
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::ForInNext(
    Register receiver, Register index, Register cache_type_array_pair) {
  if (FitsInReg8Operand(receiver) && FitsInReg8Operand(index) &&
      FitsInReg8Operand(cache_type_array_pair)) {
    Output(Bytecode::kForInNext, receiver.ToRawOperand(), index.ToRawOperand(),
           cache_type_array_pair.ToRawOperand());
  } else if (FitsInReg16Operand(receiver) && FitsInReg16Operand(index) &&
             FitsInReg16Operand(cache_type_array_pair)) {
    Output(Bytecode::kForInNextWide, receiver.ToRawOperand(),
           index.ToRawOperand(), cache_type_array_pair.ToRawOperand());
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::ForInStep(Register index) {
  Output(Bytecode::kForInStep, index.ToRawOperand());
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::MarkHandler(int handler_id,
                                                        bool will_catch) {
  handler_table_builder()->SetHandlerTarget(handler_id, bytecodes()->size());
  handler_table_builder()->SetPrediction(handler_id, will_catch);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryBegin(int handler_id,
                                                         Register context) {
  handler_table_builder()->SetTryRegionStart(handler_id, bytecodes()->size());
  handler_table_builder()->SetContextRegister(handler_id, context);
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
  handler_table_builder()->SetTryRegionEnd(handler_id, bytecodes()->size());
  return *this;
}


void BytecodeArrayBuilder::LeaveBasicBlock() {
  last_block_end_ = bytecodes()->size();
  exit_seen_in_block_ = false;
}


void BytecodeArrayBuilder::EnsureReturn() {
  if (!exit_seen_in_block_) {
    LoadUndefined();
    Return();
  }
}


BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
                                                 Register receiver,
                                                 size_t arg_count,
                                                 int feedback_slot) {
  if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver) &&
      FitsInIdx8Operand(arg_count) && FitsInIdx8Operand(feedback_slot)) {
    Output(Bytecode::kCall, callable.ToRawOperand(), receiver.ToRawOperand(),
           static_cast<uint8_t>(arg_count),
           static_cast<uint8_t>(feedback_slot));
  } else if (FitsInReg16Operand(callable) && FitsInReg16Operand(receiver) &&
             FitsInIdx16Operand(arg_count) &&
             FitsInIdx16Operand(feedback_slot)) {
    Output(Bytecode::kCallWide, callable.ToRawOperand(),
           receiver.ToRawOperand(), static_cast<uint16_t>(arg_count),
           static_cast<uint16_t>(feedback_slot));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
                                                Register first_arg,
                                                size_t arg_count) {
  if (!first_arg.is_valid()) {
    DCHECK_EQ(0u, arg_count);
    first_arg = Register(0);
  }
  if (FitsInReg8Operand(constructor) && FitsInReg8Operand(first_arg) &&
      FitsInIdx8Operand(arg_count)) {
    Output(Bytecode::kNew, constructor.ToRawOperand(), first_arg.ToRawOperand(),
           static_cast<uint8_t>(arg_count));
  } else if (FitsInReg16Operand(constructor) && FitsInReg16Operand(first_arg) &&
             FitsInIdx16Operand(arg_count)) {
    Output(Bytecode::kNewWide, constructor.ToRawOperand(),
           first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntime(
    Runtime::FunctionId function_id, Register first_arg, size_t arg_count) {
  DCHECK_EQ(1, Runtime::FunctionForId(function_id)->result_size);
  DCHECK(FitsInIdx16Operand(function_id));
  if (!first_arg.is_valid()) {
    DCHECK_EQ(0u, arg_count);
    first_arg = Register(0);
  }
  if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count)) {
    Output(Bytecode::kCallRuntime, static_cast<uint16_t>(function_id),
           first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count));
  } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count)) {
    Output(Bytecode::kCallRuntimeWide, static_cast<uint16_t>(function_id),
           first_arg.ToRawOperand(), static_cast<uint16_t>(arg_count));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CallRuntimeForPair(
    Runtime::FunctionId function_id, Register first_arg, size_t arg_count,
    Register first_return) {
  DCHECK_EQ(2, Runtime::FunctionForId(function_id)->result_size);
  DCHECK(FitsInIdx16Operand(function_id));
  if (!first_arg.is_valid()) {
    DCHECK_EQ(0u, arg_count);
    first_arg = Register(0);
  }
  if (FitsInReg8Operand(first_arg) && FitsInIdx8Operand(arg_count) &&
      FitsInReg8Operand(first_return)) {
    Output(Bytecode::kCallRuntimeForPair, static_cast<uint16_t>(function_id),
           first_arg.ToRawOperand(), static_cast<uint8_t>(arg_count),
           first_return.ToRawOperand());
  } else if (FitsInReg16Operand(first_arg) && FitsInIdx16Operand(arg_count) &&
             FitsInReg16Operand(first_return)) {
    Output(Bytecode::kCallRuntimeForPairWide,
           static_cast<uint16_t>(function_id), first_arg.ToRawOperand(),
           static_cast<uint16_t>(arg_count), first_return.ToRawOperand());
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::CallJSRuntime(int context_index,
                                                          Register receiver,
                                                          size_t arg_count) {
  DCHECK(FitsInIdx16Operand(context_index));
  if (FitsInReg8Operand(receiver) && FitsInIdx8Operand(arg_count)) {
    Output(Bytecode::kCallJSRuntime, static_cast<uint16_t>(context_index),
           receiver.ToRawOperand(), static_cast<uint8_t>(arg_count));
  } else if (FitsInReg16Operand(receiver) && FitsInIdx16Operand(arg_count)) {
    Output(Bytecode::kCallJSRuntimeWide, static_cast<uint16_t>(context_index),
           receiver.ToRawOperand(), static_cast<uint16_t>(arg_count));
  } else {
    UNIMPLEMENTED();
  }
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::Delete(Register object,
                                                   LanguageMode language_mode) {
  Output(BytecodeForDelete(language_mode), object.ToRawOperand());
  return *this;
}


BytecodeArrayBuilder& BytecodeArrayBuilder::DeleteLookupSlot() {
  Output(Bytecode::kDeleteLookupSlot);
  return *this;
}


size_t BytecodeArrayBuilder::GetConstantPoolEntry(Handle<Object> object) {
  return constant_array_builder()->Insert(object);
}

void BytecodeArrayBuilder::ForgeTemporaryRegister() {
  temporary_register_count_++;
}

int BytecodeArrayBuilder::BorrowTemporaryRegister() {
  if (free_temporaries_.empty()) {
    ForgeTemporaryRegister();
    return last_temporary_register().index();
  } else {
    auto pos = free_temporaries_.begin();
    int retval = *pos;
    free_temporaries_.erase(pos);
    return retval;
  }
}


int BytecodeArrayBuilder::BorrowTemporaryRegisterNotInRange(int start_index,
                                                            int end_index) {
  auto index = free_temporaries_.lower_bound(start_index);
  if (index == free_temporaries_.begin()) {
    // If start_index is the first free register, check for a register
    // greater than end_index.
    index = free_temporaries_.upper_bound(end_index);
    if (index == free_temporaries_.end()) {
      ForgeTemporaryRegister();
      return last_temporary_register().index();
    }
  } else {
    // If there is a free register < start_index
    index--;
  }

  int retval = *index;
  free_temporaries_.erase(index);
  return retval;
}


void BytecodeArrayBuilder::BorrowConsecutiveTemporaryRegister(int reg_index) {
  DCHECK(free_temporaries_.find(reg_index) != free_temporaries_.end());
  free_temporaries_.erase(reg_index);
}


void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) {
  DCHECK(free_temporaries_.find(reg_index) == free_temporaries_.end());
  free_temporaries_.insert(reg_index);
}


int BytecodeArrayBuilder::PrepareForConsecutiveTemporaryRegisters(
    size_t count) {
  if (count == 0) {
    return -1;
  }

  // TODO(oth): replace use of set<> here for free_temporaries with a
  // more efficient structure. And/or partition into two searches -
  // one before the translation window and one after.

  // A run will require at least |count| free temporaries.
  while (free_temporaries_.size() < count) {
    ForgeTemporaryRegister();
    free_temporaries_.insert(last_temporary_register().index());
  }

  // Search within existing temporaries for a run.
  auto start = free_temporaries_.begin();
  size_t run_length = 0;
  for (auto run_end = start; run_end != free_temporaries_.end(); run_end++) {
    int expected = *start + static_cast<int>(run_length);
    if (*run_end != expected) {
      start = run_end;
      run_length = 0;
    }
    Register reg_start(*start);
    Register reg_expected(expected);
    if (RegisterTranslator::DistanceToTranslationWindow(reg_start) > 0 &&
        RegisterTranslator::DistanceToTranslationWindow(reg_expected) <= 0) {
      // Run straddles the lower edge of the translation window. Registers
      // after the start of this boundary are displaced by the register
      // translator to provide a hole for translation. Runs either side
      // of the boundary are fine.
      start = run_end;
      run_length = 0;
    }
    if (++run_length == count) {
      return *start;
    }
  }

  // Continue run if possible across existing last temporary.
  if (temporary_register_count_ > 0 &&
      (start == free_temporaries_.end() ||
       *start + static_cast<int>(run_length) !=
           last_temporary_register().index() + 1)) {
    run_length = 0;
  }

  // Pad temporaries if extended run would cross translation boundary.
  Register reg_first(*start);
  Register reg_last(*start + static_cast<int>(count) - 1);
  DCHECK_GT(RegisterTranslator::DistanceToTranslationWindow(reg_first),
            RegisterTranslator::DistanceToTranslationWindow(reg_last));
  while (RegisterTranslator::DistanceToTranslationWindow(reg_first) > 0 &&
         RegisterTranslator::DistanceToTranslationWindow(reg_last) <= 0) {
    ForgeTemporaryRegister();
    free_temporaries_.insert(last_temporary_register().index());
    start = --free_temporaries_.end();
    reg_first = Register(*start);
    reg_last = Register(*start + static_cast<int>(count) - 1);
    run_length = 0;
  }

  // Ensure enough registers for run.
  while (run_length++ < count) {
    ForgeTemporaryRegister();
    free_temporaries_.insert(last_temporary_register().index());
  }

  int run_start =
      last_temporary_register().index() - static_cast<int>(count) + 1;
  DCHECK(RegisterTranslator::DistanceToTranslationWindow(Register(run_start)) <=
             0 ||
         RegisterTranslator::DistanceToTranslationWindow(
             Register(run_start + static_cast<int>(count) - 1)) > 0);
  return run_start;
}


bool BytecodeArrayBuilder::TemporaryRegisterIsLive(Register reg) const {
  if (temporary_register_count_ > 0) {
    DCHECK(reg.index() >= first_temporary_register().index() &&
           reg.index() <= last_temporary_register().index());
    return free_temporaries_.find(reg.index()) == free_temporaries_.end();
  } else {
    return false;
  }
}


bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
                                          uint32_t operand_value) const {
  OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
  switch (operand_type) {
    case OperandType::kNone:
      return false;
    case OperandType::kRegCount16: {
      // Expect kRegCount16 is part of a range previous operand is a
      // valid operand to start a range.
      if (operand_index > 0) {
        OperandType previous_operand_type =
            Bytecodes::GetOperandType(bytecode, operand_index - 1);
        return ((previous_operand_type == OperandType::kMaybeReg16 ||
                 previous_operand_type == OperandType::kReg16) &&
                static_cast<uint16_t>(operand_value) == operand_value);
      } else {
        return false;
      }
    }
    case OperandType::kRegCount8: {
      // Expect kRegCount8 is part of a range previous operand is a
      // valid operand to start a range.
      if (operand_index > 0) {
        OperandType previous_operand_type =
            Bytecodes::GetOperandType(bytecode, operand_index - 1);
        return ((previous_operand_type == OperandType::kMaybeReg8 ||
                 previous_operand_type == OperandType::kReg8 ||
                 previous_operand_type == OperandType::kMaybeReg16) &&
                static_cast<uint8_t>(operand_value) == operand_value);
      } else {
        return false;
      }
    }
    case OperandType::kIdx16:
      return static_cast<uint16_t>(operand_value) == operand_value;
    case OperandType::kImm8:
    case OperandType::kIdx8:
      return static_cast<uint8_t>(operand_value) == operand_value;
    case OperandType::kMaybeReg8:
      if (operand_value == 0) {
        return true;
      }
    // Fall-through to kReg8 case.
    case OperandType::kReg8:
      return RegisterIsValid(Register::FromRawOperand(operand_value),
                             operand_type);
    case OperandType::kRegPair8:
    case OperandType::kRegPair16: {
      Register reg0 = Register::FromRawOperand(operand_value);
      Register reg1 = Register(reg0.index() + 1);
      return RegisterIsValid(reg0, operand_type) &&
             RegisterIsValid(reg1, operand_type);
    }
    case OperandType::kRegTriple8:
    case OperandType::kRegTriple16: {
      Register reg0 = Register::FromRawOperand(operand_value);
      Register reg1 = Register(reg0.index() + 1);
      Register reg2 = Register(reg0.index() + 2);
      return RegisterIsValid(reg0, operand_type) &&
             RegisterIsValid(reg1, operand_type) &&
             RegisterIsValid(reg2, operand_type);
    }
    case OperandType::kMaybeReg16:
      if (operand_value == 0) {
        return true;
      }
    // Fall-through to kReg16 case.
    case OperandType::kReg16: {
      Register reg = Register::FromRawOperand(operand_value);
      return RegisterIsValid(reg, operand_type);
    }
  }
  UNREACHABLE();
  return false;
}


bool BytecodeArrayBuilder::RegisterIsValid(Register reg,
                                           OperandType reg_type) const {
  if (!reg.is_valid()) {
    return false;
  }

  switch (Bytecodes::SizeOfOperand(reg_type)) {
    case OperandSize::kByte:
      if (!FitsInReg8OperandUntranslated(reg)) {
        return false;
      }
      break;
    case OperandSize::kShort:
      if (!FitsInReg16OperandUntranslated(reg)) {
        return false;
      }
      break;
    case OperandSize::kNone:
      UNREACHABLE();
      return false;
  }

  if (reg.is_current_context() || reg.is_function_closure() ||
      reg.is_new_target()) {
    return true;
  } else if (reg.is_parameter()) {
    int parameter_index = reg.ToParameterIndex(parameter_count());
    return parameter_index >= 0 && parameter_index < parameter_count();
  } else if (RegisterTranslator::InTranslationWindow(reg)) {
    return translation_register_count() > 0;
  } else {
    reg = RegisterTranslator::UntranslateRegister(reg);
    if (reg.index() < fixed_register_count()) {
      return true;
    } else {
      return TemporaryRegisterIsLive(reg);
    }
  }
}


bool BytecodeArrayBuilder::LastBytecodeInSameBlock() const {
  return last_bytecode_start_ < bytecodes()->size() &&
         last_bytecode_start_ >= last_block_end_;
}


bool BytecodeArrayBuilder::IsRegisterInAccumulator(Register reg) {
  if (LastBytecodeInSameBlock()) {
    PreviousBytecodeHelper previous_bytecode(*this);
    Bytecode bytecode = previous_bytecode.GetBytecode();
    if (bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar) {
      Register previous_reg =
          Register::FromOperand(previous_bytecode.GetOperand(0));
      return previous_reg == reg;
    }
  }
  return false;
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
  switch (op) {
    case Token::Value::ADD:
      return Bytecode::kAdd;
    case Token::Value::SUB:
      return Bytecode::kSub;
    case Token::Value::MUL:
      return Bytecode::kMul;
    case Token::Value::DIV:
      return Bytecode::kDiv;
    case Token::Value::MOD:
      return Bytecode::kMod;
    case Token::Value::BIT_OR:
      return Bytecode::kBitwiseOr;
    case Token::Value::BIT_XOR:
      return Bytecode::kBitwiseXor;
    case Token::Value::BIT_AND:
      return Bytecode::kBitwiseAnd;
    case Token::Value::SHL:
      return Bytecode::kShiftLeft;
    case Token::Value::SAR:
      return Bytecode::kShiftRight;
    case Token::Value::SHR:
      return Bytecode::kShiftRightLogical;
    default:
      UNREACHABLE();
      return static_cast<Bytecode>(-1);
  }
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForCountOperation(Token::Value op) {
  switch (op) {
    case Token::Value::ADD:
      return Bytecode::kInc;
    case Token::Value::SUB:
      return Bytecode::kDec;
    default:
      UNREACHABLE();
      return static_cast<Bytecode>(-1);
  }
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
  switch (op) {
    case Token::Value::EQ:
      return Bytecode::kTestEqual;
    case Token::Value::NE:
      return Bytecode::kTestNotEqual;
    case Token::Value::EQ_STRICT:
      return Bytecode::kTestEqualStrict;
    case Token::Value::NE_STRICT:
      return Bytecode::kTestNotEqualStrict;
    case Token::Value::LT:
      return Bytecode::kTestLessThan;
    case Token::Value::GT:
      return Bytecode::kTestGreaterThan;
    case Token::Value::LTE:
      return Bytecode::kTestLessThanOrEqual;
    case Token::Value::GTE:
      return Bytecode::kTestGreaterThanOrEqual;
    case Token::Value::INSTANCEOF:
      return Bytecode::kTestInstanceOf;
    case Token::Value::IN:
      return Bytecode::kTestIn;
    default:
      UNREACHABLE();
      return static_cast<Bytecode>(-1);
  }
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForWideOperands(Bytecode bytecode) {
  switch (bytecode) {
    case Bytecode::kLoadICSloppy:
      return Bytecode::kLoadICSloppyWide;
    case Bytecode::kLoadICStrict:
      return Bytecode::kLoadICStrictWide;
    case Bytecode::kKeyedLoadICSloppy:
      return Bytecode::kKeyedLoadICSloppyWide;
    case Bytecode::kKeyedLoadICStrict:
      return Bytecode::kKeyedLoadICStrictWide;
    case Bytecode::kStoreICSloppy:
      return Bytecode::kStoreICSloppyWide;
    case Bytecode::kStoreICStrict:
      return Bytecode::kStoreICStrictWide;
    case Bytecode::kKeyedStoreICSloppy:
      return Bytecode::kKeyedStoreICSloppyWide;
    case Bytecode::kKeyedStoreICStrict:
      return Bytecode::kKeyedStoreICStrictWide;
    case Bytecode::kLdaGlobalSloppy:
      return Bytecode::kLdaGlobalSloppyWide;
    case Bytecode::kLdaGlobalStrict:
      return Bytecode::kLdaGlobalStrictWide;
    case Bytecode::kLdaGlobalInsideTypeofSloppy:
      return Bytecode::kLdaGlobalInsideTypeofSloppyWide;
    case Bytecode::kLdaGlobalInsideTypeofStrict:
      return Bytecode::kLdaGlobalInsideTypeofStrictWide;
    case Bytecode::kStaGlobalSloppy:
      return Bytecode::kStaGlobalSloppyWide;
    case Bytecode::kStaGlobalStrict:
      return Bytecode::kStaGlobalStrictWide;
    case Bytecode::kLdaLookupSlot:
      return Bytecode::kLdaLookupSlotWide;
    case Bytecode::kLdaLookupSlotInsideTypeof:
      return Bytecode::kLdaLookupSlotInsideTypeofWide;
    case Bytecode::kStaLookupSlotStrict:
      return Bytecode::kStaLookupSlotStrictWide;
    case Bytecode::kStaLookupSlotSloppy:
      return Bytecode::kStaLookupSlotSloppyWide;
    default:
      UNREACHABLE();
      return static_cast<Bytecode>(-1);
  }
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForLoadIC(LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kLoadICSloppy;
    case STRICT:
      return Bytecode::kLoadICStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForKeyedLoadIC(
    LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kKeyedLoadICSloppy;
    case STRICT:
      return Bytecode::kKeyedLoadICStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForStoreIC(LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kStoreICSloppy;
    case STRICT:
      return Bytecode::kStoreICStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForKeyedStoreIC(
    LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kKeyedStoreICSloppy;
    case STRICT:
      return Bytecode::kKeyedStoreICStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForLoadGlobal(LanguageMode language_mode,
                                                     TypeofMode typeof_mode) {
  switch (language_mode) {
    case SLOPPY:
      return typeof_mode == INSIDE_TYPEOF
                 ? Bytecode::kLdaGlobalInsideTypeofSloppy
                 : Bytecode::kLdaGlobalSloppy;
    case STRICT:
      return typeof_mode == INSIDE_TYPEOF
                 ? Bytecode::kLdaGlobalInsideTypeofStrict
                 : Bytecode::kLdaGlobalStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForStoreGlobal(
    LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kStaGlobalSloppy;
    case STRICT:
      return Bytecode::kStaGlobalStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForStoreLookupSlot(
    LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kStaLookupSlotSloppy;
    case STRICT:
      return Bytecode::kStaLookupSlotStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForCreateArguments(
    CreateArgumentsType type) {
  switch (type) {
    case CreateArgumentsType::kMappedArguments:
      return Bytecode::kCreateMappedArguments;
    case CreateArgumentsType::kUnmappedArguments:
      return Bytecode::kCreateUnmappedArguments;
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) {
  switch (language_mode) {
    case SLOPPY:
      return Bytecode::kDeletePropertySloppy;
    case STRICT:
      return Bytecode::kDeletePropertyStrict;
    case STRONG:
      UNIMPLEMENTED();
    default:
      UNREACHABLE();
  }
  return static_cast<Bytecode>(-1);
}


// static
bool BytecodeArrayBuilder::FitsInIdx8Operand(int value) {
  return kMinUInt8 <= value && value <= kMaxUInt8;
}


// static
bool BytecodeArrayBuilder::FitsInIdx8Operand(size_t value) {
  return value <= static_cast<size_t>(kMaxUInt8);
}


// static
bool BytecodeArrayBuilder::FitsInImm8Operand(int value) {
  return kMinInt8 <= value && value <= kMaxInt8;
}


// static
bool BytecodeArrayBuilder::FitsInIdx16Operand(int value) {
  return kMinUInt16 <= value && value <= kMaxUInt16;
}


// static
bool BytecodeArrayBuilder::FitsInIdx16Operand(size_t value) {
  return value <= static_cast<size_t>(kMaxUInt16);
}


// static
bool BytecodeArrayBuilder::FitsInReg8Operand(Register value) {
  return RegisterTranslator::FitsInReg8Operand(value);
}

// static
bool BytecodeArrayBuilder::FitsInReg8OperandUntranslated(Register value) {
  return value.is_byte_operand();
}


// static
bool BytecodeArrayBuilder::FitsInReg16Operand(Register value) {
  return RegisterTranslator::FitsInReg16Operand(value);
}

// static
bool BytecodeArrayBuilder::FitsInReg16OperandUntranslated(Register value) {
  return value.is_short_operand();
}

}  // namespace interpreter
}  // namespace internal
}  // namespace v8
