Chromium Code Reviews| Index: src/builtins/builtins-regexp.cc |
| diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc |
| index 2191268441c92687715ff86cbfecd9774b770ebc..229cd5d3d84931f0507f531fa900831db9a14558 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,7 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(Node* context, |
| StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER); |
| - GotoIf(SmiEqual(num_results, SmiConstant(Smi::FromInt(1))), &out); |
| + GotoIf(SmiEqual(num_results, SmiConstant(1)), &named_captures); |
| // Store all remaining captures. |
| Node* const limit = IntPtrAdd( |
| @@ -187,7 +188,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 +200,60 @@ 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); |
| + { |
| + // Preparations for named capture properties. Exit early if the result is |
| + // either not an IRREGEXP or does not have any named captures to minimize |
| + // performance impact. |
| + |
| + CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); |
| + Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset); |
|
jgruber
2017/01/17 09:26:51
This unconditionally adds two loads and two branch
Yang
2017/01/18 13:25:36
I think we can already make this a bit simpler: we
jgruber
2017/01/19 15:59:12
Very good point, done.
|
| + Node* const tag = LoadFixedArrayElement(data, JSRegExp::kTagIndex); |
| + GotoUnless(SmiEqual(tag, SmiConstant(JSRegExp::IRREGEXP)), &out); |
| + |
| + // 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); |
| + |
| + // 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)); |
| + |
| + Node* const language_mode = SmiConstant(Smi::FromInt(STRICT)); |
| + CallRuntime(Runtime::kSetProperty, context, result, name, capture, |
| + language_mode); |
| + |
| + var_i.Bind(i_plus_2); |
| + Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out, |
| + &loop); |
| + } |
| } |
| Bind(&out); |
| @@ -352,7 +406,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 +2576,7 @@ TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { |
| Bind(&if_matched); |
| { |
| Node* result = |
| - ConstructNewResultFromMatchInfo(context, match_indices, string); |
| + ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
| Return(result); |
| } |
| } |