Chromium Code Reviews

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

Issue 2373493002: [stubs] Port String.prototype.substr to TurboFan (Closed)
Patch Set: Address comments Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
« 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...)
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 // Check that {receiver} is coercible to Object and convert it to a String.
893 Node* const string =
894 a->ToThisString(context, receiver, "String.prototype.substr");
895
896 Node* const string_length = a->LoadStringLength(string);
897
898 // Conversions and bounds-checks for {start}.
899 {
900 Node* const start_int =
901 a->ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero);
902
903 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
904 a->Branch(a->WordIsSmi(start_int), &if_issmi, &if_isheapnumber);
905
906 a->Bind(&if_issmi);
907 {
908 Node* const zero = a->SmiConstant(Smi::FromInt(0));
909 Node* const length_plus_start = a->SmiAdd(string_length, start_int);
910 var_start.Bind(a->Select(a->SmiLessThan(start_int, zero),
911 a->SmiMax(length_plus_start, zero), start_int));
912 a->Goto(&handle_length);
913 }
914
915 a->Bind(&if_isheapnumber);
916 {
917 // Set {start} to {string}.length; this ultimately returns "".
918 var_start.Bind(string_length);
Igor Sheludko 2016/09/29 10:59:44 I think if the start index is < 0 then we should b
jgruber 2016/09/29 12:13:43 Done.
919 a->Goto(&handle_length);
920 }
921 }
922
923 // Conversions and bounds-checks for {length}.
924 a->Bind(&handle_length);
925 {
926 // Default to {string_length} if {length} is undefined.
927 {
928 Node* const length_int =
929 a->ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
930 var_length.Bind(a->Select(a->WordEqual(length, a->UndefinedConstant()),
Igor Sheludko 2016/09/29 10:59:44 Please check that we don't execute ToInteger(lengt
jgruber 2016/09/29 12:13:43 Done.
931 string_length, length_int));
932 }
933
934 Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
935 a->Branch(a->WordIsSmi(var_length.value()), &if_issmi, &if_isheapnumber);
936
937 // Set {length} to min(max({length}, 0), {string_length} - {start}
938 a->Bind(&if_issmi);
939 {
940 Node* const zero = a->SmiConstant(Smi::FromInt(0));
941 Node* const positive_length = a->SmiMax(var_length.value(), zero);
942
943 Node* const minimal_length = a->SmiSub(string_length, var_start.value());
944 var_length.Bind(a->SmiMin(positive_length, minimal_length));
945
946 a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out);
947 a->Return(a->EmptyStringConstant());
948 }
949
950 a->Bind(&if_isheapnumber);
951 {
952 // If {length} is a heap number, it is definitely out of bounds. There are
953 // two cases according to the spec: if it is negative, "" is returned; if
954 // it is positive, then length is set to {string_length} - {start}.
955
956 a->Assert(a->WordEqual(a->LoadMap(var_length.value()),
957 a->HeapNumberMapConstant()));
958
959 Label if_isnegative(a), if_ispositive(a);
960 Node* const float_zero = a->Float64Constant(0.);
961 Node* const length_float = a->LoadHeapNumberValue(var_length.value());
962 a->Branch(a->Float64LessThan(length_float, float_zero), &if_isnegative,
963 &if_ispositive);
964
965 a->Bind(&if_isnegative);
966 a->Return(a->EmptyStringConstant());
967
968 a->Bind(&if_ispositive);
969 {
970 var_length.Bind(a->SmiSub(string_length, var_start.value()));
971 a->Goto(&out);
972 }
973 }
974 }
975
976 a->Bind(&out);
977 {
978 Node* const end = a->SmiAdd(var_start.value(), var_length.value());
979 Node* const result = a->SubString(context, string, var_start.value(), end);
980 a->Return(result);
981 }
982 }
983
876 namespace { 984 namespace {
877 985
878 compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a, 986 compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a,
879 compiler::Node* context, 987 compiler::Node* context,
880 compiler::Node* value, 988 compiler::Node* value,
881 compiler::Node* limit) { 989 compiler::Node* limit) {
882 typedef CodeStubAssembler::Label Label; 990 typedef CodeStubAssembler::Label Label;
883 typedef compiler::Node Node; 991 typedef compiler::Node Node;
884 typedef CodeStubAssembler::Variable Variable; 992 typedef CodeStubAssembler::Variable Variable;
885 993
(...skipping 576 matching lines...)
1462 Runtime::kThrowIncompatibleMethodReceiver, context, 1570 Runtime::kThrowIncompatibleMethodReceiver, context,
1463 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked( 1571 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
1464 "String Iterator.prototype.next", TENURED)), 1572 "String Iterator.prototype.next", TENURED)),
1465 iterator); 1573 iterator);
1466 assembler->Return(result); // Never reached. 1574 assembler->Return(result); // Never reached.
1467 } 1575 }
1468 } 1576 }
1469 1577
1470 } // namespace internal 1578 } // namespace internal
1471 } // namespace v8 1579 } // 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