⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 269107 in webkit


Ignore:
Timestamp:
Oct 28, 2020, 10:32:26 AM (6 years ago)
Author:
rmorisset@apple.com
Message:

DFGIntegerRangeOptimization is wrong for Upsilon (as 'shadow' nodes are not in SSA form)
​https://bugs.webkit.org/show_bug.cgi?id=218073

Reviewed by Saam Barati.

JSTests:

The only testcase I managed to get for this bug loops forever when not crashing.
So I use a 1s timeout through --watchdog=1000.

  • stress/bounds-checking-in-cold-loop.js: Added.

(true.vm.ftlTrue):

Source/JavaScriptCore:

In DFGIntegerRangeOptimization, when visiting an Upsilon node, we call setEquivalence, that calls setRelationship.
But despite its name, this function does not overwrite a pre-existing relationship, it simply replaces it by an over-approximation of the intersection of the old and new relationship (see the filter method).
Since the old relationship is always (by definition) an over-approximation of this intersection, it will often do nothing at all if it cannot find a closer approximation.
This is a problem specifically for Upsilon nodes, because several of them can store to the same "shadow node" corresponding to a given Phi, so they are the only case where there can already be a completely different relationship for the same nodes (coming from a different Upsilon).

The fix is very simple thanks to a suggestion by Phil: we just remove all relationships referring to the shadow node just before executing an Upsilon.
This is correct since the upsilon effectively kills that shadow node, before making it live again with a different value, and we already aggressively prune the relationshipMaps by liveness.

  • dfg/DFGIntegerRangeOptimizationPhase.cpp:
Location:
trunk
Files:
1 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r268956 r269107  
     12020-10-28  Robin Morisset  <rmorisset@apple.com>
     2
     3        DFGIntegerRangeOptimization is wrong for Upsilon (as 'shadow' nodes are not in SSA form)
     4        https://bugs.webkit.org/show_bug.cgi?id=218073
     5
     6        Reviewed by Saam Barati.
     7
     8        The only testcase I managed to get for this bug loops forever when not crashing.
     9        So I use a 1s timeout through --watchdog=1000.
     10
     11        * stress/bounds-checking-in-cold-loop.js: Added.
     12        (true.vm.ftlTrue):
     13
    1142020-10-24  Yusuke Suzuki  <ysuzuki@apple.com>
    215
  • trunk/Source/JavaScriptCore/ChangeLog

    r269054 r269107  
     12020-10-28  Robin Morisset  <rmorisset@apple.com>
     2
     3        DFGIntegerRangeOptimization is wrong for Upsilon (as 'shadow' nodes are not in SSA form)
     4        https://bugs.webkit.org/show_bug.cgi?id=218073
     5
     6        Reviewed by Saam Barati.
     7
     8        In DFGIntegerRangeOptimization, when visiting an Upsilon node, we call setEquivalence, that calls setRelationship.
     9        But despite its name, this function does not overwrite a pre-existing relationship, it simply replaces it by an over-approximation of the intersection of the old and new relationship (see the filter method).
     10        Since the old relationship is always (by definition) an over-approximation of this intersection, it will often do nothing at all if it cannot find a closer approximation.
     11        This is a problem specifically for Upsilon nodes, because several of them can store to the same "shadow node" corresponding to a given Phi, so they are the only case where there can already be a completely different relationship for the same nodes (coming from a different Upsilon).
     12
     13        The fix is very simple thanks to a suggestion by Phil: we just remove all relationships referring to the shadow node just before executing an Upsilon.
     14        This is correct since the upsilon effectively kills that shadow node, before making it live again with a different value, and we already aggressively prune the relationshipMaps by liveness.
     15
     16        * dfg/DFGIntegerRangeOptimizationPhase.cpp:
     17
    1182020-10-27  Michael Catanzaro  <mcatanzaro@gnome.org>
    219
  • trunk/Source/JavaScriptCore/dfg/DFGIntegerRangeOptimizationPhase.cpp

    r267726 r269107  
    15041504           
    15051505        case Upsilon: {
    1506             setEquivalence(
    1507                 node->child1().node(),
    1508                 NodeFlowProjection(node->phi(), NodeFlowProjection::Shadow));
     1506            auto shadowNode = NodeFlowProjection(node->phi(), NodeFlowProjection::Shadow);
     1507            // We must first remove all relationships involving the shadow node, because setEquivalence does not overwrite them.
     1508            // Overwriting is only required here because the shadowNodes are not in SSA form (can be written to by several Upsilons).
     1509            // Another way to think of it, is that we are maintaining the invariant that relationshipMaps are pruned by liveness.
     1510            kill(shadowNode);
     1511            setEquivalence(node->child1().node(), shadowNode);
    15091512            break;
    15101513        }
    … …  
    15191522        default:
    15201523            break;
     1524        }
     1525    }
     1526
     1527    void kill(NodeFlowProjection node)
     1528    {
     1529        m_relationships.remove(node);
     1530
     1531        for (auto& relationships : m_relationships.values()) {
     1532            unsigned i = 0, j = 0;
     1533            while (i < relationships.size()) {
     1534                const Relationship& rel = relationships[i++];
     1535                ASSERT(rel.left() != node);
     1536                if (rel.right() != node)
     1537                    relationships[j++] = rel;
     1538            }
     1539            relationships.shrink(j);
    15211540        }
    15221541    }
    … …  
    15611580       
    15621581        if (DFGIntegerRangeOptimizationPhaseInternal::verbose)
    1563             dataLog("    Setting: ", relationship, " (ttl = ", timeToLive, ")\n");
     1582            dataLogLn("    Setting: ", relationship, " (ttl = ", timeToLive, ")");
    15641583
    15651584        auto result = relationshipMap.add(
    … …  
    16431662                    ASSERT(filtered.left() == relationship.left());
    16441663                    otherRelationship = filtered;
     1664                    if (DFGIntegerRangeOptimizationPhaseInternal::verbose)
     1665                        dataLogLn("      filtered: ", filtered);
    16451666                    found = true;
    16461667                }
    … …  
    17001721            }
    17011722        }
    1702        
     1723
    17031724        if (!found)
    17041725            relationships.append(relationship);
Note: See TracChangeset for help on using the changeset viewer.