Re: EG help please with getting to LW1 re: Value Types Consistency Checking

2018-07-06 Thread Tobi Ajila
I would like to propose an alternative strategy, one that would effectively
provide the same consistency checks outlined in
http://cr.openjdk.java.net/~acorn/value-types-consistency-checking-details.pdf
 without requiring eager loading of value types (VT) in the return/args of
methods during the preparation phase. This is born out of our experience
with PackedObjects which took a very similar approach to the ValueTypes
attribute.

This proposal makes use of the existing ValueTypes attribute. In addition,
it requires that each classloader keeps a registry of ‘expected’ VTs.

Proposal
--
The following steps occur in the loading phase:

1. Prior to loading the current class each type in the ValueTypes attribute
is checked see if it is loaded. If it is, the type must be a VT or ICCE is
thrown. Otherwise, the type is registered with the initiating classloaders
expected VT registry (EVTR).

2. Pre-loading of ACC_FLATTENABLE instance fields follow the same rules as
the ones specified in Karen's proposal.

3. Prior to loading the current class, if the current class is a VT it must
be in the classloader's EVTR or ICCE is thrown. If the current class is not
a VT and does appear in the EVTR, ICCE is thrown.

In link phase prior to preparation:
- Same as Karen's static field rules, "static fields declared with the
ACC_FLATTENABLE flag set have their type pre-loaded..."

In preparation phase:
- Same as Karen's method overriding rules, "any method overriding needs to
perform value type consistency checking between declarer of the overridden
method ..."

At resolution time:
- Same as Karen’s CONSTANT_Class, field and method resolution rules
---

The benefit of this approach is that as soon as anyone believes a class is
a VT, it must be loaded as a VT or it fails. As a result, there is no
inconsistency of loaded VTs. This proposal doesn't guard against cases
where a class was not expecting a method return/arg type to be a VT but
then later on turned out to be a VT when it was resolved. However, I think
don’t think Karen’s proposal offered these guarantees either.

> Some aspects of the implementation complexity that we have identified so
far:
> a) At method resolution time, if there is a mismatch in value type
consistency
> between the declaring class and the actual type in the signature, then
there
> is also a mismatch in all classes that have overridden the current
method.
> This is particularly painful with default methods in interfaces.

With this proposal the only possible inconsistency here is:
Method has a return/arg type that is believed to not be a VT but turns out
to be a VT. In this case any compiled code is doing pass by reference
calling convention which works for both VT and non-VT types.

> b) We need to ensure that we catch all method resolution, through all of
the
> alternate accessor paths, including MethodHandles, VarHandles,
Reflection, JNI,
> so that we catch both the specification and implementation changes.

All these cases are covered with the class loading consistency checks
(EVTR).

> c) Our favorite, invokespecial ACC_SUPER, needs special handling, since
it
> performs selection which is not based on overriding, but based on
virtually
> re-resolving.

same as above

> e) If we modify the specification to allow eager loading, and save errors
> to throw at method resolution, we need to work through the JVMS question
> of which errors would be saved (e.g. OOME, SOE might be thrown as part of
> the implementation vs. saving LinkageError), as well as designing a new
> implementation mechanism to repeat exceptions relative to signatures used
> for method resolution.

This wouldn’t be required in this proposal

> d) Pass by value calling convention optimizations depend on loading the
> actual type. Loading of the parameter types on first method resolution
> implies that if the caller is compiled, the caller method requires
> deoptimization/recompilation to pass arguments by value for future calls,
> which is a performance cost.

Typically, a method is run a few times before it is compiled (perhaps I’m
making implementation assumptions?). At this stage, the return/arg types
are either loaded or they are always null. This seems to suggest that
deoptimization/recompilation scenario would not be a common occurrence.


--Tobi

> From: Karen Kinnear 
> To: valhalla-spec-experts 
> Date: 2018/06/26 10:32 AM
> Subject: EG help please with getting to LW1 re: Value Types
> Consistency Checking
> Sent by: "valhalla-spec-experts"  boun...@openjdk.java.net>
>
> Summary: Could we please allow eager loading for value types in the
> locally declared method signatures
> prior to preparation  for LW1?
>
> Without that we seriously risk being able to offer an LW1 early
> access binary for the JVMLS.
> We believe it is more important to get this into people’s hands for
> experimentation and feedback than
> to delay the eager loading at this time.
>
> Details:
> At our EG 

