Skip to content

Commit 00d9e14

Browse files
retronymSethTisue
authored andcommitted
Expose VarHandle.releaseFence (or the JDK8 equivalent) in ScalaRuntime
1 parent 3783fe8 commit 00d9e14

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

src/library/scala/runtime/ScalaRunTime.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,4 +268,9 @@ object ScalaRunTime {
268268
def wrapShortArray(xs: Array[Short]): ArraySeq[Short] = if (xs ne null) new ArraySeq.ofShort(xs) else null
269269
def wrapBooleanArray(xs: Array[Boolean]): ArraySeq[Boolean] = if (xs ne null) new ArraySeq.ofBoolean(xs) else null
270270
def wrapUnitArray(xs: Array[Unit]): ArraySeq[Unit] = if (xs ne null) new ArraySeq.ofUnit(xs) else null
271+
272+
/**
273+
* Forwards to `VarHandle.releaseFence` or `sun.misc.Unsafe.storeFence` on JDK9+ or JDK8 respectively.
274+
*/
275+
@inline def releaseFence(): Unit = VM.RELEASE_FENCE.invoke()
271276
}

src/library/scala/runtime/VM.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package scala.runtime;
2+
3+
import java.lang.invoke.MethodHandle;
4+
import java.lang.invoke.MethodHandles;
5+
import java.lang.invoke.MethodType;
6+
import java.lang.reflect.Field;
7+
8+
public class VM {
9+
public static final MethodHandle RELEASE_FENCE;
10+
11+
12+
static {
13+
RELEASE_FENCE = mkHandle();
14+
}
15+
16+
private static MethodHandle mkHandle() {
17+
MethodHandles.Lookup lookup = MethodHandles.lookup();
18+
try {
19+
return lookup.findStatic(Class.forName("java.lang.invoke.VarHandle"), "releaseFence", MethodType.methodType(Void.TYPE));
20+
} catch (ClassNotFoundException e) {
21+
try {
22+
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
23+
return lookup.findVirtual(unsafeClass, "storeFence", MethodType.methodType(void.class)).bindTo(findUnsafe(unsafeClass));
24+
} catch (NoSuchMethodException | ClassNotFoundException | IllegalAccessException e1) {
25+
ExceptionInInitializerError error = new ExceptionInInitializerError(e1);
26+
error.addSuppressed(e);
27+
throw error;
28+
}
29+
} catch (NoSuchMethodException | IllegalAccessException e) {
30+
throw new ExceptionInInitializerError(e);
31+
}
32+
}
33+
34+
private static Object findUnsafe(Class<?> unsafeClass) throws IllegalAccessException {
35+
Object found = null;
36+
for (Field field : unsafeClass.getDeclaredFields()) {
37+
if (field.getType() == unsafeClass) {
38+
field.setAccessible(true);
39+
found = field.get(null);
40+
break;
41+
}
42+
}
43+
if (found == null) throw new IllegalStateException("No instance of Unsafe found");
44+
return found;
45+
}
46+
}

0 commit comments

Comments
 (0)