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

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

Issue 2827243005: Revert of [regexp] Remove remainder of native RegExpExecStub (Closed)
Patch Set: 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
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | src/code-factory.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 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::RegExpExecInternal(Node* const context, 234 Node* RegExpBuiltinsAssembler::IrregexpExec(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()));
267 Node* const regexp_stack_memory_size_address = ExternalConstant( 263 Node* const regexp_stack_memory_size_address = ExternalConstant(
268 ExternalReference::address_of_regexp_stack_memory_size(isolate())); 264 ExternalReference::address_of_regexp_stack_memory_size(isolate()));
269 Node* const static_offsets_vector_address = ExternalConstant( 265 Node* const static_offsets_vector_address = ExternalConstant(
270 ExternalReference::address_of_static_offsets_vector(isolate())); 266 ExternalReference::address_of_static_offsets_vector(isolate()));
267 Node* const pending_exception_address = ExternalConstant(
268 ExternalReference(Isolate::kPendingExceptionAddress, isolate()));
271 269
272 // Ensure that a RegExp stack is allocated. 270 // Ensure that a RegExp stack is allocated.
273 { 271 {
274 Node* const stack_size = 272 Node* const stack_size =
275 Load(MachineType::IntPtr(), regexp_stack_memory_size_address); 273 Load(MachineType::IntPtr(), regexp_stack_memory_size_address);
276 GotoIf(IntPtrEqual(stack_size, int_zero), &runtime); 274 GotoIf(IntPtrEqual(stack_size, int_zero), &runtime);
277 } 275 }
278 276
279 Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset); 277 Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset);
280 { 278 {
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 354
357 Node* const code = var_code.value(); 355 Node* const code = var_code.value();
358 GotoIf(TaggedIsSmi(code), &runtime); 356 GotoIf(TaggedIsSmi(code), &runtime);
359 CSA_ASSERT(this, HasInstanceType(code, CODE_TYPE)); 357 CSA_ASSERT(this, HasInstanceType(code, CODE_TYPE));
360 358
361 Label if_success(this), if_failure(this), 359 Label if_success(this), if_failure(this),
362 if_exception(this, Label::kDeferred); 360 if_exception(this, Label::kDeferred);
363 { 361 {
364 IncrementCounter(isolate()->counters()->regexp_entry_native(), 1); 362 IncrementCounter(isolate()->counters()->regexp_entry_native(), 1);
365 363
366 // Set up args for the final call into generated Irregexp code. 364 Callable exec_callable = CodeFactory::RegExpExec(isolate());
367 365 Node* const result = CallStub(
368 MachineType type_int32 = MachineType::Int32(); 366 exec_callable, context, string, TruncateWordToWord32(int_last_index),
369 MachineType type_tagged = MachineType::AnyTagged(); 367 var_string_start.value(), var_string_end.value(), code);
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 MachineType arg2_type = type_ptr;
385 Node* const arg2 = var_string_start.value();
386
387 // Argument 3: End of string data.
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);
427 368
428 // Check the result. 369 // Check the result.
429 // We expect exactly one result since we force the called regexp to behave 370 // We expect exactly one result since the stub forces the called regexp to
430 // as non-global. 371 // behave as non-global.
431 Node* const int_result = ChangeInt32ToIntPtr(result); 372 GotoIf(SmiEqual(result, SmiConstant(1)), &if_success);
432 GotoIf(IntPtrEqual(int_result, 373 GotoIf(SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::FAILURE)),
433 IntPtrConstant(NativeRegExpMacroAssembler::SUCCESS)),
434 &if_success);
435 GotoIf(IntPtrEqual(int_result,
436 IntPtrConstant(NativeRegExpMacroAssembler::FAILURE)),
437 &if_failure); 374 &if_failure);
438 GotoIf(IntPtrEqual(int_result, 375 GotoIf(SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::EXCEPTION)),
439 IntPtrConstant(NativeRegExpMacroAssembler::EXCEPTION)),
440 &if_exception); 376 &if_exception);
441 377
442 CSA_ASSERT(this, 378 CSA_ASSERT(
443 IntPtrEqual(int_result, 379 this, SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::RETRY)));
444 IntPtrConstant(NativeRegExpMacroAssembler::RETRY)));
445 Goto(&runtime); 380 Goto(&runtime);
446 } 381 }
447 382
448 BIND(&if_success); 383 BIND(&if_success);
449 { 384 {
450 // Check that the last match info has space for the capture registers and 385 // Check that the last match info has space for the capture registers and
451 // the additional information. Ensure no overflow in add. 386 // the additional information. Ensure no overflow in add.
452 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 387 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
453 Node* const available_slots = 388 Node* const available_slots =
454 SmiSub(LoadFixedArrayBaseLength(match_info), 389 SmiSub(LoadFixedArrayBaseLength(match_info),
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 } 433 }
499 434
500 BIND(&if_failure); 435 BIND(&if_failure);
501 { 436 {
502 var_result.Bind(NullConstant()); 437 var_result.Bind(NullConstant());
503 Goto(&out); 438 Goto(&out);
504 } 439 }
505 440
506 BIND(&if_exception); 441 BIND(&if_exception);
507 { 442 {
508 // A stack overflow was detected in RegExp code. 443 Node* const pending_exception =
509 #ifdef DEBUG 444 Load(MachineType::AnyTagged(), pending_exception_address);
510 Node* const pending_exception_address = ExternalConstant( 445
511 ExternalReference(Isolate::kPendingExceptionAddress, isolate())); 446 // If there is no pending exception, a
512 CSA_ASSERT(this, IsTheHole(Load(MachineType::AnyTagged(), 447 // stack overflow (on the backtrack stack) was detected in RegExp code.
513 pending_exception_address))); 448
514 #endif // DEBUG 449 Label stack_overflow(this), rethrow(this);
450 Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow);
451
452 BIND(&stack_overflow);
515 CallRuntime(Runtime::kThrowStackOverflow, context); 453 CallRuntime(Runtime::kThrowStackOverflow, context);
516 Unreachable(); 454 Unreachable();
455
456 BIND(&rethrow);
457 CallRuntime(Runtime::kRegExpExecReThrow, context);
458 Unreachable();
517 } 459 }
518 460
519 BIND(&runtime); 461 BIND(&runtime);
520 { 462 {
521 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp, 463 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp,
522 string, last_index, match_info); 464 string, last_index, match_info);
523 var_result.Bind(result); 465 var_result.Bind(result);
524 Goto(&out); 466 Goto(&out);
525 } 467 }
526 468
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 Node* match_indices; 564 Node* match_indices;
623 Label successful_match(this); 565 Label successful_match(this);
624 BIND(&run_exec); 566 BIND(&run_exec);
625 { 567 {
626 // Get last match info from the context. 568 // Get last match info from the context.
627 Node* const native_context = LoadNativeContext(context); 569 Node* const native_context = LoadNativeContext(context);
628 Node* const last_match_info = LoadContextElement( 570 Node* const last_match_info = LoadContextElement(
629 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 571 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
630 572
631 // Call the exec stub. 573 // Call the exec stub.
632 match_indices = RegExpExecInternal(context, regexp, string, 574 match_indices = IrregexpExec(context, regexp, string, var_lastindex.value(),
633 var_lastindex.value(), last_match_info); 575 last_match_info);
634 var_result.Bind(match_indices); 576 var_result.Bind(match_indices);
635 577
636 // {match_indices} is either null or the RegExpMatchInfo array. 578 // {match_indices} is either null or the RegExpMatchInfo array.
637 // Return early if exec failed, possibly updating last index. 579 // Return early if exec failed, possibly updating last index.
638 GotoIfNot(WordEqual(match_indices, null), &successful_match); 580 GotoIfNot(WordEqual(match_indices, null), &successful_match);
639 581
640 GotoIfNot(should_update_last_index, if_didnotmatch); 582 GotoIfNot(should_update_last_index, if_didnotmatch);
641 583
642 StoreLastIndex(context, regexp, smi_zero, is_fastpath); 584 StoreLastIndex(context, regexp, smi_zero, is_fastpath);
643 Goto(if_didnotmatch); 585 Goto(if_didnotmatch);
(...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after
2155 // array depending on whether the {regexp} matches. 2097 // array depending on whether the {regexp} matches.
2156 { 2098 {
2157 Label next(this), if_stringisempty(this, Label::kDeferred); 2099 Label next(this), if_stringisempty(this, Label::kDeferred);
2158 Branch(SmiEqual(string_length, smi_zero), &if_stringisempty, &next); 2100 Branch(SmiEqual(string_length, smi_zero), &if_stringisempty, &next);
2159 2101
2160 BIND(&if_stringisempty); 2102 BIND(&if_stringisempty);
2161 { 2103 {
2162 Node* const last_match_info = LoadContextElement( 2104 Node* const last_match_info = LoadContextElement(
2163 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 2105 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
2164 2106
2165 Node* const match_indices = RegExpExecInternal(context, regexp, string, 2107 Node* const match_indices =
2166 smi_zero, last_match_info); 2108 IrregexpExec(context, regexp, string, smi_zero, last_match_info);
2167 2109
2168 Label return_singleton_array(this); 2110 Label return_singleton_array(this);
2169 Branch(WordEqual(match_indices, null), &return_singleton_array, 2111 Branch(WordEqual(match_indices, null), &return_singleton_array,
2170 &return_empty_array); 2112 &return_empty_array);
2171 2113
2172 BIND(&return_singleton_array); 2114 BIND(&return_singleton_array);
2173 { 2115 {
2174 Node* const length = SmiConstant(1); 2116 Node* const length = SmiConstant(1);
2175 Node* const capacity = IntPtrConstant(1); 2117 Node* const capacity = IntPtrConstant(1);
2176 Node* const result = AllocateJSArray(kind, array_map, capacity, length, 2118 Node* const result = AllocateJSArray(kind, array_map, capacity, length,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2217 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out, 2159 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out,
2218 &next); 2160 &next);
2219 BIND(&next); 2161 BIND(&next);
2220 } 2162 }
2221 2163
2222 // Search for the given {regexp}. 2164 // Search for the given {regexp}.
2223 2165
2224 Node* const last_match_info = LoadContextElement( 2166 Node* const last_match_info = LoadContextElement(
2225 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 2167 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
2226 2168
2227 Node* const match_indices = RegExpExecInternal( 2169 Node* const match_indices = IrregexpExec(context, regexp, string,
2228 context, regexp, string, next_search_from, last_match_info); 2170 next_search_from, last_match_info);
2229 2171
2230 // We're done if no match was found. 2172 // We're done if no match was found.
2231 { 2173 {
2232 Label next(this); 2174 Label next(this);
2233 Branch(WordEqual(match_indices, null), &push_suffix_and_out, &next); 2175 Branch(WordEqual(match_indices, null), &push_suffix_and_out, &next);
2234 BIND(&next); 2176 BIND(&next);
2235 } 2177 }
2236 2178
2237 Node* const match_from = LoadFixedArrayElement( 2179 Node* const match_from = LoadFixedArrayElement(
2238 match_indices, RegExpMatchInfo::kFirstCaptureIndex); 2180 match_indices, RegExpMatchInfo::kFirstCaptureIndex);
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after
2899 Node* const null = NullConstant(); 2841 Node* const null = NullConstant();
2900 Node* const smi_zero = SmiConstant(0); 2842 Node* const smi_zero = SmiConstant(0);
2901 2843
2902 CSA_ASSERT(this, IsJSRegExp(regexp)); 2844 CSA_ASSERT(this, IsJSRegExp(regexp));
2903 CSA_ASSERT(this, IsString(string)); 2845 CSA_ASSERT(this, IsString(string));
2904 2846
2905 Node* const native_context = LoadNativeContext(context); 2847 Node* const native_context = LoadNativeContext(context);
2906 Node* const internal_match_info = LoadContextElement( 2848 Node* const internal_match_info = LoadContextElement(
2907 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); 2849 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
2908 2850
2909 Node* const match_indices = RegExpExecInternal(context, regexp, string, 2851 Node* const match_indices =
2910 smi_zero, internal_match_info); 2852 IrregexpExec(context, regexp, string, smi_zero, internal_match_info);
2911 2853
2912 Label if_matched(this), if_didnotmatch(this); 2854 Label if_matched(this), if_didnotmatch(this);
2913 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 2855 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
2914 2856
2915 BIND(&if_didnotmatch); 2857 BIND(&if_didnotmatch);
2916 Return(null); 2858 Return(null);
2917 2859
2918 BIND(&if_matched); 2860 BIND(&if_matched);
2919 { 2861 {
2920 Node* result = 2862 Node* result =
2921 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2863 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2922 Return(result); 2864 Return(result);
2923 } 2865 }
2924 } 2866 }
2925 2867
2926 } // namespace internal 2868 } // namespace internal
2927 } // namespace v8 2869 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | src/code-factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698