diff options
author | Paul Phillips <paulp@improving.org> | 2011-07-04 20:40:05 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-07-04 20:40:05 +0000 |
commit | 257a7e65deb01c9e161c83ea5fd7a2b3c862e5e1 (patch) | |
tree | bccde9a93d807606c604ba898968316ff61fbaf5 /test/files/run | |
parent | 9e7d7e021cd49851257aca44b81e20427d886529 (diff) | |
download | scala-257a7e65deb01c9e161c83ea5fd7a2b3c862e5e1.tar.gz scala-257a7e65deb01c9e161c83ea5fd7a2b3c862e5e1.tar.bz2 scala-257a7e65deb01c9e161c83ea5fd7a2b3c862e5e1.zip |
Fixed a bug in the optimizer which was preventi...
Fixed a bug in the optimizer which was preventing private methods from
being inlined. Also relaxes a condition related to the "liftedTry"
problem: the inliner has to exclude certain methods from consideration
if there is a value on the stack and the method being inlined has
exception handlers. The new condition is as before, except that it does
not exclude methods of the "try/finally" variety (i.e. finalizers, but
no other exception handlers.) This is necessary to optimize this common
pattern:
@inline private def foo(body: => Unit) {
val saved = something
try body
finally something = saved
}
The closure for "body" can be fully eliminated, but only if the contents
of foo can be inlined into the caller.
Closes #4764, review by rompf.
Diffstat (limited to 'test/files/run')
-rw-r--r-- | test/files/run/private-inline.check | 1 | ||||
-rw-r--r-- | test/files/run/private-inline.flags | 1 | ||||
-rw-r--r-- | test/files/run/private-inline.scala | 52 |
3 files changed, 54 insertions, 0 deletions
diff --git a/test/files/run/private-inline.check b/test/files/run/private-inline.check new file mode 100644 index 0000000000..209e3ef4b6 --- /dev/null +++ b/test/files/run/private-inline.check @@ -0,0 +1 @@ +20 diff --git a/test/files/run/private-inline.flags b/test/files/run/private-inline.flags new file mode 100644 index 0000000000..eb4d19bcb9 --- /dev/null +++ b/test/files/run/private-inline.flags @@ -0,0 +1 @@ +-optimise
\ No newline at end of file diff --git a/test/files/run/private-inline.scala b/test/files/run/private-inline.scala new file mode 100644 index 0000000000..5181ac8ba3 --- /dev/null +++ b/test/files/run/private-inline.scala @@ -0,0 +1,52 @@ + +final class A { + private var x1 = false + var x2 = false + + // manipulates private var + @inline private def wrapper1[T](body: => T): T = { + val saved = x1 + x1 = true + try body + finally x1 = saved + } + // manipulates public var + @inline private def wrapper2[T](body: => T): T = { + val saved = x2 + x2 = true + try body + finally x2 = saved + } + + // not inlined + def f1a() = wrapper1(5) + // inlined! + def f1b() = identity(wrapper1(5)) + + // not inlined + def f2a() = wrapper2(5) + // inlined! + def f2b() = identity(wrapper2(5)) +} + +object Test { + def methodClasses = List("f1a", "f1b", "f2a", "f2b") map ("A$$anonfun$" + _ + "$1") + + def main(args: Array[String]): Unit = { + val a = new A + import a._ + println(f1a() + f1b() + f2a() + f2b()) + + // Don't know how else to test this: all these should have been + // inlined, so all should fail. + methodClasses foreach { clazz => + + val foundClass = ( + try Class.forName(clazz) + catch { case _ => null } + ) + + assert(foundClass == null, foundClass) + } + } +} |