Re: EG help please with getting to LW1 re: Value Types Consistency Checking

2018-07-12 Thread Tobi Ajila
> I'm looking for reasons that
> this is a *bad* idea, so we can say in the end, "here's exactly why we
had to make
> the loading logic for VTs so tricky"–if we must.

Karen's initial post mentions our two biggest concerns. If there is no
guarantee that the VTs in the method descriptors will be used, loading them
is an overhead. We would like to minimize the cost to startup as much as
possible. The other reason is eager loading may trigger failures that would
otherwise never occur if the method wasn't run, which is change from how
the JVM normally behaves.

--Tobi

> From: Remi Forax 
> To: John Rose 
> Cc: Tobi Ajila , valhalla-spec-experts
> 
> Date: 2018/07/10 05:44 AM
> Subject: Re: EG help please with getting to LW1 re: Value Types
> Consistency Checking
>
> Hi all,
>
> De: "John Rose" 
> À: "Tobi Ajila" 
> Cc: "valhalla-spec-experts" 
> Envoyé: Samedi 7 Juillet 2018 23:08:27
> Objet: Re: EG help please with getting to LW1 re: Value Types
> Consistency Checking
> Hi Tobi.  Thanks for the write-up.
>
> To be brief, your proposed technique will seems to require lazier
> selection of calling
> sequences than what Karen proposed.  Argument and return registers
> cannot be assigned
> to values if their size is unknown, which is the case before they
> are loaded.  The JVM
> must wait as late as the first actual call (with non-null
> parameters) to determine calling
> sequences.
>
> Karen's proposal allows calling sequences to be determined at
> preparation (v-table pack)
> time, while yours requires them to be chosen much later, by the time
> of the first invocation
> of a given v-table slot.  (For JVMs without vtables, a "v-table
> slot" really means an
> equivalence class \u0015of CONSTANT_[I*]Methodrefs equated by the
> transitive closure of
> override relations.)  The bytecode instruction just before that
> invocation might have been
> a defaultvalue instruction on a previously unloaded class.  This
> means the JVM needs
> to install traps in unused v-table slots, so it can decide calling
sequences.
>
> Karen's proposal, therefore, has the advantage of allowing the JVM
> more lead time
> freedom to set up v-table calling sequences, at preparation time.
> Yours requires
> just-in-time assignment of calling sequences, which seems more difficult.
>
> This leads to the question, what advantage did you find, with Packed
> Objects, from
> making calling sequence setup lazier?  (I'm assuming that system
> scalarized arguments
> into multiple registers.)  In other words, why is your phasing of
> the checks better than
> Karen's?
>
> — John
>
> P.S. Background:
>
> So we are extending object references (Ljava/lang/Object;) to cover
> references to values
> also, at least in L-world.  This gives a simple story for the
> interpreter and a fallback for
> less-optimized JIT-compiled code, but isn't enough to compete with
> statically-compiled
> languages.
>
> So the new requirement here is to make it possible for compiled
> calling sequences
> to use specialized representations for value parameters and returns.
> In particular, we
> often wish to use one or more machine registers to hold scalarized
> fields, and we wish
> to exclude null values (which require an extra encoding and impede
> some optimizations).
>
> A secondary requirement is that we wish to pick the compiled calling
> sequence once
> and not have to revise it.  This implies picking the calling
> sequence no later than the first
> execution (compiled or interpreted) of any particular method, and
> getting it right the first
> time.
>
> Deoptimization of calling sequences–across override-trees of
> methods–is a trick we are
> holding in reserve, but it seems a risky research project rather
> than an understood technique.
> I think deoptimization at this scale hasn't been proven efficient
> yet, although it may be.
>
> It seems that in order to flatten, we are obligated to load value
> types more eagerly
> than object types.  Value types can't "hide behind" a polymorphic
> reference; any
> user of a value type in its native form (not boxed) needs to "see"
> its complete field
> list, which requires loading the classfile.  This is certainly true
> for object layout,
> where an object that contains a value-typed field must load that
> value type to see
> how much space it must reserve for it, in that object's flattened
> and packed layout.
>
> Given that we are going to routinely pre-load value type classfiles,
> it is reasonable
> to apply this technique in other places besides the layout of
> instances and fields.
> In particular, the layout of

Re: atomicity for value types

2020-01-13 Thread Tobi Ajila
Hi John

Given that inline types can be flattened there is a possibility that data
races will occur in places where users were not expecting it before. So
your `__AlwaysAtomic` modifier is a necessary tool as the existing spec
will only enforce atomicity for 32bit primitives and references. I just
want to confirm if the intention of the __AlwaysAtomic bit on an inline
class is only to ensure atomic reads and writes of inline types and that
there are no happens-before ordering expectations as there are with the
existing volatile modifier on fields.

For example:

```
__AlwaysAtomic inline class Long256 { long v1, v2, v3 ,v4;  … }

class Example {
Long256 bigLong;
int x;
int y;

void method() {
Long256 newLong = new Long256(1, 2, 3, 4);

x = 1;

//compiler is still free to re-order write to bigLong with
respect
//to writes to x and y, but the write to bigLong must be done
atomically
bigLong = newLong;

y = 2;
}
}
```

Does this match your expectations?

The reason I ask is because of the "Protection is “as if” each field were
volatile" wording in your previous note. Does this only speak to the
atomicity properties of the volatile modifier? Or do you intend further
constraints?

Regards,
--Tobi


"valhalla-spec-experts" 
wrote on 2019/12/18 08:46:42 PM:

> From: John Rose 
> To: valhalla-spec-experts 
> Date: 2019/12/18 08:47 PM
> Subject: [EXTERNAL] atomicity for value types
> Sent by: "valhalla-spec-experts"  boun...@openjdk.java.net>
>
> In a nutshell, here’s a proposal for value type atomicity:
>
> - Define a contextual keyword “alwaysatomic" (working title
“__AlwaysAtomic”).
> - It can only occur with “inline” in class declaration.
> - All instances of the given inline class are protected against races.
> - Protection is “as if” each field were volatile, “and the same” for
> array elements.
> - In the class file the ACC_VOLATILE bit is used (0x0040) to record
> the keyword.
> - This bit does not necessarily disable flattening; if the JVM can
> get away with flattening it should.
> - The JVM can get away with flattening such values on stack, in
> registers, and perhaps in final heap variables.
> - The JVM can get away with flattening such values if they are
> “naturally atomic”, meaning they can be wholly loaded or stored in
> one (atomic) hardware instruction.
>
> More details to follow.  Here’s a backgrounder I wrote a while ago:
>
> https://urldefense.proofpoint.com/v2/url?
>
u=http-3A__cr.openjdk.java.net_-7Ejrose_oblog_value-2Dtearing.html=DwIFaQ=jf_iaSHvJObTbx-

>
siA1ZOg=erClOruSa3K4FS7XawcTd7k9ZbtVLiryTZ1WIpneMMg=9WXy2DpynXX2sj1FbCiuW127ablyOD_EN13-

> aS4ug04=dhRZz0Da6RYg45c_b-x6gFBP0sqXC1VtTWP--BDHMS4=
>
> — John
>
>


Re: atomicity for value types

2020-01-14 Thread Tobi Ajila

> The only special atomicity properties of volatile I’m
> appealing to are those which apply to long and double.

Thanks for confirming that.

> In effect, if an inline object contains a pointer,
> storing it should include a previous store-store ordering
> constraint, or some other implementation of the JMM
> “freeze” operation at the end of the inline’s constructor.

Given the LW2 spec allows withfield to be used anywhere in the nest, an
inline-type containing a reference could be constructed outside of the
 factory. Should the JMM “freeze” semantics additionally apply to the
withfield bytecode?

--Tobi

> From: John Rose 
> To: Tobi Ajila 
> Cc: valhalla-spec-experts 
> Date: 2020/01/13 05:03 PM
> Subject: [EXTERNAL] Re: atomicity for value types
>
> On Jan 13, 2020, at 1:44 PM, Tobi Ajila  wrote:
> >
> > Hi John
> >
> > Given that inline types can be flattened there is a possibility
> that data races will occur in places where users were not expecting
> it before. So your `__AlwaysAtomic` modifier is a necessary tool as
> the existing spec will only enforce atomicity for 32bit primitives
> and references. I just want to confirm if the intention of the
> __AlwaysAtomic bit on an inline class is only to ensure atomic reads
> and writes of inline types and that there are no happens-before
> ordering expectations as there are with the existing volatile
> modifier on fields.
>
> Confirmed; thanks for taking the time to raise the question clearly.
>
> It really isn’t “always volatile”; that would be a different and much
less
> useful feature.
>
> > For example:
> >
> > ```
> > __AlwaysAtomic inline class Long256 { long v1, v2, v3 ,v4; … }
> >
> > class Example {
> > Long256 bigLong;
> > int x;
> > int y;
> >
> > void method() {
> > Long256 newLong = new Long256(1, 2, 3, 4);
> >
> > x = 1;
> >
> > //compiler is still free to re-order write to bigLong with respect
> > //to writes to x and y, but the write to bigLong must be done
atomically
> > bigLong = newLong;
> >
> > y = 2;
> > }
> > }
> > ```
> >
> > Does this match your expectations?
>
> Yes, it does.
>
> > The reason I ask is because of the "Protection is “as if” each
> field were volatile" wording in your previous note. Does this only
> speak to the atomicity properties of the volatile modifier? Or do
> you intend further constraints?
>
> No further constraints beyond simple atomicity of the individual
> load or store.  In particular no new ordering constraints with other
> loads or stores.
>
> The only special atomicity properties of volatile I’m appealing to
> are those which apply to long and double.  Those are the properties
> I am seeking to extend to value types, both those marked “volatile”
> at the use site of the type, and those marked “alwaysatomic” at the
> declaration site of the type.
>
> But now that you ask… there are *old* ordering constraints which
> are relevant.
>
> I expect, because an inline type’s fields are always final, that
> storing an inline value containing a pointer to a new object will
> safely publish that new object.  This rule in the JMM may need
> to be clarified.  In effect, if an inline object contains a pointer,
> storing it should include a previous store-store ordering
> constraint, or some other implementation of the JMM
> “freeze” operation at the end of the inline’s constructor.
>
> Make sense?
>
> — John
>
> P.S.  After writing unit tests for “alwaysatomic” I found tearing
> race conditions in HotSpot which were wrong for all inline types,
> and not just “alwaysatomic”.  In particular, if the JVM ever secretly
> buffers a value onto the heap, it should issue a store-store barrier
> before publishing the secret reference.  This may happen, for example,
> when an inline value is stored in an Object variable.  I’m mentioning
> this in case you have a similar issue in J9.  We had enough complicated
> paths in the HotSpot prototype that in some cases the store-store
> barrier was not being emitted, causing wrong execution.
>
> See also this thread about surprise tearing, and why it’s wrong:
>
> https://urldefense.proofpoint.com/v2/url?
>
u=http-3A__mail.openjdk.java.net_pipermail_valhalla-2Ddev_2020-2DJanuary_006706.html=DwIFaQ=jf_iaSHvJObTbx-

>
siA1ZOg=erClOruSa3K4FS7XawcTd7k9ZbtVLiryTZ1WIpneMMg=uSBdbgpyj81Z9PT43WizJufMTVJq-

> YMA3jDRYV1Fpr0=X9LNJxyH8Z8b1-Kfti4O4yQB-cmMxA3PwXIPvhoP55o=


RE: Evolving the wrapper classes

2020-06-19 Thread Tobi Ajila
Hi Dan S.

>>> - Where necessary (depending on the operations being performed), the
compiler generates conversions between 'I' and 'java/lang/Integer$val'. 'I'
is preferred wherever possible.
>>
>> We have to use QInteger$val whenever we use int as a type parameter, the
rest of the time, we can use I.
...
> (Note that none of these conversions are "boxing" or "unboxing". They're
strictly compilation artifacts. It may be useful to come up with a new word
for them.)

Given your examples can we assume that the JVM will never need to do an
implicit `Qjava/lang/Integer$val;` to `I` conversion? And these will always
be explicit conversions performed by javac?

> - The type [I is considered by the verifier to be equivalent to
[java/lang/Integer$val. Array operations (aaload, iaload, etc.) support
this.

Could you please explain the motivation behind this? Specifically, in which
cases are iaload and aaload operations both performed on `[I` ?

If `I` and `Qjava/lang/Integer$val;` will require explicit javac
conversions, shouldn't `[I` and `[java/lang/Integer$val` also?


Regards,
--Tobi


RE: Evolving the wrapper classes

2020-06-19 Thread Tobi Ajila


> Because arrays have identity (not to mention potentially large copying
costs), there is simply no reasonable conversion we can define; any
"conversion" would involve copying all the data, changing identity, or
both.  Just as with the array subtyping requirements (Point[] <: Point.ref
[] <: Object[]), these are things only the VM can do for us.

I suspected that this was likely due to the large cost of converting
between `[I` and `[java/lang/Integer$val`. However, I am still a little
unclear as to what the motivation is for this. Is this solely for
specialized generics?

In Dan's examples with `I` and `java/lang/Integer$val`, the only places
where conversions are needed are when primitives are used as type
parameters or to call instance methods on them, both of which can already
be done with primitive arrays. So in the LW3 - LW20 timeframe would we have
any need for these conversions? If so, could you provide some examples?

In the case of specialized generics, is the intention that `[I` (and I
suppose `I` as well) will appear in generic code?



RE: Evolving the wrapper classes

2020-06-19 Thread Tobi Ajila
Thanks for the example Dan, this "Object[] objs = arr; // just like Point[]
<: Object[]" makes it very clear. Brian's response makes more sense to me
now.


> From: Dan Smith 
> To: Tobi Ajila 
> Cc: Brian Goetz , valhalla-spec-experts
> , valhalla-spec-experts
> 
> Date: 2020/06/19 01:32 PM
> Subject: [EXTERNAL] Re: Evolving the wrapper classes
>
>
> > On Jun 19, 2020, at 11:07 AM, Tobi Ajila  wrote:
> >
> > I am still a little unclear as to what the motivation is for this.
> Is this solely for specialized generics?
> >
> > In Dan's examples with `I` and `java/lang/Integer$val`, the only
> places where conversions are needed are when primitives are used as
> type parameters or to call instance methods on them, both of which
> can already be done with primitive arrays. So in the LW3 - LW20
> timeframe would we have any need for these conversions? If so, could
> you provide some examples?
>
> I think it comes down to specialization and subtyping.
>
> Pre-specialization, here's one example that uses subtyping:
>
> int[] arr = { 1 };
> Object[] objs = arr; // just like Point[] <: Object[]
> Object obj = objs[0];
> Integer i = (Integer) obj;
>
> This would compile to something like:
>
> iconst_1
> newarray T_INT
> dup
> iconst_0
> iconst_1
> iastore
> astore_0
>
> aload_0
> astore_1
>
> aload_1
> iconst_0
> aaload
> astore_2
>
> aload_2
> checkcast java/lang/Integer
> astore_3
>
> Going in the other direction—allocating a [Qjava/lang/Integer; and
> then using iaload/iastore on it—may not be necessary unless/until
> the language supports "new T[]" in specialized code, but it
> tentatively makes sense to support now anyway, rather than having to
> come back and fix it up later.
>
> > In the case of specialized generics, is the intention that `[I`
> (and I suppose `I` as well) will appear in generic code?
>
> If you mean "can '[' be specialized to '[I'?", the answer is no.
> The primitive types cannot act as type arguments.


RE: Revisiting default values

2020-07-28 Thread Tobi Ajila
> Bucket #3 classes must be reference-default, and fields/arrays of their
inline type are illegal outside of the declaring class. The declaring class
can provide a flat array factory if it wants to. (A new idea from Tobi,
he'll write it up for the thread.)

```
public sealed abstract class LegacyType permits LegacyType.val { //Formerly
a concrete class, but now its abstract or maybe an interface
//factory methods
public static LegacyType makeALegacyType(...);//in some cases this
already exists
public static LegacyType[] newALegacyTypeArray(int size);//can be
flattened
}

private inline class LegacyType.val extends LegacyType { ... } //this type
is hidden, only LegacyType knows about it
```

This approach is based on what Kevin mentioned earlier, "For all of these
types, there is one really fantastic default value that does everything you
would want it to do: null. That is why these types should not become
inline-types, or certainly not val-default inline types ...". Essentially,
by making these types reference-default and by providing an avenue to
restrict the value-projection to the reference-default type, the writer
maintains control of where and when the value-projection is allowed to be
observed thus solving the bad default problem. The writer also has the
ability to supply a flattened array factory with initialized elements.

This approach is appealing for the following reasons: no additional JVM
complexity (ie. no bytecode checks for the bad default value), no javac
boilerplate (ie. guards on member access, guards on method entries, etc.).
On the other there are two big drawbacks: no instance field flattening for
these types, and creating flattened arrays is a bit unnatural since it has
to be done via a factory.

Going back to Brian's comment:

> I'd suggest, though, we back away from implementation techniques (you've
got a good menu going already), and focus more on "what language do we want
to build."  You claim:
> > I don't think totally excluding Buckets #2 and #3 is a very good
outcome.
> Which I think is a reasonable hypothesis, but I suggest we focus the
discussion on whether we believe this or not, and what we might want to do
about it (and when), first.

I think it would help if we had a clear sense as to what proportion of
inline-types we think will have this "bad default" problem. Last year when
we discussed null-default inline types the thinking was that about 75% of
the motivation for null-defaults was migrating VBC, 20% for security, 5%
for "I want null in my value set.". My assumption is that the vast majority
of inline-types will not be migrated types, they will be new types. If this
is correct then it would appear that the default value problem is really a
problem for a minority of inline-types.

All the solutions proposed have some kind of cost associated with them, and
these costs vary (ie. jvm complexity, throughput overhead, JIT compilation
time, etc.). If the default value problem is only for a minority of the
types, I would argue that the costs should be limited to types that want to
opt-in to not expose their default value or un-initialized value. How we
feel about this will determine which direction we choose to take when
exploring the solution space.

So, in short I want to second Brian's comment, I think its important to
decide if we want this kind of feature but also what we are willing to give
up to get it.

--Tobi

"valhalla-spec-experts"  wrote
on 2020/07/21 02:41:11 PM:

> From: Dan Smith 
> To: valhalla-spec-experts 
> Cc: Brian Goetz 
> Date: 2020/07/21 02:41 PM
> Subject: [EXTERNAL] Re: Revisiting default values
> Sent by: "valhalla-spec-experts"

>
>
> > On Jul 20, 2020, at 10:27 AM, Brian Goetz 
wrote:
> >
> > That said, doing so in the language is potentially more viable.
> It would mean, for classes that opt into this treatment:
> >
> >  - Ensuring that `C.default` evaluates to the right thing
> >  - Preventing `this` from escaping the constructor (which might be
> a good thing to enforce for inline classes anyway)
> >  - Ensuring all fields are DA (which we do already), and that
> assignments to fields in ctors are not their default value
> >  - Translating `new Foo[n]` (and reflective equivalent) with
> something that initializes the array elements
> >
> > The goal is to keep default instances from being observed.  If we
> lock down `this` from constructors, the major cost here is
> instantiating arrays of these things, but we already optimize array
> initialization loops like this pretty well.
> >
> > Overall this doesn't seem terrible.  It means that the cost of
> this is borne by the users of classes that opt into this treatment,
> and keeps the complexity out of the VM.  It does mean that
> "attackers" can generate bytecode to generate bad instances (a
> problem we have with multiple vectors today.)
> >
> > Call this "L".
>
> More letters!
>
> Expanding on ways to support Bucket #3 by ensuring initialization of
> fields/arrays:
>
> ---
>
>