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

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

Issue 2630233003: [regexp] Create property on result for each named capture (Closed)
Patch Set: Null proto and remove __proto__ blacklist 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 | « no previous file | src/heap-symbols.h » ('j') | 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 2191268441c92687715ff86cbfecd9774b770ebc..ea1a73ea5e1e29f288a38ceb98462fdb7a1241c3 100644
--- a/src/builtins/builtins-regexp.cc
+++ b/src/builtins/builtins-regexp.cc
@@ -33,8 +33,9 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
void StoreLastIndex(Node* context, Node* regexp, Node* value,
bool is_fastpath);
- Node* ConstructNewResultFromMatchInfo(Node* context, Node* match_info,
- Node* string);
+ Node* ConstructNewResultFromMatchInfo(Node* const context, Node* const regexp,
+ Node* const match_info,
+ Node* const string);
Node* RegExpPrototypeExecBodyWithoutResult(Node* const context,
Node* const regexp,
@@ -141,10 +142,10 @@ void RegExpBuiltinsAssembler::StoreLastIndex(Node* context, Node* regexp,
}
}
-Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(Node* context,
- Node* match_info,
- Node* string) {
- Label out(this);
+Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
+ Node* const context, Node* const regexp, Node* const match_info,
+ Node* const string) {
+ Label named_captures(this), out(this);
Node* const num_indices = SmiUntag(LoadFixedArrayElement(
match_info, RegExpMatchInfo::kNumberOfCapturesIndex));
@@ -164,7 +165,8 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(Node* context,
StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER);
- GotoIf(SmiEqual(num_results, SmiConstant(Smi::FromInt(1))), &out);
+ // If no captures exist we can skip named capture handling as well.
+ GotoIf(SmiEqual(num_results, SmiConstant(1)), &out);
// Store all remaining captures.
Node* const limit = IntPtrAdd(
@@ -187,7 +189,7 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(Node* context,
Node* const start = LoadFixedArrayElement(match_info, from_cursor);
Label next_iter(this);
- GotoIf(SmiEqual(start, SmiConstant(Smi::FromInt(-1))), &next_iter);
+ GotoIf(SmiEqual(start, SmiConstant(-1)), &next_iter);
Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1));
Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1);
@@ -199,7 +201,83 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(Node* context,
Bind(&next_iter);
var_from_cursor.Bind(IntPtrAdd(from_cursor, IntPtrConstant(2)));
var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1)));
- Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out);
+ Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop,
+ &named_captures);
+ }
+
+ Bind(&named_captures);
+ {
+ // We reach this point only if captures exist, implying that this is an
+ // IRREGEXP JSRegExp.
+
+ CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE));
+ CSA_ASSERT(this, SmiGreaterThan(num_results, SmiConstant(1)));
+
+ // Preparations for named capture properties. Exit early if the result does
+ // not have any named captures to minimize performance impact.
+
+ Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset);
+ CSA_ASSERT(this, SmiEqual(LoadFixedArrayElement(data, JSRegExp::kTagIndex),
+ SmiConstant(JSRegExp::IRREGEXP)));
+
+ // The names fixed array associates names at even indices with a capture
+ // index at odd indices.
+ Node* const names =
+ LoadFixedArrayElement(data, JSRegExp::kIrregexpCaptureNameMapIndex);
+ GotoIf(SmiEqual(names, SmiConstant(0)), &out);
+
+ // Allocate a new object to store the named capture properties.
+ // TODO(jgruber): Could be optimized by adding the object map to the heap
+ // root list.
+
+ Node* const native_context = LoadNativeContext(context);
+ Node* const map = LoadContextElement(
+ native_context, Context::SLOW_OBJECT_WITH_NULL_PROTOTYPE_MAP);
+ Node* const properties =
+ AllocateNameDictionary(NameDictionary::kInitialCapacity);
+
+ Node* const group_object = AllocateJSObjectFromMap(map, properties);
+
+ // Store it on the result as a 'group' property.
+
+ {
+ Node* const name = HeapConstant(isolate()->factory()->group_string());
+ CallRuntime(Runtime::kCreateDataProperty, context, result, name,
+ group_object);
+ }
+
+ // One or more named captures exist, add a property for each one.
+
+ CSA_ASSERT(this, HasInstanceType(names, FIXED_ARRAY_TYPE));
+ Node* const names_length = LoadAndUntagFixedArrayBaseLength(names);
+ CSA_ASSERT(this, IntPtrGreaterThan(names_length, IntPtrConstant(0)));
+
+ Variable var_i(this, MachineType::PointerRepresentation());
+ var_i.Bind(IntPtrConstant(0));
+
+ Variable* vars[] = {&var_i};
+ const int vars_count = sizeof(vars) / sizeof(vars[0]);
+ Label loop(this, vars_count, vars);
+
+ Goto(&loop);
+ Bind(&loop);
+ {
+ Node* const i = var_i.value();
+ Node* const i_plus_1 = IntPtrAdd(i, IntPtrConstant(1));
+ Node* const i_plus_2 = IntPtrAdd(i_plus_1, IntPtrConstant(1));
+
+ Node* const name = LoadFixedArrayElement(names, i);
+ Node* const index = LoadFixedArrayElement(names, i_plus_1);
+ Node* const capture =
+ LoadFixedArrayElement(result_elements, SmiUntag(index));
+
+ CallRuntime(Runtime::kCreateDataProperty, context, group_object, name,
+ capture);
+
+ var_i.Bind(i_plus_2);
+ Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out,
+ &loop);
+ }
}
Bind(&out);
@@ -352,7 +430,7 @@ Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBody(Node* const context,
{
Node* const match_indices = indices_or_null;
Node* const result =
- ConstructNewResultFromMatchInfo(context, match_indices, string);
+ ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
var_result.Bind(result);
Goto(&out);
}
@@ -2522,7 +2600,7 @@ TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) {
Bind(&if_matched);
{
Node* result =
- ConstructNewResultFromMatchInfo(context, match_indices, string);
+ ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
Return(result);
}
}
« no previous file with comments | « no previous file | src/heap-symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698