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

Unified Diff: src/builtins/builtins-string.cc

Issue 2373493002: [stubs] Port String.prototype.substr to TurboFan (Closed)
Patch Set: Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins/builtins.h ('k') | src/js/i18n.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/builtins-string.cc
diff --git a/src/builtins/builtins-string.cc b/src/builtins/builtins-string.cc
index a3aa0b6930802fcfa19a87c59a3b0c743cb9be18..b57714aee1d680ba09b89ca9816b6bb13569dbc1 100644
--- a/src/builtins/builtins-string.cc
+++ b/src/builtins/builtins-string.cc
@@ -581,6 +581,114 @@ void Builtins::Generate_StringPrototypeSubstring(CodeStubAssembler* a) {
}
}
+// ES6 section B.2.3.1 String.prototype.substr ( start, length )
+void Builtins::Generate_StringPrototypeSubstr(CodeStubAssembler* a) {
+ typedef CodeStubAssembler::Label Label;
+ typedef compiler::Node Node;
+ typedef CodeStubAssembler::Variable Variable;
+
+ Label out(a), handle_length(a);
+
+ Variable var_start(a, MachineRepresentation::kTagged);
+ Variable var_length(a, MachineRepresentation::kTagged);
+
+ Node* const receiver = a->Parameter(0);
+ Node* const start = a->Parameter(1);
+ Node* const length = a->Parameter(2);
+ Node* const context = a->Parameter(5);
+
+ // Check that {receiver} is coercible to Object and convert it to a String.
+ Node* const string =
+ a->ToThisString(context, receiver, "String.prototype.substr");
+
+ Node* const string_length = a->LoadStringLength(string);
+
+ // Conversions and bounds-checks for {start}.
+ {
+ Node* const start_int =
+ a->ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero);
+
+ Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
+ a->Branch(a->WordIsSmi(start_int), &if_issmi, &if_isheapnumber);
+
+ a->Bind(&if_issmi);
+ {
+ Node* const zero = a->SmiConstant(Smi::FromInt(0));
+ Node* const length_plus_start = a->SmiAdd(string_length, start_int);
+ var_start.Bind(a->Select(a->SmiLessThan(start_int, zero),
+ a->SmiMax(length_plus_start, zero), start_int));
+ a->Goto(&handle_length);
+ }
+
+ a->Bind(&if_isheapnumber);
+ {
+ Node* result = a->CallRuntime(Runtime::kThrowIllegalOperation, context);
Igor Sheludko 2016/09/27 12:15:06 String.prototype.substr should not throw. I guess
jgruber 2016/09/29 07:48:49 Thanks, good catch! Modified this to set var_start
+ a->DebugBreak(); // Unreachable.
+ a->Return(result);
+ }
+ }
+
+ // Conversions and bounds-checks for {length}.
+ a->Bind(&handle_length);
+ {
+ // Default to {string_length} if {length} is undefined.
+ {
+ Node* const length_int =
+ a->ToInteger(context, length, CodeStubAssembler::kTruncateMinusZero);
+ var_length.Bind(a->Select(a->WordEqual(length, a->UndefinedConstant()),
+ string_length, length_int));
+ }
+
+ Label if_issmi(a), if_isheapnumber(a, Label::kDeferred);
+ a->Branch(a->WordIsSmi(var_length.value()), &if_issmi, &if_isheapnumber);
+
+ // Set {length} to min(max({length}, 0), {string_length} - {start}
+ a->Bind(&if_issmi);
+ {
+ Node* const zero = a->SmiConstant(Smi::FromInt(0));
+ Node* const positive_length = a->SmiMax(var_length.value(), zero);
+
+ Node* const minimal_length = a->SmiSub(string_length, var_start.value());
+ var_length.Bind(a->SmiMin(positive_length, minimal_length));
+
+ a->GotoUnless(a->SmiLessThanOrEqual(var_length.value(), zero), &out);
+ a->Return(a->EmptyStringConstant());
+ }
+
+ a->Bind(&if_isheapnumber);
+ {
+ // If {length} is a heap number, it is definitely out of bounds. There are
+ // two cases according to the spec: if it is negative, "" is returned; if
+ // it is positive, then length is set to {string_length} - {start}.
+
+ a->Assert(a->WordEqual(a->LoadMap(var_length.value()),
+ a->HeapNumberMapConstant()));
+
+ Label if_isnegative(a), if_ispositive(a);
+ Node* const float_zero = a->Float64Constant(0.);
+ Node* const length_float = a->LoadHeapNumberValue(var_length.value());
+ a->Branch(a->Float64LessThan(length_float, float_zero), &if_isnegative,
+ &if_ispositive);
+
+ a->Bind(&if_isnegative);
+ a->Return(a->EmptyStringConstant());
+
+ a->Bind(&if_ispositive);
+ {
+ var_length.Bind(a->SmiSub(string_length, var_start.value()));
+ a->Goto(&out);
+ }
+ }
+ }
+
+ a->Bind(&out);
+ {
+ Node* const end = a->SmiAdd(var_start.value(), var_length.value());
+ Node* const result = a->SubString(context, string, var_start.value(), end);
+ a->Return(result);
+ }
+}
+
// ES6 section 21.1.3.25 String.prototype.toString ()
void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
« 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