United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-8007294 : ReduceFieldZeroing doesn't check for dependent load and can lead to incorrect execution

Details
Type:
Bug
Submit Date:
2013-01-31
Status:
Resolved
Updated Date:
2014-04-10
Project Name:
JDK
Resolved Date:
2013-02-25
Component:
hotspot
OS:
Sub-Component:
compiler
CPU:
Priority:
P3
Resolution:
Fixed
Affected Versions:
Fixed Versions:
hs25 (b21)

Related Reports
Backport:
Backport:
Backport:
Backport:
Backport:

Sub Tasks

Description
Issue spotted during work on incremental inlining. When stores are captured during igvns, depending on the order the nodes are processed the resulting may produce incorrect results. The following test case run with debug option -XX:+AlwaysIncrementalInline produces an incorrect result:

public class TestCapturedStores {

    int i1;
    int i2;

    TestCapturedStores(int i1, int i2) {
        this.i1 = i1;
        this.i2 = i2;
    }

    static int m1(int v) {
        return v;
    }

    static TestCapturedStores m() {
        TestCapturedStores obj = new TestCapturedStores(10, 100);
        int v1 = obj.i1;
        
        int v3 = m1(v1);
        int v2 = obj.i2;
        obj.i2 = v3;
        obj.i1 = v2;
        
        return obj;
    }

    static public void main(String[] args) {
        for (int i = 0; i < 100000; i++) {
            TestCapturedStores obj = m();
            if (obj.i1 != 100 || obj.i2 != 10) {
                System.out.println("Error " + obj.i1 + " " + obj.i2);
                throw new Error();
            }
        }
    }
}

This fails because:
- before inlining initialization stores are captured so that obj.i1=10 and obj.i2=100
- inlining of m1 puts store obj.i2 = v3 ahead of load int v2 = obj.i2 in the igvn worklist
- obj.i2 = v3 is captured by the initialization of obj so the captured stores are obj.i1=10 and obj.i2=10
- v2 = obj.i2 is processed but loads the newly stored value 10
- obj.i1 = v2 stores 10 to i1 and is captured. So the final two stores are obj.i1=10 and obj.i2=10

The logic that capture stores misses the v2 = obj.i2 load when obj.i2 = v3 is captured.

I don't think this can be reproduced easily without incremental inlining.
                                    

Comments
An other case.
                                     
2014-02-19
URL:   http://hg.openjdk.java.net/hsx/hsx25/hotspot/rev/6931f425c517
User:  amurillo
Date:  2013-03-01 16:29:47 +0000

                                     
2013-03-01
URL:   http://hg.openjdk.java.net/hsx/hotspot-comp/hotspot/rev/6931f425c517
User:  roland
Date:  2013-02-25 16:38:09 +0000

                                     
2013-02-25
The bug can be reproduce without incremental inlining with this simple method:

    static int m(int i) {
        int j = 0;
        if (i > 0) {
            j = 1;
        }

        int[] arr = new int[10];
        arr[0] = 1;
        arr[1] = 2;
        int v1 = arr[j];
        arr[0] = 3;
        arr[1] = 4;

        return v1;
    }

if i <= 0, it returns 3 instead of 1. If i > 0, it returns 4 instead of 2. 
                                     
2013-02-08
The description includes an evaluation.
                                     
2013-01-31



Hardware and Software, Engineered to Work Together