/** * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that * represents a MH bound to a generic invoker, which in turn forwards to the corresponding * getter. */ NamedFunction getterFunction(int i) { NamedFunction nf = nominalGetters[i]; assert(nf.memberDeclaringClassOrNull() == fieldHolder()); assert(nf.returnType() == fieldType(i)); return nf; }
private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) { this.typeChars = types; this.typeCodes = basicTypes(types); this.clazz = clazz; if (!INIT_DONE) { this.constructor = new MethodHandle[1]; // only one ctor this.getters = new MethodHandle[types.length()]; this.nominalGetters = new NamedFunction[types.length()]; } else { this.constructor = Factory.makeCtors(clazz, types, null); this.getters = Factory.makeGetters(clazz, types, null); this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters); } this.extensions = new SpeciesData[ARG_TYPE_LIMIT]; }
static NamedFunction[] makeNominalGetters(String types, NamedFunction[] nfs, MethodHandle[] getters) { if (nfs == null) nfs = new NamedFunction[types.length()]; for (int i = 0; i < nfs.length; ++i) { nfs[i] = new NamedFunction(getters[i]); } return nfs; }
SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) { this.typeChars = types; this.typeCodes = basicTypes(types); this.clazz = clazz; if (!INIT_DONE) { this.constructor = new MethodHandle[1]; // only one ctor this.getters = new MethodHandle[types.length()]; this.nominalGetters = new NamedFunction[types.length()]; } else { this.constructor = Factory.makeCtors(clazz, types, null); this.getters = Factory.makeGetters(clazz, types, null); this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters); } this.extensions = new SpeciesData[ARG_TYPE_LIMIT]; }
/** * Wrap a constructor call in a {@link LambdaForm}. * * If constructors ({@code <init>} methods) are called in LFs, problems might arise if the LFs * are turned into bytecode, because the call to the allocator is routed through an MH, and the * verifier cannot find a {@code NEW} instruction preceding the {@code INVOKESPECIAL} to * {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through * {@link MethodHandle#linkToSpecial}. * * The last {@link LambdaForm#Name Name} in the argument's form is expected to be the {@code void} * result of the {@code <init>} invocation. This entry is replaced. */ private static MethodHandle linkConstructor(MethodHandle cmh) { final LambdaForm lf = cmh.form; final int initNameIndex = lf.names.length - 1; final Name initName = lf.names[initNameIndex]; final MemberName ctorMN = initName.function.member; final MethodType ctorMT = ctorMN.getInvocationType(); // obtain function member (call target) // linker method type replaces initial parameter (BMH species) with BMH to avoid naming a species (anonymous class!) final MethodType linkerMT = ctorMT.changeParameterType(0, BoundMethodHandle.class).appendParameterTypes(MemberName.class); MemberName linkerMN = new MemberName(MethodHandle.class, "linkToSpecial", linkerMT, REF_invokeStatic); try { linkerMN = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linkerMN, null, NoSuchMethodException.class); assert(linkerMN.isStatic()); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } // extend arguments array Object[] newArgs = Arrays.copyOf(initName.arguments, initName.arguments.length + 1); newArgs[newArgs.length - 1] = ctorMN; // replace function final NamedFunction nf = new NamedFunction(linkerMN); final Name linkedCtor = new Name(nf, newArgs); linkedCtor.initIndex(initNameIndex); lf.names[initNameIndex] = linkedCtor; return cmh; }
/** * Wrap a constructor call in a {@link LambdaForm}. * * If constructors ({@code <init>} methods) are called in LFs, problems might arise if the LFs * are turned into bytecode, because the call to the allocator is routed through an MH, and the * verifier cannot find a {@code NEW} instruction preceding the {@code INVOKESPECIAL} to * {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through * {@link MethodHandle#linkToSpecial}. * * The last {@link LambdaForm.Name Name} in the argument's form is expected to be the {@code void} * result of the {@code <init>} invocation. This entry is replaced. */ private static MethodHandle linkConstructor(MethodHandle cmh) { final LambdaForm lf = cmh.form; final int initNameIndex = lf.names.length - 1; final Name initName = lf.names[initNameIndex]; final MemberName ctorMN = initName.function.member; final MethodType ctorMT = ctorMN.getInvocationType(); // obtain function member (call target) // linker method type replaces initial parameter (BMH species) with BMH to avoid naming a species (anonymous class!) final MethodType linkerMT = ctorMT.changeParameterType(0, BoundMethodHandle.class).appendParameterTypes(MemberName.class); MemberName linkerMN = new MemberName(MethodHandle.class, "linkToSpecial", linkerMT, REF_invokeStatic); try { linkerMN = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linkerMN, null, NoSuchMethodException.class); assert(linkerMN.isStatic()); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } // extend arguments array Object[] newArgs = Arrays.copyOf(initName.arguments, initName.arguments.length + 1); newArgs[newArgs.length - 1] = ctorMN; // replace function final NamedFunction nf = new NamedFunction(linkerMN); final Name linkedCtor = new Name(nf, newArgs); linkedCtor.initIndex(initNameIndex); lf.names[initNameIndex] = linkedCtor; return cmh; }
NamedFunction[] getterFunctions() { return nominalGetters; }