Index: test/cctest/interpreter/test-interpreter.cc |
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc |
index 2c5588513b707d5fc3d1501eba481b3ca229be96..26deea642f68fa75188daab094b9b0063d76d671 100644 |
--- a/test/cctest/interpreter/test-interpreter.cc |
+++ b/test/cctest/interpreter/test-interpreter.cc |
@@ -14,16 +14,35 @@ namespace v8 { |
namespace internal { |
namespace interpreter { |
+ |
+static MaybeHandle<Object> CallInterpreter(Isolate* isolate, |
+ Handle<JSFunction> function) { |
+ return Execution::Call(isolate, function, |
+ isolate->factory()->undefined_value(), 0, nullptr, |
+ false); |
+} |
+ |
+ |
+template <class... A> |
+static MaybeHandle<Object> CallInterpreter(Isolate* isolate, |
+ Handle<JSFunction> function, |
+ A... args) { |
+ Handle<Object> argv[] = { args... }; |
+ return Execution::Call(isolate, function, |
+ isolate->factory()->undefined_value(), sizeof...(args), |
+ argv, false); |
+} |
+ |
+ |
+template <class... A> |
class InterpreterCallable { |
public: |
InterpreterCallable(Isolate* isolate, Handle<JSFunction> function) |
: isolate_(isolate), function_(function) {} |
virtual ~InterpreterCallable() {} |
- MaybeHandle<Object> operator()() { |
- return Execution::Call(isolate_, function_, |
- isolate_->factory()->undefined_value(), 0, nullptr, |
- false); |
+ MaybeHandle<Object> operator()(A... args) { |
+ return CallInterpreter(isolate_, function_, args...); |
} |
private: |
@@ -31,30 +50,39 @@ class InterpreterCallable { |
Handle<JSFunction> function_; |
}; |
+ |
class InterpreterTester { |
public: |
InterpreterTester(Isolate* isolate, Handle<BytecodeArray> bytecode) |
- : isolate_(isolate), function_(GetBytecodeFunction(isolate, bytecode)) { |
+ : isolate_(isolate), bytecode_(bytecode) { |
i::FLAG_ignition = true; |
// Ensure handler table is generated. |
isolate->interpreter()->Initialize(); |
} |
virtual ~InterpreterTester() {} |
- InterpreterCallable GetCallable() { |
- return InterpreterCallable(isolate_, function_); |
+ template <class... A> |
+ InterpreterCallable<A...> GetCallable() { |
+ return InterpreterCallable<A...>(isolate_, GetBytecodeFunction<A...>()); |
} |
private: |
Isolate* isolate_; |
- Handle<JSFunction> function_; |
+ Handle<BytecodeArray> bytecode_; |
+ |
+ template <class... A> |
+ Handle<JSFunction> GetBytecodeFunction() { |
+ int arg_count = sizeof...(A); |
+ std::string function_text("(function("); |
+ for (int i = 0; i < arg_count; i++) { |
+ function_text += i == 0 ? "a" : ", a"; |
+ } |
+ function_text += "){})"; |
- static Handle<JSFunction> GetBytecodeFunction( |
- Isolate* isolate, Handle<BytecodeArray> bytecode_array) { |
Handle<JSFunction> function = v8::Utils::OpenHandle( |
- *v8::Handle<v8::Function>::Cast(CompileRun("(function(){})"))); |
- function->ReplaceCode(*isolate->builtins()->InterpreterEntryTrampoline()); |
- function->shared()->set_function_data(*bytecode_array); |
+ *v8::Handle<v8::Function>::Cast(CompileRun(function_text.c_str()))); |
+ function->ReplaceCode(*isolate_->builtins()->InterpreterEntryTrampoline()); |
+ function->shared()->set_function_data(*bytecode_); |
return function; |
} |
@@ -72,127 +100,135 @@ using v8::internal::Smi; |
using v8::internal::Token; |
using namespace v8::internal::interpreter; |
-TEST(TestInterpreterReturn) { |
+TEST(InterpreterReturn) { |
InitializedHandleScope handles; |
Handle<Object> undefined_value = |
handles.main_isolate()->factory()->undefined_value(); |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
builder.Return(); |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK(return_val.is_identical_to(undefined_value)); |
} |
-TEST(TestInterpreterLoadUndefined) { |
+TEST(InterpreterLoadUndefined) { |
InitializedHandleScope handles; |
Handle<Object> undefined_value = |
handles.main_isolate()->factory()->undefined_value(); |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
builder.LoadUndefined().Return(); |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK(return_val.is_identical_to(undefined_value)); |
} |
-TEST(TestInterpreterLoadNull) { |
+TEST(InterpreterLoadNull) { |
InitializedHandleScope handles; |
Handle<Object> null_value = handles.main_isolate()->factory()->null_value(); |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
builder.LoadNull().Return(); |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK(return_val.is_identical_to(null_value)); |
} |
-TEST(TestInterpreterLoadTheHole) { |
+TEST(InterpreterLoadTheHole) { |
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.set_parameter_count(1); |
builder.LoadTheHole().Return(); |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK(return_val.is_identical_to(the_hole_value)); |
} |
-TEST(TestInterpreterLoadTrue) { |
+TEST(InterpreterLoadTrue) { |
InitializedHandleScope handles; |
Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
builder.LoadTrue().Return(); |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK(return_val.is_identical_to(true_value)); |
} |
-TEST(TestInterpreterLoadFalse) { |
+TEST(InterpreterLoadFalse) { |
InitializedHandleScope handles; |
Handle<Object> false_value = handles.main_isolate()->factory()->false_value(); |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
builder.LoadFalse().Return(); |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK(return_val.is_identical_to(false_value)); |
} |
-TEST(TestInterpreterLoadLiteral) { |
+TEST(InterpreterLoadLiteral) { |
InitializedHandleScope handles; |
for (int i = -128; i < 128; i++) { |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
builder.LoadLiteral(Smi::FromInt(i)).Return(); |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(i)); |
} |
} |
-TEST(TestInterpreterLoadStoreRegisters) { |
+TEST(InterpreterLoadStoreRegisters) { |
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); |
+ builder.set_parameter_count(1); |
Register reg(i); |
builder.LoadTrue() |
.StoreAccumulatorInRegister(reg) |
@@ -202,19 +238,20 @@ TEST(TestInterpreterLoadStoreRegisters) { |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK(return_val.is_identical_to(true_value)); |
} |
} |
-TEST(TestInterpreterAdd) { |
+TEST(InterpreterAdd) { |
InitializedHandleScope handles; |
// TODO(rmcilroy): Do add tests for heap numbers and strings once we support |
// them. |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(1); |
+ builder.set_parameter_count(1); |
Register reg(0); |
builder.LoadLiteral(Smi::FromInt(1)) |
.StoreAccumulatorInRegister(reg) |
@@ -224,17 +261,18 @@ TEST(TestInterpreterAdd) { |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3)); |
} |
-TEST(TestInterpreterSub) { |
+TEST(InterpreterSub) { |
InitializedHandleScope handles; |
// TODO(rmcilroy): Do add tests for heap numbers once we support them. |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(1); |
+ builder.set_parameter_count(1); |
Register reg(0); |
builder.LoadLiteral(Smi::FromInt(5)) |
.StoreAccumulatorInRegister(reg) |
@@ -244,17 +282,18 @@ TEST(TestInterpreterSub) { |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(-26)); |
} |
-TEST(TestInterpreterMul) { |
+TEST(InterpreterMul) { |
InitializedHandleScope handles; |
// TODO(rmcilroy): Do add tests for heap numbers once we support them. |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(1); |
+ builder.set_parameter_count(1); |
Register reg(0); |
builder.LoadLiteral(Smi::FromInt(111)) |
.StoreAccumulatorInRegister(reg) |
@@ -264,17 +303,18 @@ TEST(TestInterpreterMul) { |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(666)); |
} |
-TEST(TestInterpreterDiv) { |
+TEST(InterpreterDiv) { |
InitializedHandleScope handles; |
// TODO(rmcilroy): Do add tests for heap numbers once we support them. |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(1); |
+ builder.set_parameter_count(1); |
Register reg(0); |
builder.LoadLiteral(Smi::FromInt(-20)) |
.StoreAccumulatorInRegister(reg) |
@@ -284,17 +324,18 @@ TEST(TestInterpreterDiv) { |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(-4)); |
} |
-TEST(TestInterpreterMod) { |
+TEST(InterpreterMod) { |
InitializedHandleScope handles; |
// TODO(rmcilroy): Do add tests for heap numbers once we support them. |
BytecodeArrayBuilder builder(handles.main_isolate()); |
builder.set_locals_count(1); |
+ builder.set_parameter_count(1); |
Register reg(0); |
builder.LoadLiteral(Smi::FromInt(121)) |
.StoreAccumulatorInRegister(reg) |
@@ -304,7 +345,66 @@ TEST(TestInterpreterMod) { |
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
InterpreterTester tester(handles.main_isolate(), bytecode_array); |
- InterpreterCallable callable(tester.GetCallable()); |
+ auto callable = tester.GetCallable<>(); |
Handle<Object> return_val = callable().ToHandleChecked(); |
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(21)); |
} |
+ |
+ |
+TEST(InterpreterParameter1) { |
+ InitializedHandleScope handles; |
+ BytecodeArrayBuilder builder(handles.main_isolate()); |
+ builder.set_locals_count(1); |
+ builder.set_parameter_count(1); |
+ builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return(); |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array); |
+ auto callable = tester.GetCallable<Handle<Object>>(); |
+ |
+ // Check for heap objects. |
+ Handle<Object> true_value = handles.main_isolate()->factory()->true_value(); |
+ Handle<Object> return_val = callable(true_value).ToHandleChecked(); |
+ CHECK(return_val.is_identical_to(true_value)); |
+ |
+ // Check for Smis. |
+ return_val = callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate())) |
+ .ToHandleChecked(); |
+ CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3)); |
+} |
+ |
+ |
+TEST(InterpreterParameter8) { |
+ InitializedHandleScope handles; |
+ BytecodeArrayBuilder builder(handles.main_isolate()); |
+ builder.set_locals_count(1); |
+ builder.set_parameter_count(8); |
+ builder.LoadAccumulatorWithRegister(builder.Parameter(0)) |
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(1)) |
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(2)) |
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(3)) |
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(4)) |
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(5)) |
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(6)) |
+ .BinaryOperation(Token::Value::ADD, builder.Parameter(7)) |
+ .Return(); |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array); |
+ typedef Handle<Object> H; |
+ auto callable = tester.GetCallable<H, H, H, H, H, H, H, H>(); |
+ |
+ Handle<Smi> arg1 = Handle<Smi>(Smi::FromInt(1), handles.main_isolate()); |
+ Handle<Smi> arg2 = Handle<Smi>(Smi::FromInt(2), handles.main_isolate()); |
+ Handle<Smi> arg3 = Handle<Smi>(Smi::FromInt(3), handles.main_isolate()); |
+ Handle<Smi> arg4 = Handle<Smi>(Smi::FromInt(4), handles.main_isolate()); |
+ Handle<Smi> arg5 = Handle<Smi>(Smi::FromInt(5), handles.main_isolate()); |
+ Handle<Smi> arg6 = Handle<Smi>(Smi::FromInt(6), handles.main_isolate()); |
+ Handle<Smi> arg7 = Handle<Smi>(Smi::FromInt(7), handles.main_isolate()); |
+ Handle<Smi> arg8 = Handle<Smi>(Smi::FromInt(8), handles.main_isolate()); |
+ // Check for Smis. |
+ Handle<Object> return_val = |
+ callable(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) |
+ .ToHandleChecked(); |
+ CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36)); |
+} |