[lworld] RFR: 8244231: [lworld] Add support for ref-default and val-default inline classes.

Maurizio Cimadamore mcimadamore at openjdk.java.net
Thu Jul 22 10:27:58 UTC 2021


On Thu, 22 Jul 2021 10:06:03 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:

>> W.r.t the observation: "I'm also a bit unsure (and left comment) on whether isReferenceProjection and isValueProjection are implemented correctly. They do not seem to be the dual of each other at the moment (or at least do not seem to do what the javadoc says they should)."
>> 
>> Please take a another look! I believe they are dual of each other and do what the javadoc claims - (although as I call out below, I am open to questioning whether their behavior should be redefined)
>> 
>> ATM, the javadoc of isReferenceProjection() and isValueProjection() read:
>> 
>> 
>>     /**
>>      * @return true IFF the receiver is a reference projection type of a *value favoring* primitive class
>>      * and false otherwise. Or in other words, is this a class type non-redundantly notated with .ref ??
>>      */
>>     public boolean isReferenceProjection() {
>>         return false;
>>     }
>> 
>>     /**
>>      * @return true IFF the receiver is a value projection of a *reference favoring* primitive class type
>>      * and false otherwise. Or in other words, is this a class type non-redundantly notated with .val ??
>>      */
>>     public boolean isValueProjection() {
>>         return false;
>>     }
>> 
>> 
>> 
>> You ask of com.sun.tools.javac.code.Type.ClassType#isValueProjection
>> 
>> Shouldn't we discount primitive-default primitive classes in here? (e.g. should this code be symmetric with isReferenceProjection?). E.g. what about .val in an already primitive-default primitive class?
>> 
>> 
>> We *are* already discounting primitive-default classes, because in that case the flavor would be Q_TypeOf_Q.
>> 
>> The ambiguity exists only for the flavor L_TypeOf_Q - when we have a type that is an L_TypeOf_Q it could be
>> either the (a) reference projection of value default primitive class or (b) the reference type of a reference default primitive class.   
>> 
>> Of (a) and (b) only (a) we consider to be the *reference projection* as per the javadoc.
>> 
>> On the other hand:
>> 
>> Between Q_Typeof_Q and Q_Typeof_L, only the latter is considered a value projection as per the javadoc.
>> 
>> (Backing up a bit it is a fair question to ask should the javadoc be defined that way - should both Q_Typeof_Q and Q_Typeof_L be considered value *projections* and should L_TypeOf_Q should *always* be considered a reference *projection* irrespective of whether the associated class is a reference default or value default ? I have chosen not to since that seems "natural" - but I am open to revisiting this if our experience proves otherwise.
>> 
>> Please see that this is the same issue JEP 401 grapples with by asking the question in https://openjdk.java.net/jeps/401
>> 
>> (Open question: should it be legal to redundantly apply .val to a standard primitive class name, or .ref to a reference-favoring primitive class name?)
>
>> when we have a type that is an L_TypeOf_Q it could be
>> either the (a) reference projection of value default primitive class or (b) the reference type of a reference default primitive class.
> 
> This seems at odds with what the Javadoc for that flavor says:
> 
> 
> /**
>              * Reference projection type of a primitive-favoring aka primitive-default
>              * plain vanilla primitive class type,
>              */
>             L_TypeOf_Q,
> 
> 
> E.g. javadoc suggests that Q means primitive-default already, so there should be no need to check the tsym?

More generally, I think I'm slightly uncomfortable by the use of the letters `Q` and `L` in the enum constants `X_TypeOf_Y`. Now, when `L` and `Q` are in the `X` position, the semantics is simple: `L` means `.ref`, `Q` means `.val`.

But when `L` and `Q` appear in the `Y` position, then it becomes messy - because the choice is no longer binary:

* the class is a primitive class or not (1 bit)
* if primitive, the class is reference-favoring or not (another bit)

Right now, it seems that you use `Q` to denote whether the class is primitive class or not, which is useful, I assume, to detect distinction between a legacy reference type (`L_TypeOf_L`) and a reference projection of a primitive class (`L_TypeOf_Q`). This distinction is, I believe an important one, as the former has identity, the latter doesn't, so type checking would probably differ.

What I'm less sure is whether you want/need different type checking rules for when `L_TypeOf_Q && reference-favoring` vs. `L_TypeOf_Q && !reference-favoring`. What you have is still an identity-less reference type - so why should it be important whether you get a redundant projection or not (which might even be disabled at some point during type checking) ?

So, back to your question, I guess I don't see why you have defined the current behavior as being "natural". To me, getting an X projection on a X-favoring primitive class is an idempotent operation, which you can repeat even 20 times, and the type-system shouldn't care. Are there places in the code where you need this sharper distinction?

-------------

PR: https://git.openjdk.java.net/valhalla/pull/482


More information about the valhalla-dev mailing list