Valhalla EG minutes May 22, 2019

Karen Kinnear karen.kinnear at
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

III. @Contended 
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
                          always nullable
                          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
  3. arrays: 
      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

   old contract:
     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
     e.g. HashMap
     specialization is orthogonal to inline vs. indirect

corrections welcome,

More information about the valhalla-spec-observers mailing list