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

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

Issue 1761823002: [compiler] Introduce StringEqualStub and StringNotEqualStub. (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/code-stub-assembler.h » ('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/code-factory.h"
10 #include "src/compiler/code-stub-assembler.h" 11 #include "src/compiler/code-stub-assembler.h"
11 #include "src/factory.h" 12 #include "src/factory.h"
12 #include "src/gdb-jit.h" 13 #include "src/gdb-jit.h"
13 #include "src/ic/handler-compiler.h" 14 #include "src/ic/handler-compiler.h"
14 #include "src/ic/ic.h" 15 #include "src/ic/ic.h"
15 #include "src/macro-assembler.h" 16 #include "src/macro-assembler.h"
16 #include "src/parsing/parser.h" 17 #include "src/parsing/parser.h"
17 #include "src/profiler/cpu-profiler.h" 18 #include "src/profiler/cpu-profiler.h"
18 19
19 namespace v8 { 20 namespace v8 {
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 compiler::Node* value = assembler->Parameter(0); 494 compiler::Node* value = assembler->Parameter(0);
494 compiler::Node* string = 495 compiler::Node* string =
495 assembler->LoadObjectField(value, JSValue::kValueOffset); 496 assembler->LoadObjectField(value, JSValue::kValueOffset);
496 compiler::Node* result = 497 compiler::Node* result =
497 assembler->LoadObjectField(string, String::kLengthOffset); 498 assembler->LoadObjectField(string, String::kLengthOffset);
498 assembler->Return(result); 499 assembler->Return(result);
499 } 500 }
500 501
501 namespace { 502 namespace {
502 503
503 enum StrictEqualMode { kStrictEqual, kStrictNotEqual }; 504 enum ResultMode { kDontNegateResult, kNegateResult };
504 505
505 void GenerateStrictEqual(compiler::CodeStubAssembler* assembler, 506 void GenerateStrictEqual(compiler::CodeStubAssembler* assembler,
506 StrictEqualMode mode) { 507 Isolate* isolate, ResultMode mode) {
507 // Here's pseudo-code for the algorithm below in case of kStrictEqual mode; 508 // Here's pseudo-code for the algorithm below in case of kDontNegateResult
508 // for kStrictNotEqual mode we properly negate the result. 509 // mode; for kNegateResult mode we properly negate the result.
509 // 510 //
510 // if (lhs == rhs) { 511 // if (lhs == rhs) {
511 // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN; 512 // if (lhs->IsHeapNumber()) return HeapNumber::cast(lhs)->value() != NaN;
512 // return true; 513 // return true;
513 // } 514 // }
514 // if (!lhs->IsSmi()) { 515 // if (!lhs->IsSmi()) {
515 // if (lhs->IsHeapNumber()) { 516 // if (lhs->IsHeapNumber()) {
516 // if (rhs->IsSmi()) { 517 // if (rhs->IsSmi()) {
517 // return Smi::cast(rhs)->value() == HeapNumber::cast(lhs)->value(); 518 // return Smi::cast(rhs)->value() == HeapNumber::cast(lhs)->value();
518 // } else if (rhs->IsHeapNumber()) { 519 // } else if (rhs->IsHeapNumber()) {
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler); 701 Label if_rhsisstring(assembler), if_rhsisnotstring(assembler);
701 assembler->Branch(assembler->Int32LessThan( 702 assembler->Branch(assembler->Int32LessThan(
702 rhs_instance_type, assembler->Int32Constant( 703 rhs_instance_type, assembler->Int32Constant(
703 FIRST_NONSTRING_TYPE)), 704 FIRST_NONSTRING_TYPE)),
704 &if_rhsisstring, &if_rhsisnotstring); 705 &if_rhsisstring, &if_rhsisnotstring);
705 706
706 assembler->Bind(&if_rhsisstring); 707 assembler->Bind(&if_rhsisstring);
707 { 708 {
708 // TODO(bmeurer): Optimize this further once the StringEqual 709 // TODO(bmeurer): Optimize this further once the StringEqual
709 // functionality is available in TurboFan land. 710 // functionality is available in TurboFan land.
710 Runtime::FunctionId function_id = (mode == kStrictEqual) 711 Callable callable = (mode == kDontNegateResult)
epertoso 2016/03/03 09:41:45 Does the TODO above still apply?
Benedikt Meurer 2016/03/03 09:45:07 Done.
711 ? Runtime::kStringEqual 712 ? CodeFactory::StringEqual(isolate)
712 : Runtime::kStringNotEqual; 713 : CodeFactory::StringNotEqual(isolate);
713 assembler->TailCallRuntime(function_id, context, lhs, rhs); 714 assembler->TailCallStub(callable, context, lhs, rhs);
714 } 715 }
715 716
716 assembler->Bind(&if_rhsisnotstring); 717 assembler->Bind(&if_rhsisnotstring);
717 assembler->Goto(&if_notequal); 718 assembler->Goto(&if_notequal);
718 } 719 }
719 720
720 assembler->Bind(&if_lhsisnotstring); 721 assembler->Bind(&if_lhsisnotstring);
721 { 722 {
722 // Check if {lhs} is a Simd128Value. 723 // Check if {lhs} is a Simd128Value.
723 Label if_lhsissimd128value(assembler), 724 Label if_lhsissimd128value(assembler),
724 if_lhsisnotsimd128value(assembler); 725 if_lhsisnotsimd128value(assembler);
725 assembler->Branch(assembler->Word32Equal( 726 assembler->Branch(assembler->Word32Equal(
726 lhs_instance_type, 727 lhs_instance_type,
727 assembler->Int32Constant(SIMD128_VALUE_TYPE)), 728 assembler->Int32Constant(SIMD128_VALUE_TYPE)),
728 &if_lhsissimd128value, &if_lhsisnotsimd128value); 729 &if_lhsissimd128value, &if_lhsisnotsimd128value);
729 730
730 assembler->Bind(&if_lhsissimd128value); 731 assembler->Bind(&if_lhsissimd128value);
731 { 732 {
732 // TODO(bmeurer): Inline the Simd128Value equality check. 733 // TODO(bmeurer): Inline the Simd128Value equality check.
733 Runtime::FunctionId function_id = (mode == kStrictEqual) 734 Runtime::FunctionId function_id = (mode == kDontNegateResult)
734 ? Runtime::kStrictEqual 735 ? Runtime::kStrictEqual
735 : Runtime::kStrictNotEqual; 736 : Runtime::kStrictNotEqual;
736 assembler->TailCallRuntime(function_id, context, lhs, rhs); 737 assembler->TailCallRuntime(function_id, context, lhs, rhs);
737 } 738 }
738 739
739 assembler->Bind(&if_lhsisnotsimd128value); 740 assembler->Bind(&if_lhsisnotsimd128value);
740 assembler->Goto(&if_notequal); 741 assembler->Goto(&if_notequal);
741 } 742 }
742 } 743 }
743 } 744 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 &if_notequal); 779 &if_notequal);
779 } 780 }
780 781
781 assembler->Bind(&if_rhsisnotnumber); 782 assembler->Bind(&if_rhsisnotnumber);
782 assembler->Goto(&if_notequal); 783 assembler->Goto(&if_notequal);
783 } 784 }
784 } 785 }
785 } 786 }
786 787
787 assembler->Bind(&if_equal); 788 assembler->Bind(&if_equal);
788 assembler->Return(assembler->BooleanConstant(mode == kStrictEqual)); 789 assembler->Return(assembler->BooleanConstant(mode == kDontNegateResult));
789 790
790 assembler->Bind(&if_notequal); 791 assembler->Bind(&if_notequal);
791 assembler->Return(assembler->BooleanConstant(mode == kStrictNotEqual)); 792 assembler->Return(assembler->BooleanConstant(mode == kNegateResult));
793 }
794
795 void GenerateStringEqual(compiler::CodeStubAssembler* assembler,
796 ResultMode mode) {
797 // Here's pseudo-code for the algorithm below in case of kDontNegateResult
798 // mode; for kNegateResult mode we properly negate the result.
799 //
800 // if (lhs == rhs) return true;
801 // if (lhs->length() != rhs->length()) return false;
802 // if (lhs->IsInternalizedString() && rhs->IsInternalizedString()) {
803 // return false;
804 // }
805 // if (lhs->IsSeqOneByteString() && rhs->IsSeqOneByteString()) {
806 // for (i = 0; i != lhs->length(); ++i) {
807 // if (lhs[i] != rhs[i]) return false;
808 // }
809 // return true;
810 // }
811 // return %StringEqual(lhs, rhs);
812
813 typedef compiler::CodeStubAssembler::Label Label;
814 typedef compiler::Node Node;
815 typedef compiler::CodeStubAssembler::Variable Variable;
816
817 Node* lhs = assembler->Parameter(0);
818 Node* rhs = assembler->Parameter(1);
819 Node* context = assembler->Parameter(2);
820
821 Label if_equal(assembler), if_notequal(assembler);
822
823 // Fast check to see if {lhs} and {rhs} refer to the same String object.
824 Label if_same(assembler), if_notsame(assembler);
825 assembler->Branch(assembler->WordEqual(lhs, rhs), &if_same, &if_notsame);
826
827 assembler->Bind(&if_same);
828 assembler->Goto(&if_equal);
829
830 assembler->Bind(&if_notsame);
831 {
832 // The {lhs} and {rhs} don't refer to the exact same String object.
833
834 // Load the length of {lhs} and {rhs}.
835 Node* lhs_length = assembler->LoadObjectField(lhs, String::kLengthOffset);
836 Node* rhs_length = assembler->LoadObjectField(rhs, String::kLengthOffset);
837
838 // Check if the lengths of {lhs} and {rhs} are equal.
839 Label if_lengthisequal(assembler), if_lengthisnotequal(assembler);
840 assembler->Branch(assembler->WordEqual(lhs_length, rhs_length),
841 &if_lengthisequal, &if_lengthisnotequal);
842
843 assembler->Bind(&if_lengthisequal);
844 {
845 // Load instance types of {lhs} and {rhs}.
846 Node* lhs_instance_type = assembler->LoadInstanceType(lhs);
847 Node* rhs_instance_type = assembler->LoadInstanceType(rhs);
848
849 // Combine the instance types into a single 16-bit value, so we can check
850 // both of them at once.
851 Node* both_instance_types = assembler->Word32Or(
852 lhs_instance_type,
853 assembler->Word32Shl(rhs_instance_type, assembler->Int32Constant(8)));
854
855 // Check if both {lhs} and {rhs} are internalized.
856 int const kBothInternalizedMask =
857 kIsNotInternalizedMask | (kIsNotInternalizedMask << 8);
858 int const kBothInternalizedTag =
859 kInternalizedTag | (kInternalizedTag << 8);
860 Label if_bothinternalized(assembler), if_notbothinternalized(assembler);
861 assembler->Branch(assembler->Word32Equal(
862 assembler->Word32And(both_instance_types,
863 assembler->Int32Constant(
864 kBothInternalizedMask)),
865 assembler->Int32Constant(kBothInternalizedTag)),
866 &if_bothinternalized, &if_notbothinternalized);
867
868 assembler->Bind(&if_bothinternalized);
869 {
870 // Fast negative check for internalized-to-internalized equality.
871 assembler->Goto(&if_notequal);
872 }
873
874 assembler->Bind(&if_notbothinternalized);
875 {
876 // Check that both {lhs} and {rhs} are flat one-byte strings.
877 int const kBothSeqOneByteStringMask =
878 kStringEncodingMask | kStringRepresentationMask |
879 ((kStringEncodingMask | kStringRepresentationMask) << 8);
880 int const kBothSeqOneByteStringTag =
881 kOneByteStringTag | kSeqStringTag |
882 ((kOneByteStringTag | kSeqStringTag) << 8);
883 Label if_bothonebyteseqstrings(assembler),
884 if_notbothonebyteseqstrings(assembler);
885 assembler->Branch(
886 assembler->Word32Equal(
887 assembler->Word32And(
888 both_instance_types,
889 assembler->Int32Constant(kBothSeqOneByteStringMask)),
890 assembler->Int32Constant(kBothSeqOneByteStringTag)),
891 &if_bothonebyteseqstrings, &if_notbothonebyteseqstrings);
892
893 assembler->Bind(&if_bothonebyteseqstrings);
894 {
895 // Compute the effective offset of the first character.
896 Node* begin = assembler->IntPtrConstant(
897 SeqOneByteString::kHeaderSize - kHeapObjectTag);
898
899 // Compute the first offset after the string from the length.
900 Node* end =
901 assembler->IntPtrAdd(begin, assembler->SmiUntag(lhs_length));
902
903 // Loop over the {lhs} and {rhs} strings to see if they are equal.
904 Variable var_offset(assembler, kPointerSize == 8
905 ? MachineRepresentation::kWord64
epertoso 2016/03/03 09:41:45 nit: MachineType::PointerRepresentation() does thi
Benedikt Meurer 2016/03/03 09:45:07 Done.
906 : MachineRepresentation::kWord32);
907 Label loop(assembler, &var_offset);
908 var_offset.Bind(begin);
909 assembler->Goto(&loop);
910 assembler->Bind(&loop);
911 {
912 // Check if {offset} equals {end}.
913 Node* offset = var_offset.value();
914 Label if_done(assembler), if_notdone(assembler);
915 assembler->Branch(assembler->WordEqual(offset, end), &if_done,
916 &if_notdone);
917
918 assembler->Bind(&if_notdone);
919 {
920 // Load the next characters from {lhs} and {rhs}.
921 Node* lhs_value =
922 assembler->Load(MachineType::Uint8(), lhs, offset);
923 Node* rhs_value =
924 assembler->Load(MachineType::Uint8(), rhs, offset);
925
926 // Check if the characters match.
927 Label if_valueissame(assembler), if_valueisnotsame(assembler);
928 assembler->Branch(assembler->Word32Equal(lhs_value, rhs_value),
929 &if_valueissame, &if_valueisnotsame);
930
931 assembler->Bind(&if_valueissame);
932 {
933 // Advance to next character.
934 var_offset.Bind(
935 assembler->IntPtrAdd(offset, assembler->IntPtrConstant(1)));
936 }
937 assembler->Goto(&loop);
938
939 assembler->Bind(&if_valueisnotsame);
940 assembler->Goto(&if_notequal);
941 }
942
943 assembler->Bind(&if_done);
944 assembler->Goto(&if_equal);
945 }
946 }
947
948 assembler->Bind(&if_notbothonebyteseqstrings);
949 {
950 // TODO(bmeurer): Add fast case support for flattened cons strings;
951 // also add support for two byte string equality checks.
952 Runtime::FunctionId function_id = (mode == kDontNegateResult)
953 ? Runtime::kStringEqual
954 : Runtime::kStringNotEqual;
955 assembler->TailCallRuntime(function_id, context, lhs, rhs);
956 }
957 }
958 }
959
960 assembler->Bind(&if_lengthisnotequal);
961 {
962 // Mismatch in length of {lhs} and {rhs}, cannot be equal.
963 assembler->Goto(&if_notequal);
964 }
965 }
966
967 assembler->Bind(&if_equal);
968 assembler->Return(assembler->BooleanConstant(mode == kDontNegateResult));
969
970 assembler->Bind(&if_notequal);
971 assembler->Return(assembler->BooleanConstant(mode == kNegateResult));
792 } 972 }
793 973
794 } // namespace 974 } // namespace
795 975
796 void StrictEqualStub::GenerateAssembly( 976 void StrictEqualStub::GenerateAssembly(
797 compiler::CodeStubAssembler* assembler) const { 977 compiler::CodeStubAssembler* assembler) const {
798 GenerateStrictEqual(assembler, kStrictEqual); 978 GenerateStrictEqual(assembler, isolate(), kDontNegateResult);
799 } 979 }
800 980
801 void StrictNotEqualStub::GenerateAssembly( 981 void StrictNotEqualStub::GenerateAssembly(
802 compiler::CodeStubAssembler* assembler) const { 982 compiler::CodeStubAssembler* assembler) const {
803 GenerateStrictEqual(assembler, kStrictNotEqual); 983 GenerateStrictEqual(assembler, isolate(), kNegateResult);
984 }
985
986 void StringEqualStub::GenerateAssembly(
987 compiler::CodeStubAssembler* assembler) const {
988 GenerateStringEqual(assembler, kDontNegateResult);
989 }
990
991 void StringNotEqualStub::GenerateAssembly(
992 compiler::CodeStubAssembler* assembler) const {
993 GenerateStringEqual(assembler, kNegateResult);
804 } 994 }
805 995
806 void ToBooleanStub::GenerateAssembly( 996 void ToBooleanStub::GenerateAssembly(
807 compiler::CodeStubAssembler* assembler) const { 997 compiler::CodeStubAssembler* assembler) const {
808 typedef compiler::Node Node; 998 typedef compiler::Node Node;
809 typedef compiler::CodeStubAssembler::Label Label; 999 typedef compiler::CodeStubAssembler::Label Label;
810 1000
811 Node* value = assembler->Parameter(0); 1001 Node* value = assembler->Parameter(0);
812 Label if_valueissmi(assembler), if_valueisnotsmi(assembler); 1002 Label if_valueissmi(assembler), if_valueisnotsmi(assembler);
813 1003
(...skipping 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
1371 if (type->Is(Type::UntaggedPointer())) { 1561 if (type->Is(Type::UntaggedPointer())) {
1372 return Representation::External(); 1562 return Representation::External();
1373 } 1563 }
1374 1564
1375 DCHECK(!type->Is(Type::Untagged())); 1565 DCHECK(!type->Is(Type::Untagged()));
1376 return Representation::Tagged(); 1566 return Representation::Tagged();
1377 } 1567 }
1378 1568
1379 } // namespace internal 1569 } // namespace internal
1380 } // namespace v8 1570 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/compiler/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698