Correction… The recommended reflective approach has a flaw (easily fixed), which makes indy my real recommendation.
On Apr 8, 2020, at 11:43 AM, John Rose <john.r.r...@oracle.com> wrote: > … > I have a proposal for a translation strategy: > > 1. Translate casts to inline classes differently from “classic” > casts. Add an extra step of null hostility. For very low-level > reasons, I suggest using “ldc X” followed by Class::cast. > > Generally speaking, it’s a reasonable move to use reflective > API points (like Class::cast) on constant metadata (like X.class) > to implement language semantics. This suggestion is incomplete. If the result of the cast is going to be used as type X, then the verifier must be pacified by adding `checkcast X`. Basically, you have to do both reflective and intrinsic cast operations, if you need to get the verifier on board, as well as do a null check. That tips me over to recommending indy instead, which was #2. Indy, that Swiss army knife of an instruction, can get it done in one. > The following alternatives are also possible; I present them > in decreasing order of preference: > > 2. Use invokedynamic to roll our own instruction. It will > be a trivial BSM since we are really just doing an asType > operation. But I think this is probably overkill, despite > my fondness for indy. For a conversion to type X, where X may be a null-hostile inline type (or any type whose semantics is not exactly covered by native checkcast), a single invokedynamic instruction will cover the operational semantics required and will also feed the right type to the verifier. It will have this signature: (Object) => X It will have a utility bootstrap method which materializes conversions, basically riffing on MethodHandles::identity and asType. (Not MethodHandles::explicitCastArguments, because we are concerned with checked reference conversions.) It will have *no extra arguments* (not even X.class), because the BSM can easily derive X.class from the return type of the method type signature passed to the BSM. ConstantCallSite convertBSM(Lookup ig1, String ig2, MethodType mt) { var mh = MethodHandles.identity(Object.class).asType(mt); return new ConstantCallSite(mh); } As such, it is a candidate for proposed simplifications to bootstrap method configuration (but not the simplest such simplifications, because of the need to feed X.class into the linkage logic). MethodHandle simplifiedConvertBSM() { return MethodHandles.identity(Object.class); } (At some point I should write up those simplifications, shouldn’t I?) — John