[Intepreter] Extend and move Register class.

Add methods for converting parameter index to a register and vice-versa.

Move Register class into bytecodes.h.

Update Bytecodes::Decode to pretty print parameters.

BUG=v8:4280
LOG=NO

Review URL: https://codereview.chromium.org/1325983002

Cr-Commit-Position: refs/heads/master@{#30549}
This commit is contained in:
oth 2015-09-02 10:48:10 -07:00 committed by Commit bot
parent 310f2ece0f
commit 22983f71f9
7 changed files with 162 additions and 45 deletions

View File

@ -37,10 +37,10 @@ void BytecodeArrayBuilder::set_parameter_count(int number_of_parameters) {
int BytecodeArrayBuilder::parameter_count() const { return parameter_count_; }
Register BytecodeArrayBuilder::Parameter(int param_index) {
DCHECK_GE(param_index, 0);
DCHECK_LT(param_index, parameter_count_);
return Register(kLastParamRegisterIndex - parameter_count_ + param_index + 1);
Register BytecodeArrayBuilder::Parameter(int parameter_index) {
DCHECK_GE(parameter_index, 0);
DCHECK_LT(parameter_index, parameter_count_);
return Register::FromParameterIndex(parameter_index, parameter_count_);
}
@ -229,10 +229,13 @@ bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
case OperandType::kIdx:
return true;
case OperandType::kReg: {
int reg_index = Register::FromOperand(operand_value).index();
return (reg_index >= 0 && reg_index < temporary_register_next_) ||
(reg_index <= kLastParamRegisterIndex &&
reg_index > kLastParamRegisterIndex - parameter_count_);
Register reg = Register::FromOperand(operand_value);
if (reg.is_parameter()) {
int parameter_index = reg.ToParameterIndex(parameter_count_);
return parameter_index >= 0 && parameter_index < parameter_count_;
} else {
return (reg.index() >= 0 && reg.index() < temporary_register_next_);
}
}
}
UNREACHABLE();

View File

@ -8,7 +8,6 @@
#include <vector>
#include "src/ast.h"
#include "src/frames.h"
#include "src/identity-map.h"
#include "src/interpreter/bytecodes.h"
#include "src/zone.h"
@ -64,9 +63,6 @@ class BytecodeArrayBuilder {
BytecodeArrayBuilder& Return();
private:
static const int kLastParamRegisterIndex =
-InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
static Bytecode BytecodeForBinaryOperation(Token::Value op);
static bool FitsInByteOperand(int value);
static bool FitsInByteOperand(size_t value);
@ -100,32 +96,6 @@ class BytecodeArrayBuilder {
DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArrayBuilder);
};
// An interpreter register which is located in the function's register file
// in its stack-frame.
class Register {
public:
static const int kMaxRegisterIndex = 128;
static const int kMinRegisterIndex = -127;
explicit Register(int index) : index_(index) {
DCHECK_LE(index_, kMaxRegisterIndex);
DCHECK_GE(index_, kMinRegisterIndex);
}
int index() { return index_; }
uint8_t ToOperand() { return static_cast<uint8_t>(-index_); }
static Register FromOperand(uint8_t operand) {
return Register(-static_cast<int8_t>(operand));
}
private:
void* operator new(size_t size);
void operator delete(void* p);
int index_;
};
// A stack-allocated class than allows the instantiator to allocate
// temporary registers that are cleaned up when scope is closed.
class TemporaryRegisterScope {

View File

@ -4,7 +4,7 @@
#include "src/interpreter/bytecodes.h"
#include "src/interpreter/bytecode-array-builder.h"
#include "src/frames.h"
namespace v8 {
namespace internal {
@ -103,8 +103,8 @@ int Bytecodes::MaximumSize() { return 1 + kMaxOperands; }
// static
std::ostream& Bytecodes::Decode(std::ostream& os,
const uint8_t* bytecode_start) {
std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start,
int parameter_count) {
Vector<char> buf = Vector<char>::New(50);
Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
@ -132,9 +132,20 @@ std::ostream& Bytecodes::Decode(std::ostream& os,
case interpreter::OperandType::kImm8:
os << "#" << static_cast<int>(operand);
break;
case interpreter::OperandType::kReg:
os << "r" << Register::FromOperand(operand).index();
case interpreter::OperandType::kReg: {
Register reg = Register::FromOperand(operand);
if (reg.is_parameter()) {
int parameter_index = reg.ToParameterIndex(parameter_count);
if (parameter_index == 0) {
os << "<this>";
} else {
os << "a" << parameter_index - 1;
}
} else {
os << "r" << reg.index();
}
break;
}
case interpreter::OperandType::kNone:
UNREACHABLE();
break;
@ -156,6 +167,44 @@ std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
return os << Bytecodes::OperandTypeToString(operand_type);
}
static const int kLastParamRegisterIndex =
-InterpreterFrameConstants::kLastParamFromRegisterPointer / kPointerSize;
// Registers occupy range 0-127 in 8-bit value leaving 128 unused values.
// Parameter indices are biased with the negative value kLastParamRegisterIndex
// for ease of access in the interpreter.
static const int kMaxParameterIndex = 128 + kLastParamRegisterIndex;
Register Register::FromParameterIndex(int index, int parameter_count) {
DCHECK_GE(index, 0);
DCHECK_LT(index, parameter_count);
DCHECK_LE(parameter_count, kMaxParameterIndex + 1);
int register_index = kLastParamRegisterIndex - parameter_count + index + 1;
DCHECK_LT(register_index, 0);
DCHECK_GE(register_index, Register::kMinRegisterIndex);
return Register(register_index);
}
int Register::ToParameterIndex(int parameter_count) const {
DCHECK(is_parameter());
return index() - kLastParamRegisterIndex + parameter_count - 1;
}
int Register::MaxParameterIndex() { return kMaxParameterIndex; }
uint8_t Register::ToOperand() const { return static_cast<uint8_t>(-index_); }
Register Register::FromOperand(uint8_t operand) {
return Register(-static_cast<int8_t>(operand));
}
} // namespace interpreter
} // namespace internal
} // namespace v8

View File

@ -80,6 +80,36 @@ enum class Bytecode : uint8_t {
};
// An interpreter register which is located in the function's register file
// in its stack-frame. Register hold parameters, this, and expression values.
class Register {
public:
static const int kMaxRegisterIndex = 127;
static const int kMinRegisterIndex = -128;
explicit Register(int index) : index_(index) {
DCHECK_LE(index_, kMaxRegisterIndex);
DCHECK_GE(index_, kMinRegisterIndex);
}
int index() const { return index_; }
bool is_parameter() const { return index_ < 0; }
static Register FromParameterIndex(int index, int parameter_count);
int ToParameterIndex(int parameter_count) const;
static int MaxParameterIndex();
static Register FromOperand(uint8_t operand);
uint8_t ToOperand() const;
private:
void* operator new(size_t size);
void operator delete(void* p);
int index_;
};
class Bytecodes {
public:
// Returns string representation of |bytecode|.
@ -110,7 +140,8 @@ class Bytecodes {
static int MaximumSize();
// Decode a single bytecode and operands to |os|.
static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start);
static std::ostream& Decode(std::ostream& os, const uint8_t* bytecode_start,
int number_of_parameters);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(Bytecodes);

View File

@ -11916,7 +11916,7 @@ void BytecodeArray::Disassemble(std::ostream& os) {
SNPrintF(buf, "%p", bytecode_start);
os << buf.start() << " : ";
interpreter::Bytecodes::Decode(os, bytecode_start);
interpreter::Bytecodes::Decode(os, bytecode_start, parameter_count());
os << "\n";
}

View File

@ -0,0 +1,63 @@
// Copyright 2014 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 <vector>
#include "src/v8.h"
#include "src/interpreter/bytecodes.h"
#include "test/unittests/test-utils.h"
namespace v8 {
namespace internal {
namespace interpreter {
TEST(OperandConversion, Registers) {
for (int i = 0; i < 128; i++) {
uint8_t operand_value = Register(i).ToOperand();
Register r = Register::FromOperand(operand_value);
CHECK_EQ(i, r.index());
}
}
TEST(OperandConversion, Parameters) {
int parameter_counts[] = {7, 13, 99};
size_t count = sizeof(parameter_counts) / sizeof(parameter_counts[0]);
for (size_t p = 0; p < count; p++) {
int parameter_count = parameter_counts[p];
for (int i = 0; i < parameter_count; i++) {
Register r = Register::FromParameterIndex(i, parameter_count);
uint8_t operand_value = r.ToOperand();
Register s = Register::FromOperand(operand_value);
CHECK_EQ(i, s.ToParameterIndex(parameter_count));
}
}
}
TEST(OperandConversion, RegistersParametersNoOverlap) {
std::vector<uint8_t> operand_count(256);
for (int i = 0; i <= Register::kMaxRegisterIndex; i++) {
Register r = Register(i);
uint8_t operand = r.ToOperand();
operand_count[operand] += 1;
CHECK_EQ(operand_count[operand], 1);
}
int parameter_count = Register::MaxParameterIndex() + 1;
for (int i = 0; i < parameter_count; i++) {
Register r = Register::FromParameterIndex(i, parameter_count);
uint8_t operand = r.ToOperand();
operand_count[operand] += 1;
CHECK_EQ(operand_count[operand], 1);
}
}
} // namespace interpreter
} // namespace internal
} // namespace v8

View File

@ -95,6 +95,7 @@
'compiler/value-numbering-reducer-unittest.cc',
'compiler/zone-pool-unittest.cc',
'counters-unittest.cc',
'interpreter/bytecodes-unittest.cc',
'interpreter/bytecode-array-builder-unittest.cc',
'libplatform/default-platform-unittest.cc',
'libplatform/task-queue-unittest.cc',