1.1 --- a/rt/emul/compact/src/main/java/java/lang/invoke/InnerClassLambdaMetafactory.java Sun Aug 10 06:21:50 2014 +0200
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,551 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package java.lang.invoke;
1.30 -
1.31 -import jdk.internal.org.objectweb.asm.*;
1.32 -import sun.invoke.util.BytecodeDescriptor;
1.33 -import sun.misc.Unsafe;
1.34 -import sun.security.action.GetPropertyAction;
1.35 -
1.36 -import java.io.FilePermission;
1.37 -import java.io.Serializable;
1.38 -import java.lang.reflect.Constructor;
1.39 -import java.security.AccessController;
1.40 -import java.security.PrivilegedAction;
1.41 -import java.util.LinkedHashSet;
1.42 -import java.util.concurrent.atomic.AtomicInteger;
1.43 -import java.util.PropertyPermission;
1.44 -import java.util.Set;
1.45 -
1.46 -import static jdk.internal.org.objectweb.asm.Opcodes.*;
1.47 -
1.48 -/**
1.49 - * Lambda metafactory implementation which dynamically creates an
1.50 - * inner-class-like class per lambda callsite.
1.51 - *
1.52 - * @see LambdaMetafactory
1.53 - */
1.54 -/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
1.55 - private static final Unsafe UNSAFE = Unsafe.getUnsafe();
1.56 -
1.57 - private static final int CLASSFILE_VERSION = 52;
1.58 - private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
1.59 - private static final String JAVA_LANG_OBJECT = "java/lang/Object";
1.60 - private static final String NAME_CTOR = "<init>";
1.61 - private static final String NAME_FACTORY = "get$Lambda";
1.62 -
1.63 - //Serialization support
1.64 - private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
1.65 - private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException";
1.66 - private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
1.67 - private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V";
1.68 - private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V";
1.69 - private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
1.70 - private static final String NAME_METHOD_READ_OBJECT = "readObject";
1.71 - private static final String NAME_METHOD_WRITE_OBJECT = "writeObject";
1.72 - private static final String DESCR_CTOR_SERIALIZED_LAMBDA
1.73 - = MethodType.methodType(void.class,
1.74 - Class.class,
1.75 - String.class, String.class, String.class,
1.76 - int.class, String.class, String.class, String.class,
1.77 - String.class,
1.78 - Object[].class).toMethodDescriptorString();
1.79 - private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION
1.80 - = MethodType.methodType(void.class, String.class).toMethodDescriptorString();
1.81 - private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION};
1.82 -
1.83 -
1.84 - private static final String[] EMPTY_STRING_ARRAY = new String[0];
1.85 -
1.86 - // Used to ensure that each spun class name is unique
1.87 - private static final AtomicInteger counter = new AtomicInteger(0);
1.88 -
1.89 -
1.90 - // See context values in AbstractValidatingLambdaMetafactory
1.91 - private final String implMethodClassName; // Name of type containing implementation "CC"
1.92 - private final String implMethodName; // Name of implementation method "impl"
1.93 - private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;"
1.94 - private final Class<?> implMethodReturnClass; // class for implementaion method return type "Ljava/lang/String;"
1.95 - private final MethodType constructorType; // Generated class constructor type "(CC)void"
1.96 - private final ClassWriter cw; // ASM class writer
1.97 - private final String[] argNames; // Generated names for the constructor arguments
1.98 - private final String[] argDescs; // Type descriptors for the constructor arguments
1.99 - private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1"
1.100 -
1.101 - /**
1.102 - * General meta-factory constructor, supporting both standard cases and
1.103 - * allowing for uncommon options such as serialization or bridging.
1.104 - *
1.105 - * @param caller Stacked automatically by VM; represents a lookup context
1.106 - * with the accessibility privileges of the caller.
1.107 - * @param invokedType Stacked automatically by VM; the signature of the
1.108 - * invoked method, which includes the expected static
1.109 - * type of the returned lambda object, and the static
1.110 - * types of the captured arguments for the lambda. In
1.111 - * the event that the implementation method is an
1.112 - * instance method, the first argument in the invocation
1.113 - * signature will correspond to the receiver.
1.114 - * @param samMethodName Name of the method in the functional interface to
1.115 - * which the lambda or method reference is being
1.116 - * converted, represented as a String.
1.117 - * @param samMethodType Type of the method in the functional interface to
1.118 - * which the lambda or method reference is being
1.119 - * converted, represented as a MethodType.
1.120 - * @param implMethod The implementation method which should be called (with
1.121 - * suitable adaptation of argument types, return types,
1.122 - * and adjustment for captured arguments) when methods of
1.123 - * the resulting functional interface instance are invoked.
1.124 - * @param instantiatedMethodType The signature of the primary functional
1.125 - * interface method after type variables are
1.126 - * substituted with their instantiation from
1.127 - * the capture site
1.128 - * @param isSerializable Should the lambda be made serializable? If set,
1.129 - * either the target type or one of the additional SAM
1.130 - * types must extend {@code Serializable}.
1.131 - * @param markerInterfaces Additional interfaces which the lambda object
1.132 - * should implement.
1.133 - * @param additionalBridges Method types for additional signatures to be
1.134 - * bridged to the implementation method
1.135 - * @throws LambdaConversionException If any of the meta-factory protocol
1.136 - * invariants are violated
1.137 - */
1.138 - public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
1.139 - MethodType invokedType,
1.140 - String samMethodName,
1.141 - MethodType samMethodType,
1.142 - MethodHandle implMethod,
1.143 - MethodType instantiatedMethodType,
1.144 - boolean isSerializable,
1.145 - Class<?>[] markerInterfaces,
1.146 - MethodType[] additionalBridges)
1.147 - throws LambdaConversionException {
1.148 - super(caller, invokedType, samMethodName, samMethodType,
1.149 - implMethod, instantiatedMethodType,
1.150 - isSerializable, markerInterfaces, additionalBridges);
1.151 - implMethodClassName = implDefiningClass.getName().replace('.', '/');
1.152 - implMethodName = implInfo.getName();
1.153 - implMethodDesc = implMethodType.toMethodDescriptorString();
1.154 - implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
1.155 - ? implDefiningClass
1.156 - : implMethodType.returnType();
1.157 - constructorType = invokedType.changeReturnType(Void.TYPE);
1.158 - lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
1.159 - cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
1.160 - int parameterCount = invokedType.parameterCount();
1.161 - if (parameterCount > 0) {
1.162 - argNames = new String[parameterCount];
1.163 - argDescs = new String[parameterCount];
1.164 - for (int i = 0; i < parameterCount; i++) {
1.165 - argNames[i] = "arg$" + (i + 1);
1.166 - argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i));
1.167 - }
1.168 - } else {
1.169 - argNames = argDescs = EMPTY_STRING_ARRAY;
1.170 - }
1.171 - }
1.172 -
1.173 - /**
1.174 - * Build the CallSite. Generate a class file which implements the functional
1.175 - * interface, define the class, if there are no parameters create an instance
1.176 - * of the class which the CallSite will return, otherwise, generate handles
1.177 - * which will call the class' constructor.
1.178 - *
1.179 - * @return a CallSite, which, when invoked, will return an instance of the
1.180 - * functional interface
1.181 - * @throws ReflectiveOperationException
1.182 - * @throws LambdaConversionException If properly formed functional interface
1.183 - * is not found
1.184 - */
1.185 - @Override
1.186 - CallSite buildCallSite() throws LambdaConversionException {
1.187 - final Class<?> innerClass = spinInnerClass();
1.188 - if (invokedType.parameterCount() == 0) {
1.189 - final Constructor[] ctrs = AccessController.doPrivileged(
1.190 - new PrivilegedAction<Constructor[]>() {
1.191 - @Override
1.192 - public Constructor[] run() {
1.193 - Constructor<?>[] ctrs = innerClass.getDeclaredConstructors();
1.194 - if (ctrs.length == 1) {
1.195 - // The lambda implementing inner class constructor is private, set
1.196 - // it accessible (by us) before creating the constant sole instance
1.197 - ctrs[0].setAccessible(true);
1.198 - }
1.199 - return ctrs;
1.200 - }
1.201 - });
1.202 - if (ctrs.length != 1) {
1.203 - throw new LambdaConversionException("Expected one lambda constructor for "
1.204 - + innerClass.getCanonicalName() + ", got " + ctrs.length);
1.205 - }
1.206 -
1.207 - try {
1.208 - Object inst = ctrs[0].newInstance();
1.209 - return new ConstantCallSite(MethodHandles.constant(samBase, inst));
1.210 - }
1.211 - catch (ReflectiveOperationException e) {
1.212 - throw new LambdaConversionException("Exception instantiating lambda object", e);
1.213 - }
1.214 - } else {
1.215 - try {
1.216 - UNSAFE.ensureClassInitialized(innerClass);
1.217 - return new ConstantCallSite(
1.218 - MethodHandles.Lookup.IMPL_LOOKUP
1.219 - .findStatic(innerClass, NAME_FACTORY, invokedType));
1.220 - }
1.221 - catch (ReflectiveOperationException e) {
1.222 - throw new LambdaConversionException("Exception finding constructor", e);
1.223 - }
1.224 - }
1.225 - }
1.226 -
1.227 - /**
1.228 - * Generate a class file which implements the functional
1.229 - * interface, define and return the class.
1.230 - *
1.231 - * @implNote The class that is generated does not include signature
1.232 - * information for exceptions that may be present on the SAM method.
1.233 - * This is to reduce classfile size, and is harmless as checked exceptions
1.234 - * are erased anyway, no one will ever compile against this classfile,
1.235 - * and we make no guarantees about the reflective properties of lambda
1.236 - * objects.
1.237 - *
1.238 - * @return a Class which implements the functional interface
1.239 - * @throws LambdaConversionException If properly formed functional interface
1.240 - * is not found
1.241 - */
1.242 - private Class<?> spinInnerClass() throws LambdaConversionException {
1.243 - String[] interfaces;
1.244 - String samIntf = samBase.getName().replace('.', '/');
1.245 - boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);
1.246 - if (markerInterfaces.length == 0) {
1.247 - interfaces = new String[]{samIntf};
1.248 - } else {
1.249 - // Assure no duplicate interfaces (ClassFormatError)
1.250 - Set<String> itfs = new LinkedHashSet<>(markerInterfaces.length + 1);
1.251 - itfs.add(samIntf);
1.252 - for (Class<?> markerInterface : markerInterfaces) {
1.253 - itfs.add(markerInterface.getName().replace('.', '/'));
1.254 - accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface);
1.255 - }
1.256 - interfaces = itfs.toArray(new String[itfs.size()]);
1.257 - }
1.258 -
1.259 - cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
1.260 - lambdaClassName, null,
1.261 - JAVA_LANG_OBJECT, interfaces);
1.262 -
1.263 - // Generate final fields to be filled in by constructor
1.264 - for (int i = 0; i < argDescs.length; i++) {
1.265 - FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL,
1.266 - argNames[i],
1.267 - argDescs[i],
1.268 - null, null);
1.269 - fv.visitEnd();
1.270 - }
1.271 -
1.272 - generateConstructor();
1.273 -
1.274 - if (invokedType.parameterCount() != 0) {
1.275 - generateFactory();
1.276 - }
1.277 -
1.278 - // Forward the SAM method
1.279 - MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName,
1.280 - samMethodType.toMethodDescriptorString(), null, null);
1.281 - new ForwardingMethodGenerator(mv).generate(samMethodType);
1.282 -
1.283 - // Forward the bridges
1.284 - if (additionalBridges != null) {
1.285 - for (MethodType mt : additionalBridges) {
1.286 - mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName,
1.287 - mt.toMethodDescriptorString(), null, null);
1.288 - new ForwardingMethodGenerator(mv).generate(mt);
1.289 - }
1.290 - }
1.291 -
1.292 - if (isSerializable)
1.293 - generateSerializationFriendlyMethods();
1.294 - else if (accidentallySerializable)
1.295 - generateSerializationHostileMethods();
1.296 -
1.297 - cw.visitEnd();
1.298 -
1.299 - // Define the generated class in this VM.
1.300 -
1.301 - final byte[] classBytes = cw.toByteArray();
1.302 -
1.303 - // If requested, dump out to a file for debugging purposes
1.304 - if (dumper != null) {
1.305 - AccessController.doPrivileged(new PrivilegedAction<Void>() {
1.306 - @Override
1.307 - public Void run() {
1.308 - dumper.dumpClass(lambdaClassName, classBytes);
1.309 - return null;
1.310 - }
1.311 - }, null,
1.312 - new FilePermission("<<ALL FILES>>", "read, write"),
1.313 - // createDirectories may need it
1.314 - new PropertyPermission("user.dir", "read"));
1.315 - }
1.316 -
1.317 - return UNSAFE.defineAnonymousClass(targetClass, classBytes, null);
1.318 - }
1.319 -
1.320 - /**
1.321 - * Generate the factory method for the class
1.322 - */
1.323 - private void generateFactory() {
1.324 - MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null);
1.325 - m.visitCode();
1.326 - m.visitTypeInsn(NEW, lambdaClassName);
1.327 - m.visitInsn(Opcodes.DUP);
1.328 - int parameterCount = invokedType.parameterCount();
1.329 - for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) {
1.330 - Class<?> argType = invokedType.parameterType(typeIndex);
1.331 - m.visitVarInsn(getLoadOpcode(argType), varIndex);
1.332 - varIndex += getParameterSize(argType);
1.333 - }
1.334 - m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString());
1.335 - m.visitInsn(ARETURN);
1.336 - m.visitMaxs(-1, -1);
1.337 - m.visitEnd();
1.338 - }
1.339 -
1.340 - /**
1.341 - * Generate the constructor for the class
1.342 - */
1.343 - private void generateConstructor() {
1.344 - // Generate constructor
1.345 - MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR,
1.346 - constructorType.toMethodDescriptorString(), null, null);
1.347 - ctor.visitCode();
1.348 - ctor.visitVarInsn(ALOAD, 0);
1.349 - ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR,
1.350 - METHOD_DESCRIPTOR_VOID);
1.351 - int parameterCount = invokedType.parameterCount();
1.352 - for (int i = 0, lvIndex = 0; i < parameterCount; i++) {
1.353 - ctor.visitVarInsn(ALOAD, 0);
1.354 - Class<?> argType = invokedType.parameterType(i);
1.355 - ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
1.356 - lvIndex += getParameterSize(argType);
1.357 - ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]);
1.358 - }
1.359 - ctor.visitInsn(RETURN);
1.360 - // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
1.361 - ctor.visitMaxs(-1, -1);
1.362 - ctor.visitEnd();
1.363 - }
1.364 -
1.365 - /**
1.366 - * Generate a writeReplace method that supports serialization
1.367 - */
1.368 - private void generateSerializationFriendlyMethods() {
1.369 - TypeConvertingMethodAdapter mv
1.370 - = new TypeConvertingMethodAdapter(
1.371 - cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
1.372 - NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
1.373 - null, null));
1.374 -
1.375 - mv.visitCode();
1.376 - mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
1.377 - mv.visitInsn(DUP);
1.378 - mv.visitLdcInsn(Type.getType(targetClass));
1.379 - mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/'));
1.380 - mv.visitLdcInsn(samMethodName);
1.381 - mv.visitLdcInsn(samMethodType.toMethodDescriptorString());
1.382 - mv.visitLdcInsn(implInfo.getReferenceKind());
1.383 - mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/'));
1.384 - mv.visitLdcInsn(implInfo.getName());
1.385 - mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString());
1.386 - mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString());
1.387 - mv.iconst(argDescs.length);
1.388 - mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT);
1.389 - for (int i = 0; i < argDescs.length; i++) {
1.390 - mv.visitInsn(DUP);
1.391 - mv.iconst(i);
1.392 - mv.visitVarInsn(ALOAD, 0);
1.393 - mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
1.394 - mv.boxIfTypePrimitive(Type.getType(argDescs[i]));
1.395 - mv.visitInsn(AASTORE);
1.396 - }
1.397 - mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
1.398 - DESCR_CTOR_SERIALIZED_LAMBDA);
1.399 - mv.visitInsn(ARETURN);
1.400 - // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
1.401 - mv.visitMaxs(-1, -1);
1.402 - mv.visitEnd();
1.403 - }
1.404 -
1.405 - /**
1.406 - * Generate a readObject/writeObject method that is hostile to serialization
1.407 - */
1.408 - private void generateSerializationHostileMethods() {
1.409 - MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
1.410 - NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT,
1.411 - null, SER_HOSTILE_EXCEPTIONS);
1.412 - mv.visitCode();
1.413 - mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
1.414 - mv.visitInsn(DUP);
1.415 - mv.visitLdcInsn("Non-serializable lambda");
1.416 - mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
1.417 - DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
1.418 - mv.visitInsn(ATHROW);
1.419 - mv.visitMaxs(-1, -1);
1.420 - mv.visitEnd();
1.421 -
1.422 - mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
1.423 - NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT,
1.424 - null, SER_HOSTILE_EXCEPTIONS);
1.425 - mv.visitCode();
1.426 - mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION);
1.427 - mv.visitInsn(DUP);
1.428 - mv.visitLdcInsn("Non-serializable lambda");
1.429 - mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR,
1.430 - DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION);
1.431 - mv.visitInsn(ATHROW);
1.432 - mv.visitMaxs(-1, -1);
1.433 - mv.visitEnd();
1.434 - }
1.435 -
1.436 - /**
1.437 - * This class generates a method body which calls the lambda implementation
1.438 - * method, converting arguments, as needed.
1.439 - */
1.440 - private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {
1.441 -
1.442 - ForwardingMethodGenerator(MethodVisitor mv) {
1.443 - super(mv);
1.444 - }
1.445 -
1.446 - void generate(MethodType methodType) {
1.447 - visitCode();
1.448 -
1.449 - if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
1.450 - visitTypeInsn(NEW, implMethodClassName);
1.451 - visitInsn(DUP);
1.452 - }
1.453 - for (int i = 0; i < argNames.length; i++) {
1.454 - visitVarInsn(ALOAD, 0);
1.455 - visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]);
1.456 - }
1.457 -
1.458 - convertArgumentTypes(methodType);
1.459 -
1.460 - // Invoke the method we want to forward to
1.461 - visitMethodInsn(invocationOpcode(), implMethodClassName,
1.462 - implMethodName, implMethodDesc,
1.463 - implDefiningClass.isInterface());
1.464 -
1.465 - // Convert the return value (if any) and return it
1.466 - // Note: if adapting from non-void to void, the 'return'
1.467 - // instruction will pop the unneeded result
1.468 - Class<?> samReturnClass = methodType.returnType();
1.469 - convertType(implMethodReturnClass, samReturnClass, samReturnClass);
1.470 - visitInsn(getReturnOpcode(samReturnClass));
1.471 - // Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
1.472 - visitMaxs(-1, -1);
1.473 - visitEnd();
1.474 - }
1.475 -
1.476 - private void convertArgumentTypes(MethodType samType) {
1.477 - int lvIndex = 0;
1.478 - boolean samIncludesReceiver = implIsInstanceMethod &&
1.479 - invokedType.parameterCount() == 0;
1.480 - int samReceiverLength = samIncludesReceiver ? 1 : 0;
1.481 - if (samIncludesReceiver) {
1.482 - // push receiver
1.483 - Class<?> rcvrType = samType.parameterType(0);
1.484 - visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1);
1.485 - lvIndex += getParameterSize(rcvrType);
1.486 - convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0));
1.487 - }
1.488 - int samParametersLength = samType.parameterCount();
1.489 - int argOffset = implMethodType.parameterCount() - samParametersLength;
1.490 - for (int i = samReceiverLength; i < samParametersLength; i++) {
1.491 - Class<?> argType = samType.parameterType(i);
1.492 - visitVarInsn(getLoadOpcode(argType), lvIndex + 1);
1.493 - lvIndex += getParameterSize(argType);
1.494 - convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i));
1.495 - }
1.496 - }
1.497 -
1.498 - private int invocationOpcode() throws InternalError {
1.499 - switch (implKind) {
1.500 - case MethodHandleInfo.REF_invokeStatic:
1.501 - return INVOKESTATIC;
1.502 - case MethodHandleInfo.REF_newInvokeSpecial:
1.503 - return INVOKESPECIAL;
1.504 - case MethodHandleInfo.REF_invokeVirtual:
1.505 - return INVOKEVIRTUAL;
1.506 - case MethodHandleInfo.REF_invokeInterface:
1.507 - return INVOKEINTERFACE;
1.508 - case MethodHandleInfo.REF_invokeSpecial:
1.509 - return INVOKESPECIAL;
1.510 - default:
1.511 - throw new InternalError("Unexpected invocation kind: " + implKind);
1.512 - }
1.513 - }
1.514 - }
1.515 -
1.516 - static int getParameterSize(Class<?> c) {
1.517 - if (c == Void.TYPE) {
1.518 - return 0;
1.519 - } else if (c == Long.TYPE || c == Double.TYPE) {
1.520 - return 2;
1.521 - }
1.522 - return 1;
1.523 - }
1.524 -
1.525 - static int getLoadOpcode(Class<?> c) {
1.526 - if(c == Void.TYPE) {
1.527 - throw new InternalError("Unexpected void type of load opcode");
1.528 - }
1.529 - return ILOAD + getOpcodeOffset(c);
1.530 - }
1.531 -
1.532 - static int getReturnOpcode(Class<?> c) {
1.533 - if(c == Void.TYPE) {
1.534 - return RETURN;
1.535 - }
1.536 - return IRETURN + getOpcodeOffset(c);
1.537 - }
1.538 -
1.539 - private static int getOpcodeOffset(Class<?> c) {
1.540 - if (c.isPrimitive()) {
1.541 - if (c == Long.TYPE) {
1.542 - return 1;
1.543 - } else if (c == Float.TYPE) {
1.544 - return 2;
1.545 - } else if (c == Double.TYPE) {
1.546 - return 3;
1.547 - }
1.548 - return 0;
1.549 - } else {
1.550 - return 4;
1.551 - }
1.552 - }
1.553 -
1.554 -}