Skip to content

Commit

Permalink
Cherry-pick 275255@main (3790f1e). https://bugs.webkit.org/show_bug.c…
Browse files Browse the repository at this point in the history
…gi?id=246274

    [JSC] Don't optimize String.prototype.replace for RegExp searchValue with non-numeric lastIndex.
    https://bugs.webkit.org/show_bug.cgi?id=246274

    Reviewed by Alexey Shvayka.

    In DFGByteCodeParser, String.prototype.replace with a RegExp object as searchValue is inlined into a StringReplace node.
    So after DFG, lastIndex is no longer read and updated. Therefore, searchValue.lastIndex.toString is no longer invoked.
    This patch changes the code so that it doesn't inline if searchValue.lastIndex isn't numeric.

    https://tc39.es/ecma262/#sec-string.prototype.replace

    * JSTests/stress/string-replace-regexp-deopt-lastindex.js: Added.
    (shouldBe):
    (foo.regexLastIndex.toString):
    (foo):
    * Source/JavaScriptCore/dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::addStringReplacePrimordialChecks):

    Canonical link: https://commits.webkit.org/275255@main

Canonical link: https://commits.webkit.org/274313.184@webkitglib/2.44
  • Loading branch information
sosukesuzuki authored and aperezdc committed Apr 30, 2024
1 parent 72e4315 commit f923d49
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
22 changes: 22 additions & 0 deletions JSTests/stress/string-replace-regexp-deopt-lastindex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error('bad value: ' + actual);
}

let count = 0;
function foo() {
for (let i = 0; i < 1e6; ++i) {
let r = /abcd/;
regexLastIndex = {};
regexLastIndex.toString = function () {
count++;
return "1";
};
r.lastIndex = regexLastIndex;
"test".replace(r, "cons")
}
}

foo();

shouldBe(count, 1e6);
8 changes: 8 additions & 0 deletions Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3968,6 +3968,14 @@ class FixupPhase : public Phase {
m_indexInBlock, SpecNone, Check, node->origin,
Edge(searchRegExp, RegExpObjectUse));

// Check that searchRegExp.lastIndex is a number
Node* lastIndexProperty = m_insertionSet.insertNode(
m_indexInBlock, SpecNone, GetRegExpObjectLastIndex, node->origin,
Edge(searchRegExp, RegExpObjectUse));
m_insertionSet.insertNode(
m_indexInBlock, SpecNone, Check, node->origin,
Edge(lastIndexProperty, NumberUse));

auto emitPrimordialCheckFor = [&] (JSValue primordialProperty, UniquedStringImpl* propertyUID) {
m_graph.identifiers().ensure(propertyUID);
Node* actualProperty = m_insertionSet.insertNode(
Expand Down

0 comments on commit f923d49

Please sign in to comment.