8199462: Use Reference.reachabilityFence in direct ByteBuffer methods
authorpsandoz
Mon, 12 Mar 2018 16:09:18 -0700
changeset 49210 7c795d301dbf
parent 49209 bd7c17f99a19
child 49211 948ece16567b
8199462: Use Reference.reachabilityFence in direct ByteBuffer methods Reviewed-by: psandoz, vlivanov, plevart Contributed-by: ben_walsh@uk.ibm.com
src/java.base/share/classes/java/lang/ref/Reference.java
src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template
src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template
src/java.base/share/classes/java/nio/MappedByteBuffer.java
src/java.base/share/classes/java/nio/X-Buffer.java.template
test/jdk/java/lang/ref/ReachabilityFenceTest.java
--- a/src/java.base/share/classes/java/lang/ref/Reference.java	Mon Mar 12 21:30:58 2018 +0000
+++ b/src/java.base/share/classes/java/lang/ref/Reference.java	Mon Mar 12 16:09:18 2018 -0700
@@ -25,7 +25,7 @@
 
 package java.lang.ref;
 
-import jdk.internal.vm.annotation.DontInline;
+import jdk.internal.vm.annotation.ForceInline;
 import jdk.internal.HotSpotIntrinsicCandidate;
 import jdk.internal.misc.JavaLangRefAccess;
 import jdk.internal.misc.SharedSecrets;
@@ -420,10 +420,12 @@
      * @param ref the reference. If {@code null}, this method has no effect.
      * @since 9
      */
-    @DontInline
+    @ForceInline
     public static void reachabilityFence(Object ref) {
-        // Does nothing, because this method is annotated with @DontInline
-        // HotSpot needs to retain the ref and not GC it before a call to this
-        // method
+        // Does nothing. This method is annotated with @ForceInline to eliminate
+        // most of the overhead that using @DontInline would cause with the
+        // HotSpot JVM, when this fence is used in a wide variety of situations.
+        // HotSpot JVM retains the ref and does not GC it before a call to
+        // this method, because the JIT-compilers do not have GC-only safepoints.
     }
 }
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template	Mon Mar 12 21:30:58 2018 +0000
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer-bin.java.template	Mon Mar 12 16:09:18 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -32,24 +32,40 @@
 #if[rw]
 
     private $type$ get$Type$(long a) {
-        $memtype$ x = UNSAFE.get$Memtype$Unaligned(null, a, bigEndian);
-        return $fromBits$(x);
+        try {
+            $memtype$ x = UNSAFE.get$Memtype$Unaligned(null, a, bigEndian);
+            return $fromBits$(x);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
     }
 
     public $type$ get$Type$() {
-        return get$Type$(ix(nextGetIndex($BYTES_PER_VALUE$)));
+        try {
+            return get$Type$(ix(nextGetIndex($BYTES_PER_VALUE$)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
     }
 
     public $type$ get$Type$(int i) {
-        return get$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)));
+        try {
+            return get$Type$(ix(checkIndex(i, $BYTES_PER_VALUE$)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
     }
 
 #end[rw]
 
     private ByteBuffer put$Type$(long a, $type$ x) {
 #if[rw]
-        $memtype$ y = $toBits$(x);
-        UNSAFE.put$Memtype$Unaligned(null, a, y, bigEndian);
+        try {
+            $memtype$ y = $toBits$(x);
+            UNSAFE.put$Memtype$Unaligned(null, a, y, bigEndian);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
         return this;
 #else[rw]
         throw new ReadOnlyBufferException();
--- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Mon Mar 12 21:30:58 2018 +0000
+++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template	Mon Mar 12 16:09:18 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -28,6 +28,7 @@
 package java.nio;
 
 import java.io.FileDescriptor;
+import java.lang.ref.Reference;
 import jdk.internal.misc.VM;
 import jdk.internal.ref.Cleaner;
 import sun.nio.ch.DirectBuffer;
@@ -257,16 +258,28 @@
     }
 
     public $type$ get() {
-        return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex()))));
+        try {
+            return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(nextGetIndex()))));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
     }
 
     public $type$ get(int i) {
-        return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i)))));
+        try {
+            return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(checkIndex(i)))));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
     }
 
 #if[streamableType]
     $type$ getUnchecked(int i) {
-        return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i))));
+        try {
+            return $fromBits$($swap$(UNSAFE.get$Swaptype$(ix(i))));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
     }
 #end[streamableType]
 
@@ -282,21 +295,25 @@
                 throw new BufferUnderflowException();
 
             long dstOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
