diff options
author | Michaël Zasso <targos@protonmail.com> | 2019-11-08 15:39:11 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2019-11-08 15:46:25 +0100 |
commit | 6ca81ad72a3c6fdf16c683335be748f22aaa9a0d (patch) | |
tree | 33c8ee75f729aed76c2c0b89c63f9bf1b4dd66aa /deps/v8/src/builtins/regexp-match-all.tq | |
parent | 1eee0b8bf8bba39b600fb16a9223e545e3bac2bc (diff) | |
download | node-new-6ca81ad72a3c6fdf16c683335be748f22aaa9a0d.tar.gz |
deps: update V8 to 7.9.317.20
PR-URL: https://github.com/nodejs/node/pull/30020
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Diffstat (limited to 'deps/v8/src/builtins/regexp-match-all.tq')
-rw-r--r-- | deps/v8/src/builtins/regexp-match-all.tq | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/deps/v8/src/builtins/regexp-match-all.tq b/deps/v8/src/builtins/regexp-match-all.tq new file mode 100644 index 0000000000..1be6e69afc --- /dev/null +++ b/deps/v8/src/builtins/regexp-match-all.tq @@ -0,0 +1,258 @@ +// Copyright 2019 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include 'src/builtins/builtins-regexp-gen.h' + +namespace regexp { + + extern transitioning macro RegExpBuiltinsAssembler::RegExpCreate( + implicit context: Context)(Context, Object, String): Object; + + extern transitioning macro + RegExpMatchAllAssembler::CreateRegExpStringIterator( + NativeContext, Object, String, bool, bool): JSAny; + + @export + transitioning macro RegExpPrototypeMatchAllImpl(implicit context: Context)( + nativeContext: NativeContext, receiver: JSAny, string: JSAny): JSAny { + // 1. Let R be the this value. + // 2. If Type(R) is not Object, throw a TypeError exception. + ThrowIfNotJSReceiver( + receiver, kIncompatibleMethodReceiver, 'RegExp.prototype.@@matchAll'); + const receiver = UnsafeCast<JSReceiver>(receiver); + + // 3. Let S be ? ToString(O). + const string: String = ToString_Inline(context, string); + + let matcher: Object; + let global: bool; + let unicode: bool; + + // 'FastJSRegExp' uses the strict fast path check because following code + // uses the flags property. + // TODO(jgruber): Handle slow flag accesses on the fast path and make this + // permissive. + typeswitch (receiver) { + case (fastRegExp: FastJSRegExp): { + const source = fastRegExp.source; + + // 4. Let C be ? SpeciesConstructor(R, %RegExp%). + // 5. Let flags be ? ToString(? Get(R, "flags")). + // 6. Let matcher be ? Construct(C, « R, flags »). + const flags: String = FastFlagsGetter(fastRegExp); + matcher = RegExpCreate(nativeContext, source, flags); + const matcherRegExp = UnsafeCast<JSRegExp>(matcher); + assert(IsFastRegExpPermissive(matcherRegExp)); + + // 7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). + // 8. Perform ? Set(matcher, "lastIndex", lastIndex, true). + const fastRegExp = UnsafeCast<FastJSRegExp>(receiver); + FastStoreLastIndex(matcherRegExp, fastRegExp.lastIndex); + + // 9. If flags contains "g", let global be true. + // 10. Else, let global be false. + global = FastFlagGetter(matcherRegExp, kGlobal); + + // 11. If flags contains "u", let fullUnicode be true. + // 12. Else, let fullUnicode be false. + unicode = FastFlagGetter(matcherRegExp, kUnicode); + } + case (Object): { + // 4. Let C be ? SpeciesConstructor(R, %RegExp%). + const regexpFun = + UnsafeCast<JSFunction>(nativeContext[REGEXP_FUNCTION_INDEX]); + const speciesConstructor = + UnsafeCast<Constructor>(SpeciesConstructor(receiver, regexpFun)); + + // 5. Let flags be ? ToString(? Get(R, "flags")). + const flags = GetProperty(receiver, 'flags'); + const flagsString = ToString_Inline(context, flags); + + // 6. Let matcher be ? Construct(C, « R, flags »). + matcher = Construct(speciesConstructor, receiver, flagsString); + + // 7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")). + const lastIndex: Number = + ToLength_Inline(context, SlowLoadLastIndex(receiver)); + + // 8. Perform ? Set(matcher, "lastIndex", lastIndex, true). + SlowStoreLastIndex(UnsafeCast<JSReceiver>(matcher), lastIndex); + + // 9. If flags contains "g", let global be true. + // 10. Else, let global be false. + const globalCharString: String = StringConstant('g'); + const globalIndex: Smi = + StringIndexOf(flagsString, globalCharString, 0); + global = globalIndex != -1; + + // 11. If flags contains "u", let fullUnicode be true. + // 12. Else, let fullUnicode be false. + const unicodeCharString = StringConstant('u'); + const unicodeIndex: Smi = + StringIndexOf(flagsString, unicodeCharString, 0); + unicode = unicodeIndex != -1; + } + } + + // 13. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode). + return CreateRegExpStringIterator( + nativeContext, matcher, string, global, unicode); + } + + // https://tc39.github.io/proposal-string-matchall/ + // RegExp.prototype [ @@matchAll ] ( string ) + transitioning javascript builtin RegExpPrototypeMatchAll( + js-implicit context: Context, receiver: JSAny)(string: JSAny): JSAny { + const nativeContext: NativeContext = LoadNativeContext(context); + return RegExpPrototypeMatchAllImpl(nativeContext, receiver, string); + } + + const kJSRegExpStringIteratorDone: + constexpr int31 generates '1 << JSRegExpStringIterator::kDoneBit'; + const kJSRegExpStringIteratorGlobal: constexpr int31 + generates '1 << JSRegExpStringIterator::kGlobalBit'; + const kJSRegExpStringIteratorUnicode: constexpr int31 + generates '1 << JSRegExpStringIterator::kUnicodeBit'; + + extern macro IsSetSmi(Smi, constexpr int31): bool; + + macro HasDoneFlag(flags: Smi): bool { + return IsSetSmi(flags, kJSRegExpStringIteratorDone); + } + + macro HasGlobalFlag(flags: Smi): bool { + return IsSetSmi(flags, kJSRegExpStringIteratorGlobal); + } + + macro HasUnicodeFlag(flags: Smi): bool { + return IsSetSmi(flags, kJSRegExpStringIteratorUnicode); + } + + macro SetDoneFlag(iterator: JSRegExpStringIterator, flags: Smi) { + const newFlags: Smi = flags | kJSRegExpStringIteratorDone; + iterator.flags = newFlags; + } + + extern macro RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( + implicit context: Context)(JSReceiver, RegExpMatchInfo, String): + JSRegExpResult; + + // https://tc39.github.io/proposal-string-matchall/ + // %RegExpStringIteratorPrototype%.next ( ) + transitioning javascript builtin RegExpStringIteratorPrototypeNext( + js-implicit context: Context, receiver: JSAny)(): JSAny { + // 1. Let O be the this value. + // 2. If Type(O) is not Object, throw a TypeError exception. + // 3. If O does not have all of the internal slots of a RegExp String + // Iterator Object Instance (see 5.3), throw a TypeError exception. + const methodName: constexpr string = + '%RegExpStringIterator%.prototype.next'; + const receiver = Cast<JSRegExpStringIterator>(receiver) otherwise + ThrowTypeError(kIncompatibleMethodReceiver, methodName, receiver); + + try { + // 4. If O.[[Done]] is true, then + // a. Return ! CreateIterResultObject(undefined, true). + const flags: Smi = receiver.flags; + if (HasDoneFlag(flags)) goto ReturnEmptyDoneResult; + + // 5. Let R be O.[[iteratingRegExp]]. + const iteratingRegExp: JSReceiver = receiver.iterating_reg_exp; + + // 6. Let S be O.[[IteratedString]]. + const iteratingString: String = receiver.iterated_string; + + // 7. Let global be O.[[Global]]. + // 8. Let fullUnicode be O.[[Unicode]]. + // 9. Let match be ? RegExpExec(R, S). + let match: Object; + let isFastRegExp: bool = false; + try { + if (IsFastRegExpPermissive(iteratingRegExp)) { + const matchIndices: RegExpMatchInfo = + RegExpPrototypeExecBodyWithoutResultFast( + UnsafeCast<JSRegExp>(iteratingRegExp), iteratingString) + otherwise IfNoMatch; + match = ConstructNewResultFromMatchInfo( + iteratingRegExp, matchIndices, iteratingString); + isFastRegExp = true; + } else { + match = RegExpExec(iteratingRegExp, iteratingString); + if (match == Null) { + goto IfNoMatch; + } + } + // 11. Else, + // b. Else, handle non-global case first. + if (!HasGlobalFlag(flags)) { + // i. Set O.[[Done]] to true. + SetDoneFlag(receiver, flags); + + // ii. Return ! CreateIterResultObject(match, false). + return AllocateJSIteratorResult(UnsafeCast<JSAny>(match), False); + } + // a. If global is true, + assert(HasGlobalFlag(flags)); + if (isFastRegExp) { + // i. Let matchStr be ? ToString(? Get(match, "0")). + const match = UnsafeCast<FastJSRegExpResult>(match); + const resultFixedArray = UnsafeCast<FixedArray>(match.elements); + const matchStr = UnsafeCast<String>(resultFixedArray.objects[0]); + + // When iterating_regexp is fast, we assume it stays fast even after + // accessing the first match from the RegExp result. + assert(IsFastRegExpPermissive(iteratingRegExp)); + const iteratingRegExp = UnsafeCast<JSRegExp>(iteratingRegExp); + if (matchStr == kEmptyString) { + // 1. Let thisIndex be ? ToLength(? Get(R, "lastIndex")). + const thisIndex: Smi = FastLoadLastIndex(iteratingRegExp); + + // 2. Let nextIndex be ! AdvanceStringIndex(S, thisIndex, + // fullUnicode). + const nextIndex: Smi = AdvanceStringIndexFast( + iteratingString, thisIndex, HasUnicodeFlag(flags)); + + // 3. Perform ? Set(R, "lastIndex", nextIndex, true). + FastStoreLastIndex(iteratingRegExp, nextIndex); + } + + // iii. Return ! CreateIterResultObject(match, false). + return AllocateJSIteratorResult(match, False); + } + assert(!isFastRegExp); + // i. Let matchStr be ? ToString(? Get(match, "0")). + const match = UnsafeCast<JSAny>(match); + const matchStr = + ToString_Inline(context, GetProperty(match, SmiConstant(0))); + + if (matchStr == kEmptyString) { + // 1. Let thisIndex be ? ToLength(? Get(R, "lastIndex")). + const lastIndex: JSAny = SlowLoadLastIndex(iteratingRegExp); + const thisIndex: Number = ToLength_Inline(context, lastIndex); + + // 2. Let nextIndex be ! AdvanceStringIndex(S, thisIndex, + // fullUnicode). + const nextIndex: Number = AdvanceStringIndexSlow( + iteratingString, thisIndex, HasUnicodeFlag(flags)); + + // 3. Perform ? Set(R, "lastIndex", nextIndex, true). + SlowStoreLastIndex(iteratingRegExp, nextIndex); + } + // iii. Return ! CreateIterResultObject(match, false). + return AllocateJSIteratorResult(match, False); + } + // 10. If match is null, then + label IfNoMatch { + // a. Set O.[[Done]] to true. + SetDoneFlag(receiver, flags); + + // b. Return ! CreateIterResultObject(undefined, true). + goto ReturnEmptyDoneResult; + } + } + label ReturnEmptyDoneResult { + return AllocateJSIteratorResult(Undefined, True); + } + } +} |