Re: Make new Object() backward compatible
- Mail original - > De: "Brian Goetz" > À: "Remi Forax" , "valhalla-spec-experts" > > Envoyé: Dimanche 9 Mai 2021 17:04:31 > Objet: Re: Make new Object() backward compatible >> The logical conclusion is that java.lang.Object is a parametric class with a >> parameter saying if it should implement IdentityObject or not. > > Magic hammer, meet nail :) New tool, new tricks :) Given that we want two classes for java.lang.Object, seeing them as one being a specialization of the other is not too outrageous. > > To be explicit, what you're suggesting is something like > > class Object { ... } > > where an identity class extends Object and a primitive class > extends Object (and most interfaces remain parametric in ID.) yes > > Its conceptually elegant, and we've discussed it before; in theory > parametricity could range over things other than types, such as > constants, identity-ness, etc (e.g., the ref and val projections could > be species). But to apply it to a problem as prosaic as this seems like > cracking a walnut with a two-ton bomb. (I don't thing this is what you > want to teach on day 1.) It seems that you are thinking that i want to introduce a special syntax just for specializing java.lang.Object, I don't. I'm not proposing to change to the source code of Object.java, only the bytecode. The compiler will insert the SpecializationAnchor (and the attribute that adds the identity-ness) without needing any language support. The VM can also dynamically insert the SpecializationAnchor, but modifying javac to get the bytecode we want seems an easier path. Rémi
Re: Make new Object() backward compatible
The logical conclusion is that java.lang.Object is a parametric class with a parameter saying if it should implement IdentityObject or not. Magic hammer, meet nail :) To be explicit, what you're suggesting is something like class Object { ... } where an identity class extends Object and a primitive class extends Object (and most interfaces remain parametric in ID.) Its conceptually elegant, and we've discussed it before; in theory parametricity could range over things other than types, such as constants, identity-ness, etc (e.g., the ref and val projections could be species). But to apply it to a problem as prosaic as this seems like cracking a walnut with a two-ton bomb. (I don't thing this is what you want to teach on day 1.)
Make new Object() backward compatible
I think there is a way to avoid all the issues we have with new Object(). The problem: We want to inject the interface IdentityObject on all classes that are neither a "no field" abstract class nor a primtive class. But java.lang.Object acts as a "no field" abstract class but it's not an abstract class. Clearly, there are two java.lang.Object, the one which is the root of all classes (the "no field" abstract one) and the one which can be instantiated that should implements IdentityObject. The logical conclusion is that java.lang.Object is a parametric class with a parameter saying if it should implement IdentityObject or not. The "raw" version does not implement IdentityObject, that the one used when a class extends Object. The parameterized version implements IdentityObject and is the one used by new Object() So the classfile Object.class should contain a SpecializationAnchor, and being a "no field" class or not is an attribute that references the Anchor. To maintain backward compatibility, when the VM sees the opcode NEW java/lang/Object, it adds a new constant pool entry of kind SpecializationLinkage that reference java/lang/Object with a constant asking for version that implements IdentityObject and rewrite NEW java/lang/Object to NEW Linkage(java/lang/Object). Obviously, there is the bootstraping issue with the code in java.lang.invoke making the BSM working not be initialized at the time java.lang.Object need to be available, so the VM has to inject the binding early as if it was resolved by the BSM but i think it's workable. When the VM starts, if there are some new Object() executedbefore the code of java.lang.invoke is ready, those code can be rewritten to use a special class defined in the JDK for that like package jdk.internal.whatever; class LockObject { } Even if it's not strictly necessary, javac can be changed to emit the Linkage(java/lang/Object) each time a new Object() is needed to the rewriting by the VM described above need to be done only for the classfiles that are using previous versions. I believe this change is fully source and binary compatible and nice property is that new Object().getClass() == Object.class is still true. Rémi