Re: [External] : Re: SoV-2: weak references

2022-02-10 Thread Dan Heidinga
> * For WeakHashMap use cases, I would expect that any attempts to actually 
> design something "good" that does what users really "want" would end up at 
> some different library entirely. This is something that Caffeine probably 
> does well (disclosure, I worked on the thing that became that).
>
>
> Yes, probably.  We're worried about existing applications that are built 
> around WHM, and trying to give them something reasonable that will keep them 
> going, since many of these are legacy applications with limited room for 
> rearchitecting.  So we're asking "what's the least we have to do", and the 
> simple set of policies I outlined for WHM is a candidate.

I think Kevin's hit on the key point here - WHM as a cache is often
used incorrectly and we'd be better off designing something different
entirely to solve that use case.  This matches the feedback I've
gotten when polling Red Hat developers.

Breaking the "values as WHM keys" issue into use cases:

Single maintenance domain:
(A) Migrates its own classes to values and uses them as WHM keys
(B) Uses value-based classes as WHM keys and breaks in Valhalla when
these become values

Cross maintenance domain:
(C) Other library changes its classes to be values, our library uses
them as WHM keys
(D) Our library changes its classes to be values, Other library uses
them as WHM keys

Both (A) and (D) are very similar and are essentially a consequence of
not understanding how users (self, others) are using your classes.
This is a consequence of migrating existing classes, and just like
with synchronization, users should expect it to fail with an
exception.  Don't like the exception?  Don't migrate the class to be a
value.

Cases (B) and (C) are very similar if we treat the JDK as "another
library".  And this is probably the hardest case as it intersects with
supported JDK versions.  Running on a JDK that supports Valhalla
doesn't guarantee that all the maintenance domains were compiled on
new enough JDKs.

If the library is supported on both pre-Valhalla JDK and Valhalla-JDK,
then it can't easily take advantage of the new WHM models being
proposed. (caveats: MR jars, reflection related workarounds, ...)  And
if the domain is only on post-Valhalla JDKs, then the user is in a
place to put explicit checks for values into their code (or better,
stop using WHM all together).

 Trying to keep WHM working for values is encouraging the ecosystem to
throw good money (effort) after bad.  The "keep it working" attempts
just shift the problem from a clear exception to an on-call nightmare
when the leaking WHM causes the service to go down.  I know which I'd
prefer.

--Dan



Re: JEP update: Classes for the Basic Primitives

2022-02-10 Thread Brian Goetz



* Could the doc make a clearer distinction (throughout) between which 
facts about int/Integer are happening because we expect *all* bucket-3 
classes to work that way, vs. which are special one-off tweaks for the 
8 predefined types?


A "how are int/Integer special" section would indeed be useful.  And I 
think we haven't finished enumerating what goes in it; in the 
discussions over inference, for example, several folks have been heard 
mumbling "maybe we're trying to push the int/Integer analogy too far."


* I'm curious whether it would be /possible/ to make `int` no longer a 
keyword, just a special kind of type alias that normal people don't 
get to declare. I'm /not/ claiming that'd be worth actually doing; 
just wanting to understand what forces would act to prevent it, as 
part of understanding everything that makes the 8 builtin types 
"irredeemably special".


In a previous world, `int` could have been an alias for `Integer.val`.  
But we (happily) have banished .val from the world.


I think this is a useful exercise anyway, though; we have stumbled over 
type-vs-class in a lot of places already with respect to B3, and int has 
similar problems; most uses of `int` are types, but there's also 
`int.class`, which means ... something.  What exactly? And how does that 
differ from Point.class / Point.ref.class / 
Point.class.noNotThatClassTheOtherClass() ?


* I assume the reason "the JVM type Qjava/lang/Double cannot be 
encoded with a Class object" is because the distinction between it and 
D is intentional implementation detail.


Worse :(   The J and D carriers use two slots, so even if we wanted to 
abstract over the primitive carriers, this is kind of a dead end.  The 
java/lang/Double class allows us to encode List with a class 
that carries a double but fits in one slot.


* Since I think/hope it is /not/ true that `int` will be a subtype of 
`Integer`, it's not 100% clear whether the phrase "array covariance" 
in the doc is referring to the (desirable) property that `int[] <: 
Integer[]`. I think it is.


int will not be a subtype of Integer, nor will Point be a subtype of 
Point.ref.  (It was this way in a previous iteration; the VM still 
believes the latter, but we're probably going to disabuse it of same.)  
Traditional array covariance is tied to subtyping:


      T <: U
    --  T-Cov
    T[] <: U[]

But, we're going to modify this rule somewhat.  We define a relation 
between types, called "extends".


    A extends B = A <: B    if A is a reference type
      A.ref <: B    otherwise

(We could write this more concisely as "A extends B == A.ref <: B", 
since the .ref operator is idempotent.)  We use "extends" for things 
like bounds conformance; if we have Foo, we treat 
Foo as being in bounds.


So our modified covariance is:

      T extends U
    --  T-Cov-Ext
      T[] <: U[]

which gives us int[] <: Integer[], even though we don't have int <: 
Integer.


This is no mere flourish; without it, erased generics don't work:

    class Box {
    T value();
    T[] asArray();
    }

This erases to returning Object[], and if we want to specialize 
Box, asArray() should return int[], but to be compatible with 
erasure, we need int[] <: Object[].


* I said in the meeting that "I don't think anyone cares" what kind of 
exception gets thrown if trying to store null in an `Integer[]` which 
is secretly an `int[]`. Well, I'm sure that's not at all true. :-) Sorry.


You're lucky they didn't show you their scars.

* Re: "a basic primitive class may declare an instance field of its 
own primitive" -- does it really need that field, or can we nuke it 
and just s/value/this/g throughout the file? If that could work, it 
would be so much less confusing -- nothing circular! The only magic 
would be "where are the actual bits??" but you don't see the bits of 
an object header in `Object.java` either and the number of people this 
bothers is a very round number.


Seems plausible :)



