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

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

Issue 2543483003: [regexp] Skip result construction in test, @@match, @@search (Closed)
Patch Set: Remove unused variables Created 4 years 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/builtins-regexp.cc
diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc
index fe12bfce32ba8c18cee908442f2d1301e75fc82a..4c137647ca53786c11ea38ae025432ebf7895548 100644
--- a/src/builtins/builtins-regexp.cc
+++ b/src/builtins/builtins-regexp.cc
@@ -226,22 +226,26 @@ void StoreLastIndex(CodeStubAssembler* a, Node* context, Node* regexp,
}
}
+Node* LoadMatchInfoField(CodeStubAssembler* a, Node* const match_info,
+ const int index) {
+ const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
+ Node* const result =
+ a->LoadFixedArrayElement(match_info, a->IntPtrConstant(index), 0, mode);
+ return result;
+}
+
Node* ConstructNewResultFromMatchInfo(Isolate* isolate, CodeStubAssembler* a,
Node* context, Node* match_info,
Node* string) {
CLabel out(a);
- ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
- Node* const num_indices = a->SmiUntag(a->LoadFixedArrayElement(
- match_info, a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0,
- mode));
+ Node* const num_indices = a->SmiUntag(LoadMatchInfoField(
+ a, match_info, RegExpMatchInfo::kNumberOfCapturesIndex));
Node* const num_results = a->SmiTag(a->WordShr(num_indices, 1));
- Node* const start = a->LoadFixedArrayElement(
- match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), 0,
- mode);
- Node* const end = a->LoadFixedArrayElement(
- match_info, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0,
- mode);
+ Node* const start =
+ LoadMatchInfoField(a, match_info, RegExpMatchInfo::kFirstCaptureIndex);
+ Node* const end = LoadMatchInfoField(a, match_info,
+ RegExpMatchInfo::kFirstCaptureIndex + 1);
// Calculate the substring of the first match before creating the result array
// to avoid an unnecessary write barrier storing the first result.
@@ -416,9 +420,8 @@ Node* RegExpPrototypeExecBodyWithoutResult(
a->GotoUnless(should_update_last_index, &out);
// Update the new last index from {match_indices}.
- Node* const new_lastindex = a->LoadFixedArrayElement(
- match_indices,
- a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1));
+ Node* const new_lastindex = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1);
StoreLastIndex(a, context, regexp, new_lastindex, is_fastpath);
a->Goto(&out);
@@ -461,10 +464,6 @@ Node* RegExpPrototypeExecBody(CodeStubAssembler* a, Node* const context,
return var_result.value();
}
-} // namespace
-
-namespace {
-
Node* ThrowIfNotJSReceiver(CodeStubAssembler* a, Isolate* isolate,
Node* context, Node* value,
MessageTemplate::Template msg_template,
@@ -1135,21 +1134,38 @@ void Builtins::Generate_RegExpPrototypeTest(CodeAssemblerState* state) {
Node* const context = a.Parameter(4);
// Ensure {maybe_receiver} is a JSReceiver.
- ThrowIfNotJSReceiver(&a, isolate, context, maybe_receiver,
- MessageTemplate::kIncompatibleMethodReceiver,
- "RegExp.prototype.test");
+ Node* const map = ThrowIfNotJSReceiver(
+ &a, isolate, context, maybe_receiver,
+ MessageTemplate::kIncompatibleMethodReceiver, "RegExp.prototype.test");
Node* const receiver = maybe_receiver;
// Convert {maybe_string} to a String.
Node* const string = a.ToString(context, maybe_string);
- // Call exec.
- Node* const match_indices = RegExpExec(&a, context, receiver, string);
+ CLabel fast_path(&a), slow_path(&a);
+ BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
+
+ a.Bind(&fast_path);
+ {
+ CLabel if_didnotmatch(&a);
+ RegExpPrototypeExecBodyWithoutResult(&a, context, receiver, string,
+ &if_didnotmatch, true);
+ a.Return(a.TrueConstant());
+
+ a.Bind(&if_didnotmatch);
+ a.Return(a.FalseConstant());
+ }
+
+ a.Bind(&slow_path);
+ {
+ // Call exec.
+ Node* const match_indices = RegExpExec(&a, context, receiver, string);
- // Return true iff exec matched successfully.
- Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()),
- a.FalseConstant(), a.TrueConstant());
- a.Return(result);
+ // Return true iff exec matched successfully.
+ Node* const result = a.Select(a.WordEqual(match_indices, a.NullConstant()),
+ a.FalseConstant(), a.TrueConstant());
+ a.Return(result);
+ }
}
namespace {
@@ -1319,10 +1335,9 @@ class GrowableFixedArray {
CVariable var_capacity_;
};
-void Generate_RegExpPrototypeMatchBody(CodeStubAssembler* a,
- Node* const receiver, Node* const string,
- Node* const context,
- const bool is_fastpath) {
+void RegExpPrototypeMatchBody(CodeStubAssembler* a, Node* const receiver,
+ Node* const string, Node* const context,
+ const bool is_fastpath) {
Isolate* const isolate = a->isolate();
Node* const null = a->NullConstant();
@@ -1365,45 +1380,39 @@ void Generate_RegExpPrototypeMatchBody(CodeStubAssembler* a,
a->Bind(&loop);
{
- Node* const result = is_fastpath ? RegExpPrototypeExecBody(
- a, context, regexp, string, true)
- : RegExpExec(a, context, regexp, string);
+ CVariable var_match(a, MachineRepresentation::kTagged);
CLabel if_didmatch(a), if_didnotmatch(a);
- a->Branch(a->WordEqual(result, null), &if_didnotmatch, &if_didmatch);
+ if (is_fastpath) {
+ // On the fast path, grab the matching string from the raw match index
+ // array.
+ Node* const match_indices = RegExpPrototypeExecBodyWithoutResult(
+ a, context, regexp, string, &if_didnotmatch, true);
- a->Bind(&if_didnotmatch);
- {
- // Return null if there were no matches, otherwise just exit the loop.
- a->GotoUnless(a->IntPtrEqual(array.length(), int_zero), &out);
- a->Return(null);
- }
+ Node* const match_from = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kFirstCaptureIndex);
+ Node* const match_to = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1);
- a->Bind(&if_didmatch);
- {
- Node* match = nullptr;
- if (is_fastpath) {
- // TODO(jgruber): We could optimize further here and in other
- // methods (e.g. @@search) by bypassing RegExp result construction.
- Node* const result_fixed_array = a->LoadElements(result);
- const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
- match =
- a->LoadFixedArrayElement(result_fixed_array, int_zero, 0, mode);
-
- // The match is guaranteed to be a string on the fast path.
- CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match)));
- } else {
- DCHECK(!is_fastpath);
-
- CVariable var_match(a, MachineRepresentation::kTagged);
- CLabel fast_result(a), slow_result(a), match_loaded(a);
+ Node* match = a->SubString(context, string, match_from, match_to);
+ var_match.Bind(match);
+
+ a->Goto(&if_didmatch);
+ } else {
+ DCHECK(!is_fastpath);
+ Node* const result = RegExpExec(a, context, regexp, string);
+
+ CLabel load_match(a);
+ a->Branch(a->WordEqual(result, null), &if_didnotmatch, &load_match);
+
+ a->Bind(&load_match);
+ {
+ CLabel fast_result(a), slow_result(a);
BranchIfFastRegExpResult(a, context, a->LoadMap(result), &fast_result,
&slow_result);
a->Bind(&fast_result);
{
- // TODO(jgruber): We could optimize further here and in other
- // methods (e.g. @@search) by bypassing RegExp result construction.
Node* const result_fixed_array = a->LoadElements(result);
const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
Node* const match =
@@ -1413,7 +1422,7 @@ void Generate_RegExpPrototypeMatchBody(CodeStubAssembler* a,
CSA_ASSERT(a, a->IsStringInstanceType(a->LoadInstanceType(match)));
var_match.Bind(match);
- a->Goto(&match_loaded);
+ a->Goto(&if_didmatch);
}
a->Bind(&slow_result);
@@ -1424,14 +1433,22 @@ void Generate_RegExpPrototypeMatchBody(CodeStubAssembler* a,
Node* const match =
a->CallStub(getproperty_callable, context, result, name);
- var_match.Bind(match);
- a->Goto(&match_loaded);
+ var_match.Bind(a->ToString(context, match));
+ a->Goto(&if_didmatch);
}
-
- a->Bind(&match_loaded);
- match = a->ToString(context, var_match.value());
}
- DCHECK(match != nullptr);
+ }
+
+ a->Bind(&if_didnotmatch);
+ {
+ // Return null if there were no matches, otherwise just exit the loop.
+ a->GotoUnless(a->IntPtrEqual(array.length(), int_zero), &out);
+ a->Return(null);
+ }
+
+ a->Bind(&if_didmatch);
+ {
+ Node* match = var_match.value();
// Store the match, growing the fixed array if needed.
@@ -1490,30 +1507,57 @@ void Builtins::Generate_RegExpPrototypeMatch(CodeAssemblerState* state) {
BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
a.Bind(&fast_path);
- Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, true);
+ RegExpPrototypeMatchBody(&a, receiver, string, context, true);
a.Bind(&slow_path);
- Generate_RegExpPrototypeMatchBody(&a, receiver, string, context, false);
+ RegExpPrototypeMatchBody(&a, receiver, string, context, false);
}
namespace {
-void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
- Node* const receiver,
- Node* const string, Node* const context,
- bool is_fastpath) {
+void RegExpPrototypeSearchBodyFast(CodeStubAssembler* a, Node* const receiver,
+ Node* const string, Node* const context) {
+ // Grab the initial value of last index.
+ Node* const previous_last_index = FastLoadLastIndex(a, receiver);
+
+ // Ensure last index is 0.
+ FastStoreLastIndex(a, receiver, a->SmiConstant(Smi::kZero));
+
+ // Call exec.
+ CLabel if_didnotmatch(a);
+ Node* const match_indices = RegExpPrototypeExecBodyWithoutResult(
+ a, context, receiver, string, &if_didnotmatch, true);
+
+ // Successful match.
+ {
+ // Reset last index.
+ FastStoreLastIndex(a, receiver, previous_last_index);
+
+ // Return the index of the match.
+ Node* const index = LoadMatchInfoField(a, match_indices,
+ RegExpMatchInfo::kFirstCaptureIndex);
+ a->Return(index);
+ }
+
+ a->Bind(&if_didnotmatch);
+ {
+ // Reset last index and return -1.
+ FastStoreLastIndex(a, receiver, previous_last_index);
+ a->Return(a->SmiConstant(-1));
+ }
+}
+
+void RegExpPrototypeSearchBodySlow(CodeStubAssembler* a, Node* const receiver,
+ Node* const string, Node* const context) {
Isolate* const isolate = a->isolate();
Node* const smi_zero = a->SmiConstant(Smi::kZero);
// Grab the initial value of last index.
- Node* const previous_last_index =
- LoadLastIndex(a, context, receiver, is_fastpath);
+ Node* const previous_last_index = SlowLoadLastIndex(a, context, receiver);
// Ensure last index is 0.
- if (is_fastpath) {
- FastStoreLastIndex(a, receiver, smi_zero);
- } else {
+ {
CLabel next(a);
a->GotoIf(a->SameValue(previous_last_index, smi_zero, context), &next);
@@ -1523,14 +1567,10 @@ void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
}
// Call exec.
- Node* const match_indices =
- is_fastpath ? RegExpPrototypeExecBody(a, context, receiver, string, true)
- : RegExpExec(a, context, receiver, string);
+ Node* const exec_result = RegExpExec(a, context, receiver, string);
// Reset last index if necessary.
- if (is_fastpath) {
- FastStoreLastIndex(a, receiver, previous_last_index);
- } else {
+ {
CLabel next(a);
Node* const current_last_index = SlowLoadLastIndex(a, context, receiver);
@@ -1539,34 +1579,28 @@ void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
SlowStoreLastIndex(a, context, receiver, previous_last_index);
a->Goto(&next);
+
a->Bind(&next);
}
// Return -1 if no match was found.
{
CLabel next(a);
- a->GotoUnless(a->WordEqual(match_indices, a->NullConstant()), &next);
+ a->GotoUnless(a->WordEqual(exec_result, a->NullConstant()), &next);
a->Return(a->SmiConstant(-1));
a->Bind(&next);
}
// Return the index of the match.
- if (is_fastpath) {
- Node* const index = a->LoadObjectField(
- match_indices, JSRegExpResult::kIndexOffset, MachineType::AnyTagged());
- a->Return(index);
- } else {
- DCHECK(!is_fastpath);
-
+ {
CLabel fast_result(a), slow_result(a, CLabel::kDeferred);
- BranchIfFastRegExpResult(a, context, a->LoadMap(match_indices),
- &fast_result, &slow_result);
+ BranchIfFastRegExpResult(a, context, a->LoadMap(exec_result), &fast_result,
+ &slow_result);
a->Bind(&fast_result);
{
Node* const index =
- a->LoadObjectField(match_indices, JSRegExpResult::kIndexOffset,
- MachineType::AnyTagged());
+ a->LoadObjectField(exec_result, JSRegExpResult::kIndexOffset);
a->Return(index);
}
@@ -1575,7 +1609,7 @@ void Generate_RegExpPrototypeSearchBody(CodeStubAssembler* a,
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->CallStub(getproperty_callable, context, exec_result, name);
a->Return(index);
}
}
@@ -1608,10 +1642,10 @@ void Builtins::Generate_RegExpPrototypeSearch(CodeAssemblerState* state) {
BranchIfFastPath(&a, context, map, &fast_path, &slow_path);
a.Bind(&fast_path);
- Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, true);
+ RegExpPrototypeSearchBodyFast(&a, receiver, string, context);
a.Bind(&slow_path);
- Generate_RegExpPrototypeSearchBody(&a, receiver, string, context, false);
+ RegExpPrototypeSearchBodySlow(&a, receiver, string, context);
}
namespace {
@@ -1729,9 +1763,8 @@ void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp,
a->Bind(&next);
}
- Node* const match_from = a->LoadFixedArrayElement(
- match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
- 0, mode);
+ Node* const match_from = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kFirstCaptureIndex);
// We're done if the match starts beyond the string.
{
@@ -1741,9 +1774,8 @@ void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp,
a->Bind(&next);
}
- Node* const match_to = a->LoadFixedArrayElement(
- match_indices,
- a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
+ Node* const match_to = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1);
// Advance index and continue if the match is empty.
{
@@ -1774,9 +1806,8 @@ void Generate_RegExpPrototypeSplitBody(CodeStubAssembler* a, Node* const regexp,
// Add all captures to the array.
{
- Node* const num_registers = a->LoadFixedArrayElement(
- match_indices,
- a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
+ Node* const num_registers = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kNumberOfCapturesIndex);
Node* const int_num_registers = a->SmiUntag(num_registers);
CVariable var_reg(a, MachineType::PointerRepresentation());
@@ -1994,10 +2025,8 @@ Node* ReplaceGlobalCallableFastPath(CodeStubAssembler* a, Node* context,
Node* const res_elems = a->LoadElements(res);
CSA_ASSERT(a, a->HasInstanceType(res_elems, FIXED_ARRAY_TYPE));
- ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
- Node* const num_capture_registers = a->LoadFixedArrayElement(
- last_match_info,
- a->IntPtrConstant(RegExpMatchInfo::kNumberOfCapturesIndex), 0, mode);
+ Node* const num_capture_registers = LoadMatchInfoField(
+ a, last_match_info, RegExpMatchInfo::kNumberOfCapturesIndex);
CLabel if_hasexplicitcaptures(a), if_noexplicitcaptures(a), create_result(a);
a->Branch(a->SmiEqual(num_capture_registers, a->SmiConstant(Smi::FromInt(2))),
@@ -2211,15 +2240,11 @@ Node* ReplaceSimpleStringFastPath(CodeStubAssembler* a, Node* context,
a->Bind(&if_matched);
{
- ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
-
Node* const subject_start = smi_zero;
- Node* const match_start = a->LoadFixedArrayElement(
- match_indices, a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex),
- 0, mode);
- Node* const match_end = a->LoadFixedArrayElement(
- match_indices,
- a->IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 1), 0, mode);
+ Node* const match_start = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kFirstCaptureIndex);
+ Node* const match_end = LoadMatchInfoField(
+ a, match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1);
Node* const subject_end = a->LoadStringLength(subject_string);
CLabel if_replaceisempty(a), if_replaceisnotempty(a);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698