[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}
This commit is contained in:
parent
a2462683b7
commit
f36cc258ff
@ -110,19 +110,21 @@ Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
|
||||
}
|
||||
|
||||
|
||||
Node* InterpreterAssembler::BytecodeOperand(int delta) {
|
||||
DCHECK_LT(delta, interpreter::Bytecodes::NumberOfOperands(bytecode_));
|
||||
Node* InterpreterAssembler::BytecodeOperand(int operand_index) {
|
||||
DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
|
||||
return raw_assembler_->Load(
|
||||
kMachUint8, BytecodeArrayTaggedPointer(),
|
||||
raw_assembler_->IntPtrAdd(BytecodeOffset(), Int32Constant(1 + delta)));
|
||||
raw_assembler_->IntPtrAdd(BytecodeOffset(),
|
||||
Int32Constant(1 + operand_index)));
|
||||
}
|
||||
|
||||
|
||||
Node* InterpreterAssembler::BytecodeOperandSignExtended(int delta) {
|
||||
DCHECK_LT(delta, interpreter::Bytecodes::NumberOfOperands(bytecode_));
|
||||
Node* InterpreterAssembler::BytecodeOperandSignExtended(int operand_index) {
|
||||
DCHECK_LT(operand_index, interpreter::Bytecodes::NumberOfOperands(bytecode_));
|
||||
Node* load = raw_assembler_->Load(
|
||||
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
|
||||
if (kPointerSize == 8) {
|
||||
load = raw_assembler_->ChangeInt32ToInt64(load);
|
||||
@ -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() {
|
||||
Node* exit_trampoline_code_object =
|
||||
HeapConstant(Unique<HeapObject>::CreateImmovable(
|
||||
@ -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 internal
|
||||
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_COMPILER_INTERPRETER_CODEGEN_H_
|
||||
#define V8_COMPILER_INTERPRETER_CODEGEN_H_
|
||||
#ifndef V8_COMPILER_INTERPRETER_ASSEMBLER_H_
|
||||
#define V8_COMPILER_INTERPRETER_ASSEMBLER_H_
|
||||
|
||||
// Clients of this interface shouldn't depend on lots of compiler internals.
|
||||
// Do not include anything from src/compiler here!
|
||||
@ -36,6 +36,13 @@ class InterpreterAssembler {
|
||||
|
||||
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.
|
||||
Node* GetAccumulator();
|
||||
void SetAccumulator(Node* value);
|
||||
@ -49,15 +56,16 @@ class InterpreterAssembler {
|
||||
Node* NumberConstant(double value);
|
||||
Node* HeapConstant(Unique<HeapObject> object);
|
||||
|
||||
// Tag and untag Smi values.
|
||||
Node* SmiTag(Node* value);
|
||||
Node* SmiUntag(Node* value);
|
||||
|
||||
// Returns from the function.
|
||||
void Return();
|
||||
|
||||
// Dispatch to the bytecode.
|
||||
void Dispatch();
|
||||
|
||||
Node* BytecodeOperand(int index);
|
||||
Node* BytecodeOperandSignExtended(int index);
|
||||
|
||||
protected:
|
||||
// Close the graph.
|
||||
void End();
|
||||
@ -79,6 +87,10 @@ class InterpreterAssembler {
|
||||
// Returns the offset of register |index| relative to RegisterFilePointer().
|
||||
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
|
||||
// update BytecodeOffset() itself.
|
||||
Node* Advance(int delta);
|
||||
@ -103,4 +115,4 @@ class InterpreterAssembler {
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_COMPILER_INTERPRETER_CODEGEN_H_
|
||||
#endif // V8_COMPILER_INTERPRETER_ASSEMBLER_H_
|
||||
|
@ -89,7 +89,8 @@ bool Interpreter::IsInterpreterTableInitialized(
|
||||
//
|
||||
// Load literal '0' into the accumulator.
|
||||
void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) {
|
||||
// TODO(rmcilroy) Implement.
|
||||
Node* zero_value = __ NumberConstant(0.0);
|
||||
__ SetAccumulator(zero_value);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
@ -98,7 +99,9 @@ void Interpreter::DoLdaZero(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Load an 8-bit integer literal into the accumulator as a Smi.
|
||||
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();
|
||||
}
|
||||
|
||||
@ -107,7 +110,9 @@ void Interpreter::DoLdaSmi8(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Load Undefined into the accumulator.
|
||||
void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) {
|
||||
// TODO(rmcilroy) Implement.
|
||||
Node* undefined_value = __ HeapConstant(Unique<HeapObject>::CreateImmovable(
|
||||
isolate_->factory()->undefined_value()));
|
||||
__ SetAccumulator(undefined_value);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
@ -116,7 +121,9 @@ void Interpreter::DoLdaUndefined(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Load Null into the accumulator.
|
||||
void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) {
|
||||
// TODO(rmcilroy) Implement.
|
||||
Node* null_value = __ HeapConstant(
|
||||
Unique<HeapObject>::CreateImmovable(isolate_->factory()->null_value()));
|
||||
__ SetAccumulator(null_value);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
@ -125,7 +132,9 @@ void Interpreter::DoLdaNull(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Load TheHole into the accumulator.
|
||||
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();
|
||||
}
|
||||
|
||||
@ -134,7 +143,9 @@ void Interpreter::DoLdaTheHole(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Load True into the accumulator.
|
||||
void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) {
|
||||
// TODO(rmcilroy) Implement.
|
||||
Node* true_value = __ HeapConstant(
|
||||
Unique<HeapObject>::CreateImmovable(isolate_->factory()->true_value()));
|
||||
__ SetAccumulator(true_value);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
@ -143,7 +154,9 @@ void Interpreter::DoLdaTrue(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Load False into the accumulator.
|
||||
void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) {
|
||||
// TODO(rmcilroy) Implement.
|
||||
Node* false_value = __ HeapConstant(
|
||||
Unique<HeapObject>::CreateImmovable(isolate_->factory()->false_value()));
|
||||
__ SetAccumulator(false_value);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
@ -152,7 +165,8 @@ void Interpreter::DoLdaFalse(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Load accumulator with value from register <src>.
|
||||
void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) {
|
||||
// TODO(rmcilroy) Implement.
|
||||
Node* value = __ LoadRegister(__ BytecodeOperandReg(0));
|
||||
__ SetAccumulator(value);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
@ -161,7 +175,9 @@ void Interpreter::DoLdar(compiler::InterpreterAssembler* assembler) {
|
||||
//
|
||||
// Store accumulator to register <dst>.
|
||||
void Interpreter::DoStar(compiler::InterpreterAssembler* assembler) {
|
||||
// TODO(rmcilroy) Implement.
|
||||
Node* reg_index = __ BytecodeOperandReg(0);
|
||||
Node* accumulator = __ GetAccumulator();
|
||||
__ StoreRegister(accumulator, reg_index);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace interpreter {
|
||||
|
||||
class InterpreterCallable {
|
||||
public:
|
||||
@ -60,10 +61,14 @@ class InterpreterTester {
|
||||
DISALLOW_COPY_AND_ASSIGN(InterpreterTester);
|
||||
};
|
||||
|
||||
} // namespace interpreter
|
||||
} // namespace internal
|
||||
} // 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;
|
||||
|
||||
TEST(TestInterpreterReturn) {
|
||||
@ -81,3 +86,123 @@ TEST(TestInterpreterReturn) {
|
||||
Handle<Object> return_val = callable().ToHandleChecked();
|
||||
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[] = {
|
||||
};
|
||||
|
||||
|
||||
Graph*
|
||||
InterpreterAssemblerTest::InterpreterAssemblerForTest::GetCompletedGraph() {
|
||||
End();
|
||||
return graph();
|
||||
Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher) {
|
||||
return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
|
||||
: 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(
|
||||
}
|
||||
|
||||
|
||||
Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
|
||||
const Matcher<Node*>& rhs_matcher) {
|
||||
return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
|
||||
: IsInt32Add(lhs_matcher, rhs_matcher);
|
||||
Matcher<Node*>
|
||||
InterpreterAssemblerTest::InterpreterAssemblerForTest::IsBytecodeOperand(
|
||||
int operand) {
|
||||
return IsLoad(
|
||||
kMachUint8, IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
|
||||
IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
|
||||
IsInt32Constant(1 + operand)));
|
||||
}
|
||||
|
||||
|
||||
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*> InterpreterAssemblerTest::InterpreterAssemblerForTest::
|
||||
IsBytecodeOperandSignExtended(int operand) {
|
||||
Matcher<Node*> load_matcher = IsLoad(
|
||||
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,
|
||||
const Matcher<Node*>& rhs_matcher) {
|
||||
return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
|
||||
: IsWord32Shl(lhs_matcher, rhs_matcher);
|
||||
Graph*
|
||||
InterpreterAssemblerTest::InterpreterAssemblerForTest::GetCompletedGraph() {
|
||||
End();
|
||||
return graph();
|
||||
}
|
||||
|
||||
|
||||
@ -138,34 +168,19 @@ TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
|
||||
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.BytecodeOperand(i);
|
||||
EXPECT_THAT(
|
||||
load_arg_node,
|
||||
m.IsLoad(
|
||||
kMachUint8,
|
||||
IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
|
||||
IsIntPtrAdd(
|
||||
IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
|
||||
IsInt32Constant(1 + i))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
switch (interpreter::Bytecodes::GetOperandType(bytecode, i)) {
|
||||
case interpreter::OperandType::kImm8:
|
||||
EXPECT_THAT(m.BytecodeOperandImm8(i),
|
||||
m.IsBytecodeOperandSignExtended(i));
|
||||
break;
|
||||
case interpreter::OperandType::kReg:
|
||||
EXPECT_THAT(m.BytecodeOperandReg(i),
|
||||
m.IsBytecodeOperandSignExtended(i));
|
||||
break;
|
||||
case interpreter::OperandType::kNone:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
EXPECT_THAT(load_arg_node, load_matcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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 internal
|
||||
} // namespace v8
|
||||
|
@ -38,6 +38,8 @@ class InterpreterAssemblerTest : public TestWithIsolateAndZone {
|
||||
const Matcher<Node*>& base_matcher,
|
||||
const Matcher<Node*>& index_matcher,
|
||||
const Matcher<Node*>& value_matcher);
|
||||
Matcher<Node*> IsBytecodeOperand(int operand);
|
||||
Matcher<Node*> IsBytecodeOperandSignExtended(int operand);
|
||||
|
||||
using InterpreterAssembler::call_descriptor;
|
||||
using InterpreterAssembler::graph;
|
||||
|
Loading…
Reference in New Issue
Block a user