Skip to content

Commit

Permalink
Bug 1831314 part 7 - Split RegExpBuiltinExec and RegExpExec into sepa…
Browse files Browse the repository at this point in the history
…rate versions for forTest. r=iain

Callers typically pass a constant true/false so we can get rid of a CacheIR guard in this case.

Differential Revision: https://phabricator.services.mozilla.com/D177621
  • Loading branch information
jandem committed May 12, 2023
1 parent 3146c8d commit dc74d01
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 49 deletions.
27 changes: 16 additions & 11 deletions js/src/builtin/RegExp.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ function RegExpMatch(string) {
}

// Step 5.
return RegExpBuiltinExec(rx, S, false);
return RegExpBuiltinExec(rx, S);
}

// Stes 4-6
Expand All @@ -165,7 +165,7 @@ function RegExpMatchSlowPath(rx, S) {

// Step 5.
if (!callFunction(std_String_includes, flags, "g")) {
return RegExpExec(rx, S, false);
return RegExpExec(rx, S);
}

// Step 6.a.
Expand All @@ -183,7 +183,7 @@ function RegExpMatchSlowPath(rx, S) {
// Step 6.e.
while (true) {
// Step 6.e.i.
var result = RegExpExec(rx, S, false);
var result = RegExpExec(rx, S);

// Step 6.e.ii.
if (result === null) {
Expand Down Expand Up @@ -427,7 +427,7 @@ function RegExpReplaceSlowPath(
// Steps 11-12.
while (true) {
// Step 12.a.
var result = RegExpExec(rx, S, false);
var result = RegExpExec(rx, S);

// Step 12.b.
if (result === null) {
Expand Down Expand Up @@ -976,7 +976,7 @@ function RegExpSearch(string) {
// Steps 6-10.
function RegExpSearchSlowPath(rx, S, previousLastIndex) {
// Step 6.
var result = RegExpExec(rx, S, false);
var result = RegExpExec(rx, S);

// Step 7.
var currentLastIndex = rx.lastIndex;
Expand Down Expand Up @@ -1102,7 +1102,7 @@ function RegExpSplit(string, limit) {
if (optimizable) {
z = RegExpMatcher(splitter, S, 0);
} else {
z = RegExpExec(splitter, S, false);
z = RegExpExec(splitter, S);
}

// Step 17.b.
Expand Down Expand Up @@ -1148,7 +1148,7 @@ function RegExpSplit(string, limit) {
splitter.lastIndex = q;

// Step 19.b.
z = RegExpExec(splitter, S, false);
z = RegExpExec(splitter, S);

// Step 19.c.
if (z === null) {
Expand Down Expand Up @@ -1236,10 +1236,11 @@ function RegExp_prototype_Exec(string) {
var S = ToString(string);

// Step 6.
return RegExpBuiltinExec(R, S, false);
return RegExpBuiltinExec(R, S);
}

function UnwrapAndCallRegExpBuiltinExec(R, S, forTest) {
assert(typeof forTest === "boolean", "forTest must be a boolean");
return callFunction(
CallRegExpMethodIfWrapped,
R,
Expand All @@ -1250,7 +1251,11 @@ function UnwrapAndCallRegExpBuiltinExec(R, S, forTest) {
}

function CallRegExpBuiltinExec(S, forTest) {
return RegExpBuiltinExec(this, S, forTest);
assert(typeof forTest === "boolean", "forTest must be a boolean");
if (forTest) {
return RegExpBuiltinExecForTest(this, S);
}
return RegExpBuiltinExec(this, S);
}

// ES6 21.2.5.13.
Expand All @@ -1265,7 +1270,7 @@ function RegExpTest(string) {
var S = ToString(string);

// Steps 5-6.
return RegExpExec(R, S, true);
return RegExpExecForTest(R, S);
}

// ES 2016 draft Mar 25, 2016 21.2.4.2.
Expand Down Expand Up @@ -1519,7 +1524,7 @@ function RegExpStringIteratorNext() {
}

// Step 9.
var match = RegExpExec(regexp, string, false);
var match = RegExpExec(regexp, string);

// Step 10.
if (match === null) {
Expand Down
39 changes: 14 additions & 25 deletions js/src/jit/CacheIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6572,21 +6572,18 @@ static void EmitGuardLastIndexIsNonNegativeInt32(CacheIRWriter& writer,
writer.guardInt32IsNonNegative(lastIndexId);
}

AttachDecision
InlinableNativeIRGenerator::tryAttachIntrinsicRegExpBuiltinExec() {
// Self-hosted code calls this with (regexp, string, boolean) arguments.
MOZ_ASSERT(argc_ == 3);
AttachDecision InlinableNativeIRGenerator::tryAttachIntrinsicRegExpBuiltinExec(
InlinableNative native) {
// Self-hosted code calls this with (regexp, string) arguments.
MOZ_ASSERT(argc_ == 2);
MOZ_ASSERT(args_[0].isObject());
MOZ_ASSERT(args_[1].isString());
MOZ_ASSERT(args_[2].isBoolean());

RegExpObject* re = &args_[0].toObject().as<RegExpObject>();
if (!HasOptimizableLastIndexSlot(re, cx_)) {
return AttachDecision::NoAction;
}

bool forTest = args_[2].toBoolean();

// Initialize the input operand.
initializeInputOperand();

Expand All @@ -6600,11 +6597,7 @@ InlinableNativeIRGenerator::tryAttachIntrinsicRegExpBuiltinExec() {
ValOperandId arg1Id = writer.loadArgumentFixedSlot(ArgumentKind::Arg1, argc_);
StringOperandId inputId = writer.guardToString(arg1Id);

ValOperandId arg2Id = writer.loadArgumentFixedSlot(ArgumentKind::Arg2, argc_);
Int32OperandId forTestId = writer.guardBooleanToInt32(arg2Id);
writer.guardSpecificInt32(forTestId, forTest);

if (forTest) {
if (native == InlinableNative::IntrinsicRegExpBuiltinExecForTest) {
writer.regExpBuiltinExecTestResult(regExpId, inputId);
} else {
writer.regExpBuiltinExecMatchResult(regExpId, inputId);
Expand All @@ -6615,12 +6608,12 @@ InlinableNativeIRGenerator::tryAttachIntrinsicRegExpBuiltinExec() {
return AttachDecision::Attach;
}

AttachDecision InlinableNativeIRGenerator::tryAttachIntrinsicRegExpExec() {
// Self-hosted code calls this with (object, string, boolean) arguments.
MOZ_ASSERT(argc_ == 3);
AttachDecision InlinableNativeIRGenerator::tryAttachIntrinsicRegExpExec(
InlinableNative native) {
// Self-hosted code calls this with (object, string) arguments.
MOZ_ASSERT(argc_ == 2);
MOZ_ASSERT(args_[0].isObject());
MOZ_ASSERT(args_[1].isString());
MOZ_ASSERT(args_[2].isBoolean());

if (!args_[0].toObject().is<RegExpObject>()) {
return AttachDecision::NoAction;
Expand Down Expand Up @@ -6657,8 +6650,6 @@ AttachDecision InlinableNativeIRGenerator::tryAttachIntrinsicRegExpExec() {
}
JSFunction* execFunction = &execVal.toObject().as<JSFunction>();

bool forTest = args_[2].toBoolean();

// Initialize the input operand.
initializeInputOperand();

Expand All @@ -6680,11 +6671,7 @@ AttachDecision InlinableNativeIRGenerator::tryAttachIntrinsicRegExpExec() {
ValOperandId arg1Id = writer.loadArgumentFixedSlot(ArgumentKind::Arg1, argc_);
StringOperandId inputId = writer.guardToString(arg1Id);

ValOperandId arg2Id = writer.loadArgumentFixedSlot(ArgumentKind::Arg2, argc_);
Int32OperandId forTestId = writer.guardBooleanToInt32(arg2Id);
writer.guardSpecificInt32(forTestId, forTest);

if (forTest) {
if (native == InlinableNative::IntrinsicRegExpExecForTest) {
writer.regExpBuiltinExecTestResult(regExpId, inputId);
} else {
writer.regExpBuiltinExecMatchResult(regExpId, inputId);
Expand Down Expand Up @@ -10600,9 +10587,11 @@ AttachDecision InlinableNativeIRGenerator::tryAttachStub() {
case InlinableNative::GetFirstDollarIndex:
return tryAttachGetFirstDollarIndex();
case InlinableNative::IntrinsicRegExpBuiltinExec:
return tryAttachIntrinsicRegExpBuiltinExec();
case InlinableNative::IntrinsicRegExpBuiltinExecForTest:
return tryAttachIntrinsicRegExpBuiltinExec(native);
case InlinableNative::IntrinsicRegExpExec:
return tryAttachIntrinsicRegExpExec();
case InlinableNative::IntrinsicRegExpExecForTest:
return tryAttachIntrinsicRegExpExec(native);

// String natives.
case InlinableNative::String:
Expand Down
4 changes: 2 additions & 2 deletions js/src/jit/CacheIRGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,8 @@ class MOZ_RAII InlinableNativeIRGenerator {
AttachDecision tryAttachRegExpMatcherSearcher(InlinableNative native);
AttachDecision tryAttachRegExpPrototypeOptimizable();
AttachDecision tryAttachRegExpInstanceOptimizable();
AttachDecision tryAttachIntrinsicRegExpBuiltinExec();
AttachDecision tryAttachIntrinsicRegExpExec();
AttachDecision tryAttachIntrinsicRegExpBuiltinExec(InlinableNative native);
AttachDecision tryAttachIntrinsicRegExpExec(InlinableNative native);
AttachDecision tryAttachGetFirstDollarIndex();
AttachDecision tryAttachSubstringKernel();
AttachDecision tryAttachObjectHasPrototype();
Expand Down
2 changes: 2 additions & 0 deletions js/src/jit/InlinableNatives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ bool js::jit::CanInlineNativeCrossRealm(InlinableNative native) {
case InlinableNative::IntrinsicIsPossiblyWrappedTypedArray:
case InlinableNative::IntrinsicPossiblyWrappedTypedArrayLength:
case InlinableNative::IntrinsicRegExpBuiltinExec:
case InlinableNative::IntrinsicRegExpBuiltinExecForTest:
case InlinableNative::IntrinsicRegExpExec:
case InlinableNative::IntrinsicRegExpExecForTest:
case InlinableNative::IntrinsicTypedArrayLength:
case InlinableNative::IntrinsicTypedArrayByteOffset:
case InlinableNative::IntrinsicTypedArrayElementSize:
Expand Down
2 changes: 2 additions & 0 deletions js/src/jit/InlinableNatives.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@
_(IntrinsicTypedArrayLength) \
_(IntrinsicPossiblyWrappedTypedArrayLength) \
_(IntrinsicRegExpBuiltinExec) \
_(IntrinsicRegExpBuiltinExecForTest) \
_(IntrinsicRegExpExec) \
_(IntrinsicRegExpExecForTest) \
_(IntrinsicTypedArrayByteOffset) \
_(IntrinsicTypedArrayElementSize) \
\
Expand Down
25 changes: 14 additions & 11 deletions js/src/vm/SelfHosting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1309,32 +1309,30 @@ static bool intrinsic_TypedArrayInitFromPackedArray(JSContext* cx,
return true;
}

template <bool ForTest>
static bool intrinsic_RegExpBuiltinExec(JSContext* cx, unsigned argc,
Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 3);
MOZ_ASSERT(args.length() == 2);
MOZ_ASSERT(args[0].isObject());
MOZ_ASSERT(args[0].toObject().is<RegExpObject>());
MOZ_ASSERT(args[1].isString());
MOZ_ASSERT(args[2].isBoolean());

Rooted<RegExpObject*> obj(cx, &args[0].toObject().as<RegExpObject>());
Rooted<JSString*> string(cx, args[1].toString());
bool forTest = args[2].toBoolean();
return RegExpBuiltinExec(cx, obj, string, forTest, args.rval());
return RegExpBuiltinExec(cx, obj, string, ForTest, args.rval());
}

template <bool ForTest>
static bool intrinsic_RegExpExec(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 3);
MOZ_ASSERT(args.length() == 2);
MOZ_ASSERT(args[0].isObject());
MOZ_ASSERT(args[1].isString());
MOZ_ASSERT(args[2].isBoolean());

Rooted<JSObject*> obj(cx, &args[0].toObject());
Rooted<JSString*> string(cx, args[1].toString());
bool forTest = args[2].toBoolean();
return RegExpExec(cx, obj, string, forTest, args.rval());
return RegExpExec(cx, obj, string, ForTest, args.rval());
}

static bool intrinsic_RegExpCreate(JSContext* cx, unsigned argc, Value* vp) {
Expand Down Expand Up @@ -1995,12 +1993,17 @@ static const JSFunctionSpec intrinsic_functions[] = {
intrinsic_PossiblyWrappedTypedArrayLength, 1, 0,
IntrinsicPossiblyWrappedTypedArrayLength),
JS_FN("PromiseResolve", intrinsic_PromiseResolve, 2, 0),
JS_INLINABLE_FN("RegExpBuiltinExec", intrinsic_RegExpBuiltinExec, 3, 0,
IntrinsicRegExpBuiltinExec),
JS_INLINABLE_FN("RegExpBuiltinExec", intrinsic_RegExpBuiltinExec<false>, 2,
0, IntrinsicRegExpBuiltinExec),
JS_INLINABLE_FN("RegExpBuiltinExecForTest",
intrinsic_RegExpBuiltinExec<true>, 2, 0,
IntrinsicRegExpBuiltinExecForTest),
JS_FN("RegExpConstructRaw", regexp_construct_raw_flags, 2, 0),
JS_FN("RegExpCreate", intrinsic_RegExpCreate, 2, 0),
JS_INLINABLE_FN("RegExpExec", intrinsic_RegExpExec, 3, 0,
JS_INLINABLE_FN("RegExpExec", intrinsic_RegExpExec<false>, 2, 0,
IntrinsicRegExpExec),
JS_INLINABLE_FN("RegExpExecForTest", intrinsic_RegExpExec<true>, 2, 0,
IntrinsicRegExpExecForTest),
JS_FN("RegExpGetSubstitution", intrinsic_RegExpGetSubstitution, 5, 0),
JS_INLINABLE_FN("RegExpInstanceOptimizable", RegExpInstanceOptimizable, 1,
0, RegExpInstanceOptimizable),
Expand Down

0 comments on commit dc74d01

Please sign in to comment.