< prev index next >

src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 70,99 **** this.member = member; } // Factory methods: ! static DirectMethodHandle make(byte refKind, Class<?> receiver, MemberName member) { MethodType mtype = member.getMethodOrFieldType(); if (!member.isStatic()) { ! if (!member.getDeclaringClass().isAssignableFrom(receiver) || member.isConstructor()) throw new InternalError(member.toString()); ! mtype = mtype.insertParameterTypes(0, receiver); } if (!member.isField()) { switch (refKind) { case REF_invokeSpecial: { member = member.asSpecial(); ! LambdaForm lform = preparedLambdaForm(member); ! return new Special(mtype, lform, member); } case REF_invokeInterface: { ! LambdaForm lform = preparedLambdaForm(member); ! return new Interface(mtype, lform, member, receiver); } default: { ! LambdaForm lform = preparedLambdaForm(member); return new DirectMethodHandle(mtype, lform, member); } } } else { LambdaForm lform = preparedFieldLambdaForm(member); --- 70,103 ---- this.member = member; } // Factory methods: ! static DirectMethodHandle make(byte refKind, Class<?> refc, MemberName member, Class<?> callerClass) { MethodType mtype = member.getMethodOrFieldType(); if (!member.isStatic()) { ! if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor()) throw new InternalError(member.toString()); ! mtype = mtype.insertParameterTypes(0, refc); } if (!member.isField()) { switch (refKind) { case REF_invokeSpecial: { member = member.asSpecial(); ! LambdaForm lform = preparedLambdaForm(member, callerClass); ! Class<?> checkClass = refc; // Class to use for receiver type check ! if (callerClass != null) { ! checkClass = callerClass; // potentially strengthen to caller class ! } ! return new Special(mtype, lform, member, checkClass); } case REF_invokeInterface: { ! LambdaForm lform = preparedLambdaForm(member, callerClass); ! return new Interface(mtype, lform, member, refc); } default: { ! LambdaForm lform = preparedLambdaForm(member, callerClass); return new DirectMethodHandle(mtype, lform, member); } } } else { LambdaForm lform = preparedFieldLambdaForm(member);
*** 106,120 **** assert(offset == (int)offset); return new Accessor(mtype, lform, member, (int)offset); } } } ! static DirectMethodHandle make(Class<?> receiver, MemberName member) { byte refKind = member.getReferenceKind(); if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; ! return make(refKind, receiver, member); } static DirectMethodHandle make(MemberName member) { if (member.isConstructor()) return makeAllocator(member); return make(member.getDeclaringClass(), member); --- 110,124 ---- assert(offset == (int)offset); return new Accessor(mtype, lform, member, (int)offset); } } } ! static DirectMethodHandle make(Class<?> refc, MemberName member) { byte refKind = member.getReferenceKind(); if (refKind == REF_invokeSpecial) refKind = REF_invokeVirtual; ! return make(refKind, refc, member, null /* no callerClass context */); } static DirectMethodHandle make(MemberName member) { if (member.isConstructor()) return makeAllocator(member); return make(member.getDeclaringClass(), member);
*** 159,169 **** /** * 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()) { --- 163,173 ---- /** * 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, Class<?> callerClass) { assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead MethodType mtype = m.getInvocationType().basicType(); assert(!m.isMethodHandleInvoke()) : m; int which; switch (m.getReferenceKind()) {
*** 177,211 **** 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; } private static LambdaForm preparedLambdaForm(MethodType mtype, int which) { LambdaForm lform = mtype.form().cachedLambdaForm(which); if (lform != null) return lform; lform = makePreparedLambdaForm(mtype, which); return mtype.form().setCachedLambdaForm(which, lform); } static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) { boolean needsInit = (which == LF_INVSTATIC_INIT); boolean doesAlloc = (which == LF_NEWINVSPECIAL); ! boolean needsReceiverCheck = (which == LF_INVINTERFACE); String linkerName; LambdaForm.Kind kind; switch (which) { case LF_INVVIRTUAL: linkerName = "linkToVirtual"; kind = DIRECT_INVOKE_VIRTUAL; break; case LF_INVSTATIC: linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC; break; case LF_INVSTATIC_INIT:linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC_INIT; break; case LF_INVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_INVOKE_SPECIAL; break; case LF_INVINTERFACE: linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE; break; case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_NEW_INVOKE_SPECIAL; break; default: throw new InternalError("which="+which); } --- 181,225 ---- if (which == LF_INVSTATIC && shouldBeInitialized(m)) { // precompute the barrier-free version: preparedLambdaForm(mtype, which); which = LF_INVSTATIC_INIT; } + if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) { + which = LF_INVSPECIAL_IFC; + } 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; } + private static LambdaForm preparedLambdaForm(MemberName m) { + return preparedLambdaForm(m, null); + } + private static LambdaForm preparedLambdaForm(MethodType mtype, int which) { LambdaForm lform = mtype.form().cachedLambdaForm(which); if (lform != null) return lform; lform = makePreparedLambdaForm(mtype, which); return mtype.form().setCachedLambdaForm(which, lform); } static LambdaForm makePreparedLambdaForm(MethodType mtype, int which) { boolean needsInit = (which == LF_INVSTATIC_INIT); boolean doesAlloc = (which == LF_NEWINVSPECIAL); ! boolean needsReceiverCheck = (which == LF_INVINTERFACE || ! which == LF_INVSPECIAL_IFC); ! String linkerName; LambdaForm.Kind kind; switch (which) { case LF_INVVIRTUAL: linkerName = "linkToVirtual"; kind = DIRECT_INVOKE_VIRTUAL; break; case LF_INVSTATIC: linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC; break; case LF_INVSTATIC_INIT:linkerName = "linkToStatic"; kind = DIRECT_INVOKE_STATIC_INIT; break; + case LF_INVSPECIAL_IFC:linkerName = "linkToSpecial"; kind = DIRECT_INVOKE_SPECIAL_IFC; break; case LF_INVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_INVOKE_SPECIAL; break; case LF_INVINTERFACE: linkerName = "linkToInterface"; kind = DIRECT_INVOKE_INTERFACE; break; case LF_NEWINVSPECIAL: linkerName = "linkToSpecial"; kind = DIRECT_NEW_INVOKE_SPECIAL; break; default: throw new InternalError("which="+which); }
*** 374,393 **** ((DirectMethodHandle)mh).ensureInitialized(); } /** This subclass represents invokespecial instructions. */ static class Special extends DirectMethodHandle { ! private Special(MethodType mtype, LambdaForm form, MemberName member) { super(mtype, form, member); } @Override boolean isInvokeSpecial() { return true; } @Override MethodHandle copyWith(MethodType mt, LambdaForm lf) { ! return new Special(mt, lf, member); } } /** This subclass represents invokeinterface instructions. */ static class Interface extends DirectMethodHandle { --- 388,417 ---- ((DirectMethodHandle)mh).ensureInitialized(); } /** This subclass represents invokespecial instructions. */ static class Special extends DirectMethodHandle { ! private final Class<?> caller; ! private Special(MethodType mtype, LambdaForm form, MemberName member, Class<?> caller) { super(mtype, form, member); + this.caller = caller; } @Override boolean isInvokeSpecial() { return true; } @Override MethodHandle copyWith(MethodType mt, LambdaForm lf) { ! return new Special(mt, lf, member, caller); ! } ! Object checkReceiver(Object recv) { ! if (!caller.isInstance(recv)) { ! String msg = String.format("Receiver class %s is not a subclass of caller class %s", ! recv.getClass().getName(), caller.getName()); ! throw new IncompatibleClassChangeError(msg); ! } ! return recv; } } /** This subclass represents invokeinterface instructions. */ static class Interface extends DirectMethodHandle {
*** 399,419 **** } @Override MethodHandle copyWith(MethodType mt, LambdaForm lf) { return new Interface(mt, lf, member, refc); } ! Object checkReceiver(Object recv) { if (!refc.isInstance(recv)) { ! String msg = String.format("Class %s does not implement the requested interface %s", recv.getClass().getName(), refc.getName()); throw new IncompatibleClassChangeError(msg); } return recv; } } /** This subclass handles constructor references. */ static class Constructor extends DirectMethodHandle { final MemberName initMethod; final Class<?> instanceClass; --- 423,449 ---- } @Override MethodHandle copyWith(MethodType mt, LambdaForm lf) { return new Interface(mt, lf, member, refc); } ! @Override Object checkReceiver(Object recv) { if (!refc.isInstance(recv)) { ! String msg = String.format("Receiver class %s does not implement the requested interface %s", recv.getClass().getName(), refc.getName()); throw new IncompatibleClassChangeError(msg); } return recv; } } + /** Used for interface receiver type checks, by Interface and Special modes. */ + Object checkReceiver(Object recv) { + throw new InternalError("Should only be invoked on a subclass"); + } + + /** This subclass handles constructor references. */ static class Constructor extends DirectMethodHandle { final MemberName initMethod; final Class<?> instanceClass;
*** 821,834 **** MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getField); return new NamedFunction( MemberName.getFactory() .resolveOrFail(REF_getField, member, DirectMethodHandle.class, NoSuchMethodException.class)); case NF_checkReceiver: ! member = new MemberName(Interface.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual); return new NamedFunction( MemberName.getFactory() ! .resolveOrFail(REF_invokeVirtual, member, Interface.class, NoSuchMethodException.class)); default: throw newInternalError("Unknown function: " + func); } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); --- 851,864 ---- MemberName member = new MemberName(MethodHandleStatics.class, "UNSAFE", Unsafe.class, REF_getField); return new NamedFunction( MemberName.getFactory() .resolveOrFail(REF_getField, member, DirectMethodHandle.class, NoSuchMethodException.class)); case NF_checkReceiver: ! member = new MemberName(DirectMethodHandle.class, "checkReceiver", OBJ_OBJ_TYPE, REF_invokeVirtual); return new NamedFunction( MemberName.getFactory() ! .resolveOrFail(REF_invokeVirtual, member, DirectMethodHandle.class, NoSuchMethodException.class)); default: throw newInternalError("Unknown function: " + func); } } catch (ReflectiveOperationException ex) { throw newInternalError(ex);
< prev index next >