1// Copyright 2019 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include 'src/builtins/builtins-regexp-gen.h' 6 7namespace regexp { 8 9transitioning macro 10RegExpPrototypeSearchBodyFast(implicit context: Context)( 11 regexp: JSRegExp, string: String): JSAny { 12 assert(IsFastRegExpPermissive(regexp)); 13 14 // Grab the initial value of last index. 15 const previousLastIndex: Smi = FastLoadLastIndex(regexp); 16 17 // Ensure last index is 0. 18 FastStoreLastIndex(regexp, 0); 19 20 // Call exec. 21 try { 22 const matchIndices: RegExpMatchInfo = 23 RegExpPrototypeExecBodyWithoutResultFast( 24 UnsafeCast<JSRegExp>(regexp), string) 25 otherwise DidNotMatch; 26 27 // Successful match. 28 // Reset last index. 29 FastStoreLastIndex(regexp, previousLastIndex); 30 31 // Return the index of the match. 32 return UnsafeCast<Smi>( 33 matchIndices.objects[kRegExpMatchInfoFirstCaptureIndex]); 34 } label DidNotMatch { 35 // Reset last index and return -1. 36 FastStoreLastIndex(regexp, previousLastIndex); 37 return SmiConstant(-1); 38 } 39} 40 41extern macro RegExpBuiltinsAssembler::BranchIfRegExpResult( 42 implicit context: Context)(Object): never labels IsUnmodified, 43 IsModified; 44 45macro 46IsRegExpResult(implicit context: Context)(execResult: HeapObject): bool { 47 BranchIfRegExpResult(execResult) otherwise return true, return false; 48} 49 50transitioning macro RegExpPrototypeSearchBodySlow(implicit context: Context)( 51 regexp: JSReceiver, string: String): JSAny { 52 // Grab the initial value of last index. 53 const previousLastIndex = SlowLoadLastIndex(regexp); 54 const smiZero: Smi = 0; 55 56 // Ensure last index is 0. 57 if (!SameValue(previousLastIndex, smiZero)) { 58 SlowStoreLastIndex(regexp, smiZero); 59 } 60 61 // Call exec. 62 const execResult = RegExpExec(regexp, string); 63 64 // Reset last index if necessary. 65 const currentLastIndex = SlowLoadLastIndex(regexp); 66 if (!SameValue(currentLastIndex, previousLastIndex)) { 67 SlowStoreLastIndex(regexp, previousLastIndex); 68 } 69 70 // Return -1 if no match was found. 71 if (execResult == Null) { 72 return SmiConstant(-1); 73 } 74 75 // Return the index of the match. 76 const fastExecResult = Cast<JSRegExpResult>(execResult) 77 otherwise return GetProperty(execResult, 'index'); 78 return fastExecResult.index; 79} 80 81// Helper that skips a few initial checks. and assumes... 82// 1) receiver is a "fast permissive" RegExp 83// 2) pattern is a string 84transitioning builtin RegExpSearchFast(implicit context: Context)( 85 receiver: JSRegExp, string: String): JSAny { 86 return RegExpPrototypeSearchBodyFast(receiver, string); 87} 88 89// ES#sec-regexp.prototype-@@search 90// RegExp.prototype [ @@search ] ( string ) 91transitioning javascript builtin RegExpPrototypeSearch( 92 js-implicit context: NativeContext, receiver: JSAny)(string: JSAny): JSAny { 93 ThrowIfNotJSReceiver( 94 receiver, MessageTemplate::kIncompatibleMethodReceiver, 95 'RegExp.prototype.@@search'); 96 const receiver = UnsafeCast<JSReceiver>(receiver); 97 const string: String = ToString_Inline(string); 98 99 if (IsFastRegExpPermissive(receiver)) { 100 // TODO(pwong): Could be optimized to remove the overhead of calling the 101 // builtin (at the cost of a larger builtin). 102 return RegExpSearchFast(UnsafeCast<JSRegExp>(receiver), string); 103 } 104 return RegExpPrototypeSearchBodySlow(receiver, string); 105} 106} 107