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

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

Issue 2438683005: [regexp] Move RegExp.prototype[@@search] to TF (Closed)
Patch Set: Rename to TryTaggedToFloat64 Created 4 years, 1 month 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
Index: src/builtins/builtins-regexp.cc
diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc
index de2528dc59bfa21c65ba924ae91c64828ad9e7bc..94c0075bf066182620dd81624cba363dadbb516a 100644
--- a/src/builtins/builtins-regexp.cc
+++ b/src/builtins/builtins-regexp.cc
@@ -170,34 +170,45 @@ BUILTIN(RegExpPrototypeCompile) {
namespace {
+compiler::Node* FastLoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
+ compiler::Node* regexp) {
+ // Load the in-object field.
+ static const int field_offset =
+ JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
+ return a->LoadObjectField(regexp, field_offset);
+}
+
+compiler::Node* SlowLoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
+ compiler::Node* regexp) {
+ // Load through the GetProperty stub.
+ typedef compiler::Node Node;
+
+ Node* const name =
+ a->HeapConstant(a->isolate()->factory()->lastIndex_string());
+ Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
+ return a->CallStub(getproperty_callable, context, regexp, name);
+}
+
compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
compiler::Node* has_initialmap,
compiler::Node* regexp) {
typedef CodeStubAssembler::Variable Variable;
typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
Variable var_value(a, MachineRepresentation::kTagged);
- Label out(a), if_unmodified(a), if_modified(a, Label::kDeferred);
+ Label out(a), if_unmodified(a), if_modified(a);
a->Branch(has_initialmap, &if_unmodified, &if_modified);
a->Bind(&if_unmodified);
{
- // Load the in-object field.
- static const int field_offset =
- JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize;
- var_value.Bind(a->LoadObjectField(regexp, field_offset));
+ var_value.Bind(FastLoadLastIndex(a, context, regexp));
a->Goto(&out);
}
a->Bind(&if_modified);
{
- // Load through the GetProperty stub.
- Node* const name =
- a->HeapConstant(a->isolate()->factory()->lastIndex_string());
- Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
- var_value.Bind(a->CallStub(getproperty_callable, context, regexp, name));
+ var_value.Bind(SlowLoadLastIndex(a, context, regexp));
a->Goto(&out);
}
@@ -215,13 +226,25 @@ void FastStoreLastIndex(CodeStubAssembler* a, compiler::Node* context,
a->StoreObjectField(regexp, field_offset, value);
}
+void SlowStoreLastIndex(CodeStubAssembler* a, compiler::Node* context,
+ compiler::Node* regexp, compiler::Node* value) {
+ // Store through runtime.
+ // TODO(ishell): Use SetPropertyStub here once available.
+ typedef compiler::Node Node;
+
+ Node* const name =
+ a->HeapConstant(a->isolate()->factory()->lastIndex_string());
+ Node* const language_mode = a->SmiConstant(Smi::FromInt(STRICT));
+ a->CallRuntime(Runtime::kSetProperty, context, regexp, name, value,
+ language_mode);
+}
+
void StoreLastIndex(CodeStubAssembler* a, compiler::Node* context,
compiler::Node* has_initialmap, compiler::Node* regexp,
compiler::Node* value) {
typedef CodeStubAssembler::Label Label;
- typedef compiler::Node Node;
- Label out(a), if_unmodified(a), if_modified(a, Label::kDeferred);
+ Label out(a), if_unmodified(a), if_modified(a);
a->Branch(has_initialmap, &if_unmodified, &if_modified);
a->Bind(&if_unmodified);
@@ -232,13 +255,7 @@ void StoreLastIndex(CodeStubAssembler* a, compiler::Node* context,
a->Bind(&if_modified);
{
- // Store through runtime.
- // TODO(ishell): Use SetPropertyStub here once available.
- Node* const name =
- a->HeapConstant(a->isolate()->factory()->lastIndex_string());
- Node* const language_mode = a->SmiConstant(Smi::FromInt(STRICT));
- a->CallRuntime(Runtime::kSetProperty, context, regexp, name, value,
- language_mode);
+ SlowStoreLastIndex(a, context, regexp, value);
a->Goto(&out);
}
@@ -1144,55 +1161,155 @@ BUILTIN(RegExpPrototypeMatch) {
// ES#sec-regexp.prototype-@@search
// RegExp.prototype [ @@search ] ( string )
-BUILTIN(RegExpPrototypeSearch) {
- HandleScope scope(isolate);
- CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@search");
+void Builtins::Generate_RegExpPrototypeSearch(CodeStubAssembler* a) {
+ typedef CodeStubAssembler::Label Label;
+ typedef compiler::Node Node;
- Handle<Object> string_obj = args.atOrUndefined(isolate, 1);
+ Isolate* const isolate = a->isolate();
- Handle<String> string;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string,
- Object::ToString(isolate, string_obj));
+ Node* const maybe_receiver = a->Parameter(0);
+ Node* const maybe_string = a->Parameter(1);
+ Node* const context = a->Parameter(4);
- Handle<Object> previous_last_index_obj;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, previous_last_index_obj,
- RegExpUtils::GetLastIndex(isolate, recv));
+ Node* const smi_zero = a->SmiConstant(Smi::kZero);
- if (!previous_last_index_obj->SameValue(Smi::kZero)) {
- RETURN_FAILURE_ON_EXCEPTION(isolate,
- RegExpUtils::SetLastIndex(isolate, recv, 0));
- }
+ // Ensure {maybe_receiver} is a JSReceiver.
+ Node* const map =
+ ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver,
+ MessageTemplate::kIncompatibleMethodReceiver,
+ "RegExp.prototype.@@search");
+ Node* const receiver = maybe_receiver;
- Handle<Object> result;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
- isolate, result,
- RegExpUtils::RegExpExec(isolate, recv, string,
- isolate->factory()->undefined_value()));
-
- Handle<Object> current_last_index_obj;
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, current_last_index_obj,
- RegExpUtils::GetLastIndex(isolate, recv));
-
- const bool is_last_index_unchanged =
- current_last_index_obj->SameValue(*previous_last_index_obj);
- if (!is_last_index_unchanged) {
- if (previous_last_index_obj->IsSmi()) {
- RETURN_FAILURE_ON_EXCEPTION(
- isolate,
- RegExpUtils::SetLastIndex(
- isolate, recv, Smi::cast(*previous_last_index_obj)->value()));
- } else {
- RETURN_FAILURE_ON_EXCEPTION(
- isolate,
- Object::SetProperty(recv, isolate->factory()->lastIndex_string(),
- previous_last_index_obj, STRICT));
+ // Convert {maybe_string} to a String.
+ Node* const string = a->ToString(context, maybe_string);
+
+ Label fast_path(a), slow_path(a);
+ BranchIfFastPath(a, context, map, &fast_path, &slow_path);
+
+ a->Bind(&fast_path);
+ {
+ // Grab the initial value of last index.
+ Node* const previous_last_index = FastLoadLastIndex(a, context, receiver);
Igor Sheludko 2016/11/11 16:13:21 Given that the only difference between fast and sl
jgruber 2016/11/13 13:00:09 That helper function exists and is used elsewhere
Igor Sheludko 2016/11/13 18:27:59 I meant something like this: BranchIfFastPath(..
jgruber 2016/11/15 10:02:29 Done.
+
+ // Ensure last index is 0.
+ {
+ Label next(a);
+ a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next);
Igor Sheludko 2016/11/11 16:13:20 According to my understanding of a spec we must al
jgruber 2016/11/13 13:00:09 Changes to @@search are about to be merged into th
Igor Sheludko 2016/11/13 18:27:59 Ah. Sorry, I didn't notice that. But still the id
jgruber 2016/11/15 10:02:29 Done.
Yang 2016/11/15 13:03:43 Yeah. I agree. Always writing zero avoids the comp
+
+ FastStoreLastIndex(a, context, receiver, smi_zero);
+ a->Goto(&next);
+
+ a->Bind(&next);
+ }
+
+ // Call exec.
+ Node* const match_indices = RegExpExec(a, context, receiver, string);
+
+ // Reset last index if necessary.
+ {
+ Label next(a);
+
+ Node* const current_last_index = FastLoadLastIndex(a, context, receiver);
+
+ a->GotoIf(a->SameValue(current_last_index, previous_last_index, context),
Igor Sheludko 2016/11/11 16:13:20 Same here.
jgruber 2016/11/13 13:00:09 See above.
+ &next);
+
+ FastStoreLastIndex(a, context, receiver, previous_last_index);
+ a->Goto(&next);
+
+ a->Bind(&next);
+ }
+
+ // Return -1 if no match was found.
+ {
+ Label next(a);
+ a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next);
+ a->Return(a->SmiConstant(Smi::FromInt(-1)));
Igor Sheludko 2016/11/11 16:13:20 SmiConstant(-1)
jgruber 2016/11/13 13:00:09 Nice, is this a recent change? Will fix.
Igor Sheludko 2016/11/13 18:27:59 Yes.
jgruber 2016/11/15 10:02:29 Done.
+ a->Bind(&next);
+ }
+
+ // Return the index of the match.
+ {
+ Label fast_result(a), slow_result(a, Label::kDeferred);
+
+ Node* const native_context = a->LoadNativeContext(context);
+ Node* const initial_regexp_result_map = a->LoadContextElement(
+ native_context, Context::REGEXP_RESULT_MAP_INDEX);
+ Node* const match_indices_map = a->LoadMap(match_indices);
+
+ a->Branch(a->WordEqual(match_indices_map, initial_regexp_result_map),
+ &fast_result, &slow_result);
+
+ a->Bind(&fast_result);
+ {
+ Node* const index =
+ a->LoadObjectField(match_indices, JSRegExpResult::kIndexOffset,
+ MachineType::AnyTagged());
+ a->Return(index);
+ }
+
+ a->Bind(&slow_result);
+ {
+ Node* const name = a->HeapConstant(isolate->factory()->index_string());
+ Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
+ Node* const index =
+ a->CallStub(getproperty_callable, context, match_indices, name);
+ a->Return(index);
+ }
}
}
- if (result->IsNull(isolate)) return Smi::FromInt(-1);
+ a->Bind(&slow_path);
+ {
+ // Grab the initial value of last index.
+ Node* const previous_last_index = SlowLoadLastIndex(a, context, receiver);
+
+ // Ensure last index is 0.
+ {
+ Label next(a);
+ a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next);
Igor Sheludko 2016/11/11 16:13:21 According to my understanding of a spec we must al
jgruber 2016/11/13 13:00:09 See above.
+
+ SlowStoreLastIndex(a, context, receiver, smi_zero);
+ a->Goto(&next);
+
+ a->Bind(&next);
+ }
+
+ // Call exec.
+ Node* const match_indices = RegExpExec(a, context, receiver, string);
+
+ // Reset last index if necessary.
+ {
+ Label next(a);
+
+ Node* const current_last_index = SlowLoadLastIndex(a, context, receiver);
- RETURN_RESULT_OR_FAILURE(
- isolate, Object::GetProperty(result, isolate->factory()->index_string()));
+ a->GotoIf(a->SameValue(current_last_index, previous_last_index, context),
Igor Sheludko 2016/11/11 16:13:21 Same here.
jgruber 2016/11/13 13:00:09 See above.
+ &next);
+
+ SlowStoreLastIndex(a, context, receiver, previous_last_index);
+ a->Goto(&next);
+
+ a->Bind(&next);
+ }
+
+ // Return -1 if no match was found.
+ {
+ Label next(a);
+ a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next);
+ a->Return(a->SmiConstant(Smi::FromInt(-1)));
+ a->Bind(&next);
+ }
+
+ // Return the index of the match.
Igor Sheludko 2016/11/11 16:13:20 I guess in this case the match_indices could still
jgruber 2016/11/13 13:00:09 Yes, but I decided against complicating the implem
Igor Sheludko 2016/11/13 18:27:59 Maybe if you follow the GenerateXYZBody idea menti
jgruber 2016/11/15 10:02:29 Done.
+ {
+ Node* const name = a->HeapConstant(isolate->factory()->index_string());
+ Callable getproperty_callable = CodeFactory::GetProperty(a->isolate());
+ Node* const index =
+ a->CallStub(getproperty_callable, context, match_indices, name);
+ a->Return(index);
+ }
+ }
}
namespace {
« no previous file with comments | « src/builtins/builtins.h ('k') | src/code-stub-assembler.h » ('j') | src/code-stub-assembler.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698