Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(417)

Side by Side Diff: src/code-stubs.cc

Issue 1756793002: [compiler] Introduce proper StrictNotEqualStub. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/code-stubs.h ('k') | src/compiler/js-generic-lowering.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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/code-stubs.h" 5 #include "src/code-stubs.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/compiler/code-stub-assembler.h" 10 #include "src/compiler/code-stub-assembler.h"
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 void StringLengthStub::GenerateAssembly( 466 void StringLengthStub::GenerateAssembly(
467 compiler::CodeStubAssembler* assembler) const { 467 compiler::CodeStubAssembler* assembler) const {
468 compiler::Node* value = assembler->Parameter(0); 468 compiler::Node* value = assembler->Parameter(0);
469 compiler::Node* string = 469 compiler::Node* string =
470 assembler->LoadObjectField(value, JSValue::kValueOffset); 470 assembler->LoadObjectField(value, JSValue::kValueOffset);
471 compiler::Node* result = 471 compiler::Node* result =
472 assembler->LoadObjectField(string, String::kLengthOffset); 472 assembler->LoadObjectField(string, String::kLengthOffset);
473 assembler->Return(result); 473 assembler->Return(result);
474 } 474 }
475 475
476 void StrictEqualStub::GenerateAssembly( 476 namespace {
477 compiler::CodeStubAssembler* assembler) const { 477
478 // Here's pseudo-code for the algorithm below: 478 enum StrictEqualMode { kStrictEqual, kStrictNotEqual };
479
480 void GenerateStrictEqual(compiler::CodeStubAssembler* assembler,
481 StrictEqualMode mode) {
482 // Here's pseudo-code for the algorithm below in case of kStrictEqual mode;
483 // for kStrictNotEqual mode we properly negate the result.
479 // 484 //
480 // if (lhs == rhs) { 485 // if (lhs == rhs) {
481 // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN; 486 // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN;
482 // return true; 487 // return true;
483 // } 488 // }
484 // if (!lhs->IsSmi()) { 489 // if (!lhs->IsSmi()) {
485 // if (lhs->IsHeapNumber()) { 490 // if (lhs->IsHeapNumber()) {
486 // if (rhs->IsSmi()) { 491 // if (rhs->IsSmi()) {
487 // return Smi::cast(rhs)->value() == HeapNumber::cast(lhs)->value(); 492 // return Smi::cast(rhs)->value() == HeapNumber::cast(lhs)->value();
488 // } else if (rhs->IsHeapNumber()) { 493 // } else if (rhs->IsHeapNumber()) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 // } 527 // }
523 // } 528 // }
524 529
525 typedef compiler::CodeStubAssembler::Label Label; 530 typedef compiler::CodeStubAssembler::Label Label;
526 typedef compiler::Node Node; 531 typedef compiler::Node Node;
527 532
528 Node* lhs = assembler->Parameter(0); 533 Node* lhs = assembler->Parameter(0);
529 Node* rhs = assembler->Parameter(1); 534 Node* rhs = assembler->Parameter(1);
530 Node* context = assembler->Parameter(2); 535 Node* context = assembler->Parameter(2);
531 536
532 Label if_true(assembler), if_false(assembler); 537 Label if_equal(assembler), if_notequal(assembler);
533 538
534 // Check if {lhs} and {rhs} refer to the same object. 539 // Check if {lhs} and {rhs} refer to the same object.
535 Label if_same(assembler), if_notsame(assembler); 540 Label if_same(assembler), if_notsame(assembler);
536 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame); 541 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame);
537 542
538 assembler->Bind(&if_same); 543 assembler->Bind(&if_same);
539 { 544 {
540 // The {lhs} and {rhs} reference the exact same value, yet we need special 545 // The {lhs} and {rhs} reference the exact same value, yet we need special
541 // treatment for HeapNumber, as NaN is not equal to NaN. 546 // treatment for HeapNumber, as NaN is not equal to NaN.
542 // TODO(bmeurer): This seems to violate the SIMD.js specification, but it 547 // TODO(bmeurer): This seems to violate the SIMD.js specification, but it
(...skipping 13 matching lines...) Expand all
556 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler); 561 Label if_lhsisnumber(assembler), if_lhsisnotnumber(assembler);
557 assembler->Branch(assembler->WordEqual(lhs_map, number_map), 562 assembler->Branch(assembler->WordEqual(lhs_map, number_map),
558 &if_lhsisnumber, &if_lhsisnotnumber); 563 &if_lhsisnumber, &if_lhsisnotnumber);
559 564
560 assembler->Bind(&if_lhsisnumber); 565 assembler->Bind(&if_lhsisnumber);
561 { 566 {
562 // Convert {lhs} (and therefore {rhs}) to floating point value. 567 // Convert {lhs} (and therefore {rhs}) to floating point value.
563 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); 568 Node* lhs_value = assembler->LoadHeapNumberValue(lhs);
564 569
565 // Check if the HeapNumber value is a NaN. 570 // Check if the HeapNumber value is a NaN.
566 assembler->BranchIfFloat64IsNaN(lhs_value, &if_false, &if_true); 571 assembler->BranchIfFloat64IsNaN(lhs_value, &if_notequal, &if_equal);
567 } 572 }
568 573
569 assembler->Bind(&if_lhsisnotnumber); 574 assembler->Bind(&if_lhsisnotnumber);
570 assembler->Goto(&if_true); 575 assembler->Goto(&if_equal);
571 } 576 }
572 577
573 assembler->Bind(&if_lhsissmi); 578 assembler->Bind(&if_lhsissmi);
574 assembler->Goto(&if_true); 579 assembler->Goto(&if_equal);
575 } 580 }
576 581
577 assembler->Bind(&if_notsame); 582 assembler->Bind(&if_notsame);
578 { 583 {
579 // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber, 584 // The {lhs} and {rhs} reference different objects, yet for Smi, HeapNumber,
580 // String and Simd128Value they can still be considered equal. 585 // String and Simd128Value they can still be considered equal.
581 Node* number_map = assembler->HeapNumberMapConstant(); 586 Node* number_map = assembler->HeapNumberMapConstant();
582 587
583 // Check if {lhs} is a Smi or a HeapObject. 588 // Check if {lhs} is a Smi or a HeapObject.
584 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler); 589 Label if_lhsissmi(assembler), if_lhsisnotsmi(assembler);
(...skipping 16 matching lines...) Expand all
601 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, 606 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
602 &if_rhsisnotsmi); 607 &if_rhsisnotsmi);
603 608
604 assembler->Bind(&if_rhsissmi); 609 assembler->Bind(&if_rhsissmi);
605 { 610 {
606 // Convert {lhs} and {rhs} to floating point values. 611 // Convert {lhs} and {rhs} to floating point values.
607 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); 612 Node* lhs_value = assembler->LoadHeapNumberValue(lhs);
608 Node* rhs_value = assembler->SmiToFloat64(rhs); 613 Node* rhs_value = assembler->SmiToFloat64(rhs);
609 614
610 // Perform a floating point comparison of {lhs} and {rhs}. 615 // Perform a floating point comparison of {lhs} and {rhs}.
611 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, 616 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
612 &if_false); 617 &if_notequal);
613 } 618 }
614 619
615 assembler->Bind(&if_rhsisnotsmi); 620 assembler->Bind(&if_rhsisnotsmi);
616 { 621 {
617 // Load the map of {rhs}. 622 // Load the map of {rhs}.
618 Node* rhs_map = 623 Node* rhs_map =
619 assembler->LoadObjectField(rhs, HeapObject::kMapOffset); 624 assembler->LoadObjectField(rhs, HeapObject::kMapOffset);
620 625
621 // Check if {rhs} is also a HeapNumber. 626 // Check if {rhs} is also a HeapNumber.
622 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); 627 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
623 assembler->Branch(assembler->WordEqual(rhs_map, number_map), 628 assembler->Branch(assembler->WordEqual(rhs_map, number_map),
624 &if_rhsisnumber, &if_rhsisnotnumber); 629 &if_rhsisnumber, &if_rhsisnotnumber);
625 630
626 assembler->Bind(&if_rhsisnumber); 631 assembler->Bind(&if_rhsisnumber);
627 { 632 {
628 // Convert {lhs} and {rhs} to floating point values. 633 // Convert {lhs} and {rhs} to floating point values.
629 Node* lhs_value = assembler->LoadHeapNumberValue(lhs); 634 Node* lhs_value = assembler->LoadHeapNumberValue(lhs);
630 Node* rhs_value = assembler->LoadHeapNumberValue(rhs); 635 Node* rhs_value = assembler->LoadHeapNumberValue(rhs);
631 636
632 // Perform a floating point comparison of {lhs} and {rhs}. 637 // Perform a floating point comparison of {lhs} and {rhs}.
633 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, 638 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
634 &if_false); 639 &if_notequal);
635 } 640 }
636 641
637 assembler->Bind(&if_rhsisnotnumber); 642 assembler->Bind(&if_rhsisnotnumber);
638 assembler->Goto(&if_false); 643 assembler->Goto(&if_notequal);
639 } 644 }
640 } 645 }
641 646
642 assembler->Bind(&if_lhsisnotnumber); 647 assembler->Bind(&if_lhsisnotnumber);
643 { 648 {
644 // Check if {rhs} is a Smi or a HeapObject. 649 // Check if {rhs} is a Smi or a HeapObject.
645 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); 650 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
646 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, 651 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
647 &if_rhsisnotsmi); 652 &if_rhsisnotsmi);
648 653
649 assembler->Bind(&if_rhsissmi); 654 assembler->Bind(&if_rhsissmi);
650 assembler->Goto(&if_false); 655 assembler->Goto(&if_notequal);
651 656
652 assembler->Bind(&if_rhsisnotsmi); 657 assembler->Bind(&if_rhsisnotsmi);
653 { 658 {
654 // Load the instance type of {lhs}. 659 // Load the instance type of {lhs}.
655 Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map); 660 Node* lhs_instance_type = assembler->LoadMapInstanceType(lhs_map);
656 661
657 // Check if {lhs} is a String. 662 // Check if {lhs} is a String.
658 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler); 663 Label if_lhsisstring(assembler), if_lhsisnotstring(assembler);
659 assembler->Branch(assembler->Int32LessThan( 664 assembler->Branch(assembler->Int32LessThan(
660 lhs_instance_type, 665 lhs_instance_type,
661 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), 666 assembler->Int32Constant(FIRST_NONSTRING_TYPE)),
662 &if_lhsisstring, &if_lhsisnotstring); 667 &if_lhsisstring, &if_lhsisnotstring);
663 668
664 assembler->Bind(&if_lhsisstring); 669 assembler->Bind(&if_lhsisstring);
665 { 670 {
666 // Load the instance type of {rhs}. 671 // Load the instance type of {rhs}.
667 Node* rhs_instance_type = assembler->LoadInstanceType(rhs); 672 Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
668 673
669 // Check if {rhs} is also a String. 674 // Check if {rhs} is also a String.
670 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); 675 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler);
671 assembler->Branch(assembler->Int32LessThan( 676 assembler->Branch(assembler->Int32LessThan(
672 rhs_instance_type, assembler->Int32Constant( 677 rhs_instance_type, assembler->Int32Constant(
673 FIRST_NONSTRING_TYPE)), 678 FIRST_NONSTRING_TYPE)),
674 &if_rhsisstring, &if_rhsisnotstring); 679 &if_rhsisstring, &if_rhsisnotstring);
675 680
676 assembler->Bind(&if_rhsisstring); 681 assembler->Bind(&if_rhsisstring);
677 { 682 {
678 // TODO(bmeurer): Optimize this further once the StringEqual 683 // TODO(bmeurer): Optimize this further once the StringEqual
679 // functionality is available in TurboFan land. 684 // functionality is available in TurboFan land.
680 assembler->TailCallRuntime(Runtime::kStringEqual, context, lhs, 685 Runtime::FunctionId function_id = (mode == kStrictEqual)
681 rhs); 686 ? Runtime::kStringEqual
687 : Runtime::kStringNotEqual;
688 assembler->TailCallRuntime(function_id, context, lhs, rhs);
682 } 689 }
683 690
684 assembler->Bind(&if_rhsisnotstring); 691 assembler->Bind(&if_rhsisnotstring);
685 assembler->Goto(&if_false); 692 assembler->Goto(&if_notequal);
686 } 693 }
687 694
688 assembler->Bind(&if_lhsisnotstring); 695 assembler->Bind(&if_lhsisnotstring);
689 { 696 {
690 // Check if {lhs} is a Simd128Value. 697 // Check if {lhs} is a Simd128Value.
691 Label if_lhsissimd128value(assembler), 698 Label if_lhsissimd128value(assembler),
692 if_lhsisnotsimd128value(assembler); 699 if_lhsisnotsimd128value(assembler);
693 assembler->Branch(assembler->Word32Equal( 700 assembler->Branch(assembler->Word32Equal(
694 lhs_instance_type, 701 lhs_instance_type,
695 assembler->Int32Constant(SIMD128_VALUE_TYPE)), 702 assembler->Int32Constant(SIMD128_VALUE_TYPE)),
696 &if_lhsissimd128value, &if_lhsisnotsimd128value); 703 &if_lhsissimd128value, &if_lhsisnotsimd128value);
697 704
698 assembler->Bind(&if_lhsissimd128value); 705 assembler->Bind(&if_lhsissimd128value);
699 { 706 {
700 // TODO(bmeurer): Inline the Simd128Value equality check. 707 // TODO(bmeurer): Inline the Simd128Value equality check.
701 assembler->TailCallRuntime(Runtime::kStrictEqual, context, lhs, 708 Runtime::FunctionId function_id = (mode == kStrictEqual)
702 rhs); 709 ? Runtime::kStrictEqual
710 : Runtime::kStrictNotEqual;
711 assembler->TailCallRuntime(function_id, context, lhs, rhs);
703 } 712 }
704 713
705 assembler->Bind(&if_lhsisnotsimd128value); 714 assembler->Bind(&if_lhsisnotsimd128value);
706 assembler->Goto(&if_false); 715 assembler->Goto(&if_notequal);
707 } 716 }
708 } 717 }
709 } 718 }
710 } 719 }
711 720
712 assembler->Bind(&if_lhsissmi); 721 assembler->Bind(&if_lhsissmi);
713 { 722 {
714 // We already know that {lhs} and {rhs} are not reference equal, and {lhs} 723 // We already know that {lhs} and {rhs} are not reference equal, and {lhs}
715 // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a 724 // is a Smi; so {lhs} and {rhs} can only be strictly equal if {rhs} is a
716 // HeapNumber with an equal floating point value. 725 // HeapNumber with an equal floating point value.
717 726
718 // Check if {rhs} is a Smi or a HeapObject. 727 // Check if {rhs} is a Smi or a HeapObject.
719 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler); 728 Label if_rhsissmi(assembler), if_rhsisnotsmi(assembler);
720 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi, 729 assembler->Branch(assembler->WordIsSmi(rhs), &if_rhsissmi,
721 &if_rhsisnotsmi); 730 &if_rhsisnotsmi);
722 731
723 assembler->Bind(&if_rhsissmi); 732 assembler->Bind(&if_rhsissmi);
724 assembler->Goto(&if_false); 733 assembler->Goto(&if_notequal);
725 734
726 assembler->Bind(&if_rhsisnotsmi); 735 assembler->Bind(&if_rhsisnotsmi);
727 { 736 {
728 // Load the map of the {rhs}. 737 // Load the map of the {rhs}.
729 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset); 738 Node* rhs_map = assembler->LoadObjectField(rhs, HeapObject::kMapOffset);
730 739
731 // The {rhs} could be a HeapNumber with the same value as {lhs}. 740 // The {rhs} could be a HeapNumber with the same value as {lhs}.
732 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler); 741 Label if_rhsisnumber(assembler), if_rhsisnotnumber(assembler);
733 assembler->Branch(assembler->WordEqual(rhs_map, number_map), 742 assembler->Branch(assembler->WordEqual(rhs_map, number_map),
734 &if_rhsisnumber, &if_rhsisnotnumber); 743 &if_rhsisnumber, &if_rhsisnotnumber);
735 744
736 assembler->Bind(&if_rhsisnumber); 745 assembler->Bind(&if_rhsisnumber);
737 { 746 {
738 // Convert {lhs} and {rhs} to floating point values. 747 // Convert {lhs} and {rhs} to floating point values.
739 Node* lhs_value = assembler->SmiToFloat64(lhs); 748 Node* lhs_value = assembler->SmiToFloat64(lhs);
740 Node* rhs_value = assembler->LoadHeapNumberValue(rhs); 749 Node* rhs_value = assembler->LoadHeapNumberValue(rhs);
741 750
742 // Perform a floating point comparison of {lhs} and {rhs}. 751 // Perform a floating point comparison of {lhs} and {rhs}.
743 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_true, 752 assembler->BranchIfFloat64Equal(lhs_value, rhs_value, &if_equal,
744 &if_false); 753 &if_notequal);
745 } 754 }
746 755
747 assembler->Bind(&if_rhsisnotnumber); 756 assembler->Bind(&if_rhsisnotnumber);
748 assembler->Goto(&if_false); 757 assembler->Goto(&if_notequal);
749 } 758 }
750 } 759 }
751 } 760 }
752 761
753 assembler->Bind(&if_true); 762 assembler->Bind(&if_equal);
754 assembler->Return(assembler->BooleanConstant(true)); 763 assembler->Return(assembler->BooleanConstant(mode == kStrictEqual));
755 764
756 assembler->Bind(&if_false); 765 assembler->Bind(&if_notequal);
757 assembler->Return(assembler->BooleanConstant(false)); 766 assembler->Return(assembler->BooleanConstant(mode == kStrictNotEqual));
767 }
768
769 } // namespace
770
771 void StrictEqualStub::GenerateAssembly(
772 compiler::CodeStubAssembler* assembler) const {
773 GenerateStrictEqual(assembler, kStrictEqual);
774 }
775
776 void StrictNotEqualStub::GenerateAssembly(
777 compiler::CodeStubAssembler* assembler) const {
778 GenerateStrictEqual(assembler, kStrictNotEqual);
758 } 779 }
759 780
760 void ToBooleanStub::GenerateAssembly( 781 void ToBooleanStub::GenerateAssembly(
761 compiler::CodeStubAssembler* assembler) const { 782 compiler::CodeStubAssembler* assembler) const {
762 typedef compiler::Node Node; 783 typedef compiler::Node Node;
763 typedef compiler::CodeStubAssembler::Label Label; 784 typedef compiler::CodeStubAssembler::Label Label;
764 785
765 Node* value = assembler->Parameter(0); 786 Node* value = assembler->Parameter(0);
766 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); 787 Label if_valueissmi(assembler), if_valueisnotsmi(assembler);
767 788
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 if (type->Is(Type::UntaggedPointer())) { 1346 if (type->Is(Type::UntaggedPointer())) {
1326 return Representation::External(); 1347 return Representation::External();
1327 } 1348 }
1328 1349
1329 DCHECK(!type->Is(Type::Untagged())); 1350 DCHECK(!type->Is(Type::Untagged()));
1330 return Representation::Tagged(); 1351 return Representation::Tagged();
1331 } 1352 }
1332 1353
1333 } // namespace internal 1354 } // namespace internal
1334 } // namespace v8 1355 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/compiler/js-generic-lowering.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698