Commit f36cc258 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Add implementations for load immediate bytecodes.

Adds implementations and tests for the following bytecodes:
  - LdaZero
  - LdaSmi8
  - LdaUndefined
  - LdaNull
  - LdaTheHole
  - LdaTrue
  - LdaFalse
  - LdaLdar
  - LdaStar

Also adds  Smi tagging / untagging and OperandType typed
BytecodeOperand operations to InterpreterAssembler.

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#30226}
parent a2462683
...@@ -110,19 +110,21 @@ Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) { ...@@ -110,19 +110,21 @@ Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
} }
Node* InterpreterAssembler::BytecodeOperand(int delta) { Node* InterpreterAssembler::BytecodeOperand(int operand_index) {
DCHECK_LT(delta, interpreter::Bytecodes::NumberOfOperands(bytecode_)); DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
return raw_assembler_->Load( return raw_assembler_->Load(
kMachUint8, BytecodeArrayTaggedPointer(), kMachUint8, BytecodeArrayTaggedPointer(),
raw_assembler_->IntPtrAdd(BytecodeOffset(), Int32Constant(1 + delta))); raw_assembler_->IntPtrAdd(BytecodeOffset(),
Int32Constant(1 + operand_index)));
} }
Node* InterpreterAssembler::BytecodeOperandSignExtended(int delta) { Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) {
DCHECK_LT(delta, interpreter::Bytecodes::NumberOfOperands(bytecode_)); DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
Node* load = raw_assembler_->Load( Node* load = raw_assembler_->Load(
kMachInt8, BytecodeArrayTaggedPointer(), kMachInt8, BytecodeArrayTaggedPointer(),
raw_assembler_->IntPtrAdd(BytecodeOffset(), Int32Constant(1 + delta))); raw_assembler_->IntPtrAdd(BytecodeOffset(),
Int32Constant(1 + operand_index)));
// Ensure that we sign extend to full pointer size // Ensure that we sign extend to full pointer size
if (kPointerSize == 8) { if (kPointerSize == 8) {
load = raw_assembler_->ChangeInt32ToInt64(load); load = raw_assembler_->ChangeInt32ToInt64(load);
...@@ -131,6 +133,50 @@ Node* InterpreterAssembler::BytecodeOperandSignExtended(int delta) { ...@@ -131,6 +133,50 @@ Node* InterpreterAssembler::BytecodeOperandSignExtended(int delta) {
} }
Node* InterpreterAssembler::BytecodeOperandImm8(int operand_index) {
DCHECK_EQ(interpreter::OperandType::kImm8,
interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
return BytecodeOperandSignExtended(operand_index);
}
Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) {
DCHECK_EQ(interpreter::OperandType::kReg,
interpreter::Bytecodes::GetOperandType(bytecode_, operand_index));
return BytecodeOperandSignExtended(operand_index);
}
Node* InterpreterAssembler::Int32Constant(int value) {
return raw_assembler_->Int32Constant(value);
}
Node* InterpreterAssembler::NumberConstant(double value) {
return raw_assembler_->NumberConstant(value);
}
Node* InterpreterAssembler::HeapConstant(Unique<HeapObject> object) {
return raw_assembler_->HeapConstant(object);
}
Node* InterpreterAssembler::SmiShiftBitsConstant() {
return Int32Constant(kSmiShiftSize + kSmiTagSize);
}
Node* InterpreterAssembler::SmiTag(Node* value) {
return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
}
Node* InterpreterAssembler::SmiUntag(Node* value) {
return raw_assembler_->WordSar(value, SmiShiftBitsConstant());
}
void InterpreterAssembler::Return() { void InterpreterAssembler::Return() {
Node* exit_trampoline_code_object = Node* exit_trampoline_code_object =
HeapConstant(Unique<HeapObject>::CreateImmovable( HeapConstant(Unique<HeapObject>::CreateImmovable(
...@@ -213,19 +259,6 @@ Schedule* InterpreterAssembler::schedule() { ...@@ -213,19 +259,6 @@ Schedule* InterpreterAssembler::schedule() {
} }
Node* InterpreterAssembler::Int32Constant(int value) {
return raw_assembler_->Int32Constant(value);
}
Node* InterpreterAssembler::NumberConstant(double value) {
return raw_assembler_->NumberConstant(value);
}
Node* InterpreterAssembler::HeapConstant(Unique<HeapObject> object) {
return raw_assembler_->HeapConstant(object);
}
} // namespace interpreter } // namespace interpreter
} // namespace internal } // namespace internal
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef V8_COMPILER_INTERPRETER_CODEGEN_H_ #ifndef V8_COMPILER_INTERPRETER_ASSEMBLER_H_
#define V8_COMPILER_INTERPRETER_CODEGEN_H_ #define V8_COMPILER_INTERPRETER_ASSEMBLER_H_
// Clients of this interface shouldn't depend on lots of compiler internals. // Clients of this interface shouldn't depend on lots of compiler internals.
// Do not include anything from src/compiler here! // Do not include anything from src/compiler here!
...@@ -36,6 +36,13 @@ class InterpreterAssembler { ...@@ -36,6 +36,13 @@ class InterpreterAssembler {
Handle<Code> GenerateCode(); Handle<Code> GenerateCode();
// Returns the Imm8 immediate for bytecode operand |operand_index| in the
// current bytecode.
Node* BytecodeOperandImm8(int operand_index);
// Returns the register index for bytecode operand |operand_index| in the
// current bytecode.
Node* BytecodeOperandReg(int operand_index);
// Accumulator. // Accumulator.
Node* GetAccumulator(); Node* GetAccumulator();
void SetAccumulator(Node* value); void SetAccumulator(Node* value);
...@@ -49,15 +56,16 @@ class InterpreterAssembler { ...@@ -49,15 +56,16 @@ class InterpreterAssembler {
Node* NumberConstant(double value); Node* NumberConstant(double value);
Node* HeapConstant(Unique<HeapObject> object); Node* HeapConstant(Unique<HeapObject> object);
// Tag and untag Smi values.
Node* SmiTag(Node* value);
Node* SmiUntag(Node* value);
// Returns from the function. // Returns from the function.
void Return(); void Return();
// Dispatch to the bytecode. // Dispatch to the bytecode.
void Dispatch(); void Dispatch();
Node* BytecodeOperand(int index);
Node* BytecodeOperandSignExtended(int index);
protected: protected:
// Close the graph. // Close the graph.
void End(); void End();
...@@ -79,6 +87,10 @@ class InterpreterAssembler { ...@@ -79,6 +87,10 @@ class InterpreterAssembler {
// Returns the offset of register |index| relative to RegisterFilePointer(). // Returns the offset of register |index| relative to RegisterFilePointer().
Node* RegisterFrameOffset(Node* index); Node* RegisterFrameOffset(Node* index);
Node* SmiShiftBitsConstant();
Node* BytecodeOperand(int operand_index);
Node* BytecodeOperandSignExtended(int operand_index);
// Returns BytecodeOffset() advanced by delta bytecodes. Note: this does not // Returns BytecodeOffset() advanced by delta bytecodes. Note: this does not
// update BytecodeOffset() itself. // update BytecodeOffset() itself.
Node* Advance(int delta); Node* Advance(int delta);
...@@ -103,4 +115,4 @@ class InterpreterAssembler { ...@@ -103,4 +115,4 @@ class InterpreterAssembler {
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
#endif // V8_COMPILER_INTERPRETER_CODEGEN_H_ #endif // V8_COMPILER_INTERPRETER_ASSEMBLER_H_
...@@ -89,7 +89,8 @@ bool Interpreter::IsInterpreterTableInitialized( ...@@ -89,7 +89,8 @@ bool Interpreter::IsInterpreterTableInitialized(
// //
// Load literal '0' into the accumulator. // Load literal '0' into the accumulator.
void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* zero_value = __ NumberConstant(0.0);
__ SetAccumulator(zero_value);
__ Dispatch(); __ Dispatch();
} }
...@@ -98,7 +99,9 @@ void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) { ...@@ -98,7 +99,9 @@ void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) {
// //
// Load an 8-bit integer literal into the accumulator as a Smi. // Load an 8-bit integer literal into the accumulator as a Smi.
void Interpreter::DoLdaSmi8(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdaSmi8(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement 8-bit integer to SMI promotion. Node* raw_int = __ BytecodeOperandImm8(0);
Node* smi_int = __ SmiTag(raw_int);
__ SetAccumulator(smi_int);
__ Dispatch(); __ Dispatch();
} }
...@@ -107,7 +110,9 @@ void Interpreter::DoLdaSmi8(compiler::InterpreterAssembler* assembler) { ...@@ -107,7 +110,9 @@ void Interpreter::DoLdaSmi8(compiler::InterpreterAssembler* assembler) {
// //
// Load Undefined into the accumulator. // Load Undefined into the accumulator.
void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* undefined_value = __ HeapConstant(Unique<HeapObject>::CreateImmovable(
isolate_->factory()->undefined_value()));
__ SetAccumulator(undefined_value);
__ Dispatch(); __ Dispatch();
} }
...@@ -116,7 +121,9 @@ void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) { ...@@ -116,7 +121,9 @@ void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) {
// //
// Load Null into the accumulator. // Load Null into the accumulator.
void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* null_value = __ HeapConstant(
Unique<HeapObject>::CreateImmovable(isolate_->factory()->null_value()));
__ SetAccumulator(null_value);
__ Dispatch(); __ Dispatch();
} }
...@@ -125,7 +132,9 @@ void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) { ...@@ -125,7 +132,9 @@ void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) {
// //
// Load TheHole into the accumulator. // Load TheHole into the accumulator.
void Interpreter::DoLdaTheHole(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdaTheHole(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* the_hole_value = __ HeapConstant(Unique<HeapObject>::CreateImmovable(
isolate_->factory()->the_hole_value()));
__ SetAccumulator(the_hole_value);
__ Dispatch(); __ Dispatch();
} }
...@@ -134,7 +143,9 @@ void Interpreter::DoLdaTheHole(compiler::InterpreterAssembler* assembler) { ...@@ -134,7 +143,9 @@ void Interpreter::DoLdaTheHole(compiler::InterpreterAssembler* assembler) {
// //
// Load True into the accumulator. // Load True into the accumulator.
void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* true_value = __ HeapConstant(
Unique<HeapObject>::CreateImmovable(isolate_->factory()->true_value()));
__ SetAccumulator(true_value);
__ Dispatch(); __ Dispatch();
} }
...@@ -143,7 +154,9 @@ void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) { ...@@ -143,7 +154,9 @@ void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) {
// //
// Load False into the accumulator. // Load False into the accumulator.
void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* false_value = __ HeapConstant(
Unique<HeapObject>::CreateImmovable(isolate_->factory()->false_value()));
__ SetAccumulator(false_value);
__ Dispatch(); __ Dispatch();
} }
...@@ -152,7 +165,8 @@ void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) { ...@@ -152,7 +165,8 @@ void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) {
// //
// Load accumulator with value from register <src>. // Load accumulator with value from register <src>.
void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) { void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* value = __ LoadRegister(__ BytecodeOperandReg(0));
__ SetAccumulator(value);
__ Dispatch(); __ Dispatch();
} }
...@@ -161,7 +175,9 @@ void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) { ...@@ -161,7 +175,9 @@ void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) {
// //
// Store accumulator to register <dst>. // Store accumulator to register <dst>.
void Interpreter::DoStar(compiler::InterpreterAssembler* assembler) { void Interpreter::DoStar(compiler::InterpreterAssembler* assembler) {
// TODO(rmcilroy) Implement. Node* reg_index = __ BytecodeOperandReg(0);
Node* accumulator = __ GetAccumulator();
__ StoreRegister(accumulator, reg_index);
__ Dispatch(); __ Dispatch();
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
namespace interpreter {
class InterpreterCallable { class InterpreterCallable {
public: public:
...@@ -60,10 +61,14 @@ class InterpreterTester { ...@@ -60,10 +61,14 @@ class InterpreterTester {
DISALLOW_COPY_AND_ASSIGN(InterpreterTester); DISALLOW_COPY_AND_ASSIGN(InterpreterTester);
}; };
} // namespace interpreter
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
using namespace v8::internal; using v8::internal::BytecodeArray;
using v8::internal::Handle;
using v8::internal::Object;
using v8::internal::Smi;
using namespace v8::internal::interpreter; using namespace v8::internal::interpreter;
TEST(TestInterpreterReturn) { TEST(TestInterpreterReturn) {
...@@ -81,3 +86,123 @@ TEST(TestInterpreterReturn) { ...@@ -81,3 +86,123 @@ TEST(TestInterpreterReturn) {
Handle<Object> return_val = callable().ToHandleChecked(); Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val.is_identical_to(undefined_value)); CHECK(return_val.is_identical_to(undefined_value));
} }
TEST(TestInterpreterLoadUndefined) {
InitializedHandleScope handles;
Handle<Object> undefined_value =
handles.main_isolate()->factory()->undefined_value();
BytecodeArrayBuilder builder(handles.main_isolate());
builder.set_locals_count(0);
builder.LoadUndefined().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
InterpreterTester tester(handles.main_isolate(), bytecode_array);
InterpreterCallable callable(tester.GetCallable());
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val.is_identical_to(undefined_value));
}
TEST(TestInterpreterLoadNull) {
InitializedHandleScope handles;
Handle<Object> null_value = handles.main_isolate()->factory()->null_value();
BytecodeArrayBuilder builder(handles.main_isolate());
builder.set_locals_count(0);
builder.LoadNull().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
InterpreterTester tester(handles.main_isolate(), bytecode_array);
InterpreterCallable callable(tester.GetCallable());
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val.is_identical_to(null_value));
}
TEST(TestInterpreterLoadTheHole) {
InitializedHandleScope handles;
Handle<Object> the_hole_value =
handles.main_isolate()->factory()->the_hole_value();
BytecodeArrayBuilder builder(handles.main_isolate());
builder.set_locals_count(0);
builder.LoadTheHole().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
InterpreterTester tester(handles.main_isolate(), bytecode_array);
InterpreterCallable callable(tester.GetCallable());
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val.is_identical_to(the_hole_value));
}
TEST(TestInterpreterLoadTrue) {
InitializedHandleScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
BytecodeArrayBuilder builder(handles.main_isolate());
builder.set_locals_count(0);
builder.LoadTrue().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
InterpreterTester tester(handles.main_isolate(), bytecode_array);
InterpreterCallable callable(tester.GetCallable());
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val.is_identical_to(true_value));
}
TEST(TestInterpreterLoadFalse) {
InitializedHandleScope handles;
Handle<Object> false_value = handles.main_isolate()->factory()->false_value();
BytecodeArrayBuilder builder(handles.main_isolate());
builder.set_locals_count(0);
builder.LoadFalse().Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
InterpreterTester tester(handles.main_isolate(), bytecode_array);
InterpreterCallable callable(tester.GetCallable());
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val.is_identical_to(false_value));
}
TEST(TestInterpreterLoadLiteral) {
InitializedHandleScope handles;
for (int i = -128; i < 128; i++) {
BytecodeArrayBuilder builder(handles.main_isolate());
builder.set_locals_count(0);
builder.LoadLiteral(Smi::FromInt(i)).Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
InterpreterTester tester(handles.main_isolate(), bytecode_array);
InterpreterCallable callable(tester.GetCallable());
Handle<Object> return_val = callable().ToHandleChecked();
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(i));
}
}
TEST(TestInterpreterLoadStoreRegisters) {
InitializedHandleScope handles;
Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
for (int i = 0; i <= Register::kMaxRegisterIndex; i++) {
BytecodeArrayBuilder builder(handles.main_isolate());
builder.set_locals_count(i + 1);
Register reg(i);
builder.LoadTrue()
.StoreAccumulatorInRegister(reg)
.LoadFalse()
.LoadAccumulatorWithRegister(reg)
.Return();
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
InterpreterTester tester(handles.main_isolate(), bytecode_array);
InterpreterCallable callable(tester.GetCallable());
Handle<Object> return_val = callable().ToHandleChecked();
CHECK(return_val.is_identical_to(true_value));
}
}
...@@ -23,10 +23,31 @@ const interpreter::Bytecode kBytecodes[] = { ...@@ -23,10 +23,31 @@ const interpreter::Bytecode kBytecodes[] = {
}; };
Graph* Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
InterpreterAssemblerTest::InterpreterAssemblerForTest::GetCompletedGraph() { const Matcher<Node*>& rhs_matcher) {
End(); return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
return graph(); : IsInt32Add(lhs_matcher, rhs_matcher);
}
Matcher<Node*> IsIntPtrSub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return kPointerSize == 8 ? IsInt64Sub(lhs_matcher, rhs_matcher)
: IsInt32Sub(lhs_matcher, rhs_matcher);
}
Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
: IsWord32Shl(lhs_matcher, rhs_matcher);
}
Matcher<Node*> IsWordSar(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return kPointerSize == 8 ? IsWord64Sar(lhs_matcher, rhs_matcher)
: IsWord32Sar(lhs_matcher, rhs_matcher);
} }
...@@ -48,24 +69,33 @@ Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore( ...@@ -48,24 +69,33 @@ Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore(
} }
Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher, Matcher<Node*>
const Matcher<Node*>& rhs_matcher) { InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher) int operand) {
: IsInt32Add(lhs_matcher, rhs_matcher); return IsLoad(
kMachUint8, IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
IsInt32Constant(1 + operand)));
} }
Matcher<Node*> IsIntPtrSub(const Matcher<Node*>& lhs_matcher, Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
const Matcher<Node*>& rhs_matcher) { IsBytecodeOperandSignExtended(int operand) {
return kPointerSize == 8 ? IsInt64Sub(lhs_matcher, rhs_matcher) Matcher<Node*> load_matcher = IsLoad(
: IsInt32Sub(lhs_matcher, rhs_matcher); kMachInt8, IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
IsInt32Constant(1 + operand)));
if (kPointerSize == 8) {
load_matcher = IsChangeInt32ToInt64(load_matcher);
}
return load_matcher;
} }
Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher, Graph*
const Matcher<Node*>& rhs_matcher) { InterpreterAssemblerTest::InterpreterAssemblerForTest::GetCompletedGraph() {
return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher) End();
: IsWord32Shl(lhs_matcher, rhs_matcher); return graph();
} }
...@@ -138,35 +168,20 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) { ...@@ -138,35 +168,20 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
InterpreterAssemblerForTest m(this, bytecode); InterpreterAssemblerForTest m(this, bytecode);
int number_of_operands = interpreter::Bytecodes::NumberOfOperands(bytecode); int number_of_operands = interpreter::Bytecodes::NumberOfOperands(bytecode);
for (int i = 0; i < number_of_operands; i++) { for (int i = 0; i < number_of_operands; i++) {
Node* load_arg_node = m.BytecodeOperand(i); switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
EXPECT_THAT( case interpreter::OperandType::kImm8:
load_arg_node, EXPECT_THAT(m.BytecodeOperandImm8(i),
m.IsLoad( m.IsBytecodeOperandSignExtended(i));
kMachUint8, break;
IsParameter(Linkage::kInterpreterBytecodeArrayParameter), case interpreter::OperandType::kReg:
IsIntPtrAdd( EXPECT_THAT(m.BytecodeOperandReg(i),
IsParameter(Linkage::kInterpreterBytecodeOffsetParameter), m.IsBytecodeOperandSignExtended(i));
IsInt32Constant(1 + i)))); break;
case interpreter::OperandType::kNone:
UNREACHABLE();
break;
} }
} }
}
TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperandSignExtended) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
int number_of_operands = interpreter::Bytecodes::NumberOfOperands(bytecode);
for (int i = 0; i < number_of_operands; i++) {
Node* load_arg_node = m.BytecodeOperandSignExtended(i);
Matcher<Node*> load_matcher = m.IsLoad(
kMachInt8, IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
IsInt32Constant(1 + i)));
if (kPointerSize == 8) {
load_matcher = IsChangeInt32ToInt64(load_matcher);
}
EXPECT_THAT(load_arg_node, load_matcher);
}
} }
} }
...@@ -230,6 +245,18 @@ TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) { ...@@ -230,6 +245,18 @@ TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
} }
} }
TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
Node* value = m.Int32Constant(44);
EXPECT_THAT(m.SmiTag(value),
IsWordShl(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
EXPECT_THAT(m.SmiUntag(value),
IsWordSar(value, IsInt32Constant(kSmiShiftSize + kSmiTagSize)));
}
}
} // namespace compiler } // namespace compiler
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -38,6 +38,8 @@ class InterpreterAssemblerTest : public TestWithIsolateAndZone { ...@@ -38,6 +38,8 @@ class InterpreterAssemblerTest : public TestWithIsolateAndZone {
const Matcher<Node*>& base_matcher, const Matcher<Node*>& base_matcher,
const Matcher<Node*>& index_matcher, const Matcher<Node*>& index_matcher,
const Matcher<Node*>& value_matcher); const Matcher<Node*>& value_matcher);
Matcher<Node*> IsBytecodeOperand(int operand);
Matcher<Node*> IsBytecodeOperandSignExtended(int operand);
using InterpreterAssembler::call_descriptor; using InterpreterAssembler::call_descriptor;
using InterpreterAssembler::graph; using InterpreterAssembler::graph;
......
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