Changeset 195387 in webkit


Ignore:
Timestamp:
Jan 20, 2016 3:11:32 PM (8 years ago)
Author:
benjamin@webkit.org
Message:

[JSC] The register allocator can use a dangling pointer when selecting a spill candidate
https://bugs.webkit.org/show_bug.cgi?id=153287

Reviewed by Mark Lam.

A tricky bug I discovered while experimenting with live range breaking.

We have the following initial conditions:
-UseCounts is slow, so we only compute it once for all the iterations

of the allocator.

-The only new Tmps we create are for spills and refills. They are unspillable

by definition so it is fine to not update UseCounts accordingly.

But, in selectSpill(), we go over all the spill candidates and select the best
one based on its score. The score() lambda uses useCounts, it cannot be used
with a new Tmps created for something we already spilled.

The first time we use score is correct, we started by skipping all the unspillable
Tmps from the candidate. The next use was incorrect: we were checking unspillableTmps
*after* calling score().

The existing tests did not catch this due to back luck. I added an assertion
to find similar problems in the future.

  • b3/air/AirIteratedRegisterCoalescing.cpp:
  • b3/air/AirUseCounts.h:
Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r195383 r195387  
     12016-01-20  Benjamin Poulain  <benjamin@webkit.org>
     2
     3        [JSC] The register allocator can use a dangling pointer when selecting a spill candidate
     4        https://bugs.webkit.org/show_bug.cgi?id=153287
     5
     6        Reviewed by Mark Lam.
     7
     8        A tricky bug I discovered while experimenting with live range breaking.
     9
     10        We have the following initial conditions:
     11        -UseCounts is slow, so we only compute it once for all the iterations
     12         of the allocator.
     13        -The only new Tmps we create are for spills and refills. They are unspillable
     14         by definition so it is fine to not update UseCounts accordingly.
     15
     16        But, in selectSpill(), we go over all the spill candidates and select the best
     17        one based on its score. The score() lambda uses useCounts, it cannot be used
     18        with a new Tmps created for something we already spilled.
     19
     20        The first time we use score is correct, we started by skipping all the unspillable
     21        Tmps from the candidate. The next use was incorrect: we were checking unspillableTmps
     22        *after* calling score().
     23
     24        The existing tests did not catch this due to back luck. I added an assertion
     25        to find similar problems in the future.
     26
     27        * b3/air/AirIteratedRegisterCoalescing.cpp:
     28        * b3/air/AirUseCounts.h:
     29
    1302016-01-20  Saam barati  <sbarati@apple.com>
    231
  • trunk/Source/JavaScriptCore/b3/air/AirIteratedRegisterCoalescing.cpp

    r195307 r195387  
    962962        ++iterator;
    963963        for (;iterator != m_spillWorklist.end(); ++iterator) {
     964            if (m_unspillableTmps.contains(*iterator))
     965                continue;
     966
    964967            double tmpScore = score(AbsoluteTmpMapper<type>::tmpFromAbsoluteIndex(*iterator));
    965968            if (tmpScore > maxScore) {
    966                 if (m_unspillableTmps.contains(*iterator))
    967                     continue;
    968 
    969969                victimIterator = iterator;
    970970                maxScore = tmpScore;
  • trunk/Source/JavaScriptCore/b3/air/AirUseCounts.h

    r195307 r195387  
    9898    }
    9999
    100     const Counts& operator[](const Thing& arg) const { return m_counts.find(arg)->value; }
     100    const Counts& operator[](const Thing& arg) const
     101    {
     102        auto iterator = m_counts.find(arg);
     103        ASSERT(iterator != m_counts.end());
     104        return iterator->value;
     105    }
    101106
    102107    void dump(PrintStream& out) const
Note: See TracChangeset for help on using the changeset viewer.