8199462: Use Reference.reachabilityFence in direct ByteBuffer methods
Reviewed-by: psandoz, vlivanov, plevart
Contributed-by: ben_walsh@uk.ibm.com
--- 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 {