diff options
Diffstat (limited to 'deps/v8/src/builtins/regexp-match.tq')
-rw-r--r-- | deps/v8/src/builtins/regexp-match.tq | 267 |
1 files changed, 132 insertions, 135 deletions
diff --git a/deps/v8/src/builtins/regexp-match.tq b/deps/v8/src/builtins/regexp-match.tq index 9b0255762c0..d5581e05093 100644 --- a/deps/v8/src/builtins/regexp-match.tq +++ b/deps/v8/src/builtins/regexp-match.tq @@ -6,160 +6,157 @@ namespace regexp { - const kATOM: constexpr int31 - generates 'JSRegExp::ATOM'; - const kTagIndex: constexpr int31 - generates 'JSRegExp::kTagIndex'; - const kAtomPatternIndex: constexpr int31 - generates 'JSRegExp::kAtomPatternIndex'; - - extern transitioning macro RegExpBuiltinsAssembler::FlagGetter( - implicit context: Context)(Object, constexpr Flag, constexpr bool): bool; - - extern macro UnsafeLoadFixedArrayElement(RegExpMatchInfo, constexpr int31): - Object; - - transitioning macro RegExpPrototypeMatchBody(implicit context: Context)( - regexp: JSReceiver, string: String, isFastPath: constexpr bool): JSAny { - if constexpr (isFastPath) { - assert(Is<FastJSRegExp>(regexp)); - } +const kATOM: constexpr int31 + generates 'JSRegExp::ATOM'; +const kTagIndex: constexpr int31 + generates 'JSRegExp::kTagIndex'; +const kAtomPatternIndex: constexpr int31 + generates 'JSRegExp::kAtomPatternIndex'; + +extern transitioning macro RegExpBuiltinsAssembler::FlagGetter( + implicit context: Context)(Object, constexpr Flag, constexpr bool): bool; + +extern macro UnsafeLoadFixedArrayElement( + RegExpMatchInfo, constexpr int31): Object; + +transitioning macro RegExpPrototypeMatchBody(implicit context: Context)( + regexp: JSReceiver, string: String, isFastPath: constexpr bool): JSAny { + if constexpr (isFastPath) { + assert(Is<FastJSRegExp>(regexp)); + } - const isGlobal: bool = FlagGetter(regexp, Flag::kGlobal, isFastPath); + const isGlobal: bool = FlagGetter(regexp, Flag::kGlobal, isFastPath); - if (!isGlobal) { - return isFastPath ? RegExpPrototypeExecBodyFast(regexp, string) : - RegExpExec(regexp, string); - } + if (!isGlobal) { + return isFastPath ? RegExpPrototypeExecBodyFast(regexp, string) : + RegExpExec(regexp, string); + } - assert(isGlobal); - const isUnicode: bool = FlagGetter(regexp, Flag::kUnicode, isFastPath); + assert(isGlobal); + const isUnicode: bool = FlagGetter(regexp, Flag::kUnicode, isFastPath); - StoreLastIndex(regexp, 0, isFastPath); + StoreLastIndex(regexp, 0, isFastPath); - // Allocate an array to store the resulting match strings. + // Allocate an array to store the resulting match strings. - let array = growable_fixed_array::NewGrowableFixedArray(); + let array = growable_fixed_array::NewGrowableFixedArray(); - // Check if the regexp is an ATOM type. If so, then keep the literal string - // to search for so that we can avoid calling substring in the loop below. - let atom: bool = false; - let searchString: String = EmptyStringConstant(); - if constexpr (isFastPath) { - const maybeAtomRegexp = UnsafeCast<JSRegExp>(regexp); - const data = UnsafeCast<FixedArray>(maybeAtomRegexp.data); - if (UnsafeCast<Smi>(data.objects[kTagIndex]) == kATOM) { - searchString = UnsafeCast<String>(data.objects[kAtomPatternIndex]); - atom = true; - } + // Check if the regexp is an ATOM type. If so, then keep the literal string + // to search for so that we can avoid calling substring in the loop below. + let atom: bool = false; + let searchString: String = EmptyStringConstant(); + if constexpr (isFastPath) { + const maybeAtomRegexp = UnsafeCast<JSRegExp>(regexp); + const data = UnsafeCast<FixedArray>(maybeAtomRegexp.data); + if (UnsafeCast<Smi>(data.objects[kTagIndex]) == kATOM) { + searchString = UnsafeCast<String>(data.objects[kAtomPatternIndex]); + atom = true; } + } - while (true) { - let match: String = EmptyStringConstant(); - try { - if constexpr (isFastPath) { - // On the fast path, grab the matching string from the raw match index - // array. - const matchIndices: RegExpMatchInfo = - RegExpPrototypeExecBodyWithoutResultFast( - UnsafeCast<JSRegExp>(regexp), string) otherwise IfDidNotMatch; - if (atom) { - match = searchString; - } else { - const matchFrom = UnsafeLoadFixedArrayElement( - matchIndices, kRegExpMatchInfoFirstCaptureIndex); - const matchTo = UnsafeLoadFixedArrayElement( - matchIndices, kRegExpMatchInfoFirstCaptureIndex + 1); - match = SubString( - string, UnsafeCast<Smi>(matchFrom), UnsafeCast<Smi>(matchTo)); - } + while (true) { + let match: String = EmptyStringConstant(); + try { + if constexpr (isFastPath) { + // On the fast path, grab the matching string from the raw match index + // array. + const matchIndices: RegExpMatchInfo = + RegExpPrototypeExecBodyWithoutResultFast( + UnsafeCast<JSRegExp>(regexp), string) otherwise IfDidNotMatch; + if (atom) { + match = searchString; } else { - assert(!isFastPath); - const resultTemp = RegExpExec(regexp, string); - if (resultTemp == Null) { - goto IfDidNotMatch; - } - match = ToString_Inline(GetProperty(resultTemp, SmiConstant(0))); + const matchFrom = UnsafeLoadFixedArrayElement( + matchIndices, kRegExpMatchInfoFirstCaptureIndex); + const matchTo = UnsafeLoadFixedArrayElement( + matchIndices, kRegExpMatchInfoFirstCaptureIndex + 1); + match = SubString( + string, UnsafeCast<Smi>(matchFrom), UnsafeCast<Smi>(matchTo)); + } + } else { + assert(!isFastPath); + const resultTemp = RegExpExec(regexp, string); + if (resultTemp == Null) { + goto IfDidNotMatch; } - goto IfDidMatch; + match = ToString_Inline(GetProperty(resultTemp, SmiConstant(0))); } - label IfDidNotMatch { - return array.length == 0 ? Null : array.ToJSArray(); + goto IfDidMatch; + } label IfDidNotMatch { + return array.length == 0 ? Null : array.ToJSArray(); + } label IfDidMatch { + // Store the match, growing the fixed array if needed. + + array.Push(match); + + // Advance last index if the match is the empty string. + const matchLength: Smi = match.length_smi; + if (matchLength != 0) { + continue; + } + let lastIndex = LoadLastIndex(regexp, isFastPath); + if constexpr (isFastPath) { + assert(TaggedIsPositiveSmi(lastIndex)); + } else { + lastIndex = ToLength_Inline(lastIndex); } - label IfDidMatch { - // Store the match, growing the fixed array if needed. - - array.Push(match); - - // Advance last index if the match is the empty string. - const matchLength: Smi = match.length_smi; - if (matchLength != 0) { - continue; - } - let lastIndex = LoadLastIndex(regexp, isFastPath); - if constexpr (isFastPath) { - assert(TaggedIsPositiveSmi(lastIndex)); - } else { - lastIndex = ToLength_Inline(lastIndex); - } - - const newLastIndex: Number = AdvanceStringIndex( - string, UnsafeCast<Number>(lastIndex), isUnicode, isFastPath); - - if constexpr (isFastPath) { - // On the fast path, we can be certain that lastIndex can never be - // incremented to overflow the Smi range since the maximal string - // length is less than the maximal Smi value. - const kMaxStringLengthFitsSmi: constexpr bool = - kStringMaxLengthUintptr < kSmiMaxValue; - StaticAssert(kMaxStringLengthFitsSmi); - assert(TaggedIsPositiveSmi(newLastIndex)); - } - StoreLastIndex(regexp, newLastIndex, isFastPath); + const newLastIndex: Number = AdvanceStringIndex( + string, UnsafeCast<Number>(lastIndex), isUnicode, isFastPath); + + if constexpr (isFastPath) { + // On the fast path, we can be certain that lastIndex can never be + // incremented to overflow the Smi range since the maximal string + // length is less than the maximal Smi value. + const kMaxStringLengthFitsSmi: constexpr bool = + kStringMaxLengthUintptr < kSmiMaxValue; + StaticAssert(kMaxStringLengthFitsSmi); + assert(TaggedIsPositiveSmi(newLastIndex)); } - } - VerifiedUnreachable(); + StoreLastIndex(regexp, newLastIndex, isFastPath); + } } - transitioning macro FastRegExpPrototypeMatchBody(implicit context: Context)( - receiver: FastJSRegExp, string: String): JSAny { - return RegExpPrototypeMatchBody(receiver, string, true); - } + VerifiedUnreachable(); +} - transitioning macro SlowRegExpPrototypeMatchBody(implicit context: Context)( - receiver: JSReceiver, string: String): JSAny { - return RegExpPrototypeMatchBody(receiver, string, false); - } +transitioning macro FastRegExpPrototypeMatchBody(implicit context: Context)( + receiver: FastJSRegExp, string: String): JSAny { + return RegExpPrototypeMatchBody(receiver, string, true); +} - // Helper that skips a few initial checks. and assumes... - // 1) receiver is a "fast" RegExp - // 2) pattern is a string - transitioning builtin RegExpMatchFast(implicit context: Context)( - receiver: FastJSRegExp, string: String): JSAny { - return FastRegExpPrototypeMatchBody(receiver, string); - } +transitioning macro SlowRegExpPrototypeMatchBody(implicit context: Context)( + receiver: JSReceiver, string: String): JSAny { + return RegExpPrototypeMatchBody(receiver, string, false); +} - // ES#sec-regexp.prototype-@@match - // RegExp.prototype [ @@match ] ( string ) - transitioning javascript builtin RegExpPrototypeMatch( - js-implicit context: NativeContext, - receiver: JSAny)(string: JSAny): JSAny { - ThrowIfNotJSReceiver( - receiver, MessageTemplate::kIncompatibleMethodReceiver, - 'RegExp.prototype.@@match'); - const receiver = UnsafeCast<JSReceiver>(receiver); - const string: String = ToString_Inline(string); - - // Strict: Reads global and unicode properties. - // TODO(jgruber): Handle slow flag accesses on the fast path and make this - // permissive. - const fastRegExp = Cast<FastJSRegExp>(receiver) - otherwise return SlowRegExpPrototypeMatchBody(receiver, string); - - // TODO(pwong): Could be optimized to remove the overhead of calling the - // builtin (at the cost of a larger builtin). - return RegExpMatchFast(fastRegExp, string); - } +// Helper that skips a few initial checks. and assumes... +// 1) receiver is a "fast" RegExp +// 2) pattern is a string +transitioning builtin RegExpMatchFast(implicit context: Context)( + receiver: FastJSRegExp, string: String): JSAny { + return FastRegExpPrototypeMatchBody(receiver, string); +} + +// ES#sec-regexp.prototype-@@match +// RegExp.prototype [ @@match ] ( string ) +transitioning javascript builtin RegExpPrototypeMatch( + js-implicit context: NativeContext, receiver: JSAny)(string: JSAny): JSAny { + ThrowIfNotJSReceiver( + receiver, MessageTemplate::kIncompatibleMethodReceiver, + 'RegExp.prototype.@@match'); + const receiver = UnsafeCast<JSReceiver>(receiver); + const string: String = ToString_Inline(string); + + // Strict: Reads global and unicode properties. + // TODO(jgruber): Handle slow flag accesses on the fast path and make this + // permissive. + const fastRegExp = Cast<FastJSRegExp>(receiver) + otherwise return SlowRegExpPrototypeMatchBody(receiver, string); + + // TODO(pwong): Could be optimized to remove the overhead of calling the + // builtin (at the cost of a larger builtin). + return RegExpMatchFast(fastRegExp, string); +} } |