Valhalla EG minutes May 9 and Apr 25 2018

Karen Kinnear karen.kinnear at
Wed May 23 14:11:30 UTC 2018

Corrections welcome - apologies for the delay

May 9, 2018

Attendees: Remi, Dan H, ]Dan Smith, Frederic, David Simms, Karen

JVMLS upcoming talks:
Any interest in cohosting:
1) LWorld
2) Nestmates and the Alternate Accessors
3) VT workshop
4) Condy

Plan is to get this into JDK 11
JEP is targetted
Spec update was sent for review - any questions?
Remi: ASM 6.2 will be ready next week with Condy and Nestmates (later email update: and preview version handling)
John: cleaning up issues e.g. invokespecial

Value Types:
1. Cloneable:
1) disallow override and allow call: what does it mean to return the same Value Type?
2) disallow calling clone?
Should javac give a warning?
What about backward compatibility?
For signatures that pass Object?
John: note: clone is protected so must be called from subtype
Dan H: propose prototype throw exception we can change this later

2. Null hygiene email
VM static typing model - distinguish heap vs. stack
verifier - check static type on stack
others: ensure type publishing to heap
enhance static typing model: list locally known value types - provide a classfile view
when load classfile - check if really a Value Type
lazily load other types

a) identity sensitive
most checks are dynamic type based - even if operating on “Object”

b) null suppression
(ed. note: under re-discussion)
Want static and dynamic
from classfile point of view - catch surprise nulls
Helps users, helps optimizations e.g. method scalarization

static type:
1) verifier: aconst_null
2) checkcast: if local classfile statically knows VT: add null check
3) callee checks input arguments for null
4) return: caller check

Dan H: for return - only statically declared VT known locally
John: invocations are linked, may want to cache non-nullable information

Remi: what about libraries that use null as a return type?
  e.g. Map.get()

John: wants the VM to be locally strict
  if we have to deal with occurrences of nullable VT, revisit
  maybe explore: ValueRef in the language?

Remi: 1) map.get()
2) push null to a Lambda
John: does checkcast save you?
Remi: need checkcast in bridge
what about aconst_null call to erased generic?
John: NPE is thrown, location varies
checkcast could work for non null VT, could optimize away checkcast

Remi: user may get NPE
e.g. java.util.concurrent: methods take null in API spec - null as sentinel input

Remi: prefer: nullable ValueType annotation
  VM has to not do null check
John: what about when erased to Object?
Remi: or implement interface?
John: need to handle this in the context of erasure
Perhaps lang and API folks fix the rest?
Remi: requires more bridges

John: don’t want to change fields, arrays, method descriptors - that ways lies pain
but may have to do this
Frederic: we have L descriptor which today implies nullable, perhaps a new descriptor for non-nullable?

John: what if map.get were to return a ValueRef of ComplexDouble?

Frederic: Concern is if we do the first prototype with the same descriptor but change the semantics,
 it is confusing if we add a new descriptor with the same semantics
exploring: nonnullable container for VT - without exploring general nonnullability
might help with backward compatibility for APIs with Object/Interface/[Object/[Interface
allow generic specialization to optimize if you have nonnullable references
allow javac/verifier/runtime checks

Remi: isn’t this the same as the side table?

Frederic: No. Different signature perhaps. Key is the nonnullability as a property of the container/reference, not the type
  Caller must convert 
  e.g. in new code: use NVT; - which is non-nullable
  to pass to a method that expects Object;, safe to cast NVT; -> LVT;
  do the work at the boundary
  In Q-world we changed the type hierarchy of classes. In LN world - we change the property of the container/reference, not the type of the class
  NVT; is a non-nullable reference to the same class VT as LVT; which is a nullable reference to VT
Trying to scale down the pain

Remi: Need adaptation, e.g. hierarchy of methods

John: prefer to try simpler approaches before new descriptors
  e.g. ValueRef Interface
  e.g. LComplexDouble -> LValueRef

Karen: requires changing implementation of existing code - e.g. APIs which return null

1. generic code: free to instantiate to DoubleComples, ValueRef of DoubleComplex
2. APIs which return Optional - don’t have nulls as part of the API

Concern about requiring changing existing implementations in the field: 1) erased generics and 2) APIs that assume null
  e.g. new code using old APIS that passes a non-nullable [VT and the implementation stores a null -> NPE

Works like an Int - NPE is analogous to ArrayStoreException
With a null return: checkcast will catch this immediately
Also an expectation that most users will do a null check first for APIs that use null as a sentinel e.g. that no entry was found

John: we may have to go to excited types ! and ?
  warning - that is a separate language discussion before it enters the vm discussion
Remi: need another kind of erasure
John: could use lazy casting: e.g. allow null check before casting - above the vm
Remi: not many APIs use null for sentinels
  perhaps we don’t use those methods with VT
John: perhaps only allow ?type in the return position?

Dan H: Look at Collections?
note: Brian started looking in 2012 - there is a literature of methods like this, may need to look again
John: did a verbal introduction to Brian yesterday about value type hygiene, Brian is thinking about it
Remi: type annotation may allow javac/verifier/runtime/JIT 
generics: may need special case null checks - perhaps with local annotations?

John: let’s prototype the super-strict approach and see if it helps with optimizations

Remi: there is an existing code road bock for value-based-class migration
What does == on Optional.empty do? Need VBC to use .Equals
John: libraries may need implementation changes
  e.g. Class.cast() - may need to add Class.castRef? reject null for VT? call Object.equals()

Clear that a strict vm does not solve all problems

Remi: benefit to having a prototype sooner rather than later, outside world needs to see progress

John: performance depends on the strictness dial
  benefits in experiment with and without strictness

Dan H: consider binaries via the adoptOpenJDK project?
  talk to Brian - using this for Amber

April 25, 2018

attendees: Dan H, Tobi, John, Frederic, David Simms, Lois, Karen

Value Types

1. pre-loading of classes: 
needed for field flattening
JIT method calls - preload formal parameters
maybe a single mechanism
— details not worked out yet

2. proposing a new attribute
javac view vs. runtime view
javac - list all types known to be value types
runtime: classes not listed in the attribute - don’t reload, don’t flatten
if in the attribute - preload, check if VT
can decide to flatten
can use for fields and method signatures

3. circularity
For layout we need to check circularity errors
discussion of - if we detect a circularity error - perhaps don’t fail the load but rather treat as non-flattenable
(ed. note - not sure how this would work)
Note: VTs used in fields need to preload at class load time, used in method signatures - need to load at preparation time
JIT needs to know value types for optimization

note: calling convention: if inconsistencies between superclass and subclass lists - need to follow the least specific declaring classes’ view of ValueType

Dan H: if value type is not in the list -> throw ICCE
Remove an attractive nuisance
John: if we can be null hostile at call boundaries we can allow optimizations
migrated value types are a corner case
alternative: leave as is: JIT can be null hostile if it has VT information and deoptimize if null -> reduces performance
Frederic: a common approach is to add an additional argument to specify null
John: in new code we would never have null for a VT
Karen: concern about nullability and backward compatibility

Dan H: historically tried to avoid recompilation by javac increasing performance, discouraging javac clever optimizations
Frederic: only time this would happen would be if you migrate a VBC -> VT

John: LWorld
Types are all nullable, verifier can’t tell, if values are nullable they are not flattenable
goal: have the vm be as null hostile as possible
Clearly we will check nullability for containers - instance fields, static fields, array elements
Verifier limitations: note: locals are NOT null hostile
one approach: javac could add null checks as necessary
or have a dial between hostility and leniency
John prefers complete hostility when possible
e.g arrays of VT are really flattenable and null hostile

Dan S: original LWorld discussion - QTypes expressed null hostility
alternative exploring: flag on fields
if you want full control over null - maybe need QTypes

arrays: preload the element, so we know it is a VT
fields: have a flag
could have QTypes in method signatures and verifier
OR: casts could allow nulls
locals - could expect javac to introduce null checks

If we use Types for identity and value type and we preload all VT 
ACC_FLATTENABLE allows checking non-nullability for fields

John: want the semantic effect 
  if preload a VT and mismatchL -> throw ICCE

John: summary: 
Treat Types as Types in this classfile
verifier can reject null bearing values, method call boundaries, heap containers
worth exploring

More information about the valhalla-spec-observers mailing list