Skip to content

Commit

Permalink
Bug 1833385 - Call C++ function to flatten ropes in RegExp stubs. r=iain
Browse files Browse the repository at this point in the history
On Speedometer 3, the most common reason for the stubs failing is rope input strings.
We can avoid this by doing a `callWithABI` to a helper function to flatten the rope.

Differential Revision: https://phabricator.services.mozilla.com/D178178
  • Loading branch information
jandem committed May 17, 2023
1 parent e76581c commit 8e95328
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 21 deletions.
10 changes: 10 additions & 0 deletions js/src/jit-test/tests/regexp/rope-inputs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function test() {
var re = /abc(.+)z/;
for (var i = 0; i < 100; i++) {
assertEq(re.exec(newRope("abcd", "xyz"))[1], "dxy");
assertEq(re.test(newRope("abcd", "xyz")), true);
assertEq(re[Symbol.search](newRope(".abcd", "xyz")), 1);
assertEq(re[Symbol.match](newRope("abcd", "xyz"))[1], "dxy");
}
}
test();
55 changes: 34 additions & 21 deletions js/src/jit/CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2007,8 +2007,37 @@ static bool PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm,
// Initialize MatchPairs::pairs[0]::start to MatchPair::NoMatch
masm.store32(Imm32(MatchPair::NoMatch), firstMatchStartAddress);

// Check for a linear input string.
masm.branchIfRope(input, failure);
// Determine the set of volatile inputs to save when calling into C++ or
// regexp code.
LiveGeneralRegisterSet volatileRegs;
if (lastIndex.volatile_()) {
volatileRegs.add(lastIndex);
}
if (input.volatile_()) {
volatileRegs.add(input);
}
if (regexp.volatile_()) {
volatileRegs.add(regexp);
}

// Ensure the input string is not a rope.
Label isLinear;
masm.branchIfNotRope(input, &isLinear);
{
masm.PushRegsInMask(volatileRegs);

using Fn = JSLinearString* (*)(JSString*);
masm.setupUnalignedABICall(temp1);
masm.passABIArg(input);
masm.callWithABI<Fn, js::jit::LinearizeForCharAccessPure>();

MOZ_ASSERT(!volatileRegs.has(temp1));
masm.storeCallPointerResult(temp1);
masm.PopRegsInMask(volatileRegs);

masm.branchTestPtr(Assembler::Zero, temp1, temp1, failure);
}
masm.bind(&isLinear);

// Load the RegExpShared.
Register regexpReg = temp1;
Expand All @@ -2023,14 +2052,9 @@ static bool PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm,
Address(regexpReg, RegExpShared::offsetOfPatternAtom()),
ImmWord(0), &notAtom);
{
LiveGeneralRegisterSet regsToSave(GeneralRegisterSet::Volatile());
regsToSave.takeUnchecked(temp1);
regsToSave.takeUnchecked(temp2);
regsToSave.takeUnchecked(temp3);

masm.computeEffectiveAddress(matchPairsAddress, temp3);

masm.PushRegsInMask(regsToSave);
masm.PushRegsInMask(volatileRegs);
using Fn = RegExpRunStatus (*)(RegExpShared* re, JSLinearString* input,
size_t start, MatchPairs* matchPairs);
masm.setupUnalignedABICall(temp2);
Expand All @@ -2040,8 +2064,9 @@ static bool PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm,
masm.passABIArg(temp3);
masm.callWithABI<Fn, js::ExecuteRegExpAtomRaw>();

MOZ_ASSERT(!volatileRegs.has(temp1));
masm.storeCallInt32Result(temp1);
masm.PopRegsInMask(regsToSave);
masm.PopRegsInMask(volatileRegs);

masm.jump(&checkSuccess);
}
Expand Down Expand Up @@ -2104,18 +2129,6 @@ static bool PrepareAndExecuteRegExp(JSContext* cx, MacroAssembler& masm,
masm.storePtr(temp2, matchesAddress);
masm.storePtr(lastIndex, startIndexAddress);

// Save any volatile inputs.
LiveGeneralRegisterSet volatileRegs;
if (lastIndex.volatile_()) {
volatileRegs.add(lastIndex);
}
if (input.volatile_()) {
volatileRegs.add(input);
}
if (regexp.volatile_()) {
volatileRegs.add(regexp);
}

// Execute the RegExp.
masm.computeEffectiveAddress(
Address(FramePointer, inputOutputDataStartOffset), temp2);
Expand Down

0 comments on commit 8e95328

Please sign in to comment.