aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDmitry Petrashko <dmitry.petrashko@gmail.com>2016-02-18 12:57:03 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2016-03-15 14:43:40 +0100
commitc103926177e1c5b34fc36036af8d686725490180 (patch)
tree0bc3424f84ed6677666fa8d11224a6b768c3beed /src
parent614a2361ee6b7bcebf5bf6aa7fe159acd5e8ef19 (diff)
downloaddotty-c103926177e1c5b34fc36036af8d686725490180.tar.gz
dotty-c103926177e1c5b34fc36036af8d686725490180.tar.bz2
dotty-c103926177e1c5b34fc36036af8d686725490180.zip
Mixin: create less forwarders.
There were two sources of inefficiency in previous scheme: - if symbol was no overriding anything the forwarder was still being created - the class that is will have the forwarder was not considered. Many methods do not require forwarders as JVM will dispatch correctly.
Diffstat (limited to 'src')
-rw-r--r--src/dotty/tools/dotc/transform/MixinOps.scala18
1 files changed, 14 insertions, 4 deletions
diff --git a/src/dotty/tools/dotc/transform/MixinOps.scala b/src/dotty/tools/dotc/transform/MixinOps.scala
index db89f939b..6cebf7197 100644
--- a/src/dotty/tools/dotc/transform/MixinOps.scala
+++ b/src/dotty/tools/dotc/transform/MixinOps.scala
@@ -41,11 +41,21 @@ class MixinOps(cls: ClassSymbol, thisTransform: DenotTransformer)(implicit ctx:
ctx.atPhase(thisTransform) { implicit ctx =>
cls.info.member(sym.name).hasAltWith(_.symbol == sym)
}
-
+
+ /** Does `method` need a forwarder to in class `cls`
+ * Method needs a forwarder in those cases:
+ * - there's a class defining a method with same signature
+ * - there are multiple traits defining method with same signature
+ */
def needsForwarder(meth: Symbol): Boolean = {
- lazy val overridenSymbols = meth.allOverriddenSymbols
- def needsDisambiguation = !overridenSymbols.forall(_ is Deferred)
- def hasNonInterfaceDefinition = overridenSymbols.forall(!_.owner.is(Trait))
+ lazy val competingMethods = cls.baseClasses.iterator
+ .filter(_ ne meth.owner)
+ .map(meth.overriddenSymbol)
+ .filter(_.exists)
+ .toList
+
+ def needsDisambiguation = competingMethods.exists(x=> !(x is Deferred)) // multiple implementations are available
+ def hasNonInterfaceDefinition = competingMethods.exists(!_.owner.is(Trait)) // there is a definition originating from class
meth.is(Method, butNot = PrivateOrAccessorOrDeferred) &&
isCurrent(meth) &&
(needsDisambiguation || hasNonInterfaceDefinition || meth.owner.is(Scala2x))