1 /*
2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  *
23  */
24 
25 /*
26  * @test
27  * @bug 7190310
28  * @summary Inlining WeakReference.get(), and hoisting $referent may lead to non-terminating loops
29  * @run main/othervm -Xbatch Test7190310_unsafe
30  */
31 
32 import java.lang.ref.*;
33 import java.lang.reflect.*;
34 import sun.misc.Unsafe;
35 
36 public class Test7190310_unsafe {
37 
38   static class TestObject {
toString()39     public String toString() {
40       return "TestObject";
41     }
42   };
43 
44   private static TestObject str = new TestObject();
45   private static final WeakReference ref = new WeakReference(str);
46 
47   private TestObject obj;
48 
main(String[] args)49   public static void main(String[] args) throws Exception {
50     Class c = Test7190310_unsafe.class.getClassLoader().loadClass("sun.misc.Unsafe");
51     Field f = c.getDeclaredField("theUnsafe");
52     f.setAccessible(true);
53     Unsafe unsafe = (Unsafe)f.get(c);
54 
55     f = Reference.class.getDeclaredField("referent");
56     f.setAccessible(true);
57     long referent_offset = unsafe.objectFieldOffset(f);
58 
59     Test7190310_unsafe t = new Test7190310_unsafe();
60     TestObject o = new TestObject();
61     t.obj = o;
62 
63     // Warmup (compile methods)
64     System.err.println("Warmup");
65     Object obj = null;
66     for (int i = 0; i < 11000; i++) {
67       obj = getRef0(ref);
68     }
69     for (int i = 0; i < 11000; i++) {
70       obj = getRef1(unsafe, ref, referent_offset);
71     }
72     for (int i = 0; i < 11000; i++) {
73       obj = getRef2(unsafe, ref, referent_offset);
74     }
75     for (int i = 0; i < 11000; i++) {
76       obj = getRef3(unsafe, ref, referent_offset);
77     }
78     for (int i = 0; i < 11000; i++) {
79       obj = getRef4(unsafe, t, referent_offset);
80     }
81 
82     // Access verification
83     System.err.println("Verification");
84     if (!verifyGet(referent_offset, unsafe)) {
85       System.exit(97);
86     }
87 
88     obj = getRef3(unsafe, t, referent_offset);
89     if (obj != o) {
90       System.out.println("FAILED: unsafe.getObject(Object, " + referent_offset + ") " + obj + " != " + o);
91       System.exit(97);
92     }
93     obj = getRef4(unsafe, t, referent_offset);
94     if (obj != o) {
95       System.out.println("FAILED: unsafe.getObject(Test7190310, " + referent_offset + ") " + obj + " != " + o);
96       System.exit(97);
97     }
98   }
99 
verifyGet(long referent_offset, Unsafe unsafe)100   static boolean verifyGet(long referent_offset, Unsafe unsafe) throws Exception {
101     // Access verification
102     System.out.println("referent: " + str);
103     Object obj = getRef0(ref);
104     if (obj != str) {
105       System.out.println("FAILED: weakRef.get() " + obj + " != " + str);
106       return false;
107     }
108     obj = getRef1(unsafe, ref, referent_offset);
109     if (obj != str) {
110       System.out.println("FAILED: unsafe.getObject(weakRef, " + referent_offset + ") " + obj + " != " + str);
111       return false;
112     }
113     obj = getRef2(unsafe, ref, referent_offset);
114     if (obj != str) {
115       System.out.println("FAILED: unsafe.getObject(abstRef, " + referent_offset + ") " + obj + " != " + str);
116       return false;
117     }
118     obj = getRef3(unsafe, ref, referent_offset);
119     if (obj != str) {
120       System.out.println("FAILED: unsafe.getObject(Object, " + referent_offset + ") " + obj + " != " + str);
121       return false;
122     }
123     return true;
124   }
125 
getRef0(WeakReference ref)126   static Object getRef0(WeakReference ref) throws Exception {
127     return ref.get();
128   }
getRef1(Unsafe unsafe, WeakReference ref, long referent_offset)129   static Object getRef1(Unsafe unsafe, WeakReference ref, long referent_offset) throws Exception {
130     return unsafe.getObject(ref, referent_offset);
131   }
getRef2(Unsafe unsafe, Reference ref, long referent_offset)132   static Object getRef2(Unsafe unsafe, Reference ref, long referent_offset) throws Exception {
133     return unsafe.getObject(ref, referent_offset);
134   }
getRef3(Unsafe unsafe, Object ref, long referent_offset)135   static Object getRef3(Unsafe unsafe, Object ref, long referent_offset) throws Exception {
136     return unsafe.getObject(ref, referent_offset);
137   }
getRef4(Unsafe unsafe, Test7190310_unsafe ref, long referent_offset)138   static Object getRef4(Unsafe unsafe, Test7190310_unsafe ref, long referent_offset) throws Exception {
139     return unsafe.getObject(ref, referent_offset);
140   }
141 }
142 
143