Re: Abstract class with fields implementing ValueObject

2022-02-10 Thread Remi Forax
- Original Message -
> From: "John Rose" 
> To: "Frederic Parain" 
> Cc: "valhalla-spec-experts" 
> Sent: Thursday, February 10, 2022 12:02:53 AM
> Subject: Re: Abstract class with fields implementing ValueObject

> That could be one of very many edge conditions in the JVMS that are not
> diagnosed directly by a validation, but that will eventually cause an error
> when the broken classfile is further used.
> 
> I don’t think there needs to be a special rule for this.  We don’t try to
> comprehensively diagnose all “impossible-to-use” classfiles.

or better we ditch ValueObject and IdentityObject ...

Rémi

> 
> On 9 Feb 2022, at 13:50, Frederic Parain wrote:
> 
>> There's a weird case that seems to be allowed by the Value Objects JVMS 
>> draft:
>>
>> An abstract class can declare non-static fields, which means it won't
>> have the ACC_PERMITS_VALUE flag set, but also declare that it implements
>> the ValueObject interface.
>>
>> The combination looks just wrong, because no class can subclass such class:
>>   - identity classes are not allowed because of the presence  of
>> the ValueObject interface
>>   - value classes are not allowed because of the absence of
>> ACC_PERMITS_VALUE
>>
>> I've looked for a rule that would prohibit such combination in the
>> JVMS draft but couldn't find one.
>>
>> Did I miss something?
>>
> > Fred


Re: EG meeting, 2022-02-09 [SoV-3: constructor questions]

2022-02-10 Thread Remi Forax
> From: "John Rose" 
> To: "daniel smith" 
> Cc: "valhalla-spec-experts" 
> Sent: Wednesday, February 9, 2022 7:32:07 PM
> Subject: Re: EG meeting, 2022-02-09 [SoV-3: constructor questions]

> On 8 Feb 2022, at 19:04, Dan Smith wrote:

>> "SoV-3: constructor questions": Dan asked about validation for  and 
>> 
>> methods. Answer: JVM doesn't care about  methods in abstract classes, 
>> the
>> rules about  methods still uncertain.
> On the question of JVM validation of  methods, I’m in favor of as few 
> rules
> as possible, ideally treating  as just another name. It’s super-power is
> not in its restrictions but in its conventionality: It’s the obvious choice 
> for
> constructor factory methods. But it is not necessarily limited to that use.

> Maximal limitation would be that a  method can only occur as the
> translation of a value-class constructor. Any evidence in the classfile that 
> it
> was not such a translation would be grounds for failing a validation check.
> We’d make as many such rules as we can think of.

> Arguments against:

>* Having a special method identifier in the JVMs without other restrictions
> would be a new thing, and hence suspicious.
>* Limiting the use of  as much as possible makes it clear, to higher 
> layers
>of the code (javac and reflection) what is going on in the class file, as a
> “reflection” of the source file.
>* Reflection of an irregular (non-source-conforming)  method has to be
> messy. (Is it really a constructor? Or is it just a method named  ?)

> Arguments in favor:

>* It is a new thing in the JVM for any descriptor to be constrained to 
> mention
>the same name as is the name of the constant pool item referred to by
> ClassFile.this_class item (JVMS 4.1). (It is suspicious.)
>* A maximal limitation would break hidden classes. (They must sometimes 
> return a
>supertype from their factories, since the HC is not always name-able in a
> descriptor. HCs only work because the previous point.)
>* A limitation might preclude a perhaps-desirable future translation 
> strategy
>that used  factories uniformly to translate new source code 
> expressions
> (identity or value objects, uniformly).
>* A limitation could remove a natural translation strategy for “canonical
>factory methods” in non-concrete types. This is a hypothetical language 
> feature
>for Java or some other language. (E.g., new List(a,b,c) instead of
>List.of(a,b,c) , removing the need of the user to remember whether the 
> word was
> of or make or build or some other designer choice.)
>* Most any limitation would preclude ad hoc use of  factories by
>translation strategies of other languages, such as Scala and Clojure, which
>surely have their own uses of JVM object life cycles. We want to be 
> friendly to
> non-Java languages.

> Compromise positions:

>* Require a  method to be ACC_STATIC but allow for any purpose (i.e., 
> any
> access and any descriptor).
>* Require a  method to return either the class named by this_class or 
> some
> super type (TBD how this should be checked).

> I would prefer the first compromise: It’s static but otherwise the JVM asks no
> questions.

> Regarding reflection, I think it would be OK to surface all of the  
> methods
> (of whatever signature) on the getConstructors list, even if they return
> “something odd”. Alternatively, to prevent a sharp edge we could have a new
> list Class::getFactories , and copy (not move) entries from that list onto
> getConstructors exactly when the return type matches the enclosing class. That
> is a more natural move for reflection (which operates on runtime types) than
> for class file structuring (which is more static).

> The reason I prefer to require static marking is that it would prevent the 
> funny
> name from appearing on the list of regular methods, via reflection.

I agree with static being the only requirement for the VM side. 

For reflection,i prefer the first alternative, surface the  method 
whatever the return type given that the return type is a declared type, not a 
runtime class. 
Dynamically typed languages like Groovy or JRuby may want to declare that the 
return type of  is java.lang.Object (it's the default type if no type is 
provided in Groovy), 
if reflection filter out those methods, it will be bad for the interropt 
between Java and those dynamically typed languages. 

Rémi