--- old/src/share/vm/opto/library_call.cpp 2016-11-14 00:59:37.945303475 -0800 +++ new/src/share/vm/opto/library_call.cpp 2016-11-14 00:59:37.829302773 -0800 @@ -2630,23 +2630,24 @@ val = is_store ? argument(3) : NULL; } + // Can base be NULL? Otherwise, always on-heap access. + bool can_access_non_heap = TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop)); + const TypePtr *adr_type = _gvn.type(adr)->isa_ptr(); - // Try to categorize the address. If it comes up as TypeJavaPtr::BOTTOM, - // there was not enough information to nail it down. + // Try to categorize the address. Compile::AliasType* alias_type = C->alias_type(adr_type); assert(alias_type->index() != Compile::AliasIdxBot, "no bare pointers here"); - // Only field, array element or unknown locations are supported. - if (alias_type->adr_type() != TypeRawPtr::BOTTOM && - alias_type->adr_type() != TypeOopPtr::BOTTOM && - alias_type->basic_type() == T_ILLEGAL) { - return false; + if (alias_type->adr_type() == TypeInstPtr::KLASS || + alias_type->adr_type() == TypeAryPtr::RANGE) { + return false; // not supported } bool mismatched = false; BasicType bt = alias_type->basic_type(); if (bt != T_ILLEGAL) { + assert(alias_type->adr_type()->is_oopptr(), "should be on-heap access"); if (bt == T_BYTE && adr_type->isa_aryptr()) { // Alias type doesn't differentiate between byte[] and boolean[]). // Use address type to get the element type. @@ -2663,6 +2664,8 @@ mismatched = (bt != type); } + assert(!mismatched || alias_type->adr_type()->is_oopptr(), "off-heap access can't be mismatched"); + // First guess at the value type. const Type *value_type = Type::get_const_basic_type(type); @@ -2777,7 +2780,7 @@ (void) store_to_memory(control(), adr, val, type, adr_type, mo, is_volatile, unaligned, mismatched); } else { // Possibly an oop being stored to Java heap or native memory - if (!TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop))) { + if (!can_access_non_heap) { // oop to Java heap. (void) store_oop_to_unknown(control(), heap_base_oop, adr, adr_type, val, type, mo, mismatched); } else { --- old/src/share/vm/opto/type.hpp 2016-11-14 00:59:38.364306012 -0800 +++ new/src/share/vm/opto/type.hpp 2016-11-14 00:59:38.255305352 -0800 @@ -209,11 +209,11 @@ static int cmp( const Type *const t1, const Type *const t2 ); // Test for higher or equal in lattice // Variant that drops the speculative part of the types - int higher_equal(const Type *t) const { + bool higher_equal(const Type *t) const { return !cmp(meet(t),t->remove_speculative()); } // Variant that keeps the speculative part of the types - int higher_equal_speculative(const Type *t) const { + bool higher_equal_speculative(const Type *t) const { return !cmp(meet_speculative(t),t); } --- old/test/compiler/unsafe/OpaqueAccesses.java 2016-11-14 00:59:38.746308324 -0800 +++ new/test/compiler/unsafe/OpaqueAccesses.java 2016-11-14 00:59:38.638307671 -0800 @@ -30,6 +30,22 @@ * * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions * -XX:-TieredCompilation -Xbatch + * -XX:+UseCompressedOops -XX:+UseCompressedClassPointers + * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* + * compiler.unsafe.OpaqueAccesses + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation -Xbatch + * -XX:+UseCompressedOops -XX:-UseCompressedClassPointers + * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* + * compiler.unsafe.OpaqueAccesses + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation -Xbatch + * -XX:-UseCompressedOops -XX:+UseCompressedClassPointers + * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* + * compiler.unsafe.OpaqueAccesses + * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation -Xbatch + * -XX:-UseCompressedOops -XX:-UseCompressedClassPointers * -XX:CompileCommand=dontinline,compiler.unsafe.OpaqueAccesses::test* * compiler.unsafe.OpaqueAccesses */ @@ -61,6 +77,7 @@ } private Object f = new Object(); + private long l1, l2; static Object testFixedOffsetField(Object o) { return UNSAFE.getObject(o, F_OFFSET); @@ -74,6 +91,22 @@ return UNSAFE.getInt(o, 4); } + static int testFixedOffsetHeader8(Object o) { + return UNSAFE.getInt(o, 8); + } + + static int testFixedOffsetHeader12(Object o) { + return UNSAFE.getInt(o, 12); + } + + static int testFixedOffsetHeader16(Object o) { + return UNSAFE.getInt(o, 16); + } + + static int testFixedOffsetHeader17(Object o) { + return UNSAFE.getIntUnaligned(o, 17); + } + static Object testFixedBase(long off) { return UNSAFE.getObject(INSTANCE, off); } @@ -90,6 +123,22 @@ return UNSAFE.getInt(arr, 4); } + static int testFixedOffsetHeaderArray8(Object[] arr) { + return UNSAFE.getInt(arr, 8); + } + + static int testFixedOffsetHeaderArray12(Object[] arr) { + return UNSAFE.getInt(arr, 12); + } + + static int testFixedOffsetHeaderArray16(Object[] arr) { + return UNSAFE.getInt(arr, 16); + } + + static int testFixedOffsetHeaderArray17(Object[] arr) { + return UNSAFE.getIntUnaligned(arr, 17); + } + static Object testFixedOffsetArray(Object[] arr) { return UNSAFE.getObject(arr, E_OFFSET); } @@ -118,6 +167,10 @@ testFixedOffsetField(INSTANCE); testFixedOffsetHeader0(INSTANCE); testFixedOffsetHeader4(INSTANCE); + testFixedOffsetHeader8(INSTANCE); + testFixedOffsetHeader12(INSTANCE); + testFixedOffsetHeader16(INSTANCE); + testFixedOffsetHeader17(INSTANCE); testFixedBase(F_OFFSET); testOpaque(INSTANCE, F_OFFSET); testMixedAccess(); @@ -125,6 +178,10 @@ // Array testFixedOffsetHeaderArray0(ARRAY); testFixedOffsetHeaderArray4(ARRAY); + testFixedOffsetHeaderArray8(ARRAY); + testFixedOffsetHeaderArray12(ARRAY); + testFixedOffsetHeaderArray16(ARRAY); + testFixedOffsetHeaderArray17(ARRAY); testFixedOffsetArray(ARRAY); testFixedBaseArray(E_OFFSET); testOpaqueArray(ARRAY, E_OFFSET);