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

Side by Side Diff: src/builtins/builtins-regexp.cc

Issue 2639403008: Revert of [regexp] Create property on result for each named capture (Closed)
Patch Set: 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 unified diff | Download patch
« no previous file with comments | « no previous file | src/heap-symbols.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/builtins/builtins-constructor.h" 5 #include "src/builtins/builtins-constructor.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 #include "src/builtins/builtins.h" 7 #include "src/builtins/builtins.h"
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 #include "src/code-stub-assembler.h" 9 #include "src/code-stub-assembler.h"
10 #include "src/regexp/jsregexp.h" 10 #include "src/regexp/jsregexp.h"
(...skipping 15 matching lines...) Expand all
26 protected: 26 protected:
27 Node* FastLoadLastIndex(Node* regexp); 27 Node* FastLoadLastIndex(Node* regexp);
28 Node* SlowLoadLastIndex(Node* context, Node* regexp); 28 Node* SlowLoadLastIndex(Node* context, Node* regexp);
29 Node* LoadLastIndex(Node* context, Node* regexp, bool is_fastpath); 29 Node* LoadLastIndex(Node* context, Node* regexp, bool is_fastpath);
30 30
31 void FastStoreLastIndex(Node* regexp, Node* value); 31 void FastStoreLastIndex(Node* regexp, Node* value);
32 void SlowStoreLastIndex(Node* context, Node* regexp, Node* value); 32 void SlowStoreLastIndex(Node* context, Node* regexp, Node* value);
33 void StoreLastIndex(Node* context, Node* regexp, Node* value, 33 void StoreLastIndex(Node* context, Node* regexp, Node* value,
34 bool is_fastpath); 34 bool is_fastpath);
35 35
36 Node* ConstructNewResultFromMatchInfo(Node* const context, Node* const regexp, 36 Node* ConstructNewResultFromMatchInfo(Node* context, Node* match_info,
37 Node* const match_info, 37 Node* string);
38 Node* const string);
39 38
40 Node* RegExpPrototypeExecBodyWithoutResult(Node* const context, 39 Node* RegExpPrototypeExecBodyWithoutResult(Node* const context,
41 Node* const regexp, 40 Node* const regexp,
42 Node* const string, 41 Node* const string,
43 Label* if_didnotmatch, 42 Label* if_didnotmatch,
44 const bool is_fastpath); 43 const bool is_fastpath);
45 Node* RegExpPrototypeExecBody(Node* const context, Node* const regexp, 44 Node* RegExpPrototypeExecBody(Node* const context, Node* const regexp,
46 Node* const string, const bool is_fastpath); 45 Node* const string, const bool is_fastpath);
47 46
48 Node* ThrowIfNotJSReceiver(Node* context, Node* maybe_receiver, 47 Node* ThrowIfNotJSReceiver(Node* context, Node* maybe_receiver,
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 134
136 void RegExpBuiltinsAssembler::StoreLastIndex(Node* context, Node* regexp, 135 void RegExpBuiltinsAssembler::StoreLastIndex(Node* context, Node* regexp,
137 Node* value, bool is_fastpath) { 136 Node* value, bool is_fastpath) {
138 if (is_fastpath) { 137 if (is_fastpath) {
139 FastStoreLastIndex(regexp, value); 138 FastStoreLastIndex(regexp, value);
140 } else { 139 } else {
141 SlowStoreLastIndex(context, regexp, value); 140 SlowStoreLastIndex(context, regexp, value);
142 } 141 }
143 } 142 }
144 143
145 Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( 144 Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(Node* context,
146 Node* const context, Node* const regexp, Node* const match_info, 145 Node* match_info,
147 Node* const string) { 146 Node* string) {
148 Label named_captures(this), out(this); 147 Label out(this);
149 148
150 Node* const num_indices = SmiUntag(LoadFixedArrayElement( 149 Node* const num_indices = SmiUntag(LoadFixedArrayElement(
151 match_info, RegExpMatchInfo::kNumberOfCapturesIndex)); 150 match_info, RegExpMatchInfo::kNumberOfCapturesIndex));
152 Node* const num_results = SmiTag(WordShr(num_indices, 1)); 151 Node* const num_results = SmiTag(WordShr(num_indices, 1));
153 Node* const start = 152 Node* const start =
154 LoadFixedArrayElement(match_info, RegExpMatchInfo::kFirstCaptureIndex); 153 LoadFixedArrayElement(match_info, RegExpMatchInfo::kFirstCaptureIndex);
155 Node* const end = LoadFixedArrayElement( 154 Node* const end = LoadFixedArrayElement(
156 match_info, RegExpMatchInfo::kFirstCaptureIndex + 1); 155 match_info, RegExpMatchInfo::kFirstCaptureIndex + 1);
157 156
158 // Calculate the substring of the first match before creating the result array 157 // Calculate the substring of the first match before creating the result array
159 // to avoid an unnecessary write barrier storing the first result. 158 // to avoid an unnecessary write barrier storing the first result.
160 Node* const first = SubString(context, string, start, end); 159 Node* const first = SubString(context, string, start, end);
161 160
162 Node* const result = 161 Node* const result =
163 AllocateRegExpResult(context, num_results, start, string); 162 AllocateRegExpResult(context, num_results, start, string);
164 Node* const result_elements = LoadElements(result); 163 Node* const result_elements = LoadElements(result);
165 164
166 StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER); 165 StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER);
167 166
168 // If no captures exist we can skip named capture handling as well. 167 GotoIf(SmiEqual(num_results, SmiConstant(Smi::FromInt(1))), &out);
169 GotoIf(SmiEqual(num_results, SmiConstant(1)), &out);
170 168
171 // Store all remaining captures. 169 // Store all remaining captures.
172 Node* const limit = IntPtrAdd( 170 Node* const limit = IntPtrAdd(
173 IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices); 171 IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices);
174 172
175 Variable var_from_cursor(this, MachineType::PointerRepresentation()); 173 Variable var_from_cursor(this, MachineType::PointerRepresentation());
176 Variable var_to_cursor(this, MachineType::PointerRepresentation()); 174 Variable var_to_cursor(this, MachineType::PointerRepresentation());
177 175
178 var_from_cursor.Bind(IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2)); 176 var_from_cursor.Bind(IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2));
179 var_to_cursor.Bind(IntPtrConstant(1)); 177 var_to_cursor.Bind(IntPtrConstant(1));
180 178
181 Variable* vars[] = {&var_from_cursor, &var_to_cursor}; 179 Variable* vars[] = {&var_from_cursor, &var_to_cursor};
182 Label loop(this, 2, vars); 180 Label loop(this, 2, vars);
183 181
184 Goto(&loop); 182 Goto(&loop);
185 Bind(&loop); 183 Bind(&loop);
186 { 184 {
187 Node* const from_cursor = var_from_cursor.value(); 185 Node* const from_cursor = var_from_cursor.value();
188 Node* const to_cursor = var_to_cursor.value(); 186 Node* const to_cursor = var_to_cursor.value();
189 Node* const start = LoadFixedArrayElement(match_info, from_cursor); 187 Node* const start = LoadFixedArrayElement(match_info, from_cursor);
190 188
191 Label next_iter(this); 189 Label next_iter(this);
192 GotoIf(SmiEqual(start, SmiConstant(-1)), &next_iter); 190 GotoIf(SmiEqual(start, SmiConstant(Smi::FromInt(-1))), &next_iter);
193 191
194 Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1)); 192 Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1));
195 Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1); 193 Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1);
196 194
197 Node* const capture = SubString(context, string, start, end); 195 Node* const capture = SubString(context, string, start, end);
198 StoreFixedArrayElement(result_elements, to_cursor, capture); 196 StoreFixedArrayElement(result_elements, to_cursor, capture);
199 Goto(&next_iter); 197 Goto(&next_iter);
200 198
201 Bind(&next_iter); 199 Bind(&next_iter);
202 var_from_cursor.Bind(IntPtrAdd(from_cursor, IntPtrConstant(2))); 200 var_from_cursor.Bind(IntPtrAdd(from_cursor, IntPtrConstant(2)));
203 var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1))); 201 var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1)));
204 Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, 202 Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, &out);
205 &named_captures);
206 }
207
208 Bind(&named_captures);
209 {
210 // We reach this point only if captures exist, implying that this is an
211 // IRREGEXP JSRegExp.
212
213 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE));
214 CSA_ASSERT(this, SmiGreaterThan(num_results, SmiConstant(1)));
215
216 // Preparations for named capture properties. Exit early if the result does
217 // not have any named captures to minimize performance impact.
218
219 Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset);
220 CSA_ASSERT(this, SmiEqual(LoadFixedArrayElement(data, JSRegExp::kTagIndex),
221 SmiConstant(JSRegExp::IRREGEXP)));
222
223 // The names fixed array associates names at even indices with a capture
224 // index at odd indices.
225 Node* const names =
226 LoadFixedArrayElement(data, JSRegExp::kIrregexpCaptureNameMapIndex);
227 GotoIf(SmiEqual(names, SmiConstant(0)), &out);
228
229 // Allocate a new object to store the named capture properties.
230 // TODO(jgruber): Could be optimized by adding the object map to the heap
231 // root list.
232
233 Node* const native_context = LoadNativeContext(context);
234 Node* const object_function =
235 LoadContextElement(native_context, Context::OBJECT_FUNCTION_INDEX);
236 Node* const object_function_map = LoadObjectField(
237 object_function, JSFunction::kPrototypeOrInitialMapOffset);
238
239 Node* const group_object = AllocateJSObjectFromMap(object_function_map);
240
241 // Store it on the result as a 'group' property.
242
243 {
244 Node* const name = HeapConstant(isolate()->factory()->group_string());
245 Node* const language_mode = SmiConstant(Smi::FromInt(STRICT));
246 CallRuntime(Runtime::kSetProperty, context, result, name, group_object,
247 language_mode);
248 }
249
250 // One or more named captures exist, add a property for each one.
251
252 CSA_ASSERT(this, HasInstanceType(names, FIXED_ARRAY_TYPE));
253 Node* const names_length = LoadAndUntagFixedArrayBaseLength(names);
254 CSA_ASSERT(this, IntPtrGreaterThan(names_length, IntPtrConstant(0)));
255
256 Variable var_i(this, MachineType::PointerRepresentation());
257 var_i.Bind(IntPtrConstant(0));
258
259 Variable* vars[] = {&var_i};
260 const int vars_count = sizeof(vars) / sizeof(vars[0]);
261 Label loop(this, vars_count, vars);
262
263 Goto(&loop);
264 Bind(&loop);
265 {
266 Node* const i = var_i.value();
267 Node* const i_plus_1 = IntPtrAdd(i, IntPtrConstant(1));
268 Node* const i_plus_2 = IntPtrAdd(i_plus_1, IntPtrConstant(1));
269
270 Node* const name = LoadFixedArrayElement(names, i);
271 Node* const index = LoadFixedArrayElement(names, i_plus_1);
272 Node* const capture =
273 LoadFixedArrayElement(result_elements, SmiUntag(index));
274
275 Node* const language_mode = SmiConstant(Smi::FromInt(STRICT));
276 CallRuntime(Runtime::kSetProperty, context, group_object, name, capture,
277 language_mode);
278
279 var_i.Bind(i_plus_2);
280 Branch(IntPtrGreaterThanOrEqual(var_i.value(), names_length), &out,
281 &loop);
282 }
283 } 203 }
284 204
285 Bind(&out); 205 Bind(&out);
286 return result; 206 return result;
287 } 207 }
288 208
289 // ES#sec-regexp.prototype.exec 209 // ES#sec-regexp.prototype.exec
290 // RegExp.prototype.exec ( string ) 210 // RegExp.prototype.exec ( string )
291 // Implements the core of RegExp.prototype.exec but without actually 211 // Implements the core of RegExp.prototype.exec but without actually
292 // constructing the JSRegExpResult. Returns either null (if the RegExp did not 212 // constructing the JSRegExpResult. Returns either null (if the RegExp did not
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 Variable var_result(this, MachineRepresentation::kTagged); 345 Variable var_result(this, MachineRepresentation::kTagged);
426 346
427 Label if_didnotmatch(this), out(this); 347 Label if_didnotmatch(this), out(this);
428 Node* const indices_or_null = RegExpPrototypeExecBodyWithoutResult( 348 Node* const indices_or_null = RegExpPrototypeExecBodyWithoutResult(
429 context, regexp, string, &if_didnotmatch, is_fastpath); 349 context, regexp, string, &if_didnotmatch, is_fastpath);
430 350
431 // Successful match. 351 // Successful match.
432 { 352 {
433 Node* const match_indices = indices_or_null; 353 Node* const match_indices = indices_or_null;
434 Node* const result = 354 Node* const result =
435 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 355 ConstructNewResultFromMatchInfo(context, match_indices, string);
436 var_result.Bind(result); 356 var_result.Bind(result);
437 Goto(&out); 357 Goto(&out);
438 } 358 }
439 359
440 Bind(&if_didnotmatch); 360 Bind(&if_didnotmatch);
441 { 361 {
442 var_result.Bind(null); 362 var_result.Bind(null);
443 Goto(&out); 363 Goto(&out);
444 } 364 }
445 365
(...skipping 2149 matching lines...) Expand 10 before | Expand all | Expand 10 after
2595 2515
2596 Label if_matched(this), if_didnotmatch(this); 2516 Label if_matched(this), if_didnotmatch(this);
2597 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 2517 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
2598 2518
2599 Bind(&if_didnotmatch); 2519 Bind(&if_didnotmatch);
2600 Return(null); 2520 Return(null);
2601 2521
2602 Bind(&if_matched); 2522 Bind(&if_matched);
2603 { 2523 {
2604 Node* result = 2524 Node* result =
2605 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2525 ConstructNewResultFromMatchInfo(context, match_indices, string);
2606 Return(result); 2526 Return(result);
2607 } 2527 }
2608 } 2528 }
2609 2529
2610 } // namespace internal 2530 } // namespace internal
2611 } // namespace v8 2531 } // namespace v8
OLDNEW
« 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