/** * Create a LF which can access the given field. Cache and share this structure among all fields * with the same basicType and refKind. */ private static LambdaForm preparedFieldLambdaForm(MemberName m) { Class<?> ftype = m.getFieldType(); boolean isVolatile = m.isVolatile(); byte formOp; switch (m.getReferenceKind()) { case REF_getField: formOp = AF_GETFIELD; break; case REF_putField: formOp = AF_PUTFIELD; break; case REF_getStatic: formOp = AF_GETSTATIC; break; case REF_putStatic: formOp = AF_PUTSTATIC; break; default: throw new InternalError(m.toString()); } if (shouldBeInitialized(m)) { // precompute the barrier-free version: preparedFieldLambdaForm(formOp, isVolatile, ftype); assert ((AF_GETSTATIC_INIT - AF_GETSTATIC) == (AF_PUTSTATIC_INIT - AF_PUTSTATIC)); formOp += (AF_GETSTATIC_INIT - AF_GETSTATIC); } LambdaForm lform = preparedFieldLambdaForm(formOp, isVolatile, ftype); maybeCompile(lform, m); assert (lform.methodType().dropParameterTypes(0, 1).equals(m.getInvocationType().basicType())) : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType()); return lform; }
/*non-public*/ static boolean shouldBeInitialized(MemberName member) { switch (member.getReferenceKind()) { case REF_invokeStatic: case REF_getStatic: case REF_putStatic: case REF_newInvokeSpecial: break; default: // No need to initialize the class on this kind of member. return false; } Class<?> cls = member.getDeclaringClass(); if (cls == ValueConversions.class || cls == MethodHandleImpl.class || cls == Invokers.class) { // These guys have lots of <clinit> DMH creation but we know // the MHs will not be used until the system is booted. return false; } if (VerifyAccess.isSamePackage(MethodHandle.class, cls) || VerifyAccess.isSamePackage(ValueConversions.class, cls)) { // It is a system class. It is probably in the process of // being initialized, but we will help it along just to be safe. if (UNSAFE.shouldBeInitialized(cls)) { UNSAFE.ensureClassInitialized(cls); } return false; } return UNSAFE.shouldBeInitialized(cls); }
/** * Create a LF which can invoke the given method. Cache and share this structure among all methods * with the same basicType and refKind. */ private static LambdaForm preparedLambdaForm(MemberName m) { assert (m.isInvocable()) : m; // call preparedFieldLambdaForm instead MethodType mtype = m.getInvocationType().basicType(); assert (!m.isMethodHandleInvoke()) : m; int which; switch (m.getReferenceKind()) { case REF_invokeVirtual: which = LF_INVVIRTUAL; break; case REF_invokeStatic: which = LF_INVSTATIC; break; case REF_invokeSpecial: which = LF_INVSPECIAL; break; case REF_invokeInterface: which = LF_INVINTERFACE; break; case REF_newInvokeSpecial: which = LF_NEWINVSPECIAL; break; default: throw new InternalError(m.toString()); } if (which == LF_INVSTATIC && shouldBeInitialized(m)) { // precompute the barrier-free version: preparedLambdaForm(mtype, which); which = LF_INVSTATIC_INIT; } LambdaForm lform = preparedLambdaForm(mtype, which); maybeCompile(lform, m); assert (lform.methodType().dropParameterTypes(0, 1).equals(m.getInvocationType().basicType())) : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType()); return lform; }
// Constructors and factory methods in this class *must* be package scoped or private. private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) { super(mtype, form); if (!member.isResolved()) throw new InternalError(); if (member.getDeclaringClass().isInterface() && member.isMethod() && !member.isAbstract()) { // Check for corner case: invokeinterface of Object method MemberName m = new MemberName( Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); if (m != null && m.isPublic()) { assert (member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong member = m; } } this.member = member; }
private static DirectMethodHandle makeAllocator(MemberName ctor) { assert (ctor.isConstructor() && ctor.getName().equals("<init>")); Class<?> instanceClass = ctor.getDeclaringClass(); ctor = ctor.asConstructor(); assert (ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor; MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass); LambdaForm lform = preparedLambdaForm(ctor); MemberName init = ctor.asSpecial(); assert (init.getMethodType().returnType() == void.class); return new Constructor(mtype, lform, ctor, init, instanceClass); }
static DirectMethodHandle make(Class<?> receiver, MemberName member) { byte refKind = member.getReferenceKind(); if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; return make(refKind, receiver, member); }