Skip to content

Commit 20e269e

Browse files
committed
Compiler support for JEP-193 VarHandle polymorphic signatures
VarHandles bring a host of new "polymorphic signature" methods to the Java 9 standard library. This commit updates the way we detect such methods to look at the absense/presense of the `PolymorphicSignature` annotation, so as to include these (and any future additions.) When we see applications of such methods, we disable adaptation of argument and return types. Tested manually with JDK9-ea: ``` Welcome to Scala 2.12.2-20161208-165912-3de1c0c (Java HotSpot(TM) 64-Bit Server VM, Java 9-ea). Type in expressions for evaluation. Or try :help. scala> import java.lang.invoke._, scala.runtime.IntRef import java.lang.invoke._ import scala.runtime.IntRef scala> val varHandle = MethodHandles.lookup().in(classOf[IntRef]).findVarHandle(classOf[IntRef], "elem", classOf[Int]); varHandle: java.lang.invoke.VarHandle = java.lang.invoke.VarHandleInts$FieldInstanceReadWrite@7112ce6 scala> varHandle.getAndSet(ref, 1): Int res5: Int = 0 scala> varHandle.getAndSet(ref, 1): Int res6: Int = 1 ``` Inspecting bytecode shows the absense of box/unboxing: ``` object Test { import java.lang.invoke._, scala.runtime.IntRef val varHandle = MethodHandles.lookup().in(classOf[IntRef]).findVarHandle(classOf[IntRef], "elem", classOf[Int]); def main(args: Array[String]): Unit = { val i : Int = varHandle.getAndSet(IntRef.zero, 1) } } ``` ``` public void main(java.lang.String[]); Code: 0: aload_0 1: invokevirtual #28 // Method varHandle:()Ljava/lang/invoke/VarHandle; 4: invokestatic #34 // Method scala/runtime/IntRef.zero:()Lscala/runtime/IntRef; 7: iconst_1 8: invokevirtual #40 // Method java/lang/invoke/VarHandle.getAndSet:(Lscala/runtime/IntRef;I)I 11: istore_2 12: return ```
1 parent 3de1c0c commit 20e269e

File tree

3 files changed

+12
-5
lines changed

3 files changed

+12
-5
lines changed

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3401,7 +3401,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
34013401
// governed by a) the argument types and b) the expected type
34023402
val args1 = typedArgs(args, forArgMode(fun, mode))
34033403
val pts = args1.map(_.tpe.deconst)
3404-
val clone = fun.symbol.cloneSymbol
3404+
val clone = fun.symbol.cloneSymbol.withoutAnnotations
34053405
val cloneParams = pts map (pt => clone.newValueParameter(currentUnit.freshTermName()).setInfo(pt))
34063406
val resultType = if (isFullyDefined(pt)) pt else ObjectTpe
34073407
clone.modifyInfo(mt => copyMethodType(mt, cloneParams, resultType))

src/reflect/scala/reflect/internal/Definitions.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,8 @@ trait Definitions extends api.StandardDefinitions {
429429
def isArrayOfSymbol(tp: Type, elem: Symbol) = elementTest(ArrayClass, tp)(_.typeSymbol == elem)
430430
def elementType(container: Symbol, tp: Type): Type = elementExtract(container, tp)
431431

432+
lazy val JavaLangInvokePackage = getPackageIfDefined(TermName("java.lang.invoke"))
433+
432434
// collections classes
433435
lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]]
434436
lazy val IteratorClass = requiredClass[scala.collection.Iterator[_]]
@@ -537,7 +539,8 @@ trait Definitions extends api.StandardDefinitions {
537539
lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature]
538540
lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature]
539541

540-
lazy val MethodHandle = getClassIfDefined("java.lang.invoke.MethodHandle")
542+
lazy val MethodHandleClass = getClassIfDefined("java.lang.invoke.MethodHandle")
543+
lazy val VarHandleClass = getClassIfDefined("java.lang.invoke.VarHandle")
541544

542545
// Option classes
543546
lazy val OptionClass: ClassSymbol = requiredClass[Option[_]]
@@ -1567,9 +1570,12 @@ trait Definitions extends api.StandardDefinitions {
15671570

15681571
lazy val PartialManifestClass = getTypeMember(ReflectPackage, tpnme.ClassManifest)
15691572
lazy val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
1573+
private lazy val PolymorphicSignatureClass = MethodHandleClass.companionModule.info.decl(TypeName("PolymorphicSignature"))
15701574

1571-
def isPolymorphicSignature(sym: Symbol) = PolySigMethods(sym)
1572-
private lazy val PolySigMethods: Set[Symbol] = Set[Symbol](MethodHandle.info.decl(sn.Invoke), MethodHandle.info.decl(sn.InvokeExact)).filter(_.exists)
1575+
def isPolymorphicSignature(sym: Symbol) = sym != null && sym.isJavaDefined && {
1576+
val owner = sym.safeOwner
1577+
(owner == MethodHandleClass || owner == VarHandleClass) && sym.hasAnnotation(PolymorphicSignatureClass)
1578+
}
15731579

15741580
lazy val Scala_Java8_CompatPackage = rootMirror.getPackageIfDefined("scala.runtime.java8")
15751581
}

src/reflect/scala/reflect/runtime/JavaUniverseForce.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,8 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
323323
definitions.QuasiquoteClass_api_unapply
324324
definitions.ScalaSignatureAnnotation
325325
definitions.ScalaLongSignatureAnnotation
326-
definitions.MethodHandle
326+
definitions.MethodHandleClass
327+
definitions.VarHandleClass
327328
definitions.OptionClass
328329
definitions.OptionModule
329330
definitions.SomeClass

0 commit comments

Comments
 (0)