14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.misc.Unsafe;
29 import java.lang.reflect.Method;
30 import java.util.Arrays;
31 import sun.invoke.util.VerifyAccess;
32 import static java.lang.invoke.MethodHandleNatives.Constants.*;
33 import static java.lang.invoke.LambdaForm.*;
34 import static java.lang.invoke.MethodTypeForm.*;
35 import static java.lang.invoke.MethodHandleStatics.*;
36 import java.lang.ref.WeakReference;
37 import java.lang.reflect.Field;
38 import sun.invoke.util.ValueConversions;
39 import sun.invoke.util.VerifyType;
40 import sun.invoke.util.Wrapper;
41
42 /**
43 * The flavor of method handle which implements a constant reference
44 * to a class member.
45 * @author jrose
46 */
47 class DirectMethodHandle extends MethodHandle {
48 final MemberName member;
49
50 // Constructors and factory methods in this class *must* be package scoped or private.
51 private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
52 super(mtype, form);
53 if (!member.isResolved()) throw new InternalError();
108 }
109 static DirectMethodHandle make(Method method) {
110 return make(method.getDeclaringClass(), new MemberName(method));
111 }
112 static DirectMethodHandle make(Field field) {
113 return make(field.getDeclaringClass(), new MemberName(field));
114 }
115 private static DirectMethodHandle makeAllocator(MemberName ctor) {
116 assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
117 Class<?> instanceClass = ctor.getDeclaringClass();
118 ctor = ctor.asConstructor();
119 assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
120 MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
121 LambdaForm lform = preparedLambdaForm(ctor);
122 MemberName init = ctor.asSpecial();
123 assert(init.getMethodType().returnType() == void.class);
124 return new Constructor(mtype, lform, ctor, init, instanceClass);
125 }
126
127 @Override
128 MethodHandle copyWith(MethodType mt, LambdaForm lf) {
129 return new DirectMethodHandle(mt, lf, member);
130 }
131
132 @Override
133 String internalProperties() {
134 return "/DMH="+member.toString();
135 }
136
137 //// Implementation methods.
138 @Override
139 MethodHandle viewAsType(MethodType newType) {
140 return new DirectMethodHandle(newType, form, member);
141 }
142 @Override
143 @ForceInline
144 MemberName internalMemberName() {
145 return member;
146 }
147
148 @Override
149 MethodHandle bindArgument(int pos, char basicType, Object value) {
150 // If the member needs dispatching, do so.
151 if (pos == 0 && basicType == 'L') {
152 DirectMethodHandle concrete = maybeRebind(value);
153 if (concrete != null)
154 return concrete.bindReceiver(value);
155 }
156 return super.bindArgument(pos, basicType, value);
157 }
158
159 @Override
160 MethodHandle bindReceiver(Object receiver) {
161 // If the member needs dispatching, do so.
162 DirectMethodHandle concrete = maybeRebind(receiver);
163 if (concrete != null)
164 return concrete.bindReceiver(receiver);
165 return super.bindReceiver(receiver);
166 }
167
168 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
169
170 private DirectMethodHandle maybeRebind(Object receiver) {
171 if (receiver != null) {
257 assert(names.length == nameCursor);
258 if (doesAlloc) {
259 // names = { argx,y,z,... new C, init method }
260 names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]);
261 names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]);
262 } else if (needsInit) {
263 names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]);
264 } else {
265 names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
266 }
267 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
268 assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args!
269 int result = LambdaForm.LAST_RESULT;
270 if (doesAlloc) {
271 assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one
272 System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
273 outArgs[0] = names[NEW_OBJ];
274 result = NEW_OBJ;
275 }
276 names[LINKER_CALL] = new Name(linker, outArgs);
277 lambdaName += "_" + LambdaForm.basicTypeSignature(mtype);
278 LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
279 // This is a tricky bit of code. Don't send it through the LF interpreter.
280 lform.compileToBytecode();
281 return lform;
282 }
283
284 private static void maybeCompile(LambdaForm lform, MemberName m) {
285 if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
286 // Help along bootstrapping...
287 lform.compileToBytecode();
288 }
289
290 /** Static wrapper for DirectMethodHandle.internalMemberName. */
291 @ForceInline
292 /*non-public*/ static Object internalMemberName(Object mh) {
293 return ((DirectMethodHandle)mh).member;
294 }
295
296 /** Static wrapper for DirectMethodHandle.internalMemberName.
297 * This one also forces initialization.
|
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import sun.misc.Unsafe;
29 import java.lang.reflect.Method;
30 import java.util.Arrays;
31 import sun.invoke.util.VerifyAccess;
32 import static java.lang.invoke.MethodHandleNatives.Constants.*;
33 import static java.lang.invoke.LambdaForm.*;
34 import static java.lang.invoke.LambdaForm.BasicType.*;
35 import static java.lang.invoke.MethodTypeForm.*;
36 import static java.lang.invoke.MethodHandleStatics.*;
37 import java.lang.ref.WeakReference;
38 import java.lang.reflect.Field;
39 import sun.invoke.util.ValueConversions;
40 import sun.invoke.util.VerifyType;
41 import sun.invoke.util.Wrapper;
42
43 /**
44 * The flavor of method handle which implements a constant reference
45 * to a class member.
46 * @author jrose
47 */
48 class DirectMethodHandle extends MethodHandle {
49 final MemberName member;
50
51 // Constructors and factory methods in this class *must* be package scoped or private.
52 private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) {
53 super(mtype, form);
54 if (!member.isResolved()) throw new InternalError();
109 }
110 static DirectMethodHandle make(Method method) {
111 return make(method.getDeclaringClass(), new MemberName(method));
112 }
113 static DirectMethodHandle make(Field field) {
114 return make(field.getDeclaringClass(), new MemberName(field));
115 }
116 private static DirectMethodHandle makeAllocator(MemberName ctor) {
117 assert(ctor.isConstructor() && ctor.getName().equals("<init>"));
118 Class<?> instanceClass = ctor.getDeclaringClass();
119 ctor = ctor.asConstructor();
120 assert(ctor.isConstructor() && ctor.getReferenceKind() == REF_newInvokeSpecial) : ctor;
121 MethodType mtype = ctor.getMethodType().changeReturnType(instanceClass);
122 LambdaForm lform = preparedLambdaForm(ctor);
123 MemberName init = ctor.asSpecial();
124 assert(init.getMethodType().returnType() == void.class);
125 return new Constructor(mtype, lform, ctor, init, instanceClass);
126 }
127
128 @Override
129 String internalProperties() {
130 return "/DMH="+member.toString();
131 }
132
133 //// Implementation methods.
134 @Override
135 MethodHandle viewAsType(MethodType newType) {
136 return new DirectMethodHandle(newType, form, member);
137 }
138 @Override
139 @ForceInline
140 MemberName internalMemberName() {
141 return member;
142 }
143
144 @Override
145 MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
146 // If the member needs dispatching, do so.
147 if (pos == 0 && basicType == L_TYPE) {
148 DirectMethodHandle concrete = maybeRebind(value);
149 if (concrete != null)
150 return concrete.bindReceiver(value);
151 }
152 return super.bindArgument(pos, basicType, value);
153 }
154
155 @Override
156 MethodHandle bindReceiver(Object receiver) {
157 // If the member needs dispatching, do so.
158 DirectMethodHandle concrete = maybeRebind(receiver);
159 if (concrete != null)
160 return concrete.bindReceiver(receiver);
161 return super.bindReceiver(receiver);
162 }
163
164 private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory();
165
166 private DirectMethodHandle maybeRebind(Object receiver) {
167 if (receiver != null) {
253 assert(names.length == nameCursor);
254 if (doesAlloc) {
255 // names = { argx,y,z,... new C, init method }
256 names[NEW_OBJ] = new Name(Lazy.NF_allocateInstance, names[DMH_THIS]);
257 names[GET_MEMBER] = new Name(Lazy.NF_constructorMethod, names[DMH_THIS]);
258 } else if (needsInit) {
259 names[GET_MEMBER] = new Name(Lazy.NF_internalMemberNameEnsureInit, names[DMH_THIS]);
260 } else {
261 names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]);
262 }
263 Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class);
264 assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args!
265 int result = LambdaForm.LAST_RESULT;
266 if (doesAlloc) {
267 assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one
268 System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2);
269 outArgs[0] = names[NEW_OBJ];
270 result = NEW_OBJ;
271 }
272 names[LINKER_CALL] = new Name(linker, outArgs);
273 lambdaName += "_" + shortenSignature(basicTypeSignature(mtype));
274 LambdaForm lform = new LambdaForm(lambdaName, ARG_LIMIT, names, result);
275 // This is a tricky bit of code. Don't send it through the LF interpreter.
276 lform.compileToBytecode();
277 return lform;
278 }
279
280 private static void maybeCompile(LambdaForm lform, MemberName m) {
281 if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class))
282 // Help along bootstrapping...
283 lform.compileToBytecode();
284 }
285
286 /** Static wrapper for DirectMethodHandle.internalMemberName. */
287 @ForceInline
288 /*non-public*/ static Object internalMemberName(Object mh) {
289 return ((DirectMethodHandle)mh).member;
290 }
291
292 /** Static wrapper for DirectMethodHandle.internalMemberName.
293 * This one also forces initialization.
|