| 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));
|
| +}
|
|
|