| Index: test/cctest/interpreter/test-interpreter.cc
|
| diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc
|
| index 0d15097e4e2a3e1f1c5297b761b11cdb1dfeab71..8a7024412830ddc6a7f182ec7c6408c8f8105b9e 100644
|
| --- a/test/cctest/interpreter/test-interpreter.cc
|
| +++ b/test/cctest/interpreter/test-interpreter.cc
|
| @@ -509,6 +509,229 @@ TEST(InterpreterParameter8) {
|
| CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36));
|
| }
|
|
|
| +TEST(InterpreterBinaryOpTypeFeedback) {
|
| + HandleAndZoneScope handles;
|
| + i::Isolate* isolate = handles.main_isolate();
|
| + i::Zone zone(isolate->allocator());
|
| +
|
| + struct BinaryOpExpectation {
|
| + Token::Value op;
|
| + Handle<Object> arg1;
|
| + Handle<Object> arg2;
|
| + Handle<Object> result;
|
| + int32_t feedback;
|
| + };
|
| +
|
| + BinaryOpExpectation const kTestCases[] = {
|
| + // ADD
|
| + {Token::Value::ADD, Handle<Smi>(Smi::FromInt(2), isolate),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + Handle<Smi>(Smi::FromInt(5), isolate),
|
| + BinaryOperationFeedback::kSignedSmall},
|
| + {Token::Value::ADD, Handle<Smi>(Smi::FromInt(Smi::kMaxValue), isolate),
|
| + Handle<Smi>(Smi::FromInt(1), isolate),
|
| + isolate->factory()->NewHeapNumber(Smi::kMaxValue + 1.0),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::ADD, isolate->factory()->NewHeapNumber(3.1415),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + isolate->factory()->NewHeapNumber(3.1415 + 3),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::ADD, isolate->factory()->NewHeapNumber(3.1415),
|
| + isolate->factory()->NewHeapNumber(1.4142),
|
| + isolate->factory()->NewHeapNumber(3.1415 + 1.4142),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::ADD, Handle<Smi>(Smi::FromInt(2), isolate),
|
| + isolate->factory()->NewStringFromAsciiChecked("2"),
|
| + isolate->factory()->NewStringFromAsciiChecked("22"),
|
| + BinaryOperationFeedback::kAny},
|
| + // SUB
|
| + {Token::Value::SUB, Handle<Smi>(Smi::FromInt(2), isolate),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + Handle<Smi>(Smi::FromInt(-1), isolate),
|
| + BinaryOperationFeedback::kSignedSmall},
|
| + {Token::Value::SUB, Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate),
|
| + Handle<Smi>(Smi::FromInt(1), isolate),
|
| + isolate->factory()->NewHeapNumber(Smi::kMinValue - 1.0),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::SUB, isolate->factory()->NewHeapNumber(3.1415),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + isolate->factory()->NewHeapNumber(3.1415 - 3),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::SUB, isolate->factory()->NewHeapNumber(3.1415),
|
| + isolate->factory()->NewHeapNumber(1.4142),
|
| + isolate->factory()->NewHeapNumber(3.1415 - 1.4142),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::SUB, Handle<Smi>(Smi::FromInt(2), isolate),
|
| + isolate->factory()->NewStringFromAsciiChecked("1"),
|
| + Handle<Smi>(Smi::FromInt(1), isolate), BinaryOperationFeedback::kAny},
|
| + // MUL
|
| + {Token::Value::MUL, Handle<Smi>(Smi::FromInt(2), isolate),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + Handle<Smi>(Smi::FromInt(6), isolate),
|
| + BinaryOperationFeedback::kSignedSmall},
|
| + {Token::Value::MUL, Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate),
|
| + Handle<Smi>(Smi::FromInt(2), isolate),
|
| + isolate->factory()->NewHeapNumber(Smi::kMinValue * 2.0),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::MUL, isolate->factory()->NewHeapNumber(3.1415),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + isolate->factory()->NewHeapNumber(3 * 3.1415),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::MUL, isolate->factory()->NewHeapNumber(3.1415),
|
| + isolate->factory()->NewHeapNumber(1.4142),
|
| + isolate->factory()->NewHeapNumber(3.1415 * 1.4142),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::MUL, Handle<Smi>(Smi::FromInt(2), isolate),
|
| + isolate->factory()->NewStringFromAsciiChecked("1"),
|
| + Handle<Smi>(Smi::FromInt(2), isolate), BinaryOperationFeedback::kAny},
|
| + // DIV
|
| + {Token::Value::DIV, Handle<Smi>(Smi::FromInt(6), isolate),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + Handle<Smi>(Smi::FromInt(2), isolate),
|
| + BinaryOperationFeedback::kSignedSmall},
|
| + {Token::Value::DIV, Handle<Smi>(Smi::FromInt(3), isolate),
|
| + Handle<Smi>(Smi::FromInt(2), isolate),
|
| + isolate->factory()->NewHeapNumber(3.0 / 2.0),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::DIV, isolate->factory()->NewHeapNumber(3.1415),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + isolate->factory()->NewHeapNumber(3.1415 / 3),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::DIV, isolate->factory()->NewHeapNumber(3.1415),
|
| + isolate->factory()->NewHeapNumber(
|
| + -std::numeric_limits<double>::infinity()),
|
| + isolate->factory()->NewHeapNumber(-0.0),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::DIV, Handle<Smi>(Smi::FromInt(2), isolate),
|
| + isolate->factory()->NewStringFromAsciiChecked("1"),
|
| + Handle<Smi>(Smi::FromInt(2), isolate), BinaryOperationFeedback::kAny},
|
| + // MOD
|
| + {Token::Value::MOD, Handle<Smi>(Smi::FromInt(5), isolate),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + Handle<Smi>(Smi::FromInt(2), isolate),
|
| + BinaryOperationFeedback::kSignedSmall},
|
| + {Token::Value::MOD, Handle<Smi>(Smi::FromInt(-4), isolate),
|
| + Handle<Smi>(Smi::FromInt(2), isolate),
|
| + isolate->factory()->NewHeapNumber(-0.0),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::MOD, isolate->factory()->NewHeapNumber(3.1415),
|
| + Handle<Smi>(Smi::FromInt(3), isolate),
|
| + isolate->factory()->NewHeapNumber(fmod(3.1415, 3.0)),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::MOD, isolate->factory()->NewHeapNumber(-3.1415),
|
| + isolate->factory()->NewHeapNumber(-1.4142),
|
| + isolate->factory()->NewHeapNumber(fmod(-3.1415, -1.4142)),
|
| + BinaryOperationFeedback::kNumber},
|
| + {Token::Value::MOD, Handle<Smi>(Smi::FromInt(3), isolate),
|
| + isolate->factory()->NewStringFromAsciiChecked("-2"),
|
| + Handle<Smi>(Smi::FromInt(1), isolate), BinaryOperationFeedback::kAny}};
|
| +
|
| + for (const BinaryOpExpectation& test_case : kTestCases) {
|
| + BytecodeArrayBuilder builder(isolate, handles.main_zone(), 1, 0, 1);
|
| +
|
| + i::FeedbackVectorSpec feedback_spec(&zone);
|
| + i::FeedbackVectorSlot slot0 = feedback_spec.AddGeneralSlot();
|
| +
|
| + Handle<i::TypeFeedbackVector> vector =
|
| + i::NewTypeFeedbackVector(isolate, &feedback_spec);
|
| +
|
| + Register reg(0);
|
| + builder.LoadLiteral(test_case.arg1)
|
| + .StoreAccumulatorInRegister(reg)
|
| + .LoadLiteral(test_case.arg2)
|
| + .BinaryOperation(test_case.op, reg, vector->GetIndex(slot0))
|
| + .Return();
|
| +
|
| + Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
|
| +
|
| + InterpreterTester tester(isolate, bytecode_array, vector);
|
| + auto callable = tester.GetCallable<>();
|
| +
|
| + Handle<Object> return_val = callable().ToHandleChecked();
|
| + Object* feedback0 = vector->Get(slot0);
|
| + CHECK(feedback0->IsSmi());
|
| + CHECK_EQ(test_case.feedback, static_cast<Smi*>(feedback0)->value());
|
| + CHECK(Object::Equals(test_case.result, return_val).ToChecked());
|
| + }
|
| +}
|
| +
|
| +TEST(InterpreterUnaryOpFeedback) {
|
| + HandleAndZoneScope handles;
|
| + i::Isolate* isolate = handles.main_isolate();
|
| + i::Zone zone(isolate->allocator());
|
| +
|
| + Handle<Smi> smi_one = Handle<Smi>(Smi::FromInt(1), isolate);
|
| + Handle<Smi> smi_max = Handle<Smi>(Smi::FromInt(Smi::kMaxValue), isolate);
|
| + Handle<Smi> smi_min = Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate);
|
| + Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(2.1);
|
| + Handle<String> str = isolate->factory()->NewStringFromAsciiChecked("42");
|
| +
|
| + struct TestCase {
|
| + Token::Value op;
|
| + Handle<Smi> smi_feedback_value;
|
| + Handle<Smi> smi_to_number_feedback_value;
|
| + Handle<HeapNumber> number_feedback_value;
|
| + Handle<Object> any_feedback_value;
|
| + };
|
| + TestCase const kTestCases[] = {
|
| + {Token::Value::ADD, smi_one, smi_max, number, str},
|
| + {Token::Value::SUB, smi_one, smi_min, number, str}};
|
| + for (TestCase const& test_case : kTestCases) {
|
| + BytecodeArrayBuilder builder(isolate, handles.main_zone(), 4, 0, 0);
|
| +
|
| + i::FeedbackVectorSpec feedback_spec(&zone);
|
| + i::FeedbackVectorSlot slot0 = feedback_spec.AddGeneralSlot();
|
| + i::FeedbackVectorSlot slot1 = feedback_spec.AddGeneralSlot();
|
| + i::FeedbackVectorSlot slot2 = feedback_spec.AddGeneralSlot();
|
| + i::FeedbackVectorSlot slot3 = feedback_spec.AddGeneralSlot();
|
| +
|
| + Handle<i::TypeFeedbackVector> vector =
|
| + i::NewTypeFeedbackVector(isolate, &feedback_spec);
|
| +
|
| + builder.LoadAccumulatorWithRegister(builder.Parameter(0))
|
| + .CountOperation(test_case.op, vector->GetIndex(slot0))
|
| + .LoadAccumulatorWithRegister(builder.Parameter(1))
|
| + .CountOperation(test_case.op, vector->GetIndex(slot1))
|
| + .LoadAccumulatorWithRegister(builder.Parameter(2))
|
| + .CountOperation(test_case.op, vector->GetIndex(slot2))
|
| + .LoadAccumulatorWithRegister(builder.Parameter(3))
|
| + .CountOperation(test_case.op, vector->GetIndex(slot3))
|
| + .Return();
|
| +
|
| + Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
|
| +
|
| + InterpreterTester tester(isolate, bytecode_array, vector);
|
| + typedef Handle<Object> H;
|
| + auto callable = tester.GetCallable<H, H, H, H>();
|
| +
|
| + Handle<Object> return_val =
|
| + callable(test_case.smi_feedback_value,
|
| + test_case.smi_to_number_feedback_value,
|
| + test_case.number_feedback_value, test_case.any_feedback_value)
|
| + .ToHandleChecked();
|
| + USE(return_val);
|
| + Object* feedback0 = vector->Get(slot0);
|
| + CHECK(feedback0->IsSmi());
|
| + CHECK_EQ(BinaryOperationFeedback::kSignedSmall,
|
| + static_cast<Smi*>(feedback0)->value());
|
| +
|
| + Object* feedback1 = vector->Get(slot1);
|
| + CHECK(feedback1->IsSmi());
|
| + CHECK_EQ(BinaryOperationFeedback::kNumber,
|
| + static_cast<Smi*>(feedback1)->value());
|
| +
|
| + Object* feedback2 = vector->Get(slot2);
|
| + CHECK(feedback2->IsSmi());
|
| + CHECK_EQ(BinaryOperationFeedback::kNumber,
|
| + static_cast<Smi*>(feedback2)->value());
|
| +
|
| + Object* feedback3 = vector->Get(slot3);
|
| + CHECK(feedback3->IsSmi());
|
| + CHECK_EQ(BinaryOperationFeedback::kAny,
|
| + static_cast<Smi*>(feedback3)->value());
|
| + }
|
| +}
|
| +
|
| TEST(InterpreterBitwiseTypeFeedback) {
|
| HandleAndZoneScope handles;
|
| i::Isolate* isolate = handles.main_isolate();
|
|
|