Commit 9b56924d authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[interpreter]: Update BytecodeArrayBuilder register handling.

Modifies the BytecodeArrayBuilder to create register operands which are
negative. This reduces the number of instructions to access registers
by the interpreter and allows us to use positive register operands to
access parameter values.

Adds a Register class to keep register usage typesafe and simplify the
convertion to bytecode operand values.

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#30151}
parent 890b1dfc
...@@ -39,8 +39,8 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() { ...@@ -39,8 +39,8 @@ Handle<BytecodeArray> BytecodeArrayBuilder::ToBytecodeArray() {
BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value binop, BytecodeArrayBuilder& BytecodeArrayBuilder::BinaryOperation(Token::Value binop,
int reg) { Register reg) {
Output(BytecodeForBinaryOperation(binop), reg); Output(BytecodeForBinaryOperation(binop), reg.ToOperand());
return *this; return *this;
} }
...@@ -91,15 +91,15 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() { ...@@ -91,15 +91,15 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::LoadFalse() {
BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister( BytecodeArrayBuilder& BytecodeArrayBuilder::LoadAccumulatorWithRegister(
int reg) { Register reg) {
Output(Bytecode::kLdar, reg); Output(Bytecode::kLdar, reg.ToOperand());
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister( BytecodeArrayBuilder& BytecodeArrayBuilder::StoreAccumulatorInRegister(
int reg) { Register reg) {
Output(Bytecode::kStar, reg); Output(Bytecode::kStar, reg.ToOperand());
return *this; return *this;
} }
...@@ -112,18 +112,18 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Return() { ...@@ -112,18 +112,18 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::Return() {
int BytecodeArrayBuilder::BorrowTemporaryRegister() { int BytecodeArrayBuilder::BorrowTemporaryRegister() {
DCHECK_GE(local_register_count_, 0); DCHECK_GE(local_register_count_, 0);
int temporary_register = temporary_register_next_++; int temporary_reg_index = temporary_register_next_++;
int count = temporary_register_next_ - local_register_count_; int count = temporary_register_next_ - local_register_count_;
if (count > temporary_register_count_) { if (count > temporary_register_count_) {
temporary_register_count_ = count; temporary_register_count_ = count;
} }
return temporary_register; return temporary_reg_index;
} }
void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg) { void BytecodeArrayBuilder::ReturnTemporaryRegister(int reg_index) {
DCHECK_EQ(reg, temporary_register_next_ - 1); DCHECK_EQ(reg_index, temporary_register_next_ - 1);
temporary_register_next_ = reg; temporary_register_next_ = reg_index;
} }
...@@ -136,7 +136,8 @@ bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index, ...@@ -136,7 +136,8 @@ bool BytecodeArrayBuilder::OperandIsValid(Bytecode bytecode, int operand_index,
case OperandType::kImm8: case OperandType::kImm8:
return true; return true;
case OperandType::kReg: case OperandType::kReg:
return operand_value < temporary_register_next_; return Register::FromOperand(operand_value).index() <
temporary_register_next_;
} }
UNREACHABLE(); UNREACHABLE();
return false; return false;
...@@ -200,20 +201,20 @@ Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) { ...@@ -200,20 +201,20 @@ Bytecode BytecodeArrayBuilder::BytecodeForBinaryOperation(Token::Value op) {
TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder) TemporaryRegisterScope::TemporaryRegisterScope(BytecodeArrayBuilder* builder)
: builder_(builder), count_(0), register_(-1) {} : builder_(builder), count_(0), last_register_index_(-1) {}
TemporaryRegisterScope::~TemporaryRegisterScope() { TemporaryRegisterScope::~TemporaryRegisterScope() {
while (count_-- != 0) { while (count_-- != 0) {
builder_->ReturnTemporaryRegister(register_--); builder_->ReturnTemporaryRegister(last_register_index_--);
} }
} }
int TemporaryRegisterScope::NewRegister() { Register TemporaryRegisterScope::NewRegister() {
count_++; count_++;
register_ = builder_->BorrowTemporaryRegister(); last_register_index_ = builder_->BorrowTemporaryRegister();
return register_; return Register(last_register_index_);
} }
} // namespace interpreter } // namespace interpreter
......
...@@ -17,6 +17,8 @@ class Isolate; ...@@ -17,6 +17,8 @@ class Isolate;
namespace interpreter { namespace interpreter {
class Register;
class BytecodeArrayBuilder { class BytecodeArrayBuilder {
public: public:
explicit BytecodeArrayBuilder(Isolate* isolate); explicit BytecodeArrayBuilder(Isolate* isolate);
...@@ -26,7 +28,7 @@ class BytecodeArrayBuilder { ...@@ -26,7 +28,7 @@ class BytecodeArrayBuilder {
void set_locals_count(int number_of_locals); void set_locals_count(int number_of_locals);
int locals_count() const; int locals_count() const;
// Constant loads to accumulator // Constant loads to accumulator.
BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value); BytecodeArrayBuilder& LoadLiteral(v8::internal::Smi* value);
BytecodeArrayBuilder& LoadUndefined(); BytecodeArrayBuilder& LoadUndefined();
BytecodeArrayBuilder& LoadNull(); BytecodeArrayBuilder& LoadNull();
...@@ -34,14 +36,14 @@ class BytecodeArrayBuilder { ...@@ -34,14 +36,14 @@ class BytecodeArrayBuilder {
BytecodeArrayBuilder& LoadTrue(); BytecodeArrayBuilder& LoadTrue();
BytecodeArrayBuilder& LoadFalse(); BytecodeArrayBuilder& LoadFalse();
// Register-accumulator transfers // Register-accumulator transfers.
BytecodeArrayBuilder& LoadAccumulatorWithRegister(int reg); BytecodeArrayBuilder& LoadAccumulatorWithRegister(Register reg);
BytecodeArrayBuilder& StoreAccumulatorInRegister(int reg); BytecodeArrayBuilder& StoreAccumulatorInRegister(Register reg);
// Operators // Operators.
BytecodeArrayBuilder& BinaryOperation(Token::Value binop, int reg); BytecodeArrayBuilder& BinaryOperation(Token::Value binop, Register reg);
// Flow Control // Flow Control.
BytecodeArrayBuilder& Return(); BytecodeArrayBuilder& Return();
private: private:
...@@ -56,7 +58,7 @@ class BytecodeArrayBuilder { ...@@ -56,7 +58,7 @@ class BytecodeArrayBuilder {
uint8_t operand_value) const; uint8_t operand_value) const;
int BorrowTemporaryRegister(); int BorrowTemporaryRegister();
void ReturnTemporaryRegister(int reg); void ReturnTemporaryRegister(int reg_index);
Isolate* isolate_; Isolate* isolate_;
std::vector<uint8_t> bytecodes_; std::vector<uint8_t> bytecodes_;
...@@ -70,13 +72,34 @@ class BytecodeArrayBuilder { ...@@ -70,13 +72,34 @@ class BytecodeArrayBuilder {
DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArrayBuilder); DISALLOW_IMPLICIT_CONSTRUCTORS(BytecodeArrayBuilder);
}; };
// An interpreter register which is located in the function's regsiter file
// in its stack-frame.
class Register {
public:
static const int kMaxRegisterIndex = 128;
explicit Register(int index) : index_(index) {
DCHECK_LE(index_, kMaxRegisterIndex);
}
int index() { return index_; }
uint8_t ToOperand() { return static_cast<uint8_t>(-index_); }
static Register FromOperand(uint8_t operand) { return Register(-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 // A stack-allocated class than allows the instantiator to allocate
// temporary registers that are cleaned up when scope is closed. // temporary registers that are cleaned up when scope is closed.
class TemporaryRegisterScope { class TemporaryRegisterScope {
public: public:
explicit TemporaryRegisterScope(BytecodeArrayBuilder* builder); explicit TemporaryRegisterScope(BytecodeArrayBuilder* builder);
~TemporaryRegisterScope(); ~TemporaryRegisterScope();
int NewRegister(); Register NewRegister();
private: private:
void* operator new(size_t size); void* operator new(size_t size);
...@@ -84,7 +107,7 @@ class TemporaryRegisterScope { ...@@ -84,7 +107,7 @@ class TemporaryRegisterScope {
BytecodeArrayBuilder* builder_; BytecodeArrayBuilder* builder_;
int count_; int count_;
int register_; int last_register_index_;
DISALLOW_COPY_AND_ASSIGN(TemporaryRegisterScope); DISALLOW_COPY_AND_ASSIGN(TemporaryRegisterScope);
}; };
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "src/interpreter/bytecodes.h" #include "src/interpreter/bytecodes.h"
#include "src/interpreter/bytecode-array-builder.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace interpreter { namespace interpreter {
...@@ -37,6 +39,20 @@ const char* Bytecodes::ToString(Bytecode bytecode) { ...@@ -37,6 +39,20 @@ const char* Bytecodes::ToString(Bytecode bytecode) {
} }
// static
const char* Bytecodes::OperandTypeToString(OperandType operand_type) {
switch (operand_type) {
#define CASE(Name) \
case OperandType::k##Name: \
return #Name;
OPERAND_TYPE_LIST(CASE)
#undef CASE
}
UNREACHABLE();
return "";
}
// static // static
uint8_t Bytecodes::ToByte(Bytecode bytecode) { uint8_t Bytecodes::ToByte(Bytecode bytecode) {
return static_cast<uint8_t>(bytecode); return static_cast<uint8_t>(bytecode);
...@@ -114,7 +130,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os, ...@@ -114,7 +130,7 @@ std::ostream& Bytecodes::Decode(std::ostream& os,
os << "#" << static_cast<int>(operand); os << "#" << static_cast<int>(operand);
break; break;
case interpreter::OperandType::kReg: case interpreter::OperandType::kReg:
os << "r" << static_cast<int>(operand); os << "r" << Register::FromOperand(operand).index();
break; break;
case interpreter::OperandType::kNone: case interpreter::OperandType::kNone:
UNREACHABLE(); UNREACHABLE();
...@@ -132,6 +148,11 @@ std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { ...@@ -132,6 +148,11 @@ std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) {
return os << Bytecodes::ToString(bytecode); return os << Bytecodes::ToString(bytecode);
} }
std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) {
return os << Bytecodes::OperandTypeToString(operand_type);
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -78,6 +78,9 @@ class Bytecodes { ...@@ -78,6 +78,9 @@ class Bytecodes {
// Returns string representation of |bytecode|. // Returns string representation of |bytecode|.
static const char* ToString(Bytecode bytecode); static const char* ToString(Bytecode bytecode);
// Returns string representation of |operand_type|.
static const char* OperandTypeToString(OperandType operand_type);
// Returns byte value of bytecode. // Returns byte value of bytecode.
static uint8_t ToByte(Bytecode bytecode); static uint8_t ToByte(Bytecode bytecode);
...@@ -107,6 +110,7 @@ class Bytecodes { ...@@ -107,6 +110,7 @@ class Bytecodes {
}; };
std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode); std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode);
std::ostream& operator<<(std::ostream& os, const OperandType& operand_type);
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
......
...@@ -87,7 +87,6 @@ ...@@ -87,7 +87,6 @@
'gay-fixed.cc', 'gay-fixed.cc',
'gay-precision.cc', 'gay-precision.cc',
'gay-shortest.cc', 'gay-shortest.cc',
'interpreter/test-bytecode-array-builder.cc',
'print-extension.cc', 'print-extension.cc',
'profiler-extension.cc', 'profiler-extension.cc',
'test-accessors.cc', 'test-accessors.cc',
......
...@@ -5,14 +5,21 @@ ...@@ -5,14 +5,21 @@
#include "src/v8.h" #include "src/v8.h"
#include "src/interpreter/bytecode-array-builder.h" #include "src/interpreter/bytecode-array-builder.h"
#include "test/cctest/cctest.h" #include "test/unittests/test-utils.h"
using namespace v8::internal; namespace v8 {
using namespace v8::internal::interpreter; namespace internal {
namespace interpreter {
TEST(AllBytecodesGenerated) { class BytecodeArrayBuilderTest : public TestWithIsolate {
InitializedHandleScope handle_scope; public:
BytecodeArrayBuilder builder(handle_scope.main_isolate()); BytecodeArrayBuilderTest() {}
~BytecodeArrayBuilderTest() override {}
};
TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
BytecodeArrayBuilder builder(isolate());
builder.set_locals_count(1); builder.set_locals_count(1);
CHECK_EQ(builder.locals_count(), 1); CHECK_EQ(builder.locals_count(), 1);
...@@ -27,13 +34,14 @@ TEST(AllBytecodesGenerated) { ...@@ -27,13 +34,14 @@ TEST(AllBytecodesGenerated) {
.LoadFalse(); .LoadFalse();
// Emit accumulator transfers. // Emit accumulator transfers.
builder.LoadAccumulatorWithRegister(0).StoreAccumulatorInRegister(0); Register reg(0);
builder.LoadAccumulatorWithRegister(reg).StoreAccumulatorInRegister(reg);
// Emit binary operators invocations. // Emit binary operators invocations.
builder.BinaryOperation(Token::Value::ADD, 0) builder.BinaryOperation(Token::Value::ADD, reg)
.BinaryOperation(Token::Value::SUB, 0) .BinaryOperation(Token::Value::SUB, reg)
.BinaryOperation(Token::Value::MUL, 0) .BinaryOperation(Token::Value::MUL, reg)
.BinaryOperation(Token::Value::DIV, 0); .BinaryOperation(Token::Value::DIV, reg);
// Emit control flow. Return must be the last instruction. // Emit control flow. Return must be the last instruction.
builder.Return(); builder.Return();
...@@ -66,11 +74,10 @@ TEST(AllBytecodesGenerated) { ...@@ -66,11 +74,10 @@ TEST(AllBytecodesGenerated) {
} }
TEST(FrameSizesLookGood) { TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
for (int locals = 0; locals < 5; locals++) { for (int locals = 0; locals < 5; locals++) {
for (int temps = 0; temps < 3; temps++) { for (int temps = 0; temps < 3; temps++) {
InitializedHandleScope handle_scope; BytecodeArrayBuilder builder(isolate());
BytecodeArrayBuilder builder(handle_scope.main_isolate());
builder.set_locals_count(locals); builder.set_locals_count(locals);
builder.Return(); builder.Return();
...@@ -87,16 +94,15 @@ TEST(FrameSizesLookGood) { ...@@ -87,16 +94,15 @@ TEST(FrameSizesLookGood) {
} }
TEST(TemporariesRecycled) { TEST_F(BytecodeArrayBuilderTest, TemporariesRecycled) {
InitializedHandleScope handle_scope; BytecodeArrayBuilder builder(isolate());
BytecodeArrayBuilder builder(handle_scope.main_isolate());
builder.set_locals_count(0); builder.set_locals_count(0);
builder.Return(); builder.Return();
int first; int first;
{ {
TemporaryRegisterScope temporaries(&builder); TemporaryRegisterScope temporaries(&builder);
first = temporaries.NewRegister(); first = temporaries.NewRegister().index();
temporaries.NewRegister(); temporaries.NewRegister();
temporaries.NewRegister(); temporaries.NewRegister();
temporaries.NewRegister(); temporaries.NewRegister();
...@@ -105,8 +111,12 @@ TEST(TemporariesRecycled) { ...@@ -105,8 +111,12 @@ TEST(TemporariesRecycled) {
int second; int second;
{ {
TemporaryRegisterScope temporaries(&builder); TemporaryRegisterScope temporaries(&builder);
second = temporaries.NewRegister(); second = temporaries.NewRegister().index();
} }
CHECK_EQ(first, second); CHECK_EQ(first, second);
} }
} // namespace interpreter
} // namespace internal
} // namespace v8
...@@ -94,6 +94,7 @@ ...@@ -94,6 +94,7 @@
'compiler/value-numbering-reducer-unittest.cc', 'compiler/value-numbering-reducer-unittest.cc',
'compiler/zone-pool-unittest.cc', 'compiler/zone-pool-unittest.cc',
'counters-unittest.cc', 'counters-unittest.cc',
'interpreter/bytecode-array-builder-unittest.cc',
'libplatform/default-platform-unittest.cc', 'libplatform/default-platform-unittest.cc',
'libplatform/task-queue-unittest.cc', 'libplatform/task-queue-unittest.cc',
'libplatform/worker-thread-unittest.cc', 'libplatform/worker-thread-unittest.cc',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment