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

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

Issue 2752143003: [regexp] Remove remainder of native RegExpExecStub (Closed)
Patch Set: Update comments Created 3 years, 8 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
OLDNEW
1 // Copyright 2017 the V8 project authors. All rights reserved. 1 // Copyright 2017 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-regexp-gen.h" 5 #include "src/builtins/builtins-regexp-gen.h"
6 6
7 #include "src/builtins/builtins-constructor-gen.h" 7 #include "src/builtins/builtins-constructor-gen.h"
8 #include "src/builtins/builtins-utils-gen.h" 8 #include "src/builtins/builtins-utils-gen.h"
9 #include "src/builtins/builtins.h" 9 #include "src/builtins/builtins.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 224
225 Node* const from_offset = ElementOffsetFromIndex( 225 Node* const from_offset = ElementOffsetFromIndex(
226 IntPtrAdd(offset, last_index), kind, INTPTR_PARAMETERS); 226 IntPtrAdd(offset, last_index), kind, INTPTR_PARAMETERS);
227 var_string_start->Bind(IntPtrAdd(string_data, from_offset)); 227 var_string_start->Bind(IntPtrAdd(string_data, from_offset));
228 228
229 Node* const to_offset = ElementOffsetFromIndex( 229 Node* const to_offset = ElementOffsetFromIndex(
230 IntPtrAdd(offset, string_length), kind, INTPTR_PARAMETERS); 230 IntPtrAdd(offset, string_length), kind, INTPTR_PARAMETERS);
231 var_string_end->Bind(IntPtrAdd(string_data, to_offset)); 231 var_string_end->Bind(IntPtrAdd(string_data, to_offset));
232 } 232 }
233 233
234 Node* RegExpBuiltinsAssembler::IrregexpExec(Node* const context, 234 Node* RegExpBuiltinsAssembler::RegExpExecInternal(Node* const context,
235 Node* const regexp, 235 Node* const regexp,
236 Node* const string, 236 Node* const string,
237 Node* const last_index, 237 Node* const last_index,
238 Node* const match_info) { 238 Node* const match_info) {
239 // Just jump directly to runtime if native RegExp is not selected at compile 239 // Just jump directly to runtime if native RegExp is not selected at compile
240 // time or if regexp entry in generated code is turned off runtime switch or 240 // time or if regexp entry in generated code is turned off runtime switch or
241 // at compilation. 241 // at compilation.
242 #ifdef V8_INTERPRETED_REGEXP 242 #ifdef V8_INTERPRETED_REGEXP
243 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index, 243 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index,
244 match_info); 244 match_info);
245 #else // V8_INTERPRETED_REGEXP 245 #else // V8_INTERPRETED_REGEXP
246 CSA_ASSERT(this, TaggedIsNotSmi(regexp)); 246 CSA_ASSERT(this, TaggedIsNotSmi(regexp));
247 CSA_ASSERT(this, IsJSRegExp(regexp)); 247 CSA_ASSERT(this, IsJSRegExp(regexp));
248 248
249 CSA_ASSERT(this, TaggedIsNotSmi(string)); 249 CSA_ASSERT(this, TaggedIsNotSmi(string));
250 CSA_ASSERT(this, IsString(string)); 250 CSA_ASSERT(this, IsString(string));
251 251
252 CSA_ASSERT(this, IsNumber(last_index)); 252 CSA_ASSERT(this, IsNumber(last_index));
253 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info))); 253 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info)));
254 254
255 Node* const int_zero = IntPtrConstant(0); 255 Node* const int_zero = IntPtrConstant(0);
256 256
257 ToDirectStringAssembler to_direct(state(), string); 257 ToDirectStringAssembler to_direct(state(), string);
258 258
259 VARIABLE(var_result, MachineRepresentation::kTagged); 259 VARIABLE(var_result, MachineRepresentation::kTagged);
260 Label out(this), runtime(this, Label::kDeferred); 260 Label out(this), runtime(this, Label::kDeferred);
261 261
262 // External constants. 262 // External constants.
263 Node* const isolate_address =
264 ExternalConstant(ExternalReference::isolate_address(isolate()));
265 Node* const regexp_stack_memory_address_address = ExternalConstant(
266 ExternalReference::address_of_regexp_stack_memory_address(isolate()));
263 Node* const regexp_stack_memory_size_address = ExternalConstant( 267 Node* const regexp_stack_memory_size_address = ExternalConstant(
264 ExternalReference::address_of_regexp_stack_memory_size(isolate())); 268 ExternalReference::address_of_regexp_stack_memory_size(isolate()));
265 Node* const static_offsets_vector_address = ExternalConstant( 269 Node* const static_offsets_vector_address = ExternalConstant(
266 ExternalReference::address_of_static_offsets_vector(isolate())); 270 ExternalReference::address_of_static_offsets_vector(isolate()));
267 Node* const pending_exception_address = ExternalConstant(
268 ExternalReference(Isolate::kPendingExceptionAddress, isolate()));
269 271
270 // Ensure that a RegExp stack is allocated. 272 // Ensure that a RegExp stack is allocated.
271 { 273 {
272 Node* const stack_size = 274 Node* const stack_size =
273 Load(MachineType::IntPtr(), regexp_stack_memory_size_address); 275 Load(MachineType::IntPtr(), regexp_stack_memory_size_address);
274 GotoIf(IntPtrEqual(stack_size, int_zero), &runtime); 276 GotoIf(IntPtrEqual(stack_size, int_zero), &runtime);
275 } 277 }
276 278
277 Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset); 279 Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset);
278 { 280 {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
354 356
355 Node* const code = var_code.value(); 357 Node* const code = var_code.value();
356 GotoIf(TaggedIsSmi(code), &runtime); 358 GotoIf(TaggedIsSmi(code), &runtime);
357 CSA_ASSERT(this, HasInstanceType(code, CODE_TYPE)); 359 CSA_ASSERT(this, HasInstanceType(code, CODE_TYPE));
358 360
359 Label if_success(this), if_failure(this), 361 Label if_success(this), if_failure(this),
360 if_exception(this, Label::kDeferred); 362 if_exception(this, Label::kDeferred);
361 { 363 {
362 IncrementCounter(isolate()->counters()->regexp_entry_native(), 1); 364 IncrementCounter(isolate()->counters()->regexp_entry_native(), 1);
363 365
364 Callable exec_callable = CodeFactory::RegExpExec(isolate()); 366 // Set up args for the final call into generated Irregexp code.
365 Node* const result = CallStub( 367
366 exec_callable, context, string, TruncateWordToWord32(int_last_index), 368 MachineType type_int32 = MachineType::Int32();
367 var_string_start.value(), var_string_end.value(), code); 369 MachineType type_tagged = MachineType::AnyTagged();
370 MachineType type_ptr = MachineType::Pointer();
371
372 // Result: A NativeRegExpMacroAssembler::Result return code.
373 MachineType retval_type = type_int32;
374
375 // Argument 0: Original subject string.
376 MachineType arg0_type = type_tagged;
377 Node* const arg0 = string;
378
379 // Argument 1: Previous index.
380 MachineType arg1_type = type_int32;
381 Node* const arg1 = TruncateWordToWord32(int_last_index);
382
383 // Argument 2: Start of string data.
384 // Argument 3: End of string data.
Igor Sheludko 2017/04/20 15:08:07 I'd move this comment down.
jgruber 2017/04/21 10:42:33 Done.
385 MachineType arg2_type = type_ptr;
386 Node* const arg2 = var_string_start.value();
387
388 MachineType arg3_type = type_ptr;
389 Node* const arg3 = var_string_end.value();
390
391 // Argument 4: static offsets vector buffer.
392 MachineType arg4_type = type_ptr;
393 Node* const arg4 = static_offsets_vector_address;
394
395 // Argument 5: Set the number of capture registers to zero to force global
396 // regexps to behave as non-global. This does not affect non-global
397 // regexps.
398 MachineType arg5_type = type_int32;
399 Node* const arg5 = Int32Constant(0);
400
401 // Argument 6: Start (high end) of backtracking stack memory area.
402 Node* const stack_start =
403 Load(MachineType::Pointer(), regexp_stack_memory_address_address);
404 Node* const stack_size =
405 Load(MachineType::IntPtr(), regexp_stack_memory_size_address);
406 Node* const stack_end = IntPtrAdd(stack_start, stack_size);
407
408 MachineType arg6_type = type_ptr;
409 Node* const arg6 = stack_end;
410
411 // Argument 7: Indicate that this is a direct call from JavaScript.
412 MachineType arg7_type = type_int32;
413 Node* const arg7 = Int32Constant(1);
414
415 // Argument 8: Pass current isolate address.
416 MachineType arg8_type = type_ptr;
417 Node* const arg8 = isolate_address;
418
419 Node* const code_entry =
420 IntPtrAdd(BitcastTaggedToWord(code),
421 IntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
422
423 Node* const result = CallCFunction9(
424 retval_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
425 arg5_type, arg6_type, arg7_type, arg8_type, code_entry, arg0, arg1,
426 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
368 427
369 // Check the result. 428 // Check the result.
370 // We expect exactly one result since the stub forces the called regexp to 429 // We expect exactly one result since we force the called regexp to behave
371 // behave as non-global. 430 // as non-global.
372 GotoIf(SmiEqual(result, SmiConstant(1)), &if_success); 431 Node* const int_result = ChangeInt32ToIntPtr(result);
373 GotoIf(SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::FAILURE)), 432 GotoIf(IntPtrEqual(int_result, IntPtrConstant(1)), &if_success);
Igor Sheludko 2017/04/20 15:08:07 s/1/NativeRegExpMacroAssembler::SUCCESS/
jgruber 2017/04/21 10:42:33 Done.
433 GotoIf(IntPtrEqual(int_result,
434 IntPtrConstant(NativeRegExpMacroAssembler::FAILURE)),
374 &if_failure); 435 &if_failure);
375 GotoIf(SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::EXCEPTION)), 436 GotoIf(IntPtrEqual(int_result,
437 IntPtrConstant(NativeRegExpMacroAssembler::EXCEPTION)),
376 &if_exception); 438 &if_exception);
377 439
378 CSA_ASSERT( 440 CSA_ASSERT(this,
379 this, SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::RETRY))); 441 IntPtrEqual(int_result,
442 IntPtrConstant(NativeRegExpMacroAssembler::RETRY)));
380 Goto(&runtime); 443 Goto(&runtime);
381 } 444 }
382 445
383 BIND(&if_success); 446 BIND(&if_success);
384 { 447 {
385 // Check that the last match info has space for the capture registers and 448 // Check that the last match info has space for the capture registers and
386 // the additional information. Ensure no overflow in add. 449 // the additional information. Ensure no overflow in add.
387 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 450 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
388 Node* const available_slots = 451 Node* const available_slots =
389 SmiSub(LoadFixedArrayBaseLength(match_info), 452 SmiSub(LoadFixedArrayBaseLength(match_info),
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 } 496 }
434 497
435 BIND(&if_failure); 498 BIND(&if_failure);
436 { 499 {
437 var_result.Bind(NullConstant()); 500 var_result.Bind(NullConstant());
438 Goto(&out); 501 Goto(&out);
439 } 502 }
440 503
441 BIND(&if_exception); 504 BIND(&if_exception);
442 { 505 {
443 Node* const pending_exception = 506 // A stack overflow was detected in RegExp code.
444 Load(MachineType::AnyTagged(), pending_exception_address); 507 Node* const pending_exception_address = ExternalConstant(
445 508 ExternalReference(Isolate::kPendingExceptionAddress, isolate()));
446 // If there is no pending exception, a 509 CSA_ASSERT(this, IsTheHole(Load(MachineType::AnyTagged(),
447 // stack overflow (on the backtrack stack) was detected in RegExp code. 510 pending_exception_address)));
448 511 USE(pending_exception_address);
Igor Sheludko 2017/04/20 15:08:07 I'd wrap this block in #ifdef DEBUG/#endif instead
jgruber 2017/04/21 10:42:33 Done.
449 Label stack_overflow(this), rethrow(this);
450 Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow);
451
452 BIND(&stack_overflow);
453 CallRuntime(Runtime::kThrowStackOverflow, context); 512 CallRuntime(Runtime::kThrowStackOverflow, context);
454 Unreachable(); 513 Unreachable();
455
456 BIND(&rethrow);
457 CallRuntime(Runtime::kRegExpExecReThrow, context);
458 Unreachable();
459 } 514 }
460 515
461 BIND(&runtime); 516 BIND(&runtime);
462 { 517 {
463 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp, 518 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp,
464 string, last_index, match_info); 519 string, last_index, match_info);
465 var_result.Bind(result); 520 var_result.Bind(result);
466 Goto(&out); 521 Goto(&out);
467 } 522 }
468 523
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 Node* match_indices; 619 Node* match_indices;
565 Label successful_match(this); 620 Label successful_match(this);
566 BIND(&run_exec); 621 BIND(&run_exec);
567 { 622 {
568 // Get last match info from the context. 623 // Get last match info from the context.
569 Node* const native_context = LoadNativeContext(context); 624 Node* const native_context = LoadNativeContext(context);
570 Node* const last_match_info = LoadContextElement( 625 Node* const last_match_info = LoadContextElement(
571 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 626 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
572 627
573 // Call the exec stub. 628 // Call the exec stub.
574 match_indices = IrregexpExec(context, regexp, string, var_lastindex.value(), 629 match_indices = RegExpExecInternal(context, regexp, string,
575 last_match_info); 630 var_lastindex.value(), last_match_info);
576 var_result.Bind(match_indices); 631 var_result.Bind(match_indices);
577 632
578 // {match_indices} is either null or the RegExpMatchInfo array. 633 // {match_indices} is either null or the RegExpMatchInfo array.
579 // Return early if exec failed, possibly updating last index. 634 // Return early if exec failed, possibly updating last index.
580 GotoIfNot(WordEqual(match_indices, null), &successful_match); 635 GotoIfNot(WordEqual(match_indices, null), &successful_match);
581 636
582 GotoIfNot(should_update_last_index, if_didnotmatch); 637 GotoIfNot(should_update_last_index, if_didnotmatch);
583 638
584 StoreLastIndex(context, regexp, smi_zero, is_fastpath); 639 StoreLastIndex(context, regexp, smi_zero, is_fastpath);
585 Goto(if_didnotmatch); 640 Goto(if_didnotmatch);
(...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after
2097 // array depending on whether the {regexp} matches. 2152 // array depending on whether the {regexp} matches.
2098 { 2153 {
2099 Label next(this), if_stringisempty(this, Label::kDeferred); 2154 Label next(this), if_stringisempty(this, Label::kDeferred);
2100 Branch(SmiEqual(string_length, smi_zero), &if_stringisempty, &next); 2155 Branch(SmiEqual(string_length, smi_zero), &if_stringisempty, &next);
2101 2156
2102 BIND(&if_stringisempty); 2157 BIND(&if_stringisempty);
2103 { 2158 {
2104 Node* const last_match_info = LoadContextElement( 2159 Node* const last_match_info = LoadContextElement(
2105 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 2160 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
2106 2161
2107 Node* const match_indices = 2162 Node* const match_indices = RegExpExecInternal(context, regexp, string,
2108 IrregexpExec(context, regexp, string, smi_zero, last_match_info); 2163 smi_zero, last_match_info);
2109 2164
2110 Label return_singleton_array(this); 2165 Label return_singleton_array(this);
2111 Branch(WordEqual(match_indices, null), &return_singleton_array, 2166 Branch(WordEqual(match_indices, null), &return_singleton_array,
2112 &return_empty_array); 2167 &return_empty_array);
2113 2168
2114 BIND(&return_singleton_array); 2169 BIND(&return_singleton_array);
2115 { 2170 {
2116 Node* const length = SmiConstant(1); 2171 Node* const length = SmiConstant(1);
2117 Node* const capacity = IntPtrConstant(1); 2172 Node* const capacity = IntPtrConstant(1);
2118 Node* const result = AllocateJSArray(kind, array_map, capacity, length, 2173 Node* const result = AllocateJSArray(kind, array_map, capacity, length,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2159 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out, 2214 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out,
2160 &next); 2215 &next);
2161 BIND(&next); 2216 BIND(&next);
2162 } 2217 }
2163 2218
2164 // Search for the given {regexp}. 2219 // Search for the given {regexp}.
2165 2220
2166 Node* const last_match_info = LoadContextElement( 2221 Node* const last_match_info = LoadContextElement(
2167 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 2222 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
2168 2223
2169 Node* const match_indices = IrregexpExec(context, regexp, string, 2224 Node* const match_indices = RegExpExecInternal(
2170 next_search_from, last_match_info); 2225 context, regexp, string, next_search_from, last_match_info);
2171 2226
2172 // We're done if no match was found. 2227 // We're done if no match was found.
2173 { 2228 {
2174 Label next(this); 2229 Label next(this);
2175 Branch(WordEqual(match_indices, null), &push_suffix_and_out, &next); 2230 Branch(WordEqual(match_indices, null), &push_suffix_and_out, &next);
2176 BIND(&next); 2231 BIND(&next);
2177 } 2232 }
2178 2233
2179 Node* const match_from = LoadFixedArrayElement( 2234 Node* const match_from = LoadFixedArrayElement(
2180 match_indices, RegExpMatchInfo::kFirstCaptureIndex); 2235 match_indices, RegExpMatchInfo::kFirstCaptureIndex);
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after
2841 Node* const null = NullConstant(); 2896 Node* const null = NullConstant();
2842 Node* const smi_zero = SmiConstant(0); 2897 Node* const smi_zero = SmiConstant(0);
2843 2898
2844 CSA_ASSERT(this, IsJSRegExp(regexp)); 2899 CSA_ASSERT(this, IsJSRegExp(regexp));
2845 CSA_ASSERT(this, IsString(string)); 2900 CSA_ASSERT(this, IsString(string));
2846 2901
2847 Node* const native_context = LoadNativeContext(context); 2902 Node* const native_context = LoadNativeContext(context);
2848 Node* const internal_match_info = LoadContextElement( 2903 Node* const internal_match_info = LoadContextElement(
2849 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); 2904 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
2850 2905
2851 Node* const match_indices = 2906 Node* const match_indices = RegExpExecInternal(context, regexp, string,
2852 IrregexpExec(context, regexp, string, smi_zero, internal_match_info); 2907 smi_zero, internal_match_info);
2853 2908
2854 Label if_matched(this), if_didnotmatch(this); 2909 Label if_matched(this), if_didnotmatch(this);
2855 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 2910 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
2856 2911
2857 BIND(&if_didnotmatch); 2912 BIND(&if_didnotmatch);
2858 Return(null); 2913 Return(null);
2859 2914
2860 BIND(&if_matched); 2915 BIND(&if_matched);
2861 { 2916 {
2862 Node* result = 2917 Node* result =
2863 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2918 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2864 Return(result); 2919 Return(result);
2865 } 2920 }
2866 } 2921 }
2867 2922
2868 } // namespace internal 2923 } // namespace internal
2869 } // namespace v8 2924 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698