Index: test/cctest/interpreter/test-interpreter.cc |
diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc |
index 56fa4c6257e39a6fb7870224336f1ea996066b71..f4159ab1b1627fb8e5666079ab38b3da76277621 100644 |
--- a/test/cctest/interpreter/test-interpreter.cc |
+++ b/test/cctest/interpreter/test-interpreter.cc |
@@ -558,3 +558,142 @@ TEST(InterpreterLoadKeyedProperty) { |
return_val = callable(object3).ToHandleChecked(); |
CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789)); |
} |
+ |
+ |
+TEST(InterpreterCallJS) { |
+ HandleAndZoneScope handles; |
+ i::Isolate* isolate = handles.main_isolate(); |
+ i::Factory* factory = isolate->factory(); |
+ |
+ i::Code::Kind ic_kinds[] = {i::Code::LOAD_IC}; |
+ i::FeedbackVectorSpec feedback_spec(0, 1, ic_kinds); |
+ Handle<i::TypeFeedbackVector> vector = |
+ factory->NewTypeFeedbackVector(&feedback_spec); |
+ |
+ Handle<i::String> name = factory->NewStringFromAsciiChecked("func"); |
+ name = factory->string_table()->LookupString(isolate, name); |
+ |
+ // Check with no args. |
+ { |
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); |
+ builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
+ builder.LoadLiteral(name) |
+ .LoadNamedProperty(builder.Parameter(0), vector->first_ic_slot_index(), |
+ i::SLOPPY) |
+ .CallJS(builder.Parameter(0), 1) |
+ .Return(); |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
+ auto callable = tester.GetCallable<Handle<Object>>(); |
+ |
+ Handle<Object> object = tester.NewObject( |
+ "new (function Obj() { this.func = function() { return 0x265; }})()"); |
+ Handle<Object> return_val = callable(object).ToHandleChecked(); |
+ CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265)); |
+ } |
+ |
+ // Check that reciever is passed properly. |
+ { |
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); |
+ builder.set_locals_count(0); |
+ builder.set_parameter_count(1); |
+ builder.LoadLiteral(name) |
+ .LoadNamedProperty(builder.Parameter(0), vector->first_ic_slot_index(), |
+ i::SLOPPY) |
+ .CallJS(builder.Parameter(0), 1) |
+ .Return(); |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
+ auto callable = tester.GetCallable<Handle<Object>>(); |
+ |
+ Handle<Object> object = tester.NewObject( |
+ "new (function Obj() {" |
+ " this.val = 1234;" |
+ " this.func = function() { return this.val; };" |
+ "})()"); |
+ Handle<Object> return_val = callable(object).ToHandleChecked(); |
+ CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234)); |
+ } |
+ |
+ // Check with two parameters (+ reciever). |
+ { |
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); |
+ builder.set_locals_count(3); |
+ builder.set_parameter_count(1); |
+ builder.LoadAccumulatorWithRegister(builder.Parameter(0)) |
+ .StoreAccumulatorInRegister(Register(0)) |
+ .LoadLiteral(Smi::FromInt(51)) |
+ .StoreAccumulatorInRegister(Register(1)) |
+ .LoadLiteral(Smi::FromInt(11)) |
+ .StoreAccumulatorInRegister(Register(2)) |
+ .LoadLiteral(name) |
+ .LoadNamedProperty(builder.Parameter(0), vector->first_ic_slot_index(), |
+ i::SLOPPY) |
+ .CallJS(Register(0), 3) |
+ .Return(); |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
+ auto callable = tester.GetCallable<Handle<Object>>(); |
+ |
+ Handle<Object> object = tester.NewObject( |
+ "new (function Obj() { " |
+ " this.func = function(a, b) { return a - b; }" |
+ "})()"); |
+ Handle<Object> return_val = callable(object).ToHandleChecked(); |
+ CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(40)); |
+ } |
+ |
+ // Check with 10 parameters (+ reciever). |
+ { |
+ BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone()); |
+ builder.set_locals_count(11); |
+ builder.set_parameter_count(1); |
+ builder.LoadAccumulatorWithRegister(builder.Parameter(0)) |
+ .StoreAccumulatorInRegister(Register(0)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("a")) |
+ .StoreAccumulatorInRegister(Register(1)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("b")) |
+ .StoreAccumulatorInRegister(Register(2)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("c")) |
+ .StoreAccumulatorInRegister(Register(3)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("d")) |
+ .StoreAccumulatorInRegister(Register(4)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("e")) |
+ .StoreAccumulatorInRegister(Register(5)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("f")) |
+ .StoreAccumulatorInRegister(Register(6)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("g")) |
+ .StoreAccumulatorInRegister(Register(7)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("h")) |
+ .StoreAccumulatorInRegister(Register(8)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("i")) |
+ .StoreAccumulatorInRegister(Register(9)) |
+ .LoadLiteral(factory->NewStringFromAsciiChecked("j")) |
+ .StoreAccumulatorInRegister(Register(10)) |
+ .LoadLiteral(name) |
+ .LoadNamedProperty(builder.Parameter(0), vector->first_ic_slot_index(), |
+ i::SLOPPY) |
+ .CallJS(Register(0), 11) |
+ .Return(); |
+ Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(); |
+ |
+ InterpreterTester tester(handles.main_isolate(), bytecode_array, vector); |
+ auto callable = tester.GetCallable<Handle<Object>>(); |
+ |
+ Handle<Object> object = tester.NewObject( |
+ "new (function Obj() { " |
+ " this.prefix = \"prefix_\";" |
+ " this.func = function(a, b, c, d, e, f, g, h, i, j) {" |
+ " return this.prefix + a + b + c + d + e + f + g + h + i + j;" |
+ " }" |
+ "})()"); |
+ Handle<Object> return_val = callable(object).ToHandleChecked(); |
+ Handle<i::String> expected = |
+ factory->NewStringFromAsciiChecked("prefix_abcdefghij"); |
+ CHECK(i::String::cast(*return_val)->Equals(*expected)); |
+ } |
+} |