Skip to content

Commit 4cb5617

Browse files
committed
git: rebase and squash from parent branch
Signed-off-by: Iltotore <rafbodaha@gmail.com>
2 parents cb47acd + c265957 commit 4cb5617

File tree

7 files changed

+718
-46
lines changed

7 files changed

+718
-46
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package dotty.runtime
2+
3+
import java.lang.invoke.MethodHandles
4+
5+
import scala.reflect.ClassTag
6+
7+
/**
8+
* sun.misc.Unsafe and java.lang.invoke.VarHandle receptacle.
9+
* It allows Java 8-9+ compatibility without using 9-deprecated Unsafe class.
10+
*/
11+
12+
trait RuntimeHandleReceptacle {
13+
14+
15+
def get[U <: AnyRef : ClassTag](ref: Object, clazz: Class[_], varName: String)(implicit tag: ClassTag[U]): U
16+
17+
def getLongVolatile(ref: Object, clazz: Class[_], varName: String): Long
18+
19+
def put[U <: AnyRef : ClassTag](ref: Object, clazz: Class[_], varName: String, value: U)(implicit tag: ClassTag[U]): Unit
20+
21+
def compareAndSwapLong(ref: Object, clazz: Class[_], varName: String, expected: Long, value: Long): Boolean
22+
}
23+
24+
object RuntimeHandleReceptacle {
25+
26+
private val lookup = MethodHandles.lookup()
27+
private val reference: RuntimeHandleReceptacle = {
28+
try {
29+
//Java 9+
30+
Class.forName("java.lang.invoke.VarHandle")
31+
new VarHandlerReceptacle(lookup)
32+
} catch {
33+
//Java 8
34+
case e: ClassNotFoundException =>
35+
val unsafeClass = Class.forName("sun.misc.Unsafe")
36+
var unsafeReference: sun.misc.Unsafe = null
37+
for (field <- unsafeClass.getDeclaredFields) if (field.getType.isAssignableFrom(unsafeClass)) unsafeReference = field.get(null).asInstanceOf[sun.misc.Unsafe]
38+
new UnsafeReceptacle(unsafeReference)
39+
}
40+
}
41+
42+
def apply(): RuntimeHandleReceptacle = reference
43+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package dotty.runtime
2+
3+
import sun.misc.Unsafe
4+
5+
import scala.reflect.ClassTag
6+
7+
8+
class UnsafeReceptacle(runtimeReference: Unsafe) extends RuntimeHandleReceptacle {
9+
10+
override def get[U <: AnyRef : ClassTag](ref: Object, clazz: Class[_], varName: String)(implicit tag: ClassTag[U]): U = runtimeReference.getObject(ref, getOffset(clazz, varName)).asInstanceOf[U]
11+
override def getLongVolatile(ref: Object, clazz: Class[_], varName: String): Long = runtimeReference.getLongVolatile(ref, getOffset(clazz, varName))
12+
13+
override def put[U : ClassTag](ref: Object, clazz: Class[_], varName: String, value: U)(implicit tag: ClassTag[U]): Unit = runtimeReference.putObject(ref, getOffset(clazz, varName), value)
14+
15+
override def compareAndSwapLong(ref: Object, clazz: Class[_], varName: String, expected: Long, value: Long): Boolean = runtimeReference.compareAndSwapLong(ref, getOffset(clazz, varName), expected, value)
16+
17+
private def getOffset(clazz: Class[_], varName: String): Long = runtimeReference.objectFieldOffset(clazz.getDeclaredField(varName))
18+
19+
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package dotty.runtime
2+
3+
import java.lang.invoke.MethodHandles
4+
5+
import scala.reflect.ClassTag
6+
7+
class VarHandlerReceptacle(lookup: MethodHandles.Lookup) extends RuntimeHandleReceptacle {
8+
9+
override def get[U <: AnyRef : ClassTag](ref: Object, clazz: Class[_], varName: String)(implicit tag: ClassTag[U]): U = lookup.findVarHandle(clazz, varName, tag.runtimeClass).get(ref.asInstanceOf[Object]).asInstanceOf[U]
10+
11+
override def put[U <: AnyRef : ClassTag](ref: Object, clazz: Class[_], varName: String, value: U)(implicit tag: ClassTag[U]): Unit = lookup.findVarHandle(clazz, varName, tag.runtimeClass).set(ref.asInstanceOf[Object], value.asInstanceOf[Object]).asInstanceOf[U]
12+
13+
override def compareAndSwapLong(ref: Object, clazz: Class[_], varName: String, expected: Long, value: Long): Boolean = lookup.findVarHandle(clazz, varName, classOf[Long]).compareAndSet(ref, Long.box(expected), Long.box(value))
14+
15+
override def getLongVolatile(ref: Object, clazz: Class[_], varName: String): Long = ???
16+
}

0 commit comments

Comments
 (0)