8162101: C2: Handle "wide" aliases for unsafe accesses
authorvlivanov
Thu, 25 Aug 2016 12:51:10 +0300
changeset 40880 74222f8c095e
parent 40879 1403ae60654c
child 40881 a4955213b573
8162101: C2: Handle "wide" aliases for unsafe accesses Reviewed-by: kvn
hotspot/src/share/vm/opto/library_call.cpp
hotspot/src/share/vm/opto/type.hpp
hotspot/test/compiler/unsafe/OpaqueAccesses.java
--- a/hotspot/src/share/vm/opto/library_call.cpp	Tue Aug 23 22:31:48 2016 +0000
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Thu Aug 25 12:51:10 2016 +0300
@@ -2309,25 +2309,27 @@
   if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) {
     heap_base_oop = base;
   }
+
+  // Can base be NULL? Otherwise, always on-heap access.
+  bool can_access_non_heap = TypePtr::NULL_PTR->higher_equal(_gvn.type(heap_base_oop));
+
   val = is_store ? argument(4) : NULL;
 
   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.
@@ -2342,10 +2344,12 @@
       return false;
     }
     mismatched = (bt != type);
-  } else if (alias_type->adr_type() == TypeOopPtr::BOTTOM) {
+  } else if (alias_type->adr_type()->isa_oopptr()) {
     mismatched = true; // conservatively mark all "wide" on-heap accesses as mismatched
   }
 
+  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);
 
@@ -2357,7 +2361,7 @@
   bool need_mem_bar;
   switch (kind) {
       case Relaxed:
-          need_mem_bar = (alias_type->adr_type() == TypeOopPtr::BOTTOM);
+          need_mem_bar = mismatched || can_access_non_heap;
           break;
       case Opaque:
           // Opaque uses CPUOrder membars for protection against code movement.
@@ -2512,7 +2516,7 @@
       (void) store_to_memory(control(), adr, val, type, adr_type, mo, requires_atomic_access, 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 {
--- a/hotspot/src/share/vm/opto/type.hpp	Tue Aug 23 22:31:48 2016 +0000
+++ b/hotspot/src/share/vm/opto/type.hpp	Thu Aug 25 12:51:10 2016 +0300
@@ -210,11 +210,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);
   }
 
--- a/hotspot/test/compiler/unsafe/OpaqueAccesses.java	Tue Aug 23 22:31:48 2016 +0000
+++ b/hotspot/test/compiler/unsafe/OpaqueAccesses.java	Thu Aug 25 12:51:10 2016 +0300
@@ -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);