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

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

Issue 2638393002: [builtins] Add String.prototype.indexOf fast path in TF (Closed)
Patch Set: hardcode paramater massaging Created 3 years, 11 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/code-factory.h » ('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 629b7ebb7f59780bb5ab348ddfbbc8edc909ef4d..f2b784cf053b409f5a7982329d3839582afa9d27 100644
--- a/src/builtins/builtins-string.cc
+++ b/src/builtins/builtins-string.cc
@@ -60,6 +60,10 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
Node* LoadSurrogatePairAt(Node* string, Node* length, Node* index,
UnicodeEncoding encoding);
+
+ void StringIndexOf(Node* receiver, Node* instance_type, Node* search_string,
+ Node* search_string_instance_type, Node* position,
+ std::function<void(Node*)> f_return);
};
void StringBuiltinsAssembler::GenerateStringEqual(ResultMode mode) {
@@ -785,7 +789,93 @@ BUILTIN(StringPrototypeIncludes) {
return *isolate->factory()->ToBoolean(index_in_str != -1);
}
-// ES6 #sec-string.prototype.indexof
+void StringBuiltinsAssembler::StringIndexOf(
+ Node* receiver, Node* instance_type, Node* search_string,
+ Node* search_string_instance_type, Node* position,
+ std::function<void(Node*)> f_return) {
+ CSA_ASSERT(this, IsString(receiver));
+ CSA_ASSERT(this, IsString(search_string));
+ CSA_ASSERT(this, TaggedIsSmi(position));
+
+ Label zero_length_needle(this), call_runtime_unchecked(this),
+ return_minus_1(this), check_search_string(this), continue_fast_path(this);
+
+ Node* needle_length = SmiUntag(LoadStringLength(search_string));
+ // Use faster/complex runtime fallback for long search strings.
+ GotoIf(IntPtrLessThan(IntPtrConstant(1), needle_length),
+ &call_runtime_unchecked);
+ Node* string_length = SmiUntag(LoadStringLength(receiver));
+ Node* start_position = SmiUntag(position);
+
+ GotoIf(IntPtrEqual(IntPtrConstant(0), needle_length), &zero_length_needle);
+ // Check that the needle fits in the start position.
+ GotoUnless(IntPtrLessThanOrEqual(needle_length,
+ IntPtrSub(string_length, start_position)),
+ &return_minus_1);
+ // Only support one-byte strings on the fast path.
+ BranchIfSimpleOneByteStringInstanceType(instance_type, &check_search_string,
+ &call_runtime_unchecked);
+ Bind(&check_search_string);
+ BranchIfSimpleOneByteStringInstanceType(search_string_instance_type,
+ &continue_fast_path,
+ &call_runtime_unchecked);
+ Bind(&continue_fast_path);
+ {
+ Node* needle_byte =
+ ChangeInt32ToIntPtr(LoadOneByteChar(search_string, IntPtrConstant(0)));
+ Node* start_address = OneByteCharAddress(receiver, start_position);
+ Node* search_length = IntPtrSub(string_length, start_position);
+ // Call out to the highly optimized memchr to perform the actual byte
+ // search.
+ Node* memchr =
+ ExternalConstant(ExternalReference::libc_memchr_function(isolate()));
+ Node* result_address =
+ CallCFunction3(MachineType::Pointer(), MachineType::Pointer(),
+ MachineType::IntPtr(), MachineType::UintPtr(), memchr,
+ start_address, needle_byte, search_length);
+ GotoIf(WordEqual(result_address, IntPtrConstant(0)), &return_minus_1);
+ Node* result_index =
+ IntPtrAdd(IntPtrSub(result_address, start_address), start_position);
+ f_return(SmiTag(result_index));
+ }
+ Bind(&return_minus_1);
+ { f_return(SmiConstant(-1)); }
+ Bind(&zero_length_needle);
+ {
+ Comment("0-length search_string");
+ f_return(SmiTag(IntPtrMin(string_length, start_position)));
+ }
+ Bind(&call_runtime_unchecked);
+ {
+ // Simplified version of the runtime call where the types of the arguments
+ // are already known due to type checks in this stub.
+ Comment("Call Runtime Unchecked");
+ Node* result = CallRuntime(Runtime::kStringIndexOfUnchecked, SmiConstant(0),
+ receiver, search_string, position);
+ f_return(result);
+ }
+}
+
+// ES6 String.prototype.indexOf(searchString [, position])
+// #sec-string.prototype.indexof
+// Unchecked helper for builtins lowering.
+TF_BUILTIN(StringIndexOf, StringBuiltinsAssembler) {
+ Node* receiver = Parameter(0);
+ Node* search_string = Parameter(1);
+ Node* position = Parameter(2);
+
+ Label call_runtime(this);
+
+ Node* instance_type = LoadInstanceType(receiver);
+ Node* search_string_instance_type = LoadInstanceType(search_string);
+
+ StringIndexOf(receiver, instance_type, search_string,
+ search_string_instance_type, position,
+ [this](Node* result) { this->Return(result); });
+}
+
+// ES6 String.prototype.indexOf(searchString [, position])
+// #sec-string.prototype.indexof
TF_BUILTIN(StringPrototypeIndexOf, StringBuiltinsAssembler) {
Variable search_string(this, MachineRepresentation::kTagged),
position(this, MachineRepresentation::kTagged);
@@ -832,67 +922,21 @@ TF_BUILTIN(StringPrototypeIndexOf, StringBuiltinsAssembler) {
Bind(&fast_path);
{
Comment("Fast Path");
- Label zero_length_needle(this);
GotoIf(TaggedIsSmi(receiver), &call_runtime);
Node* needle = search_string.value();
GotoIf(TaggedIsSmi(needle), &call_runtime);
+
Node* instance_type = LoadInstanceType(receiver);
GotoUnless(IsStringInstanceType(instance_type), &call_runtime);
Node* needle_instance_type = LoadInstanceType(needle);
GotoUnless(IsStringInstanceType(needle_instance_type), &call_runtime);
- // At this point we know that the receiver and the needle are Strings and
- // that position is a Smi.
-
- Node* needle_length = SmiUntag(LoadStringLength(needle));
- // Use possibly faster runtime fallback for long search strings.
- GotoIf(IntPtrLessThan(IntPtrConstant(1), needle_length),
- &call_runtime_unchecked);
- Node* string_length = SmiUntag(LoadStringLength(receiver));
- Node* start_position = SmiUntag(position.value());
-
- GotoIf(IntPtrEqual(IntPtrConstant(0), needle_length), &zero_length_needle);
- // Check that the needle fits in the start position.
- GotoUnless(IntPtrLessThanOrEqual(needle_length,
- IntPtrSub(string_length, start_position)),
- &return_minus_1);
- // Only support one-byte strings on the fast path.
- Label check_needle(this), continue_fast_path(this);
- BranchIfSimpleOneByteStringInstanceType(instance_type, &check_needle,
- &call_runtime_unchecked);
- Bind(&check_needle);
- BranchIfSimpleOneByteStringInstanceType(
- needle_instance_type, &continue_fast_path, &call_runtime_unchecked);
- Bind(&continue_fast_path);
- {
- Node* needle_byte =
- ChangeInt32ToIntPtr(LoadOneByteChar(needle, IntPtrConstant(0)));
- Node* start_address = OneByteCharAddress(receiver, start_position);
- Node* search_length = IntPtrSub(string_length, start_position);
- // Call out to the highly optimized memchr to perform the actual byte
- // search.
- Node* memchr =
- ExternalConstant(ExternalReference::libc_memchr_function(isolate()));
- Node* result_address =
- CallCFunction3(MachineType::Pointer(), MachineType::Pointer(),
- MachineType::IntPtr(), MachineType::UintPtr(), memchr,
- start_address, needle_byte, search_length);
- GotoIf(WordEqual(result_address, IntPtrConstant(0)), &return_minus_1);
- Node* result_index =
- IntPtrAdd(IntPtrSub(result_address, start_address), start_position);
- arguments.PopAndReturn(SmiTag(result_index));
- }
- Bind(&zero_length_needle);
- {
- Comment("0-length needle");
- arguments.PopAndReturn(SmiTag(IntPtrMin(string_length, start_position)));
- }
+ StringIndexOf(
+ receiver, instance_type, needle, needle_instance_type, position.value(),
+ [&arguments](Node* result) { arguments.PopAndReturn(result); });
}
- Bind(&return_minus_1);
- { arguments.PopAndReturn(SmiConstant(-1)); }
-
Bind(&call_runtime);
{
Comment("Call Runtime");
@@ -900,17 +944,6 @@ TF_BUILTIN(StringPrototypeIndexOf, StringBuiltinsAssembler) {
search_string.value(), position.value());
arguments.PopAndReturn(result);
}
-
- Bind(&call_runtime_unchecked);
- {
- // Simplified version of the runtime call where the types of the arguments
- // are already known due to type checks in this stub.
- Comment("Call Runtime Unchecked");
- Node* result =
- CallRuntime(Runtime::kStringIndexOfUnchecked, context, receiver,
- search_string.value(), position.value());
- arguments.PopAndReturn(result);
- }
}
// ES6 section 21.1.3.9
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698