diff options
Diffstat (limited to 'deps/v8/src/builtins/string-replaceall.tq')
-rw-r--r-- | deps/v8/src/builtins/string-replaceall.tq | 374 |
1 files changed, 186 insertions, 188 deletions
diff --git a/deps/v8/src/builtins/string-replaceall.tq b/deps/v8/src/builtins/string-replaceall.tq index c7589f18a66..9211304b345 100644 --- a/deps/v8/src/builtins/string-replaceall.tq +++ b/deps/v8/src/builtins/string-replaceall.tq @@ -5,218 +5,216 @@ #include 'src/builtins/builtins-string-gen.h' namespace string { - extern macro ReplaceSymbolConstant(): Symbol; - - extern macro StringBuiltinsAssembler::GetSubstitution( - implicit context: Context)(String, Smi, Smi, String): String; - - extern builtin - StringIndexOf(implicit context: Context)(String, String, Smi): Smi; - - macro TryFastAbstractStringIndexOf(implicit context: Context)( - string: String, searchString: String, fromIndex: Smi): Smi labels Slow { - const stringLen = string.length_uintptr; - const searchLen = searchString.length_uintptr; - const directString = Cast<DirectString>(string) otherwise Slow; - const directSearchStr = Cast<DirectString>(searchString) otherwise Slow; - const fromIndexUint = Unsigned(SmiUntag(fromIndex)); - - for (let i: uintptr = fromIndexUint; i < stringLen; i++) { - let j = i; - let k: uintptr = 0; - while (j < stringLen && k < searchLen && - StringCharCodeAt(directString, j) == - StringCharCodeAt(directSearchStr, k)) { - j++; - k++; - } - if (k == searchLen) { - return SmiTag(Signed(i)); - } +extern macro ReplaceSymbolConstant(): Symbol; + +extern macro StringBuiltinsAssembler::GetSubstitution( + implicit context: Context)(String, Smi, Smi, String): String; + +extern builtin +StringIndexOf(implicit context: Context)(String, String, Smi): Smi; + +macro TryFastAbstractStringIndexOf(implicit context: Context)( + string: String, searchString: String, fromIndex: Smi): Smi labels Slow { + const stringLen = string.length_uintptr; + const searchLen = searchString.length_uintptr; + const directString = Cast<DirectString>(string) otherwise Slow; + const directSearchStr = Cast<DirectString>(searchString) otherwise Slow; + const fromIndexUint = Unsigned(SmiUntag(fromIndex)); + + for (let i: uintptr = fromIndexUint; i < stringLen; i++) { + let j = i; + let k: uintptr = 0; + while (j < stringLen && k < searchLen && + StringCharCodeAt(directString, j) == + StringCharCodeAt(directSearchStr, k)) { + j++; + k++; + } + if (k == searchLen) { + return SmiTag(Signed(i)); } - return -1; } + return -1; +} - macro AbstractStringIndexOf(implicit context: Context)( - string: String, searchString: String, fromIndex: Smi): Smi { - // Special case the empty string. - const searchStringLength = searchString.length_intptr; - const stringLength = string.length_intptr; - if (searchStringLength == 0 && SmiUntag(fromIndex) <= stringLength) { - return fromIndex; - } +macro AbstractStringIndexOf(implicit context: Context)( + string: String, searchString: String, fromIndex: Smi): Smi { + // Special case the empty string. + const searchStringLength = searchString.length_intptr; + const stringLength = string.length_intptr; + if (searchStringLength == 0 && SmiUntag(fromIndex) <= stringLength) { + return fromIndex; + } - // Don't bother to search if the searchString would go past the end - // of the string. This is actually necessary because of runtime - // checks. - if (SmiUntag(fromIndex) + searchStringLength > stringLength) { - return -1; - } + // Don't bother to search if the searchString would go past the end + // of the string. This is actually necessary because of runtime + // checks. + if (SmiUntag(fromIndex) + searchStringLength > stringLength) { + return -1; + } - try { - return TryFastAbstractStringIndexOf(string, searchString, fromIndex) - otherwise Slow; - } - label Slow { - for (let i: intptr = SmiUntag(fromIndex); - i + searchStringLength <= stringLength; i++) { - if (StringCompareSequence( - context, string, searchString, Convert<Number>(SmiTag(i))) == - True) { - return SmiTag(i); - } + try { + return TryFastAbstractStringIndexOf(string, searchString, fromIndex) + otherwise Slow; + } label Slow { + for (let i: intptr = SmiUntag(fromIndex); + i + searchStringLength <= stringLength; i++) { + if (StringCompareSequence( + context, string, searchString, Convert<Number>(SmiTag(i))) == + True) { + return SmiTag(i); } - return -1; } + return -1; } +} - transitioning macro - ThrowIfNotGlobal(implicit context: Context)(searchValue: JSAny): void { - let shouldThrow: bool; - typeswitch (searchValue) { - case (fastRegExp: FastJSRegExp): { - shouldThrow = !fastRegExp.global; - } - case (Object): { - const flags = GetProperty(searchValue, 'flags'); - RequireObjectCoercible(flags, 'String.prototype.replaceAll'); - shouldThrow = - StringIndexOf(ToString_Inline(flags), StringConstant('g'), 0) == -1; - } +transitioning macro +ThrowIfNotGlobal(implicit context: Context)(searchValue: JSAny): void { + let shouldThrow: bool; + typeswitch (searchValue) { + case (fastRegExp: FastJSRegExp): { + shouldThrow = !fastRegExp.global; } - if (shouldThrow) { - ThrowTypeError( - MessageTemplate::kRegExpGlobalInvokedOnNonGlobal, - 'String.prototype.replaceAll'); + case (Object): { + const flags = GetProperty(searchValue, 'flags'); + RequireObjectCoercible(flags, 'String.prototype.replaceAll'); + shouldThrow = + StringIndexOf(ToString_Inline(flags), StringConstant('g'), 0) == -1; } } + if (shouldThrow) { + ThrowTypeError( + MessageTemplate::kRegExpGlobalInvokedOnNonGlobal, + 'String.prototype.replaceAll'); + } +} - // https://tc39.es/ecma262/#sec-string.prototype.replaceall - transitioning javascript builtin StringPrototypeReplaceAll( - js-implicit context: NativeContext, - receiver: JSAny)(searchValue: JSAny, replaceValue: JSAny): JSAny { - // 1. Let O be ? RequireObjectCoercible(this value). - RequireObjectCoercible(receiver, 'String.prototype.replaceAll'); - - // 2. If searchValue is neither undefined nor null, then - if (searchValue != Undefined && searchValue != Null) { - // a. Let isRegExp be ? IsRegExp(searchString). - // b. If isRegExp is true, then - // i. Let flags be ? Get(searchValue, "flags"). - // ii. Perform ? RequireObjectCoercible(flags). - // iii. If ? ToString(flags) does not contain "g", throw a - // TypeError exception. - if (regexp::IsRegExp(searchValue)) { - ThrowIfNotGlobal(searchValue); - } - - // TODO(joshualitt): We could easily add fast paths for string - // searchValues and potential FastRegExps. - // c. Let replacer be ? GetMethod(searchValue, @@replace). - // d. If replacer is not undefined, then - // i. Return ? Call(replacer, searchValue, « O, replaceValue »). - try { - const replacer = GetMethod(searchValue, ReplaceSymbolConstant()) - otherwise ReplaceSymbolIsNullOrUndefined; - return Call(context, replacer, searchValue, receiver, replaceValue); - } - label ReplaceSymbolIsNullOrUndefined {} +// https://tc39.es/ecma262/#sec-string.prototype.replaceall +transitioning javascript builtin StringPrototypeReplaceAll( + js-implicit context: NativeContext, receiver: JSAny)( + searchValue: JSAny, replaceValue: JSAny): JSAny { + // 1. Let O be ? RequireObjectCoercible(this value). + RequireObjectCoercible(receiver, 'String.prototype.replaceAll'); + + // 2. If searchValue is neither undefined nor null, then + if (searchValue != Undefined && searchValue != Null) { + // a. Let isRegExp be ? IsRegExp(searchString). + // b. If isRegExp is true, then + // i. Let flags be ? Get(searchValue, "flags"). + // ii. Perform ? RequireObjectCoercible(flags). + // iii. If ? ToString(flags) does not contain "g", throw a + // TypeError exception. + if (regexp::IsRegExp(searchValue)) { + ThrowIfNotGlobal(searchValue); } - // 3. Let string be ? ToString(O). - const string = ToString_Inline(receiver); + // TODO(joshualitt): We could easily add fast paths for string + // searchValues and potential FastRegExps. + // c. Let replacer be ? GetMethod(searchValue, @@replace). + // d. If replacer is not undefined, then + // i. Return ? Call(replacer, searchValue, « O, replaceValue »). + try { + const replacer = GetMethod(searchValue, ReplaceSymbolConstant()) + otherwise ReplaceSymbolIsNullOrUndefined; + return Call(context, replacer, searchValue, receiver, replaceValue); + } label ReplaceSymbolIsNullOrUndefined {} + } - // 4. Let searchString be ? ToString(searchValue). - const searchString = ToString_Inline(searchValue); + // 3. Let string be ? ToString(O). + const string = ToString_Inline(receiver); - // 5. Let functionalReplace be IsCallable(replaceValue). - let replaceValueArg = replaceValue; - const functionalReplace = TaggedIsCallable(replaceValue); + // 4. Let searchString be ? ToString(searchValue). + const searchString = ToString_Inline(searchValue); - // 6. If functionalReplace is false, then - if (!functionalReplace) { - // a. Let replaceValue be ? ToString(replaceValue). - replaceValueArg = ToString_Inline(replaceValue); - } + // 5. Let functionalReplace be IsCallable(replaceValue). + let replaceValueArg = replaceValue; + const functionalReplace = Is<Callable>(replaceValue); - // 7. Let searchLength be the length of searchString. - const searchLength = searchString.length_smi; - - // 8. Let advanceBy be max(1, searchLength). - const advanceBy = SmiMax(1, searchLength); - - // We combine the two loops from the spec into one to avoid - // needing a growable array. - // - // 9. Let matchPositions be a new empty List. - // 10. Let position be ! StringIndexOf(string, searchString, 0). - // 11. Repeat, while position is not -1 - // a. Append position to the end of matchPositions. - // b. Let position be ! StringIndexOf(string, searchString, - // position + advanceBy). - // 12. Let endOfLastMatch be 0. - // 13. Let result be the empty string value. - // 14. For each position in matchPositions, do - let endOfLastMatch: Smi = 0; - let result: String = kEmptyString; - let position = AbstractStringIndexOf(string, searchString, 0); - while (position != -1) { - // a. If functionalReplace is true, then - // b. Else, - let replacement: String; - if (functionalReplace) { - // i. Let replacement be ? ToString(? Call(replaceValue, undefined, - // « searchString, position, - // string »). - replacement = ToString_Inline(Call( - context, UnsafeCast<Callable>(replaceValueArg), Undefined, - searchString, position, string)); - } else { - // i. Assert: Type(replaceValue) is String. - const replaceValueString = UnsafeCast<String>(replaceValueArg); - - // ii. Let captures be a new empty List. - // iii. Let replacement be GetSubstitution(searchString, - // string, position, captures, - // undefined, replaceValue). - // Note: Instead we just call a simpler GetSubstitution primitive. - const matchEndPosition = position + searchLength; - replacement = GetSubstitution( - string, position, matchEndPosition, replaceValueString); - } + // 6. If functionalReplace is false, then + if (!functionalReplace) { + // a. Let replaceValue be ? ToString(replaceValue). + replaceValueArg = ToString_Inline(replaceValue); + } - // c. Let stringSlice be the substring of string consisting of the code - // units from endOfLastMatch (inclusive) up through position - // (exclusive). - const stringSlice = string::SubString( - string, Unsigned(SmiUntag(endOfLastMatch)), - Unsigned(SmiUntag(position))); + // 7. Let searchLength be the length of searchString. + const searchLength = searchString.length_smi; + + // 8. Let advanceBy be max(1, searchLength). + const advanceBy = SmiMax(1, searchLength); + + // We combine the two loops from the spec into one to avoid + // needing a growable array. + // + // 9. Let matchPositions be a new empty List. + // 10. Let position be ! StringIndexOf(string, searchString, 0). + // 11. Repeat, while position is not -1 + // a. Append position to the end of matchPositions. + // b. Let position be ! StringIndexOf(string, searchString, + // position + advanceBy). + // 12. Let endOfLastMatch be 0. + // 13. Let result be the empty string value. + // 14. For each position in matchPositions, do + let endOfLastMatch: Smi = 0; + let result: String = kEmptyString; + let position = AbstractStringIndexOf(string, searchString, 0); + while (position != -1) { + // a. If functionalReplace is true, then + // b. Else, + let replacement: String; + if (functionalReplace) { + // i. Let replacement be ? ToString(? Call(replaceValue, undefined, + // « searchString, position, + // string »). + replacement = ToString_Inline(Call( + context, UnsafeCast<Callable>(replaceValueArg), Undefined, + searchString, position, string)); + } else { + // i. Assert: Type(replaceValue) is String. + const replaceValueString = UnsafeCast<String>(replaceValueArg); + + // ii. Let captures be a new empty List. + // iii. Let replacement be GetSubstitution(searchString, + // string, position, captures, + // undefined, replaceValue). + // Note: Instead we just call a simpler GetSubstitution primitive. + const matchEndPosition = position + searchLength; + replacement = GetSubstitution( + string, position, matchEndPosition, replaceValueString); + } - // d. Let result be the string-concatenation of result, stringSlice, - // and replacement. - // TODO(joshualitt): This leaves a completely degenerate ConsString tree. - // We could be smarter here. - result = result + stringSlice + replacement; + // c. Let stringSlice be the substring of string consisting of the code + // units from endOfLastMatch (inclusive) up through position + // (exclusive). + const stringSlice = string::SubString( + string, Unsigned(SmiUntag(endOfLastMatch)), + Unsigned(SmiUntag(position))); - // e. Let endOfLastMatch be position + searchLength. - endOfLastMatch = position + searchLength; + // d. Let result be the string-concatenation of result, stringSlice, + // and replacement. + // TODO(joshualitt): This leaves a completely degenerate ConsString tree. + // We could be smarter here. + result = result + stringSlice + replacement; - position = - AbstractStringIndexOf(string, searchString, position + advanceBy); - } + // e. Let endOfLastMatch be position + searchLength. + endOfLastMatch = position + searchLength; - // 15. If endOfLastMatch < the length of string, then - if (endOfLastMatch < string.length_smi) { - // a. Let result be the string-concatenation of result and the substring - // of string consisting of the code units from endOfLastMatch - // (inclusive) up through the final code unit of string (inclusive). - result = result + - string::SubString( - string, Unsigned(SmiUntag(endOfLastMatch)), - Unsigned(string.length_intptr)); - } + position = + AbstractStringIndexOf(string, searchString, position + advanceBy); + } - // 16. Return result. - return result; + // 15. If endOfLastMatch < the length of string, then + if (endOfLastMatch < string.length_smi) { + // a. Let result be the string-concatenation of result and the substring + // of string consisting of the code units from endOfLastMatch + // (inclusive) up through the final code unit of string (inclusive). + result = result + + string::SubString( + string, Unsigned(SmiUntag(endOfLastMatch)), + Unsigned(string.length_intptr)); } + + // 16. Return result. + return result; +} } |