Index: src/builtins/builtins-string.cc |
diff --git a/src/builtins/builtins-string.cc b/src/builtins/builtins-string.cc |
index 83738415fc4bb88f7b0058cb7a4a1305678cc941..b9becc7473daad89ea61049fecf27e2d06142d88 100644 |
--- a/src/builtins/builtins-string.cc |
+++ b/src/builtins/builtins-string.cc |
@@ -471,6 +471,100 @@ BUILTIN(StringPrototypeNormalize) { |
return *string; |
} |
+namespace { |
+ |
+compiler::Node* EnsureSmiBetweenZeroAnd(CodeStubAssembler* a, |
+ compiler::Node* value, |
+ compiler::Node* limit) { |
+ typedef CodeStubAssembler::Label Label; |
+ typedef compiler::Node Node; |
+ typedef CodeStubAssembler::Variable Variable; |
+ |
+ Label out(a); |
+ Variable var_result(a, MachineRepresentation::kTagged); |
+ |
+ Label if_isinbounds(a), if_isoutofbounds(a, Label::kDeferred); |
+ a->Branch(a->SmiAbove(value, limit), &if_isoutofbounds, &if_isinbounds); |
+ |
+ a->Bind(&if_isinbounds); |
+ { |
+ var_result.Bind(value); |
+ a->Goto(&out); |
+ } |
+ |
+ a->Bind(&if_isoutofbounds); |
+ { |
+ Node* const zero = a->SmiConstant(Smi::FromInt(0)); |
+ var_result.Bind(a->Select(a->SmiLessThan(value, zero), zero, limit)); |
+ a->Goto(&out); |
+ } |
+ |
+ a->Bind(&out); |
+ return var_result.value(); |
+} |
+ |
+} // namespace |
+ |
+// ES6 section 21.1.3.19 String.prototype.substring ( start, end ) |
+void Builtins::Generate_StringPrototypeSubstring(CodeStubAssembler* a) { |
+ typedef CodeStubAssembler::Label Label; |
+ typedef compiler::Node Node; |
+ typedef CodeStubAssembler::Variable Variable; |
+ |
+ Label out(a); |
+ |
+ Variable var_start(a, MachineRepresentation::kTagged); |
+ Variable var_end(a, MachineRepresentation::kTagged); |
+ |
+ Node* const receiver = a->Parameter(0); |
+ Node* const start = a->Parameter(1); |
+ Node* const end = 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.charCodeAt"); |
+ |
+ Node* const length = a->LoadStringLength(string); |
+ Node* const zero = a->SmiConstant(Smi::FromInt(0)); |
+ |
+ // Conversion and bounds-checks for {start}. |
+ { |
+ Node* const start_int = |
+ a->ToInteger(context, start, CodeStubAssembler::kTruncateMinusZero); |
+ var_start.Bind(EnsureSmiBetweenZeroAnd(a, start_int, length)); |
+ } |
+ |
+ // Conversion and bounds-checks for {end}. |
+ { |
+ var_end.Bind(length); |
+ a->GotoIf(a->WordEqual(end, a->UndefinedConstant()), &out); |
+ |
+ Node* const end_int = |
+ a->ToInteger(context, end, CodeStubAssembler::kTruncateMinusZero); |
+ var_end.Bind(EnsureSmiBetweenZeroAnd(a, end_int, length)); |
+ |
+ Label if_endislessthanstart(a); |
+ a->Branch(a->SmiLessThan(var_end.value(), var_start.value()), |
+ &if_endislessthanstart, &out); |
+ |
+ a->Bind(&if_endislessthanstart); |
+ { |
+ Node* const tmp = var_end.value(); |
+ var_end.Bind(var_start.value()); |
+ var_start.Bind(tmp); |
+ a->Goto(&out); |
+ } |
+ } |
+ |
+ a->Bind(&out); |
+ { |
+ Node* result = |
+ a->SubString(context, string, var_start.value(), var_end.value()); |
+ a->Return(result); |
+ } |
+} |
+ |
// ES6 section 21.1.3.25 String.prototype.toString () |
void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) { |
typedef compiler::Node Node; |