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

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

Issue 2752143003: [regexp] Remove remainder of native RegExpExecStub (Closed)
Patch Set: Fix non-sim arm64 and mips builds 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::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 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);
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,
433 IntPtrConstant(NativeRegExpMacroAssembler::SUCCESS)),
434 &if_success);
435 GotoIf(IntPtrEqual(int_result,
436 IntPtrConstant(NativeRegExpMacroAssembler::FAILURE)),
374 &if_failure); 437 &if_failure);
375 GotoIf(SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::EXCEPTION)), 438 GotoIf(IntPtrEqual(int_result,
439 IntPtrConstant(NativeRegExpMacroAssembler::EXCEPTION)),
376 &if_exception); 440 &if_exception);
377 441
378 CSA_ASSERT( 442 CSA_ASSERT(this,
379 this, SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::RETRY))); 443 IntPtrEqual(int_result,
444 IntPtrConstant(NativeRegExpMacroAssembler::RETRY)));
380 Goto(&runtime); 445 Goto(&runtime);
381 } 446 }
382 447
383 BIND(&if_success); 448 BIND(&if_success);
384 { 449 {
385 // Check that the last match info has space for the capture registers and 450 // Check that the last match info has space for the capture registers and
386 // the additional information. Ensure no overflow in add. 451 // the additional information. Ensure no overflow in add.
387 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset); 452 STATIC_ASSERT(FixedArray::kMaxLength < kMaxInt - FixedArray::kLengthOffset);
388 Node* const available_slots = 453 Node* const available_slots =
389 SmiSub(LoadFixedArrayBaseLength(match_info), 454 SmiSub(LoadFixedArrayBaseLength(match_info),
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 } 498 }
434 499
435 BIND(&if_failure); 500 BIND(&if_failure);
436 { 501 {
437 var_result.Bind(NullConstant()); 502 var_result.Bind(NullConstant());
438 Goto(&out); 503 Goto(&out);
439 } 504 }
440 505
441 BIND(&if_exception); 506 BIND(&if_exception);
442 { 507 {
443 Node* const pending_exception = 508 // A stack overflow was detected in RegExp code.
444 Load(MachineType::AnyTagged(), pending_exception_address); 509 #ifdef DEBUG
445 510 Node* const pending_exception_address = ExternalConstant(
446 // If there is no pending exception, a 511 ExternalReference(Isolate::kPendingExceptionAddress, isolate()));
447 // stack overflow (on the backtrack stack) was detected in RegExp code. 512 CSA_ASSERT(this, IsTheHole(Load(MachineType::AnyTagged(),
448 513 pending_exception_address)));
449 Label stack_overflow(this), rethrow(this); 514 #endif // DEBUG
450 Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow);
451
452 BIND(&stack_overflow);
453 CallRuntime(Runtime::kThrowStackOverflow, context); 515 CallRuntime(Runtime::kThrowStackOverflow, context);
454 Unreachable(); 516 Unreachable();
455
456 BIND(&rethrow);
457 CallRuntime(Runtime::kRegExpExecReThrow, context);
458 Unreachable();
459 } 517 }
460 518
461 BIND(&runtime); 519 BIND(&runtime);
462 { 520 {
463 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp, 521 Node* const result = CallRuntime(Runtime::kRegExpExec, context, regexp,
464 string, last_index, match_info); 522 string, last_index, match_info);
465 var_result.Bind(result); 523 var_result.Bind(result);
466 Goto(&out); 524 Goto(&out);
467 } 525 }
468 526
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 Node* match_indices; 622 Node* match_indices;
565 Label successful_match(this); 623 Label successful_match(this);
566 BIND(&run_exec); 624 BIND(&run_exec);
567 { 625 {
568 // Get last match info from the context. 626 // Get last match info from the context.
569 Node* const native_context = LoadNativeContext(context); 627 Node* const native_context = LoadNativeContext(context);
570 Node* const last_match_info = LoadContextElement( 628 Node* const last_match_info = LoadContextElement(
571 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 629 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
572 630
573 // Call the exec stub. 631 // Call the exec stub.
574 match_indices = IrregexpExec(context, regexp, string, var_lastindex.value(), 632 match_indices = RegExpExecInternal(context, regexp, string,
575 last_match_info); 633 var_lastindex.value(), last_match_info);
576 var_result.Bind(match_indices); 634 var_result.Bind(match_indices);
577 635
578 // {match_indices} is either null or the RegExpMatchInfo array. 636 // {match_indices} is either null or the RegExpMatchInfo array.
579 // Return early if exec failed, possibly updating last index. 637 // Return early if exec failed, possibly updating last index.
580 GotoIfNot(WordEqual(match_indices, null), &successful_match); 638 GotoIfNot(WordEqual(match_indices, null), &successful_match);
581 639
582 GotoIfNot(should_update_last_index, if_didnotmatch); 640 GotoIfNot(should_update_last_index, if_didnotmatch);
583 641
584 StoreLastIndex(context, regexp, smi_zero, is_fastpath); 642 StoreLastIndex(context, regexp, smi_zero, is_fastpath);
585 Goto(if_didnotmatch); 643 Goto(if_didnotmatch);
(...skipping 1511 matching lines...) Expand 10 before | Expand all | Expand 10 after
2097 // array depending on whether the {regexp} matches. 2155 // array depending on whether the {regexp} matches.
2098 { 2156 {
2099 Label next(this), if_stringisempty(this, Label::kDeferred); 2157 Label next(this), if_stringisempty(this, Label::kDeferred);
2100 Branch(SmiEqual(string_length, smi_zero), &if_stringisempty, &next); 2158 Branch(SmiEqual(string_length, smi_zero), &if_stringisempty, &next);
2101 2159
2102 BIND(&if_stringisempty); 2160 BIND(&if_stringisempty);
2103 { 2161 {
2104 Node* const last_match_info = LoadContextElement( 2162 Node* const last_match_info = LoadContextElement(
2105 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 2163 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
2106 2164
2107 Node* const match_indices = 2165 Node* const match_indices = RegExpExecInternal(context, regexp, string,
2108 IrregexpExec(context, regexp, string, smi_zero, last_match_info); 2166 smi_zero, last_match_info);
2109 2167
2110 Label return_singleton_array(this); 2168 Label return_singleton_array(this);
2111 Branch(WordEqual(match_indices, null), &return_singleton_array, 2169 Branch(WordEqual(match_indices, null), &return_singleton_array,
2112 &return_empty_array); 2170 &return_empty_array);
2113 2171
2114 BIND(&return_singleton_array); 2172 BIND(&return_singleton_array);
2115 { 2173 {
2116 Node* const length = SmiConstant(1); 2174 Node* const length = SmiConstant(1);
2117 Node* const capacity = IntPtrConstant(1); 2175 Node* const capacity = IntPtrConstant(1);
2118 Node* const result = AllocateJSArray(kind, array_map, capacity, length, 2176 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, 2217 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out,
2160 &next); 2218 &next);
2161 BIND(&next); 2219 BIND(&next);
2162 } 2220 }
2163 2221
2164 // Search for the given {regexp}. 2222 // Search for the given {regexp}.
2165 2223
2166 Node* const last_match_info = LoadContextElement( 2224 Node* const last_match_info = LoadContextElement(
2167 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 2225 native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
2168 2226
2169 Node* const match_indices = IrregexpExec(context, regexp, string, 2227 Node* const match_indices = RegExpExecInternal(
2170 next_search_from, last_match_info); 2228 context, regexp, string, next_search_from, last_match_info);
2171 2229
2172 // We're done if no match was found. 2230 // We're done if no match was found.
2173 { 2231 {
2174 Label next(this); 2232 Label next(this);
2175 Branch(WordEqual(match_indices, null), &push_suffix_and_out, &next); 2233 Branch(WordEqual(match_indices, null), &push_suffix_and_out, &next);
2176 BIND(&next); 2234 BIND(&next);
2177 } 2235 }
2178 2236
2179 Node* const match_from = LoadFixedArrayElement( 2237 Node* const match_from = LoadFixedArrayElement(
2180 match_indices, RegExpMatchInfo::kFirstCaptureIndex); 2238 match_indices, RegExpMatchInfo::kFirstCaptureIndex);
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after
2841 Node* const null = NullConstant(); 2899 Node* const null = NullConstant();
2842 Node* const smi_zero = SmiConstant(0); 2900 Node* const smi_zero = SmiConstant(0);
2843 2901
2844 CSA_ASSERT(this, IsJSRegExp(regexp)); 2902 CSA_ASSERT(this, IsJSRegExp(regexp));
2845 CSA_ASSERT(this, IsString(string)); 2903 CSA_ASSERT(this, IsString(string));
2846 2904
2847 Node* const native_context = LoadNativeContext(context); 2905 Node* const native_context = LoadNativeContext(context);
2848 Node* const internal_match_info = LoadContextElement( 2906 Node* const internal_match_info = LoadContextElement(
2849 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); 2907 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
2850 2908
2851 Node* const match_indices = 2909 Node* const match_indices = RegExpExecInternal(context, regexp, string,
2852 IrregexpExec(context, regexp, string, smi_zero, internal_match_info); 2910 smi_zero, internal_match_info);
2853 2911
2854 Label if_matched(this), if_didnotmatch(this); 2912 Label if_matched(this), if_didnotmatch(this);
2855 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 2913 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
2856 2914
2857 BIND(&if_didnotmatch); 2915 BIND(&if_didnotmatch);
2858 Return(null); 2916 Return(null);
2859 2917
2860 BIND(&if_matched); 2918 BIND(&if_matched);
2861 { 2919 {
2862 Node* result = 2920 Node* result =
2863 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2921 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2864 Return(result); 2922 Return(result);
2865 } 2923 }
2866 } 2924 }
2867 2925
2868 } // namespace internal 2926 } // namespace internal
2869 } // namespace v8 2927 } // 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