summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2016-11-29 14:00:46 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2016-11-29 14:46:07 +0100
commitde25e861249826658663a6d40f13b9b91d1146fc (patch)
tree96ef6ae3a85ab104ec964aa294139e1849c04704 /src
parentb02e3914b6dee6b7da1c3da1864343ccdce5ca3c (diff)
downloadscala-de25e861249826658663a6d40f13b9b91d1146fc.tar.gz
scala-de25e861249826658663a6d40f13b9b91d1146fc.tar.bz2
scala-de25e861249826658663a6d40f13b9b91d1146fc.zip
Don't exclude super calls to trait methods from inlining
In 8020cd6, the inliner was changed to make sure trait methods bodies are not duplicated into the static super accessors, and from there into mixin forwarders. The check for mixin forwarders was too wide. In `def t = super.m`, where `m` is a trait method annotated `@inline`, we want to inline `m`. Note that `super.m` is translated to an `invokestatic T.m$`. The current check incorrectly identifies `t` as a mixin forwarder, and skip inlining.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala12
1 files changed, 8 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala
index 929e8b5ca4..4744cb9ab1 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala
@@ -65,12 +65,13 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) {
}
private def isTraitStaticSuperAccessorName(s: String) = s.endsWith("$")
+ private def traitStaticSuperAccessorName(s: String) = s + "$"
private def isTraitSuperAccessor(method: MethodNode, owner: ClassBType): Boolean = {
owner.isInterface == Right(true) && BytecodeUtils.isStaticMethod(method) && isTraitStaticSuperAccessorName(method.name)
}
- private def findCall(method: MethodNode, such: MethodInsnNode => Boolean): Option[MethodInsnNode] = {
+ private def findSingleCall(method: MethodNode, such: MethodInsnNode => Boolean): Option[MethodInsnNode] = {
@tailrec def noMoreInvoke(insn: AbstractInsnNode): Boolean = {
insn == null || (!insn.isInstanceOf[MethodInsnNode] && noMoreInvoke(insn.getNext))
}
@@ -87,12 +88,15 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) {
find(method.instructions.getFirst)
}
private def superAccessorInvocation(method: MethodNode): Option[MethodInsnNode] =
- findCall(method, mi => mi.itf && mi.getOpcode == Opcodes.INVOKESTATIC && isTraitStaticSuperAccessorName(mi.name))
+ findSingleCall(method, mi => mi.itf && mi.getOpcode == Opcodes.INVOKESTATIC && isTraitStaticSuperAccessorName(mi.name))
private def isMixinForwarder(method: MethodNode, owner: ClassBType): Boolean = {
owner.isInterface == Right(false) &&
!BytecodeUtils.isStaticMethod(method) &&
- superAccessorInvocation(method).nonEmpty
+ (superAccessorInvocation(method) match {
+ case Some(mi) => mi.name == traitStaticSuperAccessorName(method.name)
+ case _ => false
+ })
}
private def isTraitSuperAccessorOrMixinForwarder(method: MethodNode, owner: ClassBType): Boolean = {
@@ -138,7 +142,7 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) {
if (isTraitSuperAccessor(callee.callee, callee.calleeDeclarationClass)) {
// scala-dev#259: when inlining a trait super accessor, also inline the callsite to the default method
val implName = callee.callee.name.dropRight(1)
- findCall(callee.callee, mi => mi.itf && mi.getOpcode == Opcodes.INVOKESPECIAL && mi.name == implName)
+ findSingleCall(callee.callee, mi => mi.itf && mi.getOpcode == Opcodes.INVOKESPECIAL && mi.name == implName)
} else {
// scala-dev#259: when inlining a mixin forwarder, also inline the callsite to the static super accessor
superAccessorInvocation(callee.callee)