Some high-level feedback from me:

I think the idea is reasonable. In other circles, we might call this a 
"milestone". Should we define a first milestone that we're willing to commit to 
strongly, with some sort of distribution channel (something better than 
build-your-own-JDK) and some level of support commitment to users who want to 
get their hands dirty? Sure, absolutely.

There are some design decisions that surprise/confuse me. Basically, this is me 
saying "YAGNI" over and over again:

1) Automatic boxing adds tons of complexity, and I don't see the benefit. The 
feature eliminates boilerplate and supports migration, but I'm not looking for 
either of those in a minimal first step. We're talking about a handful of value 
types, which can easily be defined like this:

class Val {
    public final int i;
    public final int j;
    public static ValBox box(Val x) { return new ValBox(x); }
    public static Val unbox(ValBox b) { return b.x; }
}

class ValBox implements Foo {
    public final Val x;
    public ValBox(Val x) { this.x = x; }
}

Get rid of boxes, and you can get rid of interfaces, default methods, automatic 
conversions, constructors, ...

2) Instance methods also add tons of complexity. Again, they only exist for 
convenience and migration. If static methods can operate on value types, that's 
all you need. No longer necessary to deal with bytecode written to operate on 
an L-typed 'this' and somehow re-interpret it for a Q-typed 'this'. No longer 
necessary to deal with Object methods (because no operation supports invoking 
them).

(If we really do want instance methods, I suggest making 'this' Q-typed to 
begin with, not diverting resources into figuring out how to make L-typed 
instance methods efficient.)

3) The minimal feature set for basic operations -- field getters, default 
value, withers, comparison, arrays -- is a class (e.g., ValueTypeSupport) with 
bootstrap methods that can be called via invokedynamic. No need to touch 
MethodHandles.Lookup, etc.

More generally, why so much attention given to reflection? Sure, you need class 
objects to represent all the JVM's types. But member lookup? Fields, Methods, 
Constructors? These do not seem necessary.

If I squint, I can kind of see how the idea is that somebody might want to 
write reflective code to operate on values, since they don't have language 
support. But almost everything has to be boxed when using these libraries, 
which means if you care about performance (which is why you're using this 
prototype), you're going to be spinning bytecode to do your low-level 
operations. If this is the use case, I think a better use of resources would be 
to surface Q types in the language.

4) I don't love hacking CONSTANT_Class to encode new types, but I can probably 
live with it. My preference is to design it the "right" way -- however we 
envision these ultimately being expressed -- rather than this intermediate step 
in which everybody learns to interpret some new syntax, only to turn around and 
deprecate that syntax a little while later. (I realize it's probably easier to 
change string formats than it is to add a new constant pool form.)

I don't think it's necessary to support Q types as the receivers of 
CONSTANT_Fieldrefs and CONSTANT_Methodrefs. The receiver can be a vanilla 
CONSTANT_Class, and the client (in this case, the 'vgetfield' API point) can 
figure out what to do with the resolved reference.

—Dan

Reply via email to