| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Post-erasure of value classs in method signatures to the underlying
type wreaks havoc when the erased signature overlaps with the
generic signature from an overriden method. There just isn't room
for both. But we *really* need both; callers to the interface method
will be passing boxed values that the bridge needs to unbox and
pass to the specific method that accepts unboxed values.
This most commonly turns up with value classes that erase to
Object that are used as the parameter or the return type of
an anonymous function.
This was thought to have been intractable, unless we chose
a different name for the unboxed, specific method in the
subclass. But that sounds like a big task that would require
call-site rewriting, ala specialization.
But there is an important special case in which we don't need
to rewrite call sites. If the class defining the method is
anonymous, there is actually no need for the unboxed method;
it will *only* ever be called via the generic method.
I came to this realisation when looking at how Java 8 lambdas
are handled. I was expecting bridge methods, but found none.
The lambda body is placed directly in a method exactly matching
the generic signature.
This commit detects the clash between bridge and target,
and recovers for anonymous classes by mangling the name
of the target method's symbol. This is used as the bytecode
name. The generic bridge forward to that, as before, with
the requisite box/unbox operations.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
We were losing track of parameter names in two places:
1. Uncurry was using fresh names for the apply method
parameters during Function expansion. (The parameter names
in the tree were actually correct, they just had synthetic
symbols with "x$1" etc.)
2. When adding specialized overrides, the parameter names
of the overriden method were used, rather than the parameter
names from the overriding method in the class to which we are
adding methods.
The upshot of this is that when you're stopped in the debugger in
the body of, say, `(i: Int) => i * i`, you see `v1` rather than `i`.
This commit changes Uncurry and SpecializeTypes to remedy this.
|
|
Guards against bridge methods that clash with other methods. Two
tests: The neg test is the original ticket. The run test tweaks
things slightly so that the generated bridge method does not clash,
and tests that the necessary unboxings are indeed performed at
runtime.
|