diff options
author | Martin Odersky <odersky@gmail.com> | 2016-12-14 14:38:45 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-12-17 18:34:27 +0100 |
commit | 86dea77d3b659b48fec0e9d53495009a7bff335d (patch) | |
tree | a646109f27f82291d8660a6c1bbe4930d09230c8 /compiler | |
parent | 04adb53b8d079ea114c5432ca3b3f824c80756a7 (diff) | |
download | dotty-86dea77d3b659b48fec0e9d53495009a7bff335d.tar.gz dotty-86dea77d3b659b48fec0e9d53495009a7bff335d.tar.bz2 dotty-86dea77d3b659b48fec0e9d53495009a7bff335d.zip |
Make specialization tweakable
Introduce an option to not specialize monomorphic
targets of callsites.
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala index bf72b89c0..a9fadaa56 100644 --- a/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala +++ b/compiler/src/dotty/tools/dotc/transform/ShortcutImplicits.scala @@ -37,7 +37,7 @@ import collection.mutable * is expanded to: * * def m(xs: Ts): IF - * def m$direct(xs: Ts, ys: Us): R + * def m$direct(xs: Ts)(ys: Us): R * * (2) A reference `qual.apply` where `qual` has implicit function type and * `qual` refers to a method `m` is rewritten to a reference to `m$direct`, @@ -49,6 +49,14 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr override def phaseName: String = "shortcutImplicits" val treeTransform = new Transform + /** If this option true, we don't specialize symbols that are known to be only + * targets of monomorphic calls. + * The reason for this option is that benchmarks show that on the JVM for monomorphic dispatch + * scenarios inlining and escape analysis can often remove all calling overhead, so we might as + * well not duplicate the code. We need more experience to decide on the best setting of this option. + */ + final val specializeMonoTargets = true + class Transform extends TreeTransform { def phase = thisTransform @@ -59,6 +67,17 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr */ private val directMeth = new mutable.HashMap[Symbol, Symbol] + /** Should `sym` get a ..$direct companion? + * This is the case if (1) `sym` is a method with an implicit function type as final result type. + * However if `specializeMonoTargets` is true, we exclude symbols that are known + * to be only targets of monomorphic calls because they are effectively + * final and don't override anything. + */ + private def shouldBeSpecialized(sym: Symbol)(implicit ctx: Context) = + sym.is(Method, butNot = Accessor) && + defn.isImplicitFunctionType(sym.info.finalResultType) && + (specializeMonoTargets || !sym.isEffectivelyFinal || sym.allOverriddenSymbols.nonEmpty) + /** @pre The type's final result type is an implicit function type `implicit Ts => R`. * @return The type of the `apply` member of `implicit Ts => R`. */ @@ -93,7 +112,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo) = if (tree.name == nme.apply && defn.isImplicitFunctionType(tree.qualifier.tpe.widen) && - tree.qualifier.symbol.is(Method, butNot = Accessor)) { + shouldBeSpecialized(tree.qualifier.symbol)) { def directQual(tree: Tree): Tree = tree match { case Apply(fn, args) => cpy.Apply(tree)(directQual(fn), args) case TypeApply(fn, args) => cpy.TypeApply(tree)(directQual(fn), args) @@ -108,7 +127,7 @@ class ShortcutImplicits extends MiniPhase with IdentityDenotTransformer { thisTr /** Transform methods with implicit function type result according to rewrite rule (1) above */ override def transformDefDef(mdef: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { val original = mdef.symbol - if (defn.isImplicitFunctionType(original.info.finalResultType)) { + if (shouldBeSpecialized(original)) { val direct = directMethod(original) def splitClosure(tree: Tree): (List[Type] => List[List[Tree]] => Tree, Tree) = tree match { |