OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/execution.h" | 7 #include "src/execution.h" |
8 #include "src/handles.h" | 8 #include "src/handles.h" |
9 #include "src/interpreter/bytecode-array-builder.h" | 9 #include "src/interpreter/bytecode-array-builder.h" |
10 #include "src/interpreter/bytecode-array-iterator.h" | 10 #include "src/interpreter/bytecode-array-iterator.h" |
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 Handle<Smi> arg6 = Handle<Smi>(Smi::FromInt(6), handles.main_isolate()); | 502 Handle<Smi> arg6 = Handle<Smi>(Smi::FromInt(6), handles.main_isolate()); |
503 Handle<Smi> arg7 = Handle<Smi>(Smi::FromInt(7), handles.main_isolate()); | 503 Handle<Smi> arg7 = Handle<Smi>(Smi::FromInt(7), handles.main_isolate()); |
504 Handle<Smi> arg8 = Handle<Smi>(Smi::FromInt(8), handles.main_isolate()); | 504 Handle<Smi> arg8 = Handle<Smi>(Smi::FromInt(8), handles.main_isolate()); |
505 // Check for Smis. | 505 // Check for Smis. |
506 Handle<Object> return_val = | 506 Handle<Object> return_val = |
507 callable(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) | 507 callable(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) |
508 .ToHandleChecked(); | 508 .ToHandleChecked(); |
509 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36)); | 509 CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36)); |
510 } | 510 } |
511 | 511 |
| 512 TEST(InterpreterBinaryOpTypeFeedback) { |
| 513 HandleAndZoneScope handles; |
| 514 i::Isolate* isolate = handles.main_isolate(); |
| 515 i::Zone zone(isolate->allocator()); |
| 516 |
| 517 struct BinaryOpExpectation { |
| 518 Token::Value op; |
| 519 Handle<Object> arg1; |
| 520 Handle<Object> arg2; |
| 521 Handle<Object> result; |
| 522 int32_t feedback; |
| 523 }; |
| 524 |
| 525 BinaryOpExpectation const kTestCases[] = { |
| 526 // ADD |
| 527 {Token::Value::ADD, Handle<Smi>(Smi::FromInt(2), isolate), |
| 528 Handle<Smi>(Smi::FromInt(3), isolate), |
| 529 Handle<Smi>(Smi::FromInt(5), isolate), |
| 530 BinaryOperationFeedback::kSignedSmall}, |
| 531 {Token::Value::ADD, Handle<Smi>(Smi::FromInt(Smi::kMaxValue), isolate), |
| 532 Handle<Smi>(Smi::FromInt(1), isolate), |
| 533 isolate->factory()->NewHeapNumber(Smi::kMaxValue + 1.0), |
| 534 BinaryOperationFeedback::kNumber}, |
| 535 {Token::Value::ADD, isolate->factory()->NewHeapNumber(3.1415), |
| 536 Handle<Smi>(Smi::FromInt(3), isolate), |
| 537 isolate->factory()->NewHeapNumber(3.1415 + 3), |
| 538 BinaryOperationFeedback::kNumber}, |
| 539 {Token::Value::ADD, isolate->factory()->NewHeapNumber(3.1415), |
| 540 isolate->factory()->NewHeapNumber(1.4142), |
| 541 isolate->factory()->NewHeapNumber(3.1415 + 1.4142), |
| 542 BinaryOperationFeedback::kNumber}, |
| 543 {Token::Value::ADD, Handle<Smi>(Smi::FromInt(2), isolate), |
| 544 isolate->factory()->NewStringFromAsciiChecked("2"), |
| 545 isolate->factory()->NewStringFromAsciiChecked("22"), |
| 546 BinaryOperationFeedback::kAny}, |
| 547 // SUB |
| 548 {Token::Value::SUB, Handle<Smi>(Smi::FromInt(2), isolate), |
| 549 Handle<Smi>(Smi::FromInt(3), isolate), |
| 550 Handle<Smi>(Smi::FromInt(-1), isolate), |
| 551 BinaryOperationFeedback::kSignedSmall}, |
| 552 {Token::Value::SUB, Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate), |
| 553 Handle<Smi>(Smi::FromInt(1), isolate), |
| 554 isolate->factory()->NewHeapNumber(Smi::kMinValue - 1.0), |
| 555 BinaryOperationFeedback::kNumber}, |
| 556 {Token::Value::SUB, isolate->factory()->NewHeapNumber(3.1415), |
| 557 Handle<Smi>(Smi::FromInt(3), isolate), |
| 558 isolate->factory()->NewHeapNumber(3.1415 - 3), |
| 559 BinaryOperationFeedback::kNumber}, |
| 560 {Token::Value::SUB, isolate->factory()->NewHeapNumber(3.1415), |
| 561 isolate->factory()->NewHeapNumber(1.4142), |
| 562 isolate->factory()->NewHeapNumber(3.1415 - 1.4142), |
| 563 BinaryOperationFeedback::kNumber}, |
| 564 {Token::Value::SUB, Handle<Smi>(Smi::FromInt(2), isolate), |
| 565 isolate->factory()->NewStringFromAsciiChecked("1"), |
| 566 Handle<Smi>(Smi::FromInt(1), isolate), BinaryOperationFeedback::kAny}, |
| 567 // MUL |
| 568 {Token::Value::MUL, Handle<Smi>(Smi::FromInt(2), isolate), |
| 569 Handle<Smi>(Smi::FromInt(3), isolate), |
| 570 Handle<Smi>(Smi::FromInt(6), isolate), |
| 571 BinaryOperationFeedback::kSignedSmall}, |
| 572 {Token::Value::MUL, Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate), |
| 573 Handle<Smi>(Smi::FromInt(2), isolate), |
| 574 isolate->factory()->NewHeapNumber(Smi::kMinValue * 2.0), |
| 575 BinaryOperationFeedback::kNumber}, |
| 576 {Token::Value::MUL, isolate->factory()->NewHeapNumber(3.1415), |
| 577 Handle<Smi>(Smi::FromInt(3), isolate), |
| 578 isolate->factory()->NewHeapNumber(3 * 3.1415), |
| 579 BinaryOperationFeedback::kNumber}, |
| 580 {Token::Value::MUL, isolate->factory()->NewHeapNumber(3.1415), |
| 581 isolate->factory()->NewHeapNumber(1.4142), |
| 582 isolate->factory()->NewHeapNumber(3.1415 * 1.4142), |
| 583 BinaryOperationFeedback::kNumber}, |
| 584 {Token::Value::MUL, Handle<Smi>(Smi::FromInt(2), isolate), |
| 585 isolate->factory()->NewStringFromAsciiChecked("1"), |
| 586 Handle<Smi>(Smi::FromInt(2), isolate), BinaryOperationFeedback::kAny}, |
| 587 // DIV |
| 588 {Token::Value::DIV, Handle<Smi>(Smi::FromInt(6), isolate), |
| 589 Handle<Smi>(Smi::FromInt(3), isolate), |
| 590 Handle<Smi>(Smi::FromInt(2), isolate), |
| 591 BinaryOperationFeedback::kSignedSmall}, |
| 592 {Token::Value::DIV, Handle<Smi>(Smi::FromInt(3), isolate), |
| 593 Handle<Smi>(Smi::FromInt(2), isolate), |
| 594 isolate->factory()->NewHeapNumber(3.0 / 2.0), |
| 595 BinaryOperationFeedback::kNumber}, |
| 596 {Token::Value::DIV, isolate->factory()->NewHeapNumber(3.1415), |
| 597 Handle<Smi>(Smi::FromInt(3), isolate), |
| 598 isolate->factory()->NewHeapNumber(3.1415 / 3), |
| 599 BinaryOperationFeedback::kNumber}, |
| 600 {Token::Value::DIV, isolate->factory()->NewHeapNumber(3.1415), |
| 601 isolate->factory()->NewHeapNumber( |
| 602 -std::numeric_limits<double>::infinity()), |
| 603 isolate->factory()->NewHeapNumber(-0.0), |
| 604 BinaryOperationFeedback::kNumber}, |
| 605 {Token::Value::DIV, Handle<Smi>(Smi::FromInt(2), isolate), |
| 606 isolate->factory()->NewStringFromAsciiChecked("1"), |
| 607 Handle<Smi>(Smi::FromInt(2), isolate), BinaryOperationFeedback::kAny}, |
| 608 // MOD |
| 609 {Token::Value::MOD, Handle<Smi>(Smi::FromInt(5), isolate), |
| 610 Handle<Smi>(Smi::FromInt(3), isolate), |
| 611 Handle<Smi>(Smi::FromInt(2), isolate), |
| 612 BinaryOperationFeedback::kSignedSmall}, |
| 613 {Token::Value::MOD, Handle<Smi>(Smi::FromInt(-4), isolate), |
| 614 Handle<Smi>(Smi::FromInt(2), isolate), |
| 615 isolate->factory()->NewHeapNumber(-0.0), |
| 616 BinaryOperationFeedback::kNumber}, |
| 617 {Token::Value::MOD, isolate->factory()->NewHeapNumber(3.1415), |
| 618 Handle<Smi>(Smi::FromInt(3), isolate), |
| 619 isolate->factory()->NewHeapNumber(fmod(3.1415, 3.0)), |
| 620 BinaryOperationFeedback::kNumber}, |
| 621 {Token::Value::MOD, isolate->factory()->NewHeapNumber(-3.1415), |
| 622 isolate->factory()->NewHeapNumber(-1.4142), |
| 623 isolate->factory()->NewHeapNumber(fmod(-3.1415, -1.4142)), |
| 624 BinaryOperationFeedback::kNumber}, |
| 625 {Token::Value::MOD, Handle<Smi>(Smi::FromInt(3), isolate), |
| 626 isolate->factory()->NewStringFromAsciiChecked("-2"), |
| 627 Handle<Smi>(Smi::FromInt(1), isolate), BinaryOperationFeedback::kAny}}; |
| 628 |
| 629 for (const BinaryOpExpectation& test_case : kTestCases) { |
| 630 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 1, 0, 1); |
| 631 |
| 632 i::FeedbackVectorSpec feedback_spec(&zone); |
| 633 i::FeedbackVectorSlot slot0 = feedback_spec.AddGeneralSlot(); |
| 634 |
| 635 Handle<i::TypeFeedbackVector> vector = |
| 636 i::NewTypeFeedbackVector(isolate, &feedback_spec); |
| 637 |
| 638 Register reg(0); |
| 639 builder.LoadLiteral(test_case.arg1) |
| 640 .StoreAccumulatorInRegister(reg) |
| 641 .LoadLiteral(test_case.arg2) |
| 642 .BinaryOperation(test_case.op, reg, vector->GetIndex(slot0)) |
| 643 .Return(); |
| 644 |
| 645 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); |
| 646 |
| 647 InterpreterTester tester(isolate, bytecode_array, vector); |
| 648 auto callable = tester.GetCallable<>(); |
| 649 |
| 650 Handle<Object> return_val = callable().ToHandleChecked(); |
| 651 Object* feedback0 = vector->Get(slot0); |
| 652 CHECK(feedback0->IsSmi()); |
| 653 CHECK_EQ(test_case.feedback, static_cast<Smi*>(feedback0)->value()); |
| 654 CHECK(Object::Equals(test_case.result, return_val).ToChecked()); |
| 655 } |
| 656 } |
| 657 |
| 658 TEST(InterpreterUnaryOpFeedback) { |
| 659 HandleAndZoneScope handles; |
| 660 i::Isolate* isolate = handles.main_isolate(); |
| 661 i::Zone zone(isolate->allocator()); |
| 662 |
| 663 Handle<Smi> smi_one = Handle<Smi>(Smi::FromInt(1), isolate); |
| 664 Handle<Smi> smi_max = Handle<Smi>(Smi::FromInt(Smi::kMaxValue), isolate); |
| 665 Handle<Smi> smi_min = Handle<Smi>(Smi::FromInt(Smi::kMinValue), isolate); |
| 666 Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(2.1); |
| 667 Handle<String> str = isolate->factory()->NewStringFromAsciiChecked("42"); |
| 668 |
| 669 struct TestCase { |
| 670 Token::Value op; |
| 671 Handle<Smi> smi_feedback_value; |
| 672 Handle<Smi> smi_to_number_feedback_value; |
| 673 Handle<HeapNumber> number_feedback_value; |
| 674 Handle<Object> any_feedback_value; |
| 675 }; |
| 676 TestCase const kTestCases[] = { |
| 677 {Token::Value::ADD, smi_one, smi_max, number, str}, |
| 678 {Token::Value::SUB, smi_one, smi_min, number, str}}; |
| 679 for (TestCase const& test_case : kTestCases) { |
| 680 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 4, 0, 0); |
| 681 |
| 682 i::FeedbackVectorSpec feedback_spec(&zone); |
| 683 i::FeedbackVectorSlot slot0 = feedback_spec.AddGeneralSlot(); |
| 684 i::FeedbackVectorSlot slot1 = feedback_spec.AddGeneralSlot(); |
| 685 i::FeedbackVectorSlot slot2 = feedback_spec.AddGeneralSlot(); |
| 686 i::FeedbackVectorSlot slot3 = feedback_spec.AddGeneralSlot(); |
| 687 |
| 688 Handle<i::TypeFeedbackVector> vector = |
| 689 i::NewTypeFeedbackVector(isolate, &feedback_spec); |
| 690 |
| 691 builder.LoadAccumulatorWithRegister(builder.Parameter(0)) |
| 692 .CountOperation(test_case.op, vector->GetIndex(slot0)) |
| 693 .LoadAccumulatorWithRegister(builder.Parameter(1)) |
| 694 .CountOperation(test_case.op, vector->GetIndex(slot1)) |
| 695 .LoadAccumulatorWithRegister(builder.Parameter(2)) |
| 696 .CountOperation(test_case.op, vector->GetIndex(slot2)) |
| 697 .LoadAccumulatorWithRegister(builder.Parameter(3)) |
| 698 .CountOperation(test_case.op, vector->GetIndex(slot3)) |
| 699 .Return(); |
| 700 |
| 701 Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); |
| 702 |
| 703 InterpreterTester tester(isolate, bytecode_array, vector); |
| 704 typedef Handle<Object> H; |
| 705 auto callable = tester.GetCallable<H, H, H, H>(); |
| 706 |
| 707 Handle<Object> return_val = |
| 708 callable(test_case.smi_feedback_value, |
| 709 test_case.smi_to_number_feedback_value, |
| 710 test_case.number_feedback_value, test_case.any_feedback_value) |
| 711 .ToHandleChecked(); |
| 712 USE(return_val); |
| 713 Object* feedback0 = vector->Get(slot0); |
| 714 CHECK(feedback0->IsSmi()); |
| 715 CHECK_EQ(BinaryOperationFeedback::kSignedSmall, |
| 716 static_cast<Smi*>(feedback0)->value()); |
| 717 |
| 718 Object* feedback1 = vector->Get(slot1); |
| 719 CHECK(feedback1->IsSmi()); |
| 720 CHECK_EQ(BinaryOperationFeedback::kNumber, |
| 721 static_cast<Smi*>(feedback1)->value()); |
| 722 |
| 723 Object* feedback2 = vector->Get(slot2); |
| 724 CHECK(feedback2->IsSmi()); |
| 725 CHECK_EQ(BinaryOperationFeedback::kNumber, |
| 726 static_cast<Smi*>(feedback2)->value()); |
| 727 |
| 728 Object* feedback3 = vector->Get(slot3); |
| 729 CHECK(feedback3->IsSmi()); |
| 730 CHECK_EQ(BinaryOperationFeedback::kAny, |
| 731 static_cast<Smi*>(feedback3)->value()); |
| 732 } |
| 733 } |
| 734 |
512 TEST(InterpreterBitwiseTypeFeedback) { | 735 TEST(InterpreterBitwiseTypeFeedback) { |
513 HandleAndZoneScope handles; | 736 HandleAndZoneScope handles; |
514 i::Isolate* isolate = handles.main_isolate(); | 737 i::Isolate* isolate = handles.main_isolate(); |
515 i::Zone zone(isolate->allocator()); | 738 i::Zone zone(isolate->allocator()); |
516 const Token::Value kBitwiseBinaryOperators[] = { | 739 const Token::Value kBitwiseBinaryOperators[] = { |
517 Token::Value::BIT_OR, Token::Value::BIT_XOR, Token::Value::BIT_AND, | 740 Token::Value::BIT_OR, Token::Value::BIT_XOR, Token::Value::BIT_AND, |
518 Token::Value::SHL, Token::Value::SHR, Token::Value::SAR}; | 741 Token::Value::SHL, Token::Value::SHR, Token::Value::SAR}; |
519 | 742 |
520 for (Token::Value op : kBitwiseBinaryOperators) { | 743 for (Token::Value op : kBitwiseBinaryOperators) { |
521 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 4, 0, 0); | 744 BytecodeArrayBuilder builder(isolate, handles.main_zone(), 4, 0, 0); |
(...skipping 3831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4353 auto callable = tester.GetCallable<>(); | 4576 auto callable = tester.GetCallable<>(); |
4354 | 4577 |
4355 Handle<i::Object> return_value = callable().ToHandleChecked(); | 4578 Handle<i::Object> return_value = callable().ToHandleChecked(); |
4356 CHECK(return_value->SameValue(*tests[i].second)); | 4579 CHECK(return_value->SameValue(*tests[i].second)); |
4357 } | 4580 } |
4358 } | 4581 } |
4359 | 4582 |
4360 } // namespace interpreter | 4583 } // namespace interpreter |
4361 } // namespace internal | 4584 } // namespace internal |
4362 } // namespace v8 | 4585 } // namespace v8 |
OLD | NEW |