+            try {
 #if[!byte]
-            if (order() != ByteOrder.nativeOrder())
-                UNSAFE.copySwapMemory(null,
+                if (order() != ByteOrder.nativeOrder())
+                    UNSAFE.copySwapMemory(null,
+                                          ix(pos),
+                                          dst,
+                                          dstOffset,
+                                          (long)length << $LG_BYTES_PER_VALUE$,
+                                          (long)1 << $LG_BYTES_PER_VALUE$);
+                else
+#end[!byte]
+                    UNSAFE.copyMemory(null,
                                       ix(pos),
                                       dst,
                                       dstOffset,
-                                      (long)length << $LG_BYTES_PER_VALUE$,
-                                      (long)1 << $LG_BYTES_PER_VALUE$);
-            else
-#end[!byte]
-                UNSAFE.copyMemory(null,
-                                  ix(pos),
-                                  dst,
-                                  dstOffset,
-                                  (long)length << $LG_BYTES_PER_VALUE$);
+                                      (long)length << $LG_BYTES_PER_VALUE$);
+            } finally {
+                Reference.reachabilityFence(this);
+            }
             position(pos + length);
         } else {
             super.get(dst, offset, length);
@@ -311,7 +328,11 @@
 
     public $Type$Buffer put($type$ x) {
 #if[rw]
-        UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
+        try {
+            UNSAFE.put$Swaptype$(ix(nextPutIndex()), $swap$($toBits$(x)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
         return this;
 #else[rw]
         throw new ReadOnlyBufferException();
@@ -320,7 +341,11 @@
 
     public $Type$Buffer put(int i, $type$ x) {
 #if[rw]
-        UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
+        try {
+            UNSAFE.put$Swaptype$(ix(checkIndex(i)), $swap$($toBits$(x)));
+        } finally {
+            Reference.reachabilityFence(this);
+        }
         return this;
 #else[rw]
         throw new ReadOnlyBufferException();
@@ -346,7 +371,12 @@
 
             if (srem > rem)
                 throw new BufferOverflowException();
-            UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
+            try {
+                UNSAFE.copyMemory(sb.ix(spos), ix(pos), (long)srem << $LG_BYTES_PER_VALUE$);
+            } finally {
+                Reference.reachabilityFence(sb);
+                Reference.reachabilityFence(this);
+            }
             sb.position(spos + srem);
             position(pos + srem);
         } else if (src.hb != null) {
@@ -380,21 +410,25 @@
                 throw new BufferOverflowException();
 
             long srcOffset = ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
+            try {
 #if[!byte]
-            if (order() != ByteOrder.nativeOrder())
-                UNSAFE.copySwapMemory(src,
+                if (order() != ByteOrder.nativeOrder())
+                    UNSAFE.copySwapMemory(src,
+                                          srcOffset,
+                                          null,
+                                          ix(pos),
+                                          (long)length << $LG_BYTES_PER_VALUE$,
+                                          (long)1 << $LG_BYTES_PER_VALUE$);
+                else
+#end[!byte]
+                    UNSAFE.copyMemory(src,
                                       srcOffset,
                                       null,
                                       ix(pos),
-                                      (long)length << $LG_BYTES_PER_VALUE$,
-                                      (long)1 << $LG_BYTES_PER_VALUE$);
-            else
-#end[!byte]
-                UNSAFE.copyMemory(src,
-                                  srcOffset,
-                                  null,
-                                  ix(pos),
-                                  (long)length << $LG_BYTES_PER_VALUE$);
+                                      (long)length << $LG_BYTES_PER_VALUE$);
+            } finally {
+                Reference.reachabilityFence(this);
+            }
             position(pos + length);
         } else {
             super.put(src, offset, length);
@@ -411,8 +445,11 @@
         int lim = limit();
         assert (pos <= lim);
         int rem = (pos <= lim ? lim - pos : 0);
-
-        UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
+        try {
+            UNSAFE.copyMemory(ix(pos), ix(0), (long)rem << $LG_BYTES_PER_VALUE$);
+        } finally {
+            Reference.reachabilityFence(this);
+        }
         position(rem);
         limit(capacity());
         discardMark();
@@ -497,19 +534,6 @@
 
 
 #if[byte]
-
-    byte _get(int i) {                          // package-private
-        return UNSAFE.getByte(address + i);
-    }
-
-    void _put(int i, byte b) {                  // package-private
-#if[rw]
-        UNSAFE.putByte(address + i, b);
-#else[rw]
-        throw new ReadOnlyBufferException();
-#end[rw]
-    }
-
     // #BIN
     //
     // Binary-data access methods  for short, char, int, long, float,
--- a/src/java.base/share/classes/java/nio/MappedByteBuffer.java	Mon Mar 12 21:30:58 2018 +0000
+++ b/src/java.base/share/classes/java/nio/MappedByteBuffer.java	Mon Mar 12 16:09:18 2018 -0700
@@ -26,6 +26,7 @@
 package java.nio;
 
 import java.io.FileDescriptor;
+import java.lang.ref.Reference;
 import jdk.internal.misc.Unsafe;
 
 
@@ -166,9 +167,15 @@
         int count = Bits.pageCount(length);
         long a = mappingAddress(offset);
         byte x = 0;
-        for (int i=0; i<count; i++) {
-            x ^= unsafe.getByte(a);
-            a += ps;
+        try {
+            for (int i=0; i<count; i++) {
+                // TODO consider changing to getByteOpaque thus avoiding
+                // dead code elimination and the need to calculate a checksum
+                x ^= unsafe.getByte(a);
+                a += ps;
+            }
+        } finally {
+            Reference.reachabilityFence(this);
         }
         if (unused != 0)
             unused = x;
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template	Mon Mar 12 21:30:58 2018 +0000
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template	Mon Mar 12 16:09:18 2018 -0700
@@ -1749,11 +1749,6 @@
 
     abstract ByteBuffer slice(int pos, int lim);
 
-    // Unchecked accessors, for use by ByteBufferAs-X-Buffer classes
-    //
-    abstract byte _get(int i);                          // package-private
-    abstract void _put(int i, byte b);                  // package-private
-
     // #BIN
     //
     // Binary-data access methods  for short, char, int, long, float,
--- a/test/jdk/java/lang/ref/ReachabilityFenceTest.java	Mon Mar 12 21:30:58 2018 +0000
+++ b/test/jdk/java/lang/ref/ReachabilityFenceTest.java	Mon Mar 12 16:09:18 2018 -0700
@@ -122,9 +122,11 @@
             }
         }
 
-        Reference.reachabilityFence(o);
-
-        return finalized.get();
+        try {
+            return finalized.get();
+        } finally {
+            Reference.reachabilityFence(o);
+        }
     }
 
     private static class MyFinalizeable {