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