Mercurial > hg > icedtea7-forest > hotspot
changeset 6414:601fbf4bf8c1 icedtea-2.7.0pre06
8158260, PR2992, RH1341258: PPC64: unaligned Unsafe.getInt can lead to the generation of illegal instructions
Summary: Adjust instruction generation. Includes portions of 8026049 for test case.
Reviewed-by: goetz
Contributed-by: gromero@linux.vnet.ibm.com, horii@jp.ibm.com
author | simonis |
---|---|
date | Wed, 20 Jul 2016 03:15:59 +0100 |
parents | dbe5bbcb8a41 |
children | d408ae5f1f73 |
files | src/cpu/aarch64/vm/vm_version_aarch64.cpp src/cpu/ppc/vm/ppc.ad src/cpu/ppc/vm/vm_version_ppc.cpp src/cpu/sparc/vm/vm_version_sparc.cpp src/cpu/x86/vm/vm_version_x86.cpp src/cpu/zero/vm/vm_version_zero.cpp src/cpu/zero/vm/vm_version_zero.hpp src/share/vm/prims/unsafe.cpp src/share/vm/runtime/globals.hpp test/compiler/unsafe/JdkInternalMiscUnsafeUnalignedAccess.java |
diffstat | 10 files changed, 393 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/cpu/aarch64/vm/vm_version_aarch64.cpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/cpu/aarch64/vm/vm_version_aarch64.cpp Wed Jul 20 03:15:59 2016 +0100 @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013, Red Hat Inc. * Copyright (c) 1997, 2012, Oracle and/or its affiliates. + * Copyright (c) 2015, Red Hat Inc. All rights reserved. * All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -183,6 +183,12 @@ if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { UseCRC32Intrinsics = true; } + + // This machine allows unaligned memory accesses + if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { + FLAG_SET_DEFAULT(UseUnalignedAccesses, true); + } + #ifdef COMPILER2 if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true;
--- a/src/cpu/ppc/vm/ppc.ad Tue Jul 19 23:59:47 2016 +0100 +++ b/src/cpu/ppc/vm/ppc.ad Wed Jul 20 03:15:59 2016 +0100 @@ -7653,7 +7653,7 @@ // SAPJVM GL 2013-10-29 Match ConvI2L(LoadI) // Match loading integer and casting it to long. -instruct loadI2L(iRegLdst dst, memory mem) %{ +instruct loadI2L(iRegLdst dst, memoryAlg4 mem) %{ match(Set dst (ConvI2L (LoadI mem))); predicate(_kids[0]->_leaf->as_Load()->is_unordered()); ins_cost(MEMORY_REF_COST); @@ -7665,7 +7665,7 @@ %} // Match loading integer and casting it to long - acquire. -instruct loadI2L_ac(iRegLdst dst, memory mem) %{ +instruct loadI2L_ac(iRegLdst dst, memoryAlg4 mem) %{ match(Set dst (ConvI2L (LoadI mem))); ins_cost(3*MEMORY_REF_COST);
--- a/src/cpu/ppc/vm/vm_version_ppc.cpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/cpu/ppc/vm/vm_version_ppc.cpp Wed Jul 20 03:15:59 2016 +0100 @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright 2012, 2014 SAP AG. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012, 2015 SAP AG. 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 @@ -142,6 +142,11 @@ AllocatePrefetchStyle = 1; // Fall back if inappropriate. assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); + + // This machine allows unaligned memory accesses + if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { + FLAG_SET_DEFAULT(UseUnalignedAccesses, true); + } } void VM_Version::print_features() {
--- a/src/cpu/sparc/vm/vm_version_sparc.cpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/cpu/sparc/vm/vm_version_sparc.cpp Wed Jul 20 03:15:59 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, 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 @@ -274,6 +274,13 @@ if (!has_vis1()) // Drop to 0 if no VIS1 support UseVIS = 0; + // This machine does not allow unaligned memory accesses + if (UseUnalignedAccesses) { + if (!FLAG_IS_DEFAULT(UseUnalignedAccesses)) + warning("Unaligned memory access is not available on this CPU"); + FLAG_SET_DEFAULT(UseUnalignedAccesses, false); + } + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("L2 data cache line size: %u", L2_data_cache_line_size());
--- a/src/cpu/x86/vm/vm_version_x86.cpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/cpu/x86/vm/vm_version_x86.cpp Wed Jul 20 03:15:59 2016 +0100 @@ -752,6 +752,11 @@ PrefetchFieldsAhead = prefetch_fields_ahead(); #endif + // This machine allows unaligned memory accesses + if (FLAG_IS_DEFAULT(UseUnalignedAccesses)) { + FLAG_SET_DEFAULT(UseUnalignedAccesses, true); + } + #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("Logical CPUs per core: %u",
--- a/src/cpu/zero/vm/vm_version_zero.cpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/cpu/zero/vm/vm_version_zero.cpp Wed Jul 20 03:15:59 2016 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * Copyright 2009 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,4 +36,12 @@ # include "os_bsd.inline.hpp" #endif -// This file is intentionally empty + +void VM_Version::initialize() { + get_processor_features(); + // This machine does not allow unaligned memory accesses + if (! FLAG_IS_DEFAULT(UseUnalignedAccesses)) { + warning("Unaligned memory access is not available on this CPU"); + FLAG_SET_DEFAULT(UseUnalignedAccesses, false); + } +}
--- a/src/cpu/zero/vm/vm_version_zero.hpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/cpu/zero/vm/vm_version_zero.hpp Wed Jul 20 03:15:59 2016 +0100 @@ -1,6 +1,6 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007 Red Hat, Inc. + * Copyright 2015 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,9 +38,7 @@ #endif } - static void initialize() { - get_processor_features(); - } + static void initialize(); static const char* cpu_features() { return "";
--- a/src/share/vm/prims/unsafe.cpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/share/vm/prims/unsafe.cpp Wed Jul 20 03:15:59 2016 +0100 @@ -360,6 +360,24 @@ #endif // not SPARC and not X86 +UNSAFE_ENTRY(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) + UnsafeWrapper("Unsafe_IsBigEndian0"); + { +#ifdef VM_LITTLE_ENDIAN + return false; +#else + return true; +#endif + } +UNSAFE_END + +UNSAFE_ENTRY(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) + UnsafeWrapper("Unsafe_UnalignedAccess0"); + { + return UseUnalignedAccesses; + } +UNSAFE_END + #define DEFINE_GETSETOOP(jboolean, Boolean) \ \ UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \ @@ -1600,6 +1618,11 @@ {CC"shouldBeInitialized",CC"("CLS")Z", FN_PTR(Unsafe_ShouldBeInitialized)}, }; +JNINativeMethod machine_methods[] = { + {CC"isBigEndian0", CC"()Z", FN_PTR(Unsafe_isBigEndian0)}, + {CC"unalignedAccess0", CC"()Z", FN_PTR(Unsafe_unalignedAccess0)} +}; + #undef CC #undef FN_PTR @@ -1661,6 +1684,15 @@ } } } + { + env->RegisterNatives(unsafecls, machine_methods, sizeof(machine_methods)/sizeof(JNINativeMethod)); + if (env->ExceptionOccurred()) { + if (PrintMiscellaneous && (Verbose || WizardMode)) { + tty->print_cr("Warning: SDK 1.7 Unsafe.isBigEndian0/unalignedAccess0 not found."); + } + env->ExceptionClear(); + } + } if (EnableInvokeDynamic) { env->RegisterNatives(unsafecls, anonk_methods, sizeof(anonk_methods)/sizeof(JNINativeMethod)); if (env->ExceptionOccurred()) {
--- a/src/share/vm/runtime/globals.hpp Tue Jul 19 23:59:47 2016 +0100 +++ b/src/share/vm/runtime/globals.hpp Wed Jul 20 03:15:59 2016 +0100 @@ -3715,7 +3715,11 @@ product(bool, EnableTracing, false, \ "Enable event-based tracing") \ product(bool, UseLockedTracing, false, \ - "Use locked-tracing when doing event-based tracing") + "Use locked-tracing when doing event-based tracing") \ + \ + diagnostic(bool, UseUnalignedAccesses, false, \ + "Use unaligned memory accesses in sun.misc.Unsafe") \ + \ /* * Macros for factoring of globals
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/unsafe/JdkInternalMiscUnsafeUnalignedAccess.java Wed Jul 20 03:15:59 2016 +0100 @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2016 SAP SE. 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 8158260 + * @summary Test unaligned Unsafe accesses + * @modules java.base/jdk.internal.misc + * @run main/othervm -Diters=20000 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation JdkInternalMiscUnsafeUnalignedAccess + * @author volker.simonis@gmail.com + */ + +import java.lang.reflect.Field; +import java.nio.ByteOrder; +import sun.misc.Unsafe; + +public class JdkInternalMiscUnsafeUnalignedAccess { + static final int ITERS = Integer.getInteger("iters", 20_000); + private static final boolean BIG_ENDIAN = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN); + private static final Unsafe UNSAFE; + private static final int SIZE = 1024; + private static long memory; + + static { + try { + Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + unsafeField.setAccessible(true); + UNSAFE = (Unsafe) unsafeField.get(null); + } + catch (Exception e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + + static int getInt_0() { + return UNSAFE.getInt(memory + 0); + } + static int getInt_1() { + return UNSAFE.getInt(memory + 1); + } + static int getInt_4() { + return UNSAFE.getInt(memory + 4); + } + static int getInt_17() { + return UNSAFE.getInt(memory + 17); + } + + static long getIntAsLong_0() { + return UNSAFE.getInt(memory + 0); + } + static long getIntAsLong_1() { + return UNSAFE.getInt(memory + 1); + } + static long getIntAsLong_4() { + return UNSAFE.getInt(memory + 4); + } + static long getIntAsLong_17() { + return UNSAFE.getInt(memory + 17); + } + + static long getLong_0() { + return UNSAFE.getLong(memory + 0); + } + static long getLong_1() { + return UNSAFE.getLong(memory + 1); + } + static long getLong_4() { + return UNSAFE.getLong(memory + 4); + } + static long getLong_8() { + return UNSAFE.getLong(memory + 8); + } + static long getLong_17() { + return UNSAFE.getLong(memory + 17); + } + + static void putInt_0(int i) { + UNSAFE.putInt(memory + 0, i); + } + static void putInt_1(int i) { + UNSAFE.putInt(memory + 1, i); + } + static void putInt_4(int i) { + UNSAFE.putInt(memory + 4, i); + } + static void putInt_17(int i) { + UNSAFE.putInt(memory + 17, i); + } + + static void putLong_0(long l) { + UNSAFE.putLong(memory + 0, l); + } + static void putLong_1(long l) { + UNSAFE.putLong(memory + 1, l); + } + static void putLong_4(long l) { + UNSAFE.putLong(memory + 4, l); + } + static void putLong_8(long l) { + UNSAFE.putLong(memory + 8, l); + } + static void putLong_17(long l) { + UNSAFE.putLong(memory + 17, l); + } + + public static void main(String[] args) throws Exception { + + if (!UNSAFE.unalignedAccess()) { + System.out.println("Platform is not supporting unaligned access - nothing to test."); + return; + } + + memory = UNSAFE.allocateMemory(SIZE); + + UNSAFE.putInt(memory + 0, 0x00112233); + UNSAFE.putInt(memory + 4, 0x44556677); + UNSAFE.putInt(memory + 8, 0x8899aabb); + UNSAFE.putInt(memory + 12, 0xccddeeff); + UNSAFE.putInt(memory + 16, 0x01234567); + UNSAFE.putInt(memory + 20, 0x89abcdef); + UNSAFE.putInt(memory + 24, 0x01234567); + + // Unsafe.getInt() + int res; + for (int i = 0; i < ITERS; i++) { + res = getInt_0(); + if (res != 0x00112233) { + throw new Exception(res + " != 0x00112233"); + } + } + + for (int i = 0; i < ITERS; i++) { + res = getInt_1(); + if (res != (BIG_ENDIAN ? 0x11223344 : 0x77001122)) { + throw new Exception(res + " != " + (BIG_ENDIAN ? 0x11223344 : 0x77001122)); + } + } + + for (int i = 0; i < ITERS; i++) { + res = getInt_4(); + if (res != 0x44556677) { + throw new Exception(res + " != 0x44556677"); + } + } + + for (int i = 0; i < ITERS; i++) { + res = getInt_17(); + if (res != (BIG_ENDIAN ? 0x23456789 : 0xef012345)) { + throw new Exception(res + " != " + (BIG_ENDIAN ? 0x23456789 : 0xef012345)); + } + } + + // (long)Unsafe.getInt() + long lres; + for (int i = 0; i < ITERS; i++) { + lres = getIntAsLong_0(); + if (lres != (long)0x00112233) { + throw new Exception(lres + " != 0x00112233"); + } + } + + for (int i = 0; i < ITERS; i++) { + lres = getIntAsLong_1(); + if (lres != (BIG_ENDIAN ? (long)0x11223344 : (long)0x77001122)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? (long)0x11223344 : (long)0x77001122)); + } + } + + for (int i = 0; i < ITERS; i++) { + lres = getIntAsLong_4(); + if (lres != (long)0x44556677) { + throw new Exception(lres + " != 0x44556677"); + } + } + + for (int i = 0; i < ITERS; i++) { + lres = getIntAsLong_17(); + if (lres != (BIG_ENDIAN ? (long)0x23456789 : (long)0xef012345)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? (long)0x23456789 : (long)0xef012345)); + } + } + + // Unsafe.getLong() + for (int i = 0; i < ITERS; i++) { + lres = getLong_0(); + if (lres != (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L)); + } + } + + for (int i = 0; i < ITERS; i++) { + lres = getLong_1(); + if (lres != (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L)); + } + } + + for (int i = 0; i < ITERS; i++) { + lres = getLong_4(); + if (lres != (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L)); + } + } + + for (int i = 0; i < ITERS; i++) { + lres = getLong_8(); + if (lres != (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL)); + } + } + + for (int i = 0; i < ITERS; i++) { + lres = getLong_17(); + if (lres != (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L)); + } + } + + // Unsafe.putInt() + for (int i = 0; i < ITERS; i++) { + putInt_0(0x00112233); + res = getInt_0(); + if (res != 0x00112233) { + throw new Exception(res + " != 0x00112233"); + } + } + + for (int i = 0; i < ITERS; i++) { + putInt_1(BIG_ENDIAN ? 0x11223344 : 0x77001122); + res = getInt_1(); + if (res != (BIG_ENDIAN ? 0x11223344 : 0x77001122)) { + throw new Exception(res + " != " + (BIG_ENDIAN ? 0x11223344 : 0x77001122)); + } + } + + for (int i = 0; i < ITERS; i++) { + putInt_4(0x44556677); + res = getInt_4(); + if (res != 0x44556677) { + throw new Exception(res + " != 0x44556677"); + } + } + + for (int i = 0; i < ITERS; i++) { + putInt_17(BIG_ENDIAN ? 0x23456789 : 0xef012345); + res = getInt_17(); + if (res != (BIG_ENDIAN ? 0x23456789 : 0xef012345)) { + throw new Exception(res + " != " + (BIG_ENDIAN ? 0x23456789 : 0xef012345)); + } + } + + + // Unsafe.putLong() + for (int i = 0; i < ITERS; i++) { + putLong_0(BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L); + lres = getLong_0(); + if (lres != (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x0011223344556677L : 0x4455667700112233L)); + } + } + + for (int i = 0; i < ITERS; i++) { + putLong_1(BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L); + lres = getLong_1(); + if (lres != (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x1122334455667788L : 0xbb44556677001122L)); + } + } + + for (int i = 0; i < ITERS; i++) { + putLong_4(BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L); + lres = getLong_4(); + if (lres != (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x445566778899aabbL : 0x8899aabb44556677L)); + } + } + + for (int i = 0; i < ITERS; i++) { + putLong_8(BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL); + lres = getLong_8(); + if (lres != (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x8899aabbccddeeffL : 0xccddeeff8899aabbL)); + } + } + + for (int i = 0; i < ITERS; i++) { + putLong_17(BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L); + lres = getLong_17(); + if (lres != (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L)) { + throw new Exception(lres + " != " + (BIG_ENDIAN ? 0x23456789abcdef01L : 0x6789abcdef012345L)); + } + } + } + +}