diff options
author | Adriaan Moors <adriaan@lightbend.com> | 2016-07-05 14:15:04 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-07-05 14:15:04 -0700 |
commit | 968276345e9b0dae66ef025c2a6fdca013f295e5 (patch) | |
tree | bbb70a78f0ab1b2a7808a9837cc4c5982e90b68f | |
parent | 7644f1091b6f4e46f8290d8ad66ab2045f3ed448 (diff) | |
parent | e5886361006f1b315af13f6aa98cf54a2f7ebe0b (diff) | |
download | scala-968276345e9b0dae66ef025c2a6fdca013f295e5.tar.gz scala-968276345e9b0dae66ef025c2a6fdca013f295e5.tar.bz2 scala-968276345e9b0dae66ef025c2a6fdca013f295e5.zip |
Merge pull request #5256 from lrytz/t9515
SI-9515 closure elimination also for non-Scala-Function SAM types
5 files changed, 25 insertions, 38 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index 1feca56923..d65380aa1f 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -217,26 +217,6 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { nonOverloadedConstructors(tupleClassSymbols) } - // enumeration of specialized classes is temporary, while we still use the java-defined JFunctionN. - // once we switch to ordinary FunctionN, we can use specializedSubclasses just like for tuples. - private def specializedJFunctionSymbols(base: String): Seq[Symbol] = { - def primitives = Seq("B", "S", "I", "J", "C", "F", "D", "Z", "V") - def ijfd = Iterator("I", "J", "F", "D") - def ijfdzv = Iterator("I", "J", "F", "D", "Z", "V") - def ijd = Iterator("I", "J", "D") - val classNames = { - primitives.map(base + "0$mc" + _ + "$sp") // Function0 - } ++ { - // return type specializations appear first in the name string (alphabetical sorting) - for (r <- ijfdzv; a <- ijfd) yield base + "1$mc" + r + a + "$sp" // Function1 - } ++ { - for (r <- ijfdzv; a <- ijd; b <- ijd) yield base + "2$mc" + r + a + b + "$sp" // Function2 - } - classNames map getRequiredClass - } - - lazy val functionRefs: Set[InternalName] = (FunctionClass.seq ++ specializedJFunctionSymbols("scala.runtime.java8.JFunction")).map(classBTypeFromSymbol(_).internalName).toSet - lazy val typeOfArrayOp: Map[Int, BType] = { import scalaPrimitives._ Map( @@ -342,8 +322,6 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] { def srRefConstructors : Map[InternalName, MethodNameAndType] def tupleClassConstructors : Map[InternalName, MethodNameAndType] - def functionRefs: Set[InternalName] - def lambdaMetaFactoryBootstrapHandle : asm.Handle def lambdaDeserializeBootstrapHandle : asm.Handle } @@ -410,8 +388,6 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def srRefConstructors : Map[InternalName, MethodNameAndType] = _coreBTypes.srRefConstructors def tupleClassConstructors : Map[InternalName, MethodNameAndType] = _coreBTypes.tupleClassConstructors - def functionRefs: Set[InternalName] = _coreBTypes.functionRefs - def srSymbolLiteral : ClassBType = _coreBTypes.srSymbolLiteral def srStructuralCallSite : ClassBType = _coreBTypes.srStructuralCallSite def srLambdaDeserialize : ClassBType = _coreBTypes.srLambdaDeserialize diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala index 539435a326..83615abc31 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -131,7 +131,6 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { private val anonfunAdaptedName = """.*\$anonfun\$.*\$\d+\$adapted""".r def hasAdaptedImplMethod(closureInit: ClosureInstantiation): Boolean = { - isBuiltinFunctionType(Type.getReturnType(closureInit.lambdaMetaFactoryCall.indy.desc).getInternalName) && anonfunAdaptedName.pattern.matcher(closureInit.lambdaMetaFactoryCall.implMethod.getName).matches } @@ -256,8 +255,6 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { } } - def isBuiltinFunctionType(internalName: InternalName): Boolean = functionRefs(internalName) - /** * Visit the class node and collect all referenced nested classes. */ 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 d6942d9ff9..5248183337 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CallGraph.scala @@ -430,7 +430,7 @@ class CallGraph[BT <: BTypes](val btypes: BT) { def unapply(insn: AbstractInsnNode): Option[(InvokeDynamicInsnNode, Type, Handle, Type)] = insn match { case indy: InvokeDynamicInsnNode if indy.bsm == metafactoryHandle || indy.bsm == altMetafactoryHandle => indy.bsmArgs match { - case Array(samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type, xs@_*) => // xs binding because IntelliJ gets confused about _@_* + case Array(samMethodType: Type, implMethod: Handle, instantiatedMethodType: Type, _@_*) => // LambdaMetaFactory performs a number of automatic adaptations when invoking the lambda // implementation method (casting, boxing, unboxing, and primitive widening, see Javadoc). // diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala index 4163d62df7..b05669ce89 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala @@ -295,18 +295,12 @@ class CopyProp[BT <: BTypes](val btypes: BT) { } /** - * Eliminate the closure value produced by `indy`. If the SAM type is known to construct - * without side-effects (e.g. scala/FunctionN), the `indy` and its inputs - * are eliminated, otherwise a POP is inserted. + * Eliminate LMF `indy` and its inputs. */ def handleClosureInst(indy: InvokeDynamicInsnNode): Unit = { - if (isBuiltinFunctionType(Type.getReturnType(indy.desc).getInternalName)) { - toRemove += indy - callGraph.removeClosureInstantiation(indy, method) - handleInputs(indy, Type.getArgumentTypes(indy.desc).length) - } else { - toInsertAfter(indy) = getPop(1) - } + toRemove += indy + callGraph.removeClosureInstantiation(indy, method) + handleInputs(indy, Type.getArgumentTypes(indy.desc).length) } def runQueue(): Unit = while (queue.nonEmpty) { diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala index 938bc7b846..2c697bfe50 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOptsTest.scala @@ -750,4 +750,24 @@ class MethodLevelOptsTest extends BytecodeTesting { -1, LDC, ASTORE, -1, ALOAD, ARETURN)) } + + @Test + def elimSamLambda(): Unit = { + val code = + """class C { + | def t1(x: Int) = { + | val fun: java.util.function.IntFunction[Int] = y => y + 1 + | fun(x) + | } + | def t2(x: Int) = { + | val fun: T = i => i + 1 + | fun.f(x) + | } + |} + |trait T { def f(x: Int): Int } + """.stripMargin + val List(c, t) = compileClasses(code) + assertSameSummary(getMethod(c, "t1"), List(ILOAD, "$anonfun$t1$1", IRETURN)) + assertSameSummary(getMethod(c, "t2"), List(ILOAD, "$anonfun$t2$1", IRETURN)) + } } |