Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(360)

Unified Diff: src/interpreter/register-translator.cc

Issue 1613163002: [interpreter] Wide register support. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Compilation fixes for gcc/msvc. Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/interpreter/register-translator.cc
diff --git a/src/interpreter/register-translator.cc b/src/interpreter/register-translator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d4b5cbaeb06c912609569876647d98666df71777
--- /dev/null
+++ b/src/interpreter/register-translator.cc
@@ -0,0 +1,208 @@
+// 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/register-translator.h"
+
+#include "src/interpreter/bytecode-array-builder.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+RegisterTranslator::RegisterTranslator(RegisterMover* mover)
+ : mover_(mover), emitting_moves_(false), window_registers_count_(0) {}
+
+
+void RegisterTranslator::TranslateRegisters(Bytecode bytecode,
+ uint32_t* raw_operands,
+ int raw_operand_count) {
+ DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), raw_operand_count);
+ if (!emitting_moves_) {
+ emitting_moves_ = true;
+ DCHECK_EQ(window_registers_count_, 0);
+ int register_bitmap = Bytecodes::GetRegisterOperandBitmap(bytecode);
+ for (int i = 0; i < raw_operand_count; i++) {
+ if ((register_bitmap & (1 << i)) == 0) {
+ DCHECK(NonRegisterOperandIsValid(bytecode, i));
+ continue;
+ }
+ Register in_reg = Register::FromRawOperand(raw_operands[i]);
+ Register out_reg = TranslateAndMove(bytecode, i, in_reg);
+ raw_operands[i] = out_reg.ToRawOperand();
+ }
+ emitting_moves_ = false;
+ } else {
+ // When the register translator is translating registers, it will
+ // cause the bytecode generator to emit moves on it's behalf. This
+ // path is reached by these moves.
+ DCHECK(bytecode == Bytecode::kMovWide && raw_operand_count == 2 &&
+ Register::FromRawOperand(raw_operands[0]).is_valid() &&
+ Register::FromRawOperand(raw_operands[1]).is_valid());
+ }
+}
+
+
+Register RegisterTranslator::TranslateAndMove(Bytecode bytecode,
+ int operand_index, Register reg) {
+ OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
+ Register translated_reg = Translate(reg);
+ Register addressable_reg = MakeAddressable(translated_reg, operand_type);
+ if (addressable_reg != translated_reg) {
+ if (operand_type == OperandType::kReg8 &&
+ OperandIsMoveable(bytecode, operand_index)) {
+ mover()->MoveRegisterUntranslated(translated_reg, addressable_reg);
+ } else {
+ Register invalid_reg;
+ mover()->MoveRegisterUntranslated(invalid_reg, invalid_reg);
rmcilroy 2016/01/25 12:12:05 Maybe we can make this a Death test instead? If
oth 2016/01/25 16:51:57 Didn't appreciate death test was an option. Have n
+ }
+ }
+ return addressable_reg;
+}
+
+
+void RegisterTranslator::UntranslateRegisters() {
+ 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);
+ }
+ 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
+bool RegisterTranslator::NonRegisterOperandIsValid(Bytecode bytecode,
+ int operand_index) {
+ OperandType operand_type = Bytecodes::GetOperandType(bytecode, operand_index);
+ if (operand_type == OperandType::kRegCount8 ||
+ operand_type == OperandType::kRegCount16) {
rmcilroy 2016/01/25 12:12:05 Should this not be checked in OperandIsValid in by
oth 2016/01/25 16:51:57 Done.
+ if (operand_index > 0) {
+ switch (Bytecodes::GetOperandType(bytecode, operand_index - 1)) {
+ case OperandType::kMaybeReg8:
+ case OperandType::kMaybeReg16:
+ case OperandType::kReg8:
+ case OperandType::kReg16:
+ return true;
+ case OperandType::kNone:
+ UNREACHABLE();
+ case OperandType::kIdx8:
+ case OperandType::kIdx16:
+ case OperandType::kImm8:
+ case OperandType::kRegCount8:
+ case OperandType::kRegCount16:
+ case OperandType::kRegPair8:
+ case OperandType::kRegPair16:
+ case OperandType::kRegTriple8:
+ case OperandType::kRegTriple16:
+ break;
+ }
+ }
+ return false;
+ } else {
+ return true;
+ }
+}
+
+
+// static
+bool RegisterTranslator::OperandIsMoveable(Bytecode bytecode,
rmcilroy 2016/01/25 12:12:05 This could be exposed as part of the RegisterMover
oth 2016/01/25 16:51:56 Done.
+ int operand_index) {
+ // By design, the translator does not copy any register ranges into
+ // the translation window. 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) {
+ if (operand_index == Bytecodes::NumberOfOperands(bytecode) - 1) {
+ return true;
+ }
+ OperandType next_operand_type =
+ Bytecodes::GetOperandType(bytecode, operand_index + 1);
+ return (next_operand_type != OperandType::kRegCount8 &&
+ next_operand_type != OperandType::kRegCount16);
+ } else {
+ return false;
+ }
+}
+
+
+// static
+Register RegisterTranslator::Translate(Register reg) {
+ if (reg.index() >= kTranslationWindowStart) {
+ return Register(reg.index() + kTranslationWindowLength);
+ } else {
+ return reg;
+ }
+}
+
+
+// static
+bool RegisterTranslator::InTranslationWindow(Register reg) {
+ return (reg.index() >= kTranslationWindowStart &&
+ reg.index() <= kTranslationWindowLimit);
+}
+
+
+// static
+int RegisterTranslator::DistanceToTranslationWindow(Register reg) {
+ return kTranslationWindowStart - reg.index();
+}
+
+
+// static
+bool RegisterTranslator::FitsInReg8Operand(Register reg) {
+ return reg.is_byte_operand() && reg.index() < kTranslationWindowStart;
+}
+
+
+// static
+bool RegisterTranslator::FitsInReg16Operand(Register reg) {
+ int max_index = Register::MaxRegisterIndex() - kTranslationWindowLength + 1;
+ return reg.is_short_operand() && reg.index() < max_index;
+}
+
+
+// static
+int RegisterTranslator::RegisterCountAdjustment(int register_count,
+ int parameter_count) {
+ if (register_count > kTranslationWindowStart) {
+ return kTranslationWindowLength;
+ } else if (parameter_count > 0) {
+ Register param0 = Register::FromParameterIndex(0, parameter_count);
+ if (!param0.is_byte_operand()) {
+ // TODO(oth): Move translation window in this scenario.
rmcilroy 2016/01/25 12:12:05 Explain why (i.e., the translation window causes a
oth 2016/01/25 16:51:56 Done.
+ return kTranslationWindowLimit + 1 - register_count;
+ }
+ }
+ return 0;
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8

Powered by Google App Engine
This is Rietveld 408576698