| Index: src/interpreter/register-translator.cc
|
| diff --git a/src/interpreter/register-translator.cc b/src/interpreter/register-translator.cc
|
| index 741c21cf0e006de0bfbe362a9bd0d7064b7c4684..3eba42f0dca179face77674d737dc3b2501a367c 100644
|
| --- a/src/interpreter/register-translator.cc
|
| +++ b/src/interpreter/register-translator.cc
|
| @@ -11,7 +11,10 @@ namespace internal {
|
| namespace interpreter {
|
|
|
| RegisterTranslator::RegisterTranslator(RegisterMover* mover)
|
| - : mover_(mover), emitting_moves_(false), window_registers_count_(0) {}
|
| + : mover_(mover),
|
| + emitting_moves_(false),
|
| + window_registers_count_(0),
|
| + output_moves_count_(0) {}
|
|
|
| void RegisterTranslator::TranslateInputRegisters(Bytecode bytecode,
|
| uint32_t* raw_operands,
|
| @@ -29,6 +32,7 @@ void RegisterTranslator::TranslateInputRegisters(Bytecode bytecode,
|
| Register out_reg = TranslateAndMove(bytecode, i, in_reg);
|
| raw_operands[i] = out_reg.ToRawOperand();
|
| }
|
| + window_registers_count_ = 0;
|
| emitting_moves_ = false;
|
| } else {
|
| // When the register translator is translating registers, it will
|
| @@ -42,49 +46,70 @@ void RegisterTranslator::TranslateInputRegisters(Bytecode bytecode,
|
|
|
| Register RegisterTranslator::TranslateAndMove(Bytecode bytecode,
|
| int operand_index, Register reg) {
|
| + if (FitsInReg8Operand(reg)) {
|
| + return reg;
|
| + }
|
| +
|
| OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
|
| + OperandSize operand_size = Bytecodes::SizeOfOperand(operand_type);
|
| + if (operand_size == OperandSize::kShort) {
|
| + CHECK(FitsInReg16Operand(reg));
|
| + return Translate(reg);
|
| + }
|
| +
|
| + CHECK((operand_type == OperandType::kReg8 ||
|
| + operand_type == OperandType::kRegOut8) &&
|
| + RegisterIsMovableToWindow(bytecode, operand_index));
|
| Register translated_reg = Translate(reg);
|
| - Register addressable_reg = MakeAddressable(translated_reg, operand_type);
|
| - if (addressable_reg != translated_reg) {
|
| - CHECK(operand_type == OperandType::kReg8 &&
|
| - mover()->RegisterOperandIsMovable(bytecode, operand_index));
|
| - mover()->MoveRegisterUntranslated(translated_reg, addressable_reg);
|
| + Register window_reg(kTranslationWindowStart + window_registers_count_);
|
| + window_registers_count_ += 1;
|
| + if (Bytecodes::IsRegisterInputOperandType(operand_type)) {
|
| + DCHECK(!Bytecodes::IsRegisterOutputOperandType(operand_type));
|
| + mover()->MoveRegisterUntranslated(translated_reg, window_reg);
|
| + } else if (Bytecodes::IsRegisterOutputOperandType(operand_type)) {
|
| + DCHECK_LT(output_moves_count_, kTranslationWindowLength);
|
| + output_moves_[output_moves_count_] =
|
| + std::make_pair(window_reg, translated_reg);
|
| + output_moves_count_ += 1;
|
| + } else {
|
| + UNREACHABLE();
|
| + }
|
| + return window_reg;
|
| +}
|
| +
|
| +// static
|
| +bool RegisterTranslator::RegisterIsMovableToWindow(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::kRegOut8) {
|
| + 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);
|
| }
|
| - return addressable_reg;
|
| }
|
|
|
| void RegisterTranslator::TranslateOutputRegisters() {
|
| if (!emitting_moves_) {
|
| emitting_moves_ = true;
|
| - while (window_registers_count_ > 0) {
|
| - window_registers_count_ -= 1;
|
| - Register source(kTranslationWindowStart + window_registers_count_);
|
| - Register destination = window_registers_[window_registers_count_];
|
| - mover()->MoveRegisterUntranslated(source, destination);
|
| + while (output_moves_count_ > 0) {
|
| + output_moves_count_ -= 1;
|
| + mover()->MoveRegisterUntranslated(
|
| + output_moves_[output_moves_count_].first,
|
| + output_moves_[output_moves_count_].second);
|
| }
|
| emitting_moves_ = false;
|
| }
|
| }
|
|
|
| -Register RegisterTranslator::MakeAddressable(Register reg,
|
| - OperandType reg_type) {
|
| - DCHECK(!InTranslationWindow(reg));
|
| - OperandSize reg_size = Bytecodes::SizeOfOperand(reg_type);
|
| - if (reg_size == OperandSize::kByte && !FitsInReg8Operand(reg)) {
|
| - // TODO(oth): Moves into and out from translation window could be
|
| - // decoupled if there were metadata to say whether the register
|
| - // operand was an input, output, or input-and-output for a given
|
| - // bytecode.
|
| - Register destination(kTranslationWindowStart + window_registers_count_);
|
| - window_registers_[window_registers_count_] = reg;
|
| - window_registers_count_ += 1;
|
| - DCHECK_LE(window_registers_count_, kTranslationWindowLength);
|
| - return destination;
|
| - } else {
|
| - return reg;
|
| - }
|
| -}
|
| -
|
| // static
|
| Register RegisterTranslator::Translate(Register reg) {
|
| if (reg.index() >= kTranslationWindowStart) {
|
|
|