From 3ae39036771acb107cbb4a37fe6113c243d89acc Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 25 Mar 2016 19:08:23 -0700 Subject: Target FunctionN, not scala/runtime/java8/JFunction. We compile FunctionN to Java 8's idea of a function now, so no need to target the artisanal JFunction and friends, except when the function is specialized, as I don't yet see how we can use LMF with the way specialization handles FunctionN: First, the working status quo -- the hand-crafted specialized versions of JFunction0. Notice how `apply$mcB$sp` is looking pretty SAMmy: ``` @FunctionalInterface public interface JFunction0$mcB$sp extends JFunction0 { @Override public byte apply$mcB$sp(); @Override default public Object apply() { return BoxesRunTime.boxToByte(this.apply$mcB$sp()); } } ``` Contrast this with our specialized standard FunctionN: ``` public interface Function0 { public R apply(); default public byte apply$mcB$sp() { return BoxesRunTime.unboxToByte(this.apply()); } } public interface Function0$mcB$sp extends Function0 { } ``` The single abstract method in `Function0$mcB$sp` is `apply`, and the method that would let us avoid boxing, if it were abstract, is `apply$mcB$sp`... TODO (after M4): - do same for specialized functions (issues with boxing?) - remove scala/runtime/java8/JFunction* (need new STARR?) --- src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala | 14 ++++++-------- .../tools/nsc/backend/jvm/analysis/BackendUtils.scala | 4 ++-- .../scala/tools/nsc/backend/jvm/opt/CopyProp.scala | 4 ++-- src/compiler/scala/tools/nsc/transform/Delambdafy.scala | 2 +- 4 files changed, 11 insertions(+), 13 deletions(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala index 696a164c56..ab9fd94a93 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/CoreBTypes.scala @@ -219,14 +219,12 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { // 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 functionClasses(base: String): Set[Symbol] = { - def primitives = Iterator("B", "S", "I", "J", "C", "F", "D", "Z", "V") + 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 = Set.empty[String] ++ { - (0 to 22).map(base + _) - } ++ { + val classNames = { primitives.map(base + "0$mc" + _ + "$sp") // Function0 } ++ { // return type specializations appear first in the name string (alphabetical sorting) @@ -237,7 +235,7 @@ class CoreBTypes[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: BTFS) { classNames map getRequiredClass } - lazy val srJFunctionRefs: Set[InternalName] = functionClasses("scala.runtime.java8.JFunction").map(classBTypeFromSymbol(_).internalName) + lazy val functionRefs: Set[InternalName] = (FunctionClass.seq ++ specializedJFunctionSymbols("scala.runtime.java8.JFunction")).map(classBTypeFromSymbol(_).internalName).toSet lazy val typeOfArrayOp: Map[Int, BType] = { import scalaPrimitives._ @@ -343,7 +341,7 @@ trait CoreBTypesProxyGlobalIndependent[BTS <: BTypes] { def srRefConstructors : Map[InternalName, MethodNameAndType] def tupleClassConstructors : Map[InternalName, MethodNameAndType] - def srJFunctionRefs: Set[InternalName] + def functionRefs: Set[InternalName] def lambdaMetaFactoryBootstrapHandle : asm.Handle def lambdaDeserializeBootstrapHandle : asm.Handle @@ -410,7 +408,7 @@ final class CoreBTypesProxy[BTFS <: BTypesFromSymbols[_ <: Global]](val bTypes: def srRefConstructors : Map[InternalName, MethodNameAndType] = _coreBTypes.srRefConstructors def tupleClassConstructors : Map[InternalName, MethodNameAndType] = _coreBTypes.tupleClassConstructors - def srJFunctionRefs: Set[InternalName] = _coreBTypes.srJFunctionRefs + def functionRefs: Set[InternalName] = _coreBTypes.functionRefs def srSymbolLiteral : ClassBType = _coreBTypes.srSymbolLiteral def srStructuralCallSite : ClassBType = _coreBTypes.srStructuralCallSite 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 bd7d5d2608..a6b9faa933 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/BackendUtils.scala @@ -125,7 +125,7 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { private val anonfunAdaptedName = """.*\$anonfun\$\d+\$adapted""".r def hasAdaptedImplMethod(closureInit: ClosureInstantiation): Boolean = { - isrJFunctionType(Type.getReturnType(closureInit.lambdaMetaFactoryCall.indy.desc).getInternalName) && + isBuiltinFunctionType(Type.getReturnType(closureInit.lambdaMetaFactoryCall.indy.desc).getInternalName) && anonfunAdaptedName.pattern.matcher(closureInit.lambdaMetaFactoryCall.implMethod.getName).matches } @@ -250,7 +250,7 @@ class BackendUtils[BT <: BTypes](val btypes: BT) { } } - def isrJFunctionType(internalName: InternalName): Boolean = srJFunctionRefs(internalName) + 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/CopyProp.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala index f1eaebd27c..d28565b9bc 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/CopyProp.scala @@ -296,11 +296,11 @@ 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/runtime/java8/JFunctionN), the `indy` and its inputs + * without side-effects (e.g. scala/FunctionN), the `indy` and its inputs * are eliminated, otherwise a POP is inserted. */ def handleClosureInst(indy: InvokeDynamicInsnNode): Unit = { - if (isrJFunctionType(Type.getReturnType(indy.desc).getInternalName)) { + if (isBuiltinFunctionType(Type.getReturnType(indy.desc).getInternalName)) { toRemove += indy callGraph.removeClosureInstantiation(indy, method) handleInputs(indy, Type.getArgumentTypes(indy.desc).length) diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala index 7ccaec2f50..76c84bd428 100644 --- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala +++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala @@ -241,7 +241,7 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre val isSpecialized = specializedName != funSym.name val functionalInterface = // TODO: this is no longer needed, right? we can just use the regular function classes if (isSpecialized) currentRun.runDefinitions.Scala_Java8_CompatPackage.info.decl(specializedName.prepend("J")) - else currentRun.runDefinitions.Scala_Java8_CompatPackage_JFunction(originalFunction.vparams.length) + else FunctionClass(originalFunction.vparams.length) (functionalInterface, isSpecialized) } -- cgit v1.2.3