blob: b683a899e2f265e39aca15c9ad01297920f058c6 [file] [log] [blame]
// 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.
#ifndef V8_INTERPRETER_REGISTER_TRANSLATOR_H_
#define V8_INTERPRETER_REGISTER_TRANSLATOR_H_
#include "src/interpreter/bytecodes.h"
namespace v8 {
namespace internal {
namespace interpreter {
class RegisterMover;
// A class that enables bytecodes having only byte sized register operands
// to access all registers in the two byte space. Most bytecode uses few
// registers so space can be saved if most bytecodes with register operands
// just take byte operands.
//
// To reach the wider register space, a translation window is reserved in
// the byte addressable space specifically for copying registers into and
// out of before a bytecode is emitted. The translation window occupies
// the last register slots at the top of the byte addressable range.
//
// Because of the translation window any registers which naturally lie
// at above the translation window have to have their register index
// incremented by the window width before they are emitted.
//
// This class does not support moving ranges of registers to and from
// the translation window. It would be straightforward to add support
// for constrained ranges, e.g. kRegPair8, kRegTriple8 operands, but
// these would have two negative effects. The translation window would
// need to be wider, further limiting the space for byte operands. And
// every register in a range would need to be moved consuming more
// space in the bytecode array.
class RegisterTranslator final {
public:
explicit RegisterTranslator(RegisterMover* mover);
// Translate and re-write the register operands that are inputs
// to |bytecode| when it is about to be emitted.
void TranslateInputRegisters(Bytecode bytecode, uint32_t* raw_operands,
int raw_operand_count);
// Translate and re-write the register operands that are outputs
// from |bytecode| when it has just been output.
void TranslateOutputRegisters();
// Returns true if |reg| is in the translation window.
static bool InTranslationWindow(Register reg);
// Return register value as if it had been translated.
static Register UntranslateRegister(Register reg);
// Returns the distance in registers between the translation window
// start and |reg|. The result is negative when |reg| is above the
// start of the translation window.
static int DistanceToTranslationWindow(Register reg);
// Returns true if |reg| can be represented as an 8-bit operand
// after translation.
static bool FitsInReg8Operand(Register reg);
// Returns true if |reg| can be represented as an 16-bit operand
// after translation.
static bool FitsInReg16Operand(Register reg);
// Returns the increment to the register count necessary if the
// value indicates the translation window is required.
static int RegisterCountAdjustment(int register_count, int parameter_count);
private:
static const int kTranslationWindowLength = 4;
static const int kTranslationWindowLimit = -kMinInt8;
static const int kTranslationWindowStart =
kTranslationWindowLimit - kTranslationWindowLength + 1;
Register TranslateAndMove(Bytecode bytecode, int operand_index, Register reg);
static bool RegisterIsMovableToWindow(Bytecode bytecode, int operand_index);
static Register Translate(Register reg);
RegisterMover* mover() const { return mover_; }
// Entity to perform register moves necessary to translate registers
// and ensure reachability.
RegisterMover* mover_;
// Flag to avoid re-entrancy when emitting move bytecodes for
// translation.
bool emitting_moves_;
// Number of window registers in use.
int window_registers_count_;
// State for restoring register moves emitted by TranslateOutputRegisters.
std::pair<Register, Register> output_moves_[kTranslationWindowLength];
int output_moves_count_;
};
// Interface for RegisterTranslator helper class that will emit
// register move bytecodes at the translator's behest.
class RegisterMover {
public:
virtual ~RegisterMover() {}
// Move register |from| to register |to| with no translation.
// returns false if either register operand is invalid. Implementations
// of this method must be aware that register moves with bad
// register values are a security hole.
virtual void MoveRegisterUntranslated(Register from, Register to) = 0;
};
} // namespace interpreter
} // namespace internal
} // namespace v8
#endif // V8_INTERPRETER_REGISTER_TRANSLATOR_H_