caution: bleeding-edge ahead!
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Mon Jan 12 16:17:38 UTC 2015
Dear honorable warriors,
I've just pushed a compiler/specializer patch that should add some basic
support for peeled methods. This is totally experimental (as I mentioned
to Peter last week), and the support is based on the clunky
__WhereRef/Val keywords - i.e. it's not an implementation of the
layering proposal as described in Brian's document, nor is it a serious
proposal of how the syntax would work ... it's just a hack to move the
experiments forward. Here's an example on how you might want to peel a
method:
class Test<any T> {
void peeledMethod() {
__WhereRef(T) {
//ref implemnetation goes here
}
__WhereVal(T) {
//val implementation goes here
}
}
}
The compiler will type-check the two bodies as if they were the 'only'
body - meaning flow analysis should work as expected (i.e. you can have
two return statements, one in each body, and the compiler will be happy
with that). At specialization time, the whole method will be splitted in
two parts - a real method (for the reference impl) and a 'template
method' - the class will look like:
class Test<any T> {
void peeledMethod() {
//ref implemnetation goes here
}
void template$peeledMethod() {
//val implementation goes here
}
}
The two methods will contain special Where bytecode attributes to let
the specializer reconstruct the specialized classes with the right
methods in them.
One obvious limitation (I'm sure there are many other I haven't thought
about) of this implemented, hacky route is that you cannot have a method
that is part concrete, part abstract; but I think you can emulate that
with the following idiom:
class Test<any T> {
void partiallyAbstractMethod() {
__WhereRef(T) {
throw new AbstractMethodError();
}
__WhereVal(T) {
//val implementation goes here
}
}
}
One last note: the compiler will try to detect situations where multiple
where blocks might apply on a given specialized class:
class Test<any X, any Y> {
void ambiguiousPeeling() {
__WhereVal(Y) {
//impl1
}
__WhereRef(X) {
//impl2
}
}
}
This is flagged as 'ambiguous' - think of what happens if you have i.e.
a Test<String, int> - both blocks will match - meaning that the
specializer won't know which to pick. There's also a dual check that
prevents a peeling method from having 'missing' blocks - i.e. a
combination of ref/val instantiation which is not matched by any block
in the peeled method.
Good luck with the experiments - and please refrain from commenting on
the specifics of the implemented syntax - we all know it's very, very
ugly :-) :-) :-)
Cheers
Maurizio
More information about the valhalla-dev
mailing list