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