Skip to content

Commit e89bdde

Browse files
authored
Merge pull request scala#8188 from lrytz/sd618
Inline calls to static trait super accessors if trait method is trivial
2 parents 26f34d0 + 2d66bd0 commit e89bdde

File tree

3 files changed

+44
-5
lines changed

3 files changed

+44
-5
lines changed

build.sbt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,7 +1155,7 @@ intellij := {
11551155
}
11561156

11571157
def moduleDep(name: String, jars: Seq[File]) = {
1158-
val entries = jars.map(f => s""" <root url="jar://${f.toURI.getRawPath}!/" />""").mkString("\n")
1158+
val entries = jars.map(f => s""" <root url="jar://${f.toURI.getPath}!/" />""").mkString("\n")
11591159
s"""| <library name="$name-deps">
11601160
| <CLASSES>
11611161
|$entries
@@ -1166,7 +1166,7 @@ intellij := {
11661166
}
11671167

11681168
def starrDep(jars: Seq[File]) = {
1169-
val entries = jars.map(f => s""" <root url="file://${f.toURI.getRawPath}" />""").mkString("\n")
1169+
val entries = jars.map(f => s""" <root url="file://${f.toURI.getPath}" />""").mkString("\n")
11701170
s"""| <library name="starr" type="Scala">
11711171
| <properties>
11721172
| <option name="languageLevel" value="Scala_2_12" />

src/compiler/scala/tools/nsc/backend/jvm/opt/InlinerHeuristics.scala

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,21 @@ abstract class InlinerHeuristics extends PerRunInit {
244244
// inlined in turn (chosen by the same heuristic), or the code is rolled back. but we don't inline them just because
245245
// they are forwarders.
246246
val isTraitSuperAccessor = backendUtils.isTraitSuperAccessor(callee.callee, callee.calleeDeclarationClass)
247-
if (isTraitSuperAccessor) null
247+
if (isTraitSuperAccessor) {
248+
// inline static trait super accessors if the corresponding trait method is a forwarder or trivial (scala-dev#618)
249+
{
250+
val css = callGraph.callsites(callee.callee)
251+
if (css.sizeIs == 1) css.head._2 else null
252+
} match {
253+
case null => null
254+
case traitMethodCallsite =>
255+
val tmCallee = traitMethodCallsite.callee.get
256+
val traitMethodForwarderKind = backendUtils.looksLikeForwarderOrFactoryOrTrivial(
257+
tmCallee.callee, tmCallee.calleeDeclarationClass.internalName, allowPrivateCalls = false)
258+
if (traitMethodForwarderKind > 0) GenericForwarder
259+
else null
260+
}
261+
}
248262
else {
249263
val forwarderKind = backendUtils.looksLikeForwarderOrFactoryOrTrivial(callee.callee, callee.calleeDeclarationClass.internalName, allowPrivateCalls = false)
250264
if (forwarderKind < 0)

test/junit/scala/tools/nsc/backend/jvm/opt/InlinerTest.scala

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1642,8 +1642,8 @@ class InlinerTest extends BytecodeTesting {
16421642
assertInvoke(getMethod(c, "t5"), "T", "m3a") // could not inline
16431643
assertNoInvoke(getMethod(c, "t6")) // both forwarders inlined, closure eliminated
16441644

1645-
assertInvoke(getMethod(c, "t7"), "T", "m1a$")
1646-
assertInvoke(getMethod(c, "t8"), "T", "m1b$")
1645+
assertNoInvoke(getMethod(c, "t7"))
1646+
assertNoInvoke(getMethod(c, "t8"))
16471647

16481648
assertNoInvoke(getMethod(c, "t9"))
16491649
assertNoInvoke(getMethod(c, "t10"))
@@ -2208,4 +2208,29 @@ class InlinerTest extends BytecodeTesting {
22082208
}
22092209
assertEquals(List("A", "$anonfun$f$1"), args.head)
22102210
}
2211+
2212+
@Test
2213+
def sd618(): Unit = {
2214+
val code =
2215+
"""trait T {
2216+
| final def m1 = 1 // trivial
2217+
| final def m2 = p // forwarder
2218+
| @noinline def p = 42
2219+
|}
2220+
|
2221+
|object TT extends T // gets mixin forwarders m1 / m2 which call the static T.m1$ / T.m2$
2222+
|
2223+
|class C {
2224+
| def t1a(t: T) = t.m1 // inlined, so we get 1
2225+
| def t1b = TT.m1 // mixin forwarder is inlined, static forwarder then as well because the final method is trivial
2226+
| def t2a(t: T) = t.m2 // inlined, so we get T.p
2227+
| def t2b = TT.m2 // mixin forwarder is inlined, static forwarder then as well because the final method is forwarder
2228+
|}
2229+
""".stripMargin
2230+
val c :: _ = compileClasses(code)
2231+
assertNoInvoke(getMethod(c, "t1a"))
2232+
assertNoInvoke(getMethod(c, "t1b"))
2233+
assertInvoke(getMethod(c, "t2a"), "T", "p")
2234+
assertInvoke(getMethod(c, "t2b"), "T", "p")
2235+
}
22112236
}

0 commit comments

Comments
 (0)