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