scala/scala — pull request #1124 by VladUreche (2012-08-11 23:05:44+00:00)
Title: SI-4767 Inline @inline final trait methods

A trait consists of an interface and an implementation class. From a
JVM perspective, a class that extends a trait will actually implement
the interface and unless it overrides the member, will get a forwarder
to the implementation class:

for:
```
trait Foo { @inline final def foo(x: Int) = println(x) }
class Baz extends Foo
```

Baz is compled down to:
```
class Baz extends Object with Foo {
@inline final def foo(x: Int): Unit = Foo$class.foo(FooImpl.this, x)
...
}
```

Now, say we have:
```
def bar(y: Foo) = y.foo(7)
```

The type of `Foo` is `interface Foo`. Thus there's no way for the
inliner to load the bytecode for foo. The first part of this patch
addresses this problem, by transforming the call to `y.foo(7)` to
`Foo$class.foo(y, 7)` if the foo method is final and @inline marked.

The second part is actually inlining the static call to `Foo$class.foo`.
Now, the trick is that the inliner actually expects the calls it
inlines to have an instance on which they're run. I relaxed the inline
conditions to include static calls and changed the inliner to generate
correct code for static calls. (the VerifyError was caused by this)

The third part was adapting the ICodeReader to be able to pick up the
code from implementation classes. I think the ICodeReader needs a real
maintainer, I was only after getting the test cases to pass, but there
are still some failures visible with -Ydebug -Ylog:inliner.

Finally, added a couple of tests using Greg's instrumented partest
addon, and it's awesome!

Thanks to @magarciaEPFL, @lrytz and @xeno-by for their help!

Mandatory review by @paulp if we're going to get this in 2.10.