Valhalla EG minutes May 22, 2019
karen.kinnear at oracle.com
Fri May 31 18:51:32 UTC 2019
Attendees: Remi, Tobi, Dan H, John, David Simms, Frederic, Karen
I. Remi: the new static <init>()this needs to work with indy, but today you can’t use “<>” in the name.
John: the MethodHandle is legit
Dan H: name in a BSM does not have to relate to the underling method
Remi: BSM has to change so that the name allows <init> (i.e. brackets)
II. withfield - is staying
Ignore for an inline class or within an inline class, ok for a field containing an inline class
Dan H: @Contended is for bootclasspath only, only support class level today
Frederic: javadoc on the annotation: Just a hint
also: “trusted" classes only
ed. note: I believe trusted classes means bootclasspath or platform class loader
IV. Karen: There have been some email exchanges recently and I wanted to make sure we
all were using the same terminology. For example, when we get to LW20 and offer support
for null-default inline classes, we have been using the symbols:
NV and NV?
Note - that both are nullable.
My question - what is the difference between them and do we need two “types” here?
Remi: presented a session last week. “?” syntax was confusing to people
a. relative to Kotlin and b. why not on reference classes
John: Nullable is a side issue. The difference between NV and NV? for an inline class
is whether the class is handled embedded vs. indirect
Remi: NV? has an L-signature, right? Still, it is an inline class?
John: “L” notation - does not allow us to find out if it is an inline class before use. So consistently, it is not determinable if this is an inline class.
Remi: Once we load the class we will know it is an inline class. Need to consider separate compilation handling.
Karen: Note that the “L” descriptor in this model does NOT imply identity. It does imply indirect.
Remi: What if we were to throw an exception if an L descriptor defined an inline class, even when lazily loaded
(e.g. post verification)?
Karen: Due to the current proposal of VBC migration, existing “L” signatures would be used, and some clients
would be aware that this was now an inline class and some would not.
Remi: If NV? is not flattenable - is it still scalarizable on stack?
John: Trying to avoid corner cases - which cause a long trail of tears
old contract vs. new contract
old contract: always indirect references
heap storage is always indirect
can be treated opaquely
allows lazy loading
allows circularity because it allows lazy loading
Remi: There is a declaration world and a runtime world. If you declare as L and actually load the class and it is an inline class - does acmp determine identity handling vs. identities handling via descriptor?
[ed note: no - acmp has to check the runtime type to see if it is inline vs. supports identity)
John: Container semantics - define what it can contain - old vs. new contract
new contract: load before layout
Karen: concern about needing to know if nullable or not
both programmer’s perspective - if switching from Point to Point? not only changes to indirect, but also allows null
and vm perspective - as we discussed in the past, the JIT needs to know null-free for max optimizations
John: bridging will allow going from old descriptor to new descriptor
maybe also allow changing name?
Remi: For renaming - what if that information was in module-info? The module-infos are loaded before the
Karen: that is a partial solution to the problem
John: great when you can do it. The vm always needs to know.
Remi: all value-based-classes (VBCs) are currently in java.base or JDK
Karen: Do others use VBCs? We could restrict migration of VBCs to java.base or JDK or in a module
John: “adhoc” types we control
need to define an overall policy
clear old and new contracts and bridging technology
Karen: Question is: with a new (not migrated VBC) null-default inline class - e.g. Person, does it need two representations?
John: When would a developer need to specify “indirect”?
1. instance field circularity
2. atomicity - for containers in the heap only
if the use-site does not want to say Volatile
e.g. performance - for heap container - e.g. if lots of copies are performed
e.g. large object
John: The translation strategy makes adhoc decisions between the old and new contract
(ed. note - I think what John is saying that even if a user specifies “new” contract, i.e. please inline,
the vm makes the decision of whether an inline class is inlined or not - e.g. based on size or atomicity)
set a default policy
allow advanced users to influence the decision
Remi: One challenge for power users, is that an specific optimization often applies at one point in time, and not later (changes in software or hardware) - like “register” keyword in C - the decision was meaningful at one time
An annotation perhaps
Dan H: This might be different - since it ties into the data structure layout
A change might be a surprise to users, they might be concerned if we ignore the hint
Remi: Not want the hint in JVMS, like @Contended
John: there is a language syntax point of view
goal: simplest default - does the desirable thing
want naturally inline object
might want different - e.g. for generics or performance
want a syntax that implies that this would not be for general use
Karen: For NV and NV? (or Person/Person?) would we be looking at a subtype relationship or a conversion?
This impacts verification and array covariance
John: If contract is about containers
This allows the vm to check correctness - specifically for a value set
e.g. checkcast/ArrayStoreException/NullPointerException - if try to add null
goal: the verifier type system forces the right checks
whether that is a subtype/supertype or checkcast check
prefer never checkcast to LObject (ed. note - my notes are not clear here)
John: new contract:
load class file eagerly and look at the definition
verifier - only use information you have from descriptor, still tries to not load classes eagerly
you do not know if you have an inline class or an indirect class
you do not know if you have null ok or null free
Karen: We have already discussed that we want the verifier to not eagerly load and still be able to exclude nulls
so we need a use-site signal
John: That is a requirement on the descriptor format, that the container is null-hostile
Karen: Need to be clear that inline vs. indirect is not about null-ok/null-hostile
John: distinguish between - “can use opaquely” vs. “must eagerly load and find out from class file”
Agreed: verifier specifically - without loading can check null-free
In the end we might not need that
Remi: Kotlin - require-not null
John: shake out in prototyping
null-ok/null-hostile is not the primary dimension
John: Also want old/new contract with templates
templatedtype as a pure symbol vs. expand
e.g. Optional<int> vs. Optional<long>
some uses of template type need to be opaque, to allow circularities
need to distinguish - indirect with abstraction vs. inlining with eager expansion
still need a pair of contracts
Karen: Doesn’t the wildcard/raw type already represent the non-expanded abstract use case? Or the erased generic use of jlObject? What problem does this not solve?
John: Those are both old contract
This solves most problems - but not corner cases such as
- changes to overloading and overriding rules based on signature matching
- therefore would want different method descriptors
Remi: Useful for code specialization, even if indirect type
specialization is orthogonal to inline vs. indirect
More information about the valhalla-spec-observers