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

Side by Side Diff: src/builtins/builtins-string.cc

Issue 2373493002: [stubs] Port String.prototype.substr to TurboFan (Closed)
Patch Set: Additional tests Created 4 years, 2 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/builtins/builtins.h ('k') | src/js/i18n.js » ('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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 855 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 Handle<String> valid_forms = 866 Handle<String> valid_forms =
867 isolate->factory()->NewStringFromStaticChars("NFC, NFD, NFKC, NFKD"); 867 isolate->factory()->NewStringFromStaticChars("NFC, NFD, NFKC, NFKD");
868 THROW_NEW_ERROR_RETURN_FAILURE( 868 THROW_NEW_ERROR_RETURN_FAILURE(
869 isolate, 869 isolate,
870 NewRangeError(MessageTemplate::kNormalizationForm, valid_forms)); 870 NewRangeError(MessageTemplate::kNormalizationForm, valid_forms));
871 } 871 }
872 872
873 return *string; 873 return *string;
874 } 874 }
875 875
876 // ES6 section B.2.3.1 String.prototype.substr ( start, length )
877 void Builtins::Generate_StringPrototypeSubstr(CodeStubAssembler* a) {
878 typedef CodeStubAssembler::Label Label;
879 typedef compiler::Node Node;
880 typedef CodeStubAssembler::Variable Variable;
881
882 Label out(a), handle_length(a);
883
884 Variable var_start(a, MachineRepresentation::kTagged);
885 Variable var_length(a, MachineRepresentation::kTagged);
886
887 Node* const receiver = a->Parameter(0);
888 Node* const start = a->Parameter(1);
889 Node* const length = a->Parameter(2);
890 Node* const context = a->Parameter(5);
891
892 Node* const zero = a->SmiConstant(Smi::FromInt(0));
893
894 // Check that {receiver} is coercible to Object and convert it to a String.
895 Node* const string =
896 a->ToThisString(context, receiver, "String.prototype.substr");
897
898 Node* const string_length = a->LoadStringLength(string);
899
900 // Conversions and bounds-checks for {start}.
901 {
902 Node* const start_int =
903 a->ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero);
904
905 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
906 a->Branch(a->WordIsSmi(start_int), &if_issmi, &if_isheapnumber);
907
908 a->Bind(&if_issmi);
909 {
910 Node* const length_plus_start = a->SmiAdd(string_length, start_int);
911 var_start.Bind(a->Select(a->SmiLessThan(start_int, zero),
912 a->SmiMax(length_plus_start, zero), start_int));
913 a->Goto(&handle_length);
914 }
915
916 a->Bind(&if_isheapnumber);
917 {
918 // If {start} is a heap number, it is definitely out of bounds. If it is
919 // negative, {start} = max({string_length} + {start}),0) = 0'. If it is
920 // positive, set {start} to {string_length} which ultimately results in
921 // returning an empty string.
922 Node* const float_zero = a->Float64Constant(0.);
923 Node* const start_float = a->LoadHeapNumberValue(start_int);
924 var_start.Bind(a->Select(a->Float64LessThan(start_float, float_zero),
925 zero, string_length));
926 a->Goto(&handle_length);
927 }
928 }
929
930 // Conversions and bounds-checks for {length}.
931 a->Bind(&handle_length);
932 {
933 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
934
935 // Default to {string_length} if {length} is undefined.
936 {
937 Label if_isundefined(a, Label::kDeferred), if_isnotundefined(a);
938 a->Branch(a->WordEqual(length, a->UndefinedConstant()), &if_isundefined,
939 &if_isnotundefined);
940
941 a->Bind(&if_isundefined);
942 var_length.Bind(string_length);
943 a->Goto(&if_issmi);
944
945 a->Bind(&if_isnotundefined);
946 var_length.Bind(
947 a->ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero));
948 }
949
950 a->Branch(a->WordIsSmi(var_length.value()), &if_issmi, &if_isheapnumber);
951
952 // Set {length} to min(max({length}, 0), {string_length} - {start}
953 a->Bind(&if_issmi);
954 {
955 Node* const positive_length = a->SmiMax(var_length.value(), zero);
956
957 Node* const minimal_length = a->SmiSub(string_length, var_start.value());
958 var_length.Bind(a->SmiMin(positive_length, minimal_length));
959
960 a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out);
961 a->Return(a->EmptyStringConstant());
962 }
963
964 a->Bind(&if_isheapnumber);
965 {
966 // If {length} is a heap number, it is definitely out of bounds. There are
967 // two cases according to the spec: if it is negative, "" is returned; if
968 // it is positive, then length is set to {string_length} - {start}.
969
970 a->Assert(a->WordEqual(a->LoadMap(var_length.value()),
971 a->HeapNumberMapConstant()));
972
973 Label if_isnegative(a), if_ispositive(a);
974 Node* const float_zero = a->Float64Constant(0.);
975 Node* const length_float = a->LoadHeapNumberValue(var_length.value());
976 a->Branch(a->Float64LessThan(length_float, float_zero), &if_isnegative,
977 &if_ispositive);
978
979 a->Bind(&if_isnegative);
980 a->Return(a->EmptyStringConstant());
981
982 a->Bind(&if_ispositive);
983 {
984 var_length.Bind(a->SmiSub(string_length, var_start.value()));
985 a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out);
986 a->Return(a->EmptyStringConstant());
987 }
988 }
989 }
990
991 a->Bind(&out);
992 {
993 Node* const end = a->SmiAdd(var_start.value(), var_length.value());
994 Node* const result = a->SubString(context, string, var_start.value(), end);
995 a->Return(result);
996 }
997 }
998
876 namespace { 999 namespace {
877 1000
878 compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a, 1001 compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a,
879 compiler::Node* context, 1002 compiler::Node* context,
880 compiler::Node* value, 1003 compiler::Node* value,
881 compiler::Node* limit) { 1004 compiler::Node* limit) {
882 typedef CodeStubAssembler::Label Label; 1005 typedef CodeStubAssembler::Label Label;
883 typedef compiler::Node Node; 1006 typedef compiler::Node Node;
884 typedef CodeStubAssembler::Variable Variable; 1007 typedef CodeStubAssembler::Variable Variable;
885 1008
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 Runtime::kThrowIncompatibleMethodReceiver, context, 1585 Runtime::kThrowIncompatibleMethodReceiver, context,
1463 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( 1586 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
1464 "String Iterator.prototype.next", TENURED)), 1587 "String Iterator.prototype.next", TENURED)),
1465 iterator); 1588 iterator);
1466 assembler->Return(result); // Never reached. 1589 assembler->Return(result); // Never reached.
1467 } 1590 }
1468 } 1591 }
1469 1592
1470 } // namespace internal 1593 } // namespace internal
1471 } // namespace v8 1594 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/js/i18n.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698