Skip to content

Commit

Permalink
Cherry-pick b0b694f. rdar://problem/100902686
Browse files Browse the repository at this point in the history
    Strength reduction analyzes RegEx.exec incorrectly and generate a hole for the result array
    https://bugs.webkit.org/show_bug.cgi?id=245464
    rdar://100494428

    Reviewed by Mark Lam.

    When employing RegExp.exec strength reductions, we need to create "undefined" entries in the result array
    instead of null entries per the EcmaScript spec for RegExp.match.

    * JSTests/stress/regexp-strengthreduce-results-noholes.js: Added.
    (runRegExp):
    (assertSameAsFirstResult):
    * Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp:
    (JSC::DFG::StrengthReductionPhase::handleNode):

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

Canonical link: https://commits.webkit.org/245886.843@safari-7613.4.1.0-branch
  • Loading branch information
msaboff authored and alancoon committed Nov 9, 2022
1 parent 34444ef commit 5ab53f3
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 7 deletions.
42 changes: 42 additions & 0 deletions JSTests/stress/regexp-strengthreduce-results-noholes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// This teset passes if it doesn't throw.

function runRegExp()
{
let m = /ab(c)?d/.exec("abd");
return m;
}

noInline(runRegExp);

let firstResult = undefined;
let firstResultKeys = undefined;

function assertSameAsFirstResult(testRun, o)
{
if (firstResult.length != o.length)
throw testRun + " results have different length than the first results";

oKeys = Object.keys(o);

if (firstResultKeys.length != oKeys.length)
throw testRun + " results have different number of keys than the first result, first result keys: " + firstResultKeys + " this result keys: " + oKeys;

for (let i = 0; i < firstResultKeys.length; i++)
{
if (firstResultKeys[i] != oKeys[i])
throw testRun + " results mismatch, first result keys: " + firstResultKeys + " this result keys: " + oKeys;
}
}

let count = 20000;

for (let i=0; i < count; i++) {
let result = runRegExp();
if (i == 0) {
firstResult = result;
firstResultKeys = Object.keys(firstResult);
continue;
}

assertSameAsFirstResult(i, result);
}
15 changes: 8 additions & 7 deletions Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,8 +743,10 @@ class StrengthReductionPhase : public Phase {
PromotedLocationDescriptor(NamedPropertyPLoc, groupsIndex));

auto materializeString = [&] (const String& string) -> Node* {
if (string.isNull())
return nullptr;
if (string.isNull()) {
return m_insertionSet.insertConstant(
m_nodeIndex, origin, jsUndefined());
}
if (string.isEmpty()) {
return m_insertionSet.insertConstant(
m_nodeIndex, origin, vm().smallStrings.emptyString());
Expand All @@ -756,11 +758,10 @@ class StrengthReductionPhase : public Phase {
};

for (unsigned i = 0; i < resultArray.size(); ++i) {
if (Node* node = materializeString(resultArray[i])) {
m_graph.m_varArgChildren.append(Edge(node, UntypedUse));
data->m_properties.append(
PromotedLocationDescriptor(IndexedPropertyPLoc, i));
}
Node* node = materializeString(resultArray[i]);
m_graph.m_varArgChildren.append(Edge(node, UntypedUse));
data->m_properties.append(
PromotedLocationDescriptor(IndexedPropertyPLoc, i));
}

Node* resultNode = m_insertionSet.insertNode(
Expand Down

0 comments on commit 5ab53f3

Please sign in to comment.