Changeset 195446 in webkit


Ignore:
Timestamp:
Jan 21, 2016 11:24:36 PM (8 years ago)
Author:
benjamin@webkit.org
Message:

[JSC] The IRC allocator can mess up the degree of Tmps interfering with move-related Tmps
https://bugs.webkit.org/show_bug.cgi?id=153340

Reviewed by Filip Pizlo.

The JavaScriptCore tests uncovered an interested bug in the iterated register
coalescing allocator. When coalescing a move under the right conditions, it is
possible to mess-up the graph for the Tmps interfering with the coalesced Tmps.

Some context first:
-When coalescing a move, we alias one Tmp to another. Let say that we had

Move X, Y

the coalescing may alias Y to X: Y->X.

-Since X and Y are equivalent after coalescing, any interference

edge with Y is "moved" to X.
The way this was done was to add an edge to X for every edge there was with Y.
Say we had an edge R--Y, we add an edge R--X.
Adding an edge increases the degree of R and Y. The degree of R was then
fixed by calling decrementDegree() on it.

-decrementDegree() is non trivial. It will move the Tmp to the right list

for further processing if the Tmp's degree becomes lower than the number
of available registers.

The bug appear in a particular case. Say we have 3 Tmp, A, B, and C.
-A and B are move related, they can be coalesced.
-A has an interference edge with C.
-B does not have and interfence edge with C.
-C's degree is exactly the number of avaialble registers/colors minus one (k - 1).

-> This implies C is already in its list.

We coalesce A and B into B (A->B).
-The first step, addEdgeDistinct() adds an edge between B and C. The degrees of

B and C are increased by one. The degree of C becomes k.

-Next, decrementDegree() is called on C. Its degree decreases to k-1.

Because of the change from k to k-1, decrementDegree() adds C to a list again.

We have two kinds of bugs depending on the test:
-A Tmp can be added to the simplifyWorklist several time.
-A Tmp can be in both simplifyWorklist and freezeWorklist (because its move-related

status changed since the last decrementDegree()).

In both cases, the Tmps interfering with the duplicated Tmp will end up with
a degree lower than their real value.

  • b3/air/AirIteratedRegisterCoalescing.cpp:
Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r195440 r195446  
     12016-01-21  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        [JSC] The IRC allocator can mess up the degree of Tmps interfering with move-related Tmps
     4        https://bugs.webkit.org/show_bug.cgi?id=153340
     5
     6        Reviewed by Filip Pizlo.
     7
     8        The JavaScriptCore tests uncovered an interested bug in the iterated register
     9        coalescing allocator. When coalescing a move under the right conditions, it is
     10        possible to mess-up the graph for the Tmps interfering with the coalesced Tmps.
     11
     12        Some context first:
     13        -When coalescing a move, we alias one Tmp to another. Let say that we had
     14             Move X, Y
     15         the coalescing may alias Y to X: Y->X.
     16        -Since X and Y are equivalent after coalescing, any interference
     17         edge with Y is "moved" to X.
     18         The way this was done was to add an edge to X for every edge there was with Y.
     19         Say we had an edge R--Y, we add an edge R--X.
     20         Adding an edge increases the degree of R and Y. The degree of R was then
     21         fixed by calling decrementDegree() on it.
     22        -decrementDegree() is non trivial. It will move the Tmp to the right list
     23         for further processing if the Tmp's degree becomes lower than the number
     24         of available registers.
     25
     26        The bug appear in a particular case. Say we have 3 Tmp, A, B, and C.
     27        -A and B are move related, they can be coalesced.
     28        -A has an interference edge with C.
     29        -B does not have and interfence edge with C.
     30        -C's degree is exactly the number of avaialble registers/colors minus one (k - 1).
     31         -> This implies C is already in its list.
     32
     33        We coalesce A and B into B (A->B).
     34        -The first step, addEdgeDistinct() adds an edge between B and C. The degrees of
     35         B and C are increased by one. The degree of C becomes k.
     36        -Next, decrementDegree() is called on C. Its degree decreases to k-1.
     37         Because of the change from k to k-1, decrementDegree() adds C to a list again.
     38
     39        We have two kinds of bugs depending on the test:
     40        -A Tmp can be added to the simplifyWorklist several time.
     41        -A Tmp can be in both simplifyWorklist and freezeWorklist (because its move-related
     42         status changed since the last decrementDegree()).
     43        In both cases, the Tmps interfering with the duplicated Tmp will end up with
     44        a degree lower than their real value.
     45
     46        * b3/air/AirIteratedRegisterCoalescing.cpp:
     47
    1482016-01-21  Andreas Kling  <akling@apple.com>
    249
  • trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp

    r195395 r195446  
    292292    }
    293293
     294
     295    bool addEdgeDistinctWithoutDegreeChange(IndexType a, IndexType b)
     296    {
     297        ASSERT(a != b);
     298        if (m_interferenceEdges.add(InterferenceEdge(a, b)).isNewEntry) {
     299            if (!isPrecolored(a)) {
     300                ASSERT(!m_adjacencyList[a].contains(b));
     301                m_adjacencyList[a].append(b);
     302            }
     303
     304            if (!isPrecolored(b)) {
     305                ASSERT(!m_adjacencyList[b].contains(a));
     306                m_adjacencyList[b].append(a);
     307            }
     308            return true;
     309        }
     310        return false;
     311    }
     312
    294313    bool isMoveRelated(IndexType tmpIndex)
    295314    {
     
    366385
    367386        forEachAdjacent(v, [this, u] (IndexType adjacentTmpIndex) {
    368             addEdgeDistinct(adjacentTmpIndex, u);
    369             decrementDegree(adjacentTmpIndex);
     387            if (addEdgeDistinctWithoutDegreeChange(adjacentTmpIndex, u)) {
     388                // If we added a new edge between the adjacentTmp and u, it replaces the edge
     389                // that existed with v.
     390                // The degree of adjacentTmp remains the same since the edge just changed from u to v.
     391                // All we need to do is update the degree of u.
     392                if (!isPrecolored(u))
     393                    m_degrees[u]++;
     394            } else {
     395                // If we already had an edge between the adjacentTmp and u, the degree of u
     396                // is already correct. The degree of the adjacentTmp decreases since the edge
     397                // with v is no longer relevant (we can think of it as merged with the edge with u).
     398                decrementDegree(adjacentTmpIndex);
     399            }
    370400        });
    371401
Note: See TracChangeset for help on using the changeset viewer.