Commit 5914c29e authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[regexp] Port RegExp.prototype[@@replace] to Torque

Just the outermost wrapper function (which does almost nothing).

Bug: v8:8976
Change-Id: I8137f86bde5e10ba7edd5051e7c86bfc631bfe94
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1528531
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Reviewed-by: 's avatarSimon Zünd <szuend@chromium.org>
Reviewed-by: 's avatarPeter Wong <peter.wm.wong@gmail.com>
Cr-Commit-Position: refs/heads/master@{#60402}
parent 955dfb50
......@@ -936,6 +936,8 @@ torque_files = [
"src/builtins/iterator.tq",
"src/builtins/object-fromentries.tq",
"src/builtins/proxy-revoke.tq",
"src/builtins/regexp.tq",
"src/builtins/regexp-replace.tq",
"src/builtins/string-endswith.tq",
"src/builtins/string-html.tq",
"src/builtins/string-repeat.tq",
......@@ -981,6 +983,8 @@ torque_namespaces = [
"iterator",
"object",
"proxy",
"regexp",
"regexp-replace",
"string",
"string-html",
"string-repeat",
......
......@@ -4210,11 +4210,12 @@ void Genesis::InitializeGlobal_harmony_string_matchall() {
InstallFunctionAtSymbol(isolate(), regexp_prototype,
factory()->match_all_symbol(), "[Symbol.matchAll]",
Builtins::kRegExpPrototypeMatchAll, 1, true);
DCHECK_EQ(JSRegExp::kSymbolMatchAllFunctionDescriptorIndex,
regexp_prototype->map()->LastAdded());
Handle<Map> regexp_prototype_map(regexp_prototype->map(), isolate());
Map::SetShouldBeFastPrototypeMap(regexp_prototype_map, true, isolate());
native_context()->set_regexp_prototype_map(*regexp_prototype_map);
DCHECK_EQ(JSRegExp::kSymbolMatchAllFunctionDescriptorIndex,
regexp_prototype->map()->LastAdded());
}
{ // --- R e g E x p S t r i n g I t e r a t o r ---
......
......@@ -1310,6 +1310,12 @@ Cast<HeapNumber>(o: HeapObject): HeapNumber
goto CastError;
}
Cast<JSRegExp>(o: HeapObject): JSRegExp
labels CastError {
if (IsJSRegExp(o)) return %RawDownCast<JSRegExp>(o);
goto CastError;
}
Cast<Map>(implicit context: Context)(o: HeapObject): Map
labels CastError {
if (IsMap(o)) return %RawDownCast<Map>(o);
......@@ -2019,6 +2025,7 @@ extern macro IsCallable(HeapObject): bool;
extern macro IsConstructor(HeapObject): bool;
extern macro IsJSArray(HeapObject): bool;
extern macro IsJSProxy(HeapObject): bool;
extern macro IsJSRegExp(HeapObject): bool;
extern macro IsMap(HeapObject): bool;
extern macro IsJSFunction(HeapObject): bool;
extern macro IsJSObject(HeapObject): bool;
......
......@@ -935,8 +935,6 @@ namespace internal {
TFJ(RegExpPrototypeUnicodeGetter, 0, kReceiver) \
CPP(RegExpRightContextGetter) \
\
/* ES #sec-regexp.prototype-@@replace */ \
TFJ(RegExpPrototypeReplace, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES #sec-regexp.prototype-@@split */ \
TFJ(RegExpPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* RegExp helpers */ \
......
......@@ -3032,65 +3032,10 @@ TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) {
}
BIND(&runtime);
Return(CallRuntime(Runtime::kRegExpReplace, context, regexp, string,
Return(CallRuntime(Runtime::kRegExpReplaceRT, context, regexp, string,
replace_value));
}
// ES#sec-regexp.prototype-@@replace
// RegExp.prototype [ @@replace ] ( string, replaceValue )
TF_BUILTIN(RegExpPrototypeReplace, RegExpBuiltinsAssembler) {
const int kStringArg = 0;
const int kReplaceValueArg = 1;
TNode<IntPtrT> argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
TNode<Object> maybe_receiver = args.GetReceiver();
TNode<Object> maybe_string = args.GetOptionalArgumentValue(kStringArg);
TNode<Object> replace_value = args.GetOptionalArgumentValue(kReplaceValueArg);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
// RegExpPrototypeReplace is a bit of a beast - a summary of dispatch logic:
//
// if (!IsFastRegExp(receiver)) CallRuntime(RegExpReplace)
// if (IsCallable(replace)) {
// if (IsGlobal(receiver)) {
// // Called 'fast-path' but contains several runtime calls.
// ReplaceGlobalCallableFastPath()
// } else {
// CallRuntime(StringReplaceNonGlobalRegExpWithFunction)
// }
// } else {
// if (replace.contains("$")) {
// CallRuntime(RegExpReplace)
// } else {
// ReplaceSimpleStringFastPath()
// }
// }
// Ensure {maybe_receiver} is a JSReceiver.
ThrowIfNotJSReceiver(context, maybe_receiver,
MessageTemplate::kIncompatibleMethodReceiver,
"RegExp.prototype.@@replace");
Node* const receiver = maybe_receiver;
// Convert {maybe_string} to a String.
TNode<String> const string = ToString_Inline(context, maybe_string);
// Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance?
Label stub(this), runtime(this, Label::kDeferred);
BranchIfFastRegExp(context, receiver, &stub, &runtime);
BIND(&stub);
args.PopAndReturn(CallBuiltin(Builtins::kRegExpReplace, context, receiver,
string, replace_value));
BIND(&runtime);
args.PopAndReturn(CallRuntime(Runtime::kRegExpReplace, context, receiver,
string, replace_value));
}
class RegExpStringIteratorAssembler : public RegExpBuiltinsAssembler {
public:
explicit RegExpStringIteratorAssembler(compiler::CodeAssemblerState* state)
......
......@@ -32,7 +32,6 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
TNode<BoolT> IsRegExp(TNode<Context> context, TNode<Object> maybe_receiver);
protected:
TNode<Smi> SmiZero();
TNode<IntPtrT> IntPtrZero();
......
// 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.
namespace regexp_replace {
extern transitioning builtin
RegExpReplace(implicit context: Context)(JSRegExp, String, Object): Object;
extern transitioning runtime
RegExpReplaceRT(Context, JSReceiver, String, Object): String;
transitioning javascript builtin RegExpPrototypeReplace(
context: Context, receiver: Object, ...arguments): Object {
const methodName: constexpr string = 'RegExp.prototype.@@replace';
// RegExpPrototypeReplace is a bit of a beast - a summary of dispatch logic:
//
// if (!IsFastRegExp(receiver)) CallRuntime(RegExpReplace)
// if (IsCallable(replace)) {
// if (IsGlobal(receiver)) {
// // Called 'fast-path' but contains several runtime calls.
// ReplaceGlobalCallableFastPath()
// } else {
// CallRuntime(StringReplaceNonGlobalRegExpWithFunction)
// }
// } else {
// if (replace.contains("$")) {
// CallRuntime(RegExpReplace)
// } else {
// ReplaceSimpleStringFastPath()
// }
// }
const string: Object = arguments[0];
const replaceValue: Object = arguments[1];
// Let rx be the this value.
// If Type(rx) is not Object, throw a TypeError exception.
const rx = Cast<JSReceiver>(receiver)
otherwise ThrowTypeError(kIncompatibleMethodReceiver, methodName);
// Let S be ? ToString(string).
const s = ToString_Inline(context, string);
// Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance?
if (regexp::BranchIfFastRegExp(context, rx)) {
return RegExpReplace(UnsafeCast<JSRegExp>(rx), s, replaceValue);
} else {
return RegExpReplaceRT(context, rx, s, replaceValue);
}
}
}
// 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 macro RegExpBuiltinsAssembler::BranchIfFastRegExp(Context, Object):
never labels IsFast, IsSlow;
}
......@@ -1684,7 +1684,7 @@ RUNTIME_FUNCTION(Runtime_RegExpSplit) {
// Slow path for:
// ES#sec-regexp.prototype-@@replace
// RegExp.prototype [ @@replace ] ( string, replaceValue )
RUNTIME_FUNCTION(Runtime_RegExpReplace) {
RUNTIME_FUNCTION(Runtime_RegExpReplaceRT) {
HandleScope scope(isolate);
DCHECK_EQ(3, args.length());
......
......@@ -369,7 +369,7 @@ namespace internal {
F(RegExpExec, 4, 1) \
F(RegExpExecMultiple, 4, 1) \
F(RegExpInitializeAndCompile, 3, 1) \
F(RegExpReplace, 3, 1) \
F(RegExpReplaceRT, 3, 1) \
F(RegExpSplit, 3, 1) \
F(StringReplaceNonGlobalRegExpWithFunction, 3, 1) \
F(StringSplit, 3, 1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment