From e619b033350a3378d650db4c3e5b1bfc83b73d81 Mon Sep 17 00:00:00 2001 From: Lukas Rytz Date: Wed, 20 Jul 2016 17:36:54 +0200 Subject: Upgrade asm to 5.1 The constructor of scala.tools.asm.Handle now takes an additional boolean parameter to denote whether the owner is an interface. --- .../tools/nsc/backend/jvm/BCodeBodyBuilder.scala | 8 +++-- .../tools/nsc/backend/jvm/BTypesFromSymbols.scala | 3 +- .../scala/tools/nsc/backend/jvm/CoreBTypes.scala | 34 +++++++++++++++++----- .../tools/nsc/backend/jvm/opt/CallGraph.scala | 16 +--------- .../scala/tools/partest/ASMConverters.scala | 6 ++-- src/reflect/scala/reflect/internal/StdNames.scala | 1 + test/files/run/classfile-format-51.scala | 2 +- test/files/run/noInlineUnknownIndy/Test.scala | 7 ++++- versions.properties | 2 +- 9 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index 55fe47bde6..acedf83016 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -1334,11 +1334,13 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { val isStaticMethod = lambdaTarget.hasFlag(Flags.STATIC) def asmType(sym: Symbol) = classBTypeFromSymbol(sym).toASMType + val isInterface = lambdaTarget.owner.isTrait val implMethodHandle = - new asm.Handle(if (lambdaTarget.hasFlag(Flags.STATIC)) asm.Opcodes.H_INVOKESTATIC else if (lambdaTarget.owner.isTrait) asm.Opcodes.H_INVOKEINTERFACE else asm.Opcodes.H_INVOKEVIRTUAL, + new asm.Handle(if (lambdaTarget.hasFlag(Flags.STATIC)) asm.Opcodes.H_INVOKESTATIC else if (isInterface) asm.Opcodes.H_INVOKEINTERFACE else asm.Opcodes.H_INVOKEVIRTUAL, classBTypeFromSymbol(lambdaTarget.owner).internalName, lambdaTarget.name.toString, - methodBTypeFromSymbol(lambdaTarget).descriptor) + methodBTypeFromSymbol(lambdaTarget).descriptor, + /* itf = */ isInterface) val receiver = if (isStaticMethod) Nil else lambdaTarget.owner :: Nil val (capturedParams, lambdaParams) = lambdaTarget.paramss.head.splitAt(lambdaTarget.paramss.head.length - arity) // Requires https://github.com/scala/scala-java8-compat on the runtime classpath @@ -1351,7 +1353,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { val flags = java.lang.invoke.LambdaMetafactory.FLAG_SERIALIZABLE | java.lang.invoke.LambdaMetafactory.FLAG_MARKERS val ScalaSerializable = classBTypeFromSymbol(definitions.SerializableClass).toASMType - bc.jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryBootstrapHandle, + bc.jmethod.visitInvokeDynamicInsn(samName, invokedType, lambdaMetaFactoryAltMetafactoryHandle, /* samMethodType = */ samMethodType, /* implMethod = */ implMethodHandle, /* instantiatedMethodType = */ constrainedType, diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 1a4590e7d1..383347a0d3 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -157,7 +157,8 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { def staticHandleFromSymbol(sym: Symbol): asm.Handle = { val owner = if (sym.owner.isModuleClass) sym.owner.linkedClassOfClass else sym.owner val descriptor = methodBTypeFromMethodType(sym.info, isConstructor = false).descriptor - new asm.Handle(asm.Opcodes.H_INVOKESTATIC, classBTypeFromSymbol(owner).internalName, sym.name.encoded, descriptor) + val ownerBType = classBTypeFromSymbol(owner) + new asm.Handle(asm.Opcodes.H_INVOKESTATIC, ownerBType.internalName, sym.name.encoded, descriptor, /* itf = */ ownerBType.isInterface.get) } /** diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index d65380aa1f..c2010d2828 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -248,7 +248,22 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { }) } - lazy val lambdaMetaFactoryBootstrapHandle = + lazy val lambdaMetaFactoryMetafactoryHandle = + new asm.Handle(asm.Opcodes.H_INVOKESTATIC, + coreBTypes.jliLambdaMetafactoryRef.internalName, sn.Metafactory.toString, + MethodBType( + List( + coreBTypes.jliMethodHandlesLookupRef, + coreBTypes.StringRef, + coreBTypes.jliMethodTypeRef, + coreBTypes.jliMethodTypeRef, + coreBTypes.jliMethodHandleRef, + coreBTypes.jliMethodTypeRef), + coreBTypes.jliCallSiteRef + ).descriptor, + /* itf = */ coreBTypes.jliLambdaMetafactoryRef.isInterface.get) + + lazy val lambdaMetaFactoryAltMetafactoryHandle = new asm.Handle(asm.Opcodes.H_INVOKESTATIC, coreBTypes.jliLambdaMetafactoryRef.internalName, sn.AltMetafactory.toString, MethodBType( @@ -258,7 +273,8 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { coreBTypes.jliMethodTypeRef, ArrayBType(ObjectRef)), coreBTypes.jliCallSiteRef - ).descriptor) + ).descriptor, + /* itf = */ coreBTypes.jliLambdaMetafactoryRef.isInterface.get) lazy val lambdaDeserializeBootstrapHandle = new scala.tools.asm.Handle(scala.tools.asm.Opcodes.H_INVOKESTATIC, @@ -270,7 +286,8 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { coreBTypes.jliMethodTypeRef ), coreBTypes.jliCallSiteRef - ).descriptor) + ).descriptor, + /* itf = */ coreBTypes.srLambdaDeserialize.isInterface.get) } /** @@ -299,6 +316,7 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] { def juHashMapRef : ClassBType def juMapRef : ClassBType def jliCallSiteRef : ClassBType + def jliLambdaMetafactoryRef : ClassBType def jliMethodTypeRef : ClassBType def jliSerializedLambdaRef : ClassBType def jliMethodHandleRef : ClassBType @@ -322,8 +340,9 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] { def srRefConstructors : Map[InternalName, MethodNameAndType] def tupleClassConstructors : Map[InternalName, MethodNameAndType] - def lambdaMetaFactoryBootstrapHandle : asm.Handle - def lambdaDeserializeBootstrapHandle : asm.Handle + def lambdaMetaFactoryMetafactoryHandle : asm.Handle + def lambdaMetaFactoryAltMetafactoryHandle : asm.Handle + def lambdaDeserializeBootstrapHandle : asm.Handle } /** @@ -405,6 +424,7 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def String_valueOf: Symbol = _coreBTypes.String_valueOf - def lambdaMetaFactoryBootstrapHandle = _coreBTypes.lambdaMetaFactoryBootstrapHandle - def lambdaDeserializeBootstrapHandle = _coreBTypes.lambdaDeserializeBootstrapHandle + def lambdaMetaFactoryMetafactoryHandle : asm.Handle = _coreBTypes.lambdaMetaFactoryMetafactoryHandle + def lambdaMetaFactoryAltMetafactoryHandle : asm.Handle = _coreBTypes.lambdaMetaFactoryAltMetafactoryHandle + def lambdaDeserializeBootstrapHandle : asm.Handle = _coreBTypes.lambdaDeserializeBootstrapHandle } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala index 5248183337..b088b5ee48 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -413,22 +413,8 @@ class CallGraph[BT <: BTypes](val btypes: BT) { final case class LambdaMetaFactoryCall(indy: InvokeDynamicInsnNode, samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type) object LambdaMetaFactoryCall { - private val lambdaMetaFactoryInternalName: InternalName = "java/lang/invoke/LambdaMetafactory" - - private val metafactoryHandle = { - val metafactoryMethodName: String = "metafactory" - val metafactoryDesc: String = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;" - new Handle(Opcodes.H_INVOKESTATIC, lambdaMetaFactoryInternalName, metafactoryMethodName, metafactoryDesc) - } - - private val altMetafactoryHandle = { - val altMetafactoryMethodName: String = "altMetafactory" - val altMetafactoryDesc: String = "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;" - new Handle(Opcodes.H_INVOKESTATIC, lambdaMetaFactoryInternalName, altMetafactoryMethodName, altMetafactoryDesc) - } - def unapply(insn: AbstractInsnNode): Option[(InvokeDynamicInsnNode, Type, Handle, Type)] = insn match { - case indy: InvokeDynamicInsnNode if indy.bsm == metafactoryHandle || indy.bsm == altMetafactoryHandle => + case indy: InvokeDynamicInsnNode if indy.bsm == coreBTypes.lambdaMetaFactoryMetafactoryHandle || indy.bsm == coreBTypes.lambdaMetaFactoryAltMetafactoryHandle => indy.bsmArgs match { case Array(samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type, _@_*) => // LambdaMetaFactory performs a number of automatic adaptations when invoking the lambda diff --git a/src/partest-extras/scala/tools/partest/ASMConverters.scala b/src/partest-extras/scala/tools/partest/ASMConverters.scala index a3d849a9c1..445d3c89c2 100644 --- a/src/partest-extras/scala/tools/partest/ASMConverters.scala +++ b/src/partest-extras/scala/tools/partest/ASMConverters.scala @@ -94,7 +94,7 @@ object ASMConverters { case class FrameEntry (`type`: Int, local: List[Any], stack: List[Any]) extends Instruction { def opcode: Int = -1 } case class LineNumber (line: Int, start: Label) extends Instruction { def opcode: Int = -1 } - case class MethodHandle(tag: Int, owner: String, name: String, desc: String) + case class MethodHandle(tag: Int, owner: String, name: String, desc: String, itf: Boolean) case class ExceptionHandler(start: Label, end: Label, handler: Label, desc: Option[String]) case class LocalVariable(name: String, desc: String, signature: Option[String], start: Label, end: Label, index: Int) @@ -147,7 +147,7 @@ object ASMConverters { case _ => a // can be: Class, method Type, primitive constant })(collection.breakOut) - private def convertMethodHandle(h: asm.Handle): MethodHandle = MethodHandle(h.getTag, h.getOwner, h.getName, h.getDesc) + private def convertMethodHandle(h: asm.Handle): MethodHandle = MethodHandle(h.getTag, h.getOwner, h.getName, h.getDesc, h.isInterface) private def convertHandlers(method: t.MethodNode): List[ExceptionHandler] = { method.tryCatchBlocks.asScala.map(h => ExceptionHandler(applyLabel(h.start), applyLabel(h.end), applyLabel(h.handler), Option(h.`type`)))(collection.breakOut) @@ -227,7 +227,7 @@ object ASMConverters { case x => x.asInstanceOf[Object] } - def unconvertMethodHandle(h: MethodHandle): asm.Handle = new asm.Handle(h.tag, h.owner, h.name, h.desc) + def unconvertMethodHandle(h: MethodHandle): asm.Handle = new asm.Handle(h.tag, h.owner, h.name, h.desc, h.itf) def unconvertBsmArgs(a: List[Object]): Array[Object] = a.map({ case h: MethodHandle => unconvertMethodHandle(h) case o => o diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala index 4f5a545c95..11b5db9793 100644 --- a/src/reflect/scala/reflect/internal/StdNames.scala +++ b/src/reflect/scala/reflect/internal/StdNames.scala @@ -1171,6 +1171,7 @@ trait StdNames { final val Invoke: TermName = newTermName("invoke") final val InvokeExact: TermName = newTermName("invokeExact") + final val Metafactory: TermName = newTermName("metafactory") final val AltMetafactory: TermName = newTermName("altMetafactory") final val Bootstrap: TermName = newTermName("bootstrap") diff --git a/test/files/run/classfile-format-51.scala b/test/files/run/classfile-format-51.scala index 3a6c4861f1..40eebee198 100644 --- a/test/files/run/classfile-format-51.scala +++ b/test/files/run/classfile-format-51.scala @@ -80,7 +80,7 @@ object Test extends DirectTest { val test = cw.visitMethod(ACC_PUBLIC + ACC_FINAL, "test", s"()Ljava/lang/String;", null, null) test.visitCode() - val bootstrapHandle = new Handle(H_INVOKESTATIC, invokerClassName, bootstrapMethodName, bootStrapMethodType) + val bootstrapHandle = new Handle(H_INVOKESTATIC, invokerClassName, bootstrapMethodName, bootStrapMethodType, /* itf = */ false) test.visitInvokeDynamicInsn("invoke", targetMethodType, bootstrapHandle) test.visitInsn(ARETURN) test.visitMaxs(1, 1) diff --git a/test/files/run/noInlineUnknownIndy/Test.scala b/test/files/run/noInlineUnknownIndy/Test.scala index c6d227b6f2..a666146f15 100644 --- a/test/files/run/noInlineUnknownIndy/Test.scala +++ b/test/files/run/noInlineUnknownIndy/Test.scala @@ -15,7 +15,12 @@ object Test extends DirectTest { } def show(): Unit = { - val unknownBootstrapMethod = new Handle(Opcodes.H_INVOKESTATIC, "not/java/lang/SomeLambdaMetafactory", "notAMetaFactoryMethod", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;") + val unknownBootstrapMethod = new Handle( + Opcodes.H_INVOKESTATIC, + "not/java/lang/SomeLambdaMetafactory", + "notAMetaFactoryMethod", + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;", + /* itf = */ false) modifyClassFile(new File(testOutput.toFile, "A_1.class"))((cn: ClassNode) => { val testMethod = cn.methods.iterator.asScala.find(_.name == "test").head val indy = testMethod.instructions.iterator.asScala.collect({ case i: InvokeDynamicInsnNode => i }).next() diff --git a/versions.properties b/versions.properties index 4d24e0d598..ed90768780 100644 --- a/versions.properties +++ b/versions.properties @@ -27,7 +27,7 @@ scala-parser-combinators.version.number=1.0.4 scala-swing.version.number=2.0.0-M2 scala-swing.version.osgi=2.0.0.M2 jline.version=2.14.1 -scala-asm.version=5.0.4-scala-3 +scala-asm.version=5.1.0-scala-1 # external modules, used internally (not shipped) partest.version.number=1.0.17 -- cgit v1.2.3