Skip to content

Commit 0c51534

Browse files
committed
Tests for compilation with various -opt-inline-from settings
1 parent be5126f commit 0c51534

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import java.util.regex.Pattern
1111

1212
import scala.annotation.tailrec
1313
import scala.collection.JavaConverters._
14+
import scala.collection.generic.Clearable
1415
import scala.tools.asm.Opcodes
1516
import scala.tools.asm.tree.{AbstractInsnNode, MethodInsnNode, MethodNode}
1617
import scala.tools.nsc.backend.jvm.BTypes.InternalName
@@ -21,7 +22,17 @@ class InlinerHeuristics[BT <: BTypes](val bTypes: BT) {
2122
import bTypes._
2223
import callGraph._
2324

24-
val inlineSourceMatcher = new InlineSourceMatcher(compilerSettings.optInlineFrom.value)
25+
// Hack to read the `optInlineFrom` once per run. It happens at the end of a run though..
26+
// We use it in InlineSourceMatcherTest so we can change the setting without a new Global.
27+
// Better, general idea here: https://github.com/scala/scala/pull/5825#issuecomment-291542859
28+
object HasMatcher extends Clearable {
29+
recordPerRunCache(this)
30+
private def build() = new InlineSourceMatcher(compilerSettings.optInlineFrom.value)
31+
var m: InlineSourceMatcher = build()
32+
override def clear(): Unit = m = build()
33+
}
34+
35+
def inlineSourceMatcher = HasMatcher.m
2536

2637
final case class InlineRequest(callsite: Callsite, post: List[InlineRequest], reason: String) {
2738
// invariant: all post inline requests denote callsites in the callee of the main callsite

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

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,20 @@ import org.junit.runners.JUnit4
88
import scala.tools.nsc.backend.jvm.BTypes.InternalName
99
import scala.tools.nsc.backend.jvm.opt.InlineSourceMatcherTest._
1010
import scala.tools.nsc.backend.jvm.opt.InlinerHeuristics._
11+
import scala.tools.testing.BytecodeTesting
12+
import scala.tools.testing.BytecodeTesting._
1113

1214
@RunWith(classOf[JUnit4])
13-
class InlineSourceMatcherTest {
15+
class InlineSourceMatcherTest extends BytecodeTesting {
16+
import compiler._
17+
18+
override def compilerArgs = "-opt:l:inline -opt-warnings"
19+
def setInlineFrom(s: String): Unit = {
20+
global.settings.optInlineFrom.value = s
21+
// the setting is read once per run
22+
global.perRunCaches.clearAll()
23+
}
24+
1425
case class E(regex: String, negated: Boolean = false, terminal: Boolean = true)
1526

1627
def check(pat: String, expect: E*): InlineSourceMatcher = {
@@ -158,6 +169,63 @@ class InlineSourceMatcherTest {
158169
m.d("a/C")
159170
}
160171
}
172+
173+
@Test
174+
def inlineFromSameClass(): Unit = {
175+
val code =
176+
"""class C {
177+
| @inline final def f = 1
178+
| def t = f
179+
|}
180+
""".stripMargin
181+
182+
def n(): Unit = assertInvoke(getMethod(compileClass(code), "t"), "C", "f")
183+
def y(): Unit = assertNoInvoke(getMethod(compileClass(code), "t"))
184+
185+
setInlineFrom(""); n()
186+
setInlineFrom("C"); y()
187+
setInlineFrom("**:!**.C"); n()
188+
setInlineFrom("**:!**.C:C"); y()
189+
}
190+
191+
@Test
192+
def inlineFromPackages(): Unit = {
193+
val code =
194+
"""package a { class C {
195+
| object D { @inline def f = 1 }
196+
| @inline final def f = 2
197+
|}}
198+
|package b { class E { import a._
199+
| def t1(c: C) = c.f
200+
| def t2(c: C) = c.D.f
201+
|}}
202+
""".stripMargin
203+
204+
{
205+
setInlineFrom("")
206+
val List(_, _, e) = compileClasses(code)
207+
assertInvoke(getMethod(e, "t1"), "a/C", "f")
208+
assertInvoke(getMethod(e, "t2"), "a/C$D$", "f")
209+
}
210+
{
211+
setInlineFrom("a.C")
212+
val List(_, _, e) = compileClasses(code)
213+
assertNoInvoke(getMethod(e, "t1"))
214+
assertInvoke(getMethod(e, "t2"), "a/C$D$", "f")
215+
}
216+
{
217+
setInlineFrom("a.C*")
218+
val List(_, _, e) = compileClasses(code)
219+
assertNoInvoke(getMethod(e, "t1"))
220+
assertDoesNotInvoke(getMethod(e, "t2"), "f") // t2 still has an invocation to the getter `D`
221+
}
222+
{
223+
setInlineFrom("a.C*:!a.C*$")
224+
val List(_, _, e) = compileClasses(code)
225+
assertNoInvoke(getMethod(e, "t1"))
226+
assertInvoke(getMethod(e, "t2"), "a/C$D$", "f")
227+
}
228+
}
161229
}
162230

163231
object InlineSourceMatcherTest {

0 commit comments

Comments
 (0)