Valhalla Meeting Notes Jan 30, 2019
Karen Kinnear
karen.kinnear at oracle.com
Wed Feb 13 15:41:37 UTC 2019
Next meeting Feb 13, 2019
Attendees:
John, Brian, Remi, Tobi, Dan H, Frederic, Karen
AI: Remi: send GitHub POC experiment outside of vm with bridge forwarding
I. Problem: Where do I put privileged, final, value-specific behaviors
initial example: Object.wait*/notify*.
Is there a clean way to do this without JVM magic?
You can not have final methods in interfaces, and Object methods are always found first.
Proposal: JVM injects new super class: RefObject for all reference objects, i.e. all existing class files.
Require ValObject as super class for all value classes.
java.lang.Object is treated as an honorary interface top type, e.g. in descriptors
new Object[] uses Object as the interface top type and can hold any RefObject or ValObject
BG: This fits with longer term new top type for Arrays, e.g. interface Array<any T>
Proposal 2: Extend the canonical factory model used by e.g. List.of()
Allow java.lang.Objects and Generics to create a default factory for interfaces and abstract classes
“new” bytecode (without new/dup/<init> would invoke the default factory, e.g. a static <init>
This would be used to allow instantiation of Object(), so new Object() would create a canonical Object
which has RefObject as a super class.
Brian does not want RefObject or ValObject to be instantiable
DH: Are factories responsible for Super calls?
KK: How does the vm tell a new “new” bytecode from an old one?
JR: At link resolution time, you know the type you wanted
DH: What if the CP entry is used by ldc also?
JR: For “new” might need to renumber the CP index or store resolution separately
Concerns:
1. Class.getSuperClass() explicitly assumed to be java.lang.Object
* need to find frequency of this in codebases
2. Code that assumes explicit hierarchy depth -> can adapt source
Alternative I: both as interface
RF: easier to inject
BG: VM must enforce not allowing implementing both at once
Teaching - this model is not clean from a user expectation perspective
Alternative II: (fallback): ValObject as super class, RefObject as super interface
BG: wait/notify: need final implementation of wait/notify that normal tools understand vs. adhoc rules
DH: Retcon Object -> RefObject? What if we were to change wait/notify to only exist for RefObject
BG: concern about speed of translation
JR: Generics have parallel reflective problems with ArrayList and Object, with getClass and getSpecies
KK: sync is special in the vm for ValObject anyway, so not significant to handle wait/notify specially
BG: if from scratch would do classes, if too hard to retrofit could explore Alternative II
BG: List<? extends ValObject> can allow any value class
RF: [ValObject]
BG: abstract type, nullable and not flattened
RF: Lambda super is Object
BG: Actually it is not specified
FP: JVMS: Interface: link to Object methods must succeed, not required from Object
II. Bridge Methods - BG
Goals: 1. wildcards for specialized generics
2. least important: current bridge methods are a constant source of pain
separate compilation can give wrong answer, generate in vm could help
Foo<T> { T f1; }
Foo<?> f1 has type Object (past and future), can reference through a wildcard
methods: could do bridges (also want asType() conversions)
fields: want to link with asType() conversions
capture that two signatures describe the same member
language level: 1 member
vm level: 2 unrelated bridges
Farther future goal:
3. Member type signature migration
e.g. Collection.size() int -> C.s()long or OptionalInt -> Optional<int>
RF: goal 3 is not just covariance
BG: clients and subtypes
Proposal: Forwarding bridges
use info: resolution and selection time
if the compiler generated bridge, only used at selection time
if resolution hits the bridge, rerun resolution with new descriptor
if only at selection time: miss ability to correct bridge loops
RF: ok with forward
asType must be done by target
BG: “asType” e.g. Date -> LocalDate: need plug in code
RF: which class decides xform?
BG: declaration of migration must provide asType conversion
BG: Change signature type: declare signature and provide asType
JR: behave as if bridge was there as synthetic
BG: if trivial, vm knows widening rules
JR: upfront - not want loops
combinatorial complexity with species
dynamic injection of synthetic methods
KK: like having forward info in the vm, need to walk the details - e.g. table of client/subtype & overriding, could
use use cases
BG: Dan Smith aid we need to check mixing old style bridges and forwarding
JR: thought experiment: Mindy - what if we had a class with no method, BSM for all linkage requests for methods
BG: prototype strategy
use annotations
all member access -> indy
easier to prototype resolution behavior than selection behavior
RF: have a POC on GitHub
JR: helpful to experiment with semantics of resolution without changing vm
BG: Vicente has a javac mode that does not generate current bridges
BG: or could use a bytecode weaver
javac allows overloads with different return types today - could use those as experiments
DH/TA: look at J9 - spinning MethodHandles for the new behavior
JR: Maybe parallel tables, hard to wedge MH
KK: still need to study expected behaviors, e.g. for virtual fields
RF: vtable for fields
DH: will the vm know all signatures at vtable build time?
BG: yes classfile contains orig sig and forward sig
JR: fixed set of members at class load time
with BSM adaptors - could change (ed. note - what could change?)
BG: old signature in vtable “as if final” = migrated, can’t override migrated methods
linktime forwarding: change slot, have receiver do selection time forwarding
RF: Can’t call the BSM until the first call
KK: Two sets of asType adaptations
III. Equality
JR: 1. Substitutability check != Reference equality except for RefObject, does not require identity
Value Types: fields pairwise substitutable
Interface/Object: need dynamic check for Val vs Ref
if Ref: ref equality, if Val: val substitutability
2. SubstitutabilityHash != Object.HashCode, != IdentityHashCode
system.substitutability
retcon acmp as substitutability test
BG: cost benefits discussion
DH: one design center: numerics
will write methods w/operator overloading
== fits nicely into operator overloading
BG: more fundamental case
pass sentinel into code that takes m(Object) or m()Object
== to check sentinel or existence of element
if values, invisible even though allowed as input/return
JR: operator overload
if statically know type - great
other: legacy code, generic code
DH: what about generic code == followed by .equals “most” use
JR: well constructed code - is not helped, we must ensure not harmed
DH: .equals may start with ==, so pay cost twice
BG: JIT - if can inline .equals, can CSE to only have 1 acmp
DH: not if generic
BG: all generics over VT are specialized
DH: ArrayList<Object> is not specialized
JR: either a fountain of razor blades for users or engineering tasks for us
e.g. LIFE (legacy idiom for equality): JIT: if dynamically value -> …
explore - maybe spec? .equals allowed to absorb a preceding substitutability test?
BG: need data on costs rather than “living in fear”
KK: Need to gather performance data on larger apps & code cache costs
Need to deal with deep recursion/SOE
JR: agree there are risks - need to experiment and measure
Corrections/clarifications welcome,
thanks,
Karen
More information about the valhalla-spec-observers
mailing list