changeset 12000:8d77d02828d9

8016474: Crash in sun.reflect.UnsafeObjectFieldAccessorImpl.get Summary: C1's GetUnsafeObject G1 pre-barrier uses the wrong type to read the klass pointer. Reviewed-by: iveresov, kvn
author twisti
date Mon, 29 Jul 2013 16:32:38 -0700
parents 79a5283f4595
children 446cb5d25d03
files src/share/vm/c1/c1_LIRGenerator.cpp test/compiler/unsafe/GetUnsafeObjectG1PreBarrier.java
diffstat 2 files changed, 72 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Jul 29 11:54:18 2013 +0400
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Mon Jul 29 16:32:38 2013 -0700
@@ -2295,7 +2295,7 @@
       if (gen_type_check) {
         // We have determined that offset == referent_offset && src != null.
         // if (src->_klass->_reference_type == REF_NONE) -> continue
-        __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), UseCompressedKlassPointers ? T_OBJECT : T_ADDRESS), src_klass);
+        __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
         LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE);
         LIR_Opr reference_type = new_register(T_INT);
         __ move(reference_type_addr, reference_type);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/compiler/unsafe/GetUnsafeObjectG1PreBarrier.java	Mon Jul 29 16:32:38 2013 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8016474
+ * @summary The bug only happens with C1 and G1 using a different ObjectAlignmentInBytes than KlassAlignmentInBytes (which is 8)
+ * @run main/othervm -Xbatch -XX:ObjectAlignmentInBytes=32 GetUnsafeObjectG1PreBarrier
+ */
+
+import java.lang.reflect.Field;
+
+import sun.misc.Unsafe;
+
+public class GetUnsafeObjectG1PreBarrier {
+    private static final Unsafe unsafe;
+    private static final int N = 100_000;
+
+    static {
+        try {
+            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafe.setAccessible(true);
+            unsafe = (Unsafe) theUnsafe.get(null);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public Object a;
+
+    public static void main(String[] args) throws Throwable {
+        new GetUnsafeObjectG1PreBarrier();
+    }
+
+    public GetUnsafeObjectG1PreBarrier() throws Throwable {
+        doit();
+    }
+
+    private void doit() throws Throwable {
+        Field field = GetUnsafeObjectG1PreBarrier.class.getField("a");
+        long fieldOffset = unsafe.objectFieldOffset(field);
+
+        for (int i = 0; i < N; i++) {
+            readField(this, fieldOffset);
+        }
+    }
+
+    private void readField(Object o, long fieldOffset) {
+        unsafe.getObject(o, fieldOffset);
+    }
+}