diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-07-07 14:34:11 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-07-07 14:39:33 +0200 |
commit | 6e273f7cb6a0f6ff12d899676d30aff5d83b3bb1 (patch) | |
tree | a205774f06159d0f7430d3a5b215039c5e0ae74c /src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala | |
parent | e9c742e1d27c41ee8646ea20dfb59efbc3d94ef3 (diff) | |
download | scala-6e273f7cb6a0f6ff12d899676d30aff5d83b3bb1.tar.gz scala-6e273f7cb6a0f6ff12d899676d30aff5d83b3bb1.tar.bz2 scala-6e273f7cb6a0f6ff12d899676d30aff5d83b3bb1.zip |
Small refactoring to the closure optimizer
Introduces an extractor `LMFInvokeDynamic` that matches InvokeDynamic
instructions that are LambdaMetaFactory calls.
The case class `LambdaMetaFactoryCall` holds such an InvokeDynamic
instruction. It also holds the bootstrap arguments (samMethodType,
implMethod, instantiatedMethodType) so that they can be accessed
without casting the indy.bsmArgs.
The `closureInstantiations` map in the call graph now stores
ClosureInstantiation objects instead of a tuple.
This simplifies some code and gets rid of a few casts.
Diffstat (limited to 'src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala | 31 |
1 files changed, 15 insertions, 16 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala index 4a022b7bc4..3794ee9950 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/Inliner.scala @@ -456,9 +456,9 @@ class Inliner[BT <: BTypes](val btypes: BT) { case indy: InvokeDynamicInsnNode => callGraph.closureInstantiations.get(indy) match { - case Some((methodNode, ownerClass)) => + case Some(closureInit) => val newIndy = instructionMap(indy).asInstanceOf[InvokeDynamicInsnNode] - callGraph.closureInstantiations(newIndy) = (callsiteMethod, callsiteClass) + callGraph.closureInstantiations(newIndy) = ClosureInstantiation(closureInit.lambdaMetaFactoryCall.copy(indy = newIndy), callsiteMethod, callsiteClass) case None => } @@ -688,7 +688,7 @@ class Inliner[BT <: BTypes](val btypes: BT) { } } - case indy: InvokeDynamicInsnNode => + case LMFInvokeDynamic(lmf) => // an indy instr points to a "call site specifier" (CSP) [1] // - a reference to a bootstrap method [2] // - bootstrap method name @@ -734,21 +734,20 @@ class Inliner[BT <: BTypes](val btypes: BT) { // the implMethod is public, lambdaMetaFactory doesn't use the Lookup object's extended // capability, and we can safely inline the instruction into a different class. - if (destinationClass == calleeDeclarationClass) { + val methodRefClass = classBTypeFromParsedClassfile(lmf.implMethod.getOwner) + for { + (methodNode, methodDeclClassNode) <- byteCodeRepository.methodNode(methodRefClass.internalName, lmf.implMethod.getName, lmf.implMethod.getDesc): Either[OptimizerWarning, (MethodNode, InternalName)] + methodDeclClass = classBTypeFromParsedClassfile(methodDeclClassNode) + res <- memberIsAccessible(methodNode.access, methodDeclClass, methodRefClass, destinationClass) + } yield { + res + } + + case indy: InvokeDynamicInsnNode => + if (destinationClass == calleeDeclarationClass) Right(true) // within the same class, any indy instruction can be inlined - } else if (closureOptimizer.isClosureInstantiation(indy)) { - val implMethod = indy.bsmArgs(1).asInstanceOf[Handle] // safe, checked in isClosureInstantiation - val methodRefClass = classBTypeFromParsedClassfile(implMethod.getOwner) - for { - (methodNode, methodDeclClassNode) <- byteCodeRepository.methodNode(methodRefClass.internalName, implMethod.getName, implMethod.getDesc): Either[OptimizerWarning, (MethodNode, InternalName)] - methodDeclClass = classBTypeFromParsedClassfile(methodDeclClassNode) - res <- memberIsAccessible(methodNode.access, methodDeclClass, methodRefClass, destinationClass) - } yield { - res - } - } else { + else Left(UnknownInvokeDynamicInstruction) - } case ci: LdcInsnNode => ci.cst match { case t: asm.Type => classIsAccessible(bTypeForDescriptorOrInternalNameFromClassfile(t.getInternalName), destinationClass) |