jdk/src/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
author darcy
Thu, 27 Jun 2013 19:02:02 -0700
changeset 18569 0e46c17766b7
parent 18556 0fe397a41c18
child 18716 9723e722b955
permissions -rw-r--r--
8019357: Fix doclint warnings in java.lang.invoke Reviewed-by: jrose
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     1
/*
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     2
 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     4
 *
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    10
 *
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    15
 * accompanied this code).
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    16
 *
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    20
 *
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    23
 * questions.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    24
 */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    25
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    26
package java.lang.invoke;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    27
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    28
import java.lang.reflect.Constructor;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    29
import java.lang.reflect.Method;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    30
import java.security.ProtectionDomain;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    31
import java.util.concurrent.atomic.AtomicInteger;
18182
a86f1b828425 8015402: Lambda metafactory should not attempt to determine bridge methods
rfield
parents: 16859
diff changeset
    32
import jdk.internal.org.objectweb.asm.*;
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    33
import static jdk.internal.org.objectweb.asm.Opcodes.*;
18182
a86f1b828425 8015402: Lambda metafactory should not attempt to determine bridge methods
rfield
parents: 16859
diff changeset
    34
import sun.misc.Unsafe;
a86f1b828425 8015402: Lambda metafactory should not attempt to determine bridge methods
rfield
parents: 16859
diff changeset
    35
import java.security.AccessController;
a86f1b828425 8015402: Lambda metafactory should not attempt to determine bridge methods
rfield
parents: 16859
diff changeset
    36
import java.security.PrivilegedAction;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    37
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    38
/**
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    39
 * Lambda metafactory implementation which dynamically creates an inner-class-like class per lambda callsite.
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    40
 *
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    41
 * @see LambdaMetafactory
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    42
 */
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    43
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory {
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    44
    private static final int CLASSFILE_VERSION = 51;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    45
    private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    46
    private static final String NAME_MAGIC_ACCESSOR_IMPL = "java/lang/invoke/MagicLambdaImpl";
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    47
    private static final String NAME_CTOR = "<init>";
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    48
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    49
    //Serialization support
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    50
    private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda";
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    51
    private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;";
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    52
    private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace";
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    53
    private static final String NAME_OBJECT = "java/lang/Object";
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    54
    private static final String DESCR_CTOR_SERIALIZED_LAMBDA
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    55
            = MethodType.methodType(void.class,
16034
cb5fbea1ecec 8008770: SerializedLambda incorrect class loader for lambda deserializing class
rfield
parents: 16001
diff changeset
    56
                                    Class.class,
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    57
                                    int.class, String.class, String.class, String.class,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    58
                                    int.class, String.class, String.class, String.class,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    59
                                    String.class,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
    60
                                    Object[].class).toMethodDescriptorString();
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    61
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    62
    // Used to ensure that each spun class name is unique
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    63
    private static final AtomicInteger counter = new AtomicInteger(0);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    64
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    65
    // See context values in AbstractValidatingLambdaMetafactory
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    66
    private final String implMethodClassName;        // Name of type containing implementation "CC"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    67
    private final String implMethodName;             // Name of implementation method "impl"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    68
    private final String implMethodDesc;             // Type descriptor for implementation methods "(I)Ljava/lang/String;"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    69
    private final Type[] implMethodArgumentTypes;    // ASM types for implementaion method parameters
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    70
    private final Type implMethodReturnType;         // ASM type for implementaion method return type "Ljava/lang/String;"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    71
    private final MethodType constructorType;        // Generated class constructor type "(CC)void"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    72
    private final String constructorDesc;            // Type descriptor for constructor "(LCC;)V"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    73
    private final ClassWriter cw;                    // ASM class writer
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    74
    private final Type[] argTypes;                   // ASM types for the constructor arguments
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    75
    private final String[] argNames;                 // Generated names for the constructor arguments
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    76
    private final String lambdaClassName;            // Generated name for the generated class "X$$Lambda$1"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    77
    private final Type[] instantiatedArgumentTypes;  // ASM types for the functional interface arguments
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    78
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    79
    /**
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    80
     * General meta-factory constructor, standard cases and allowing for uncommon options such as serialization.
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    81
     *
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    82
     * @param caller Stacked automatically by VM; represents a lookup context with the accessibility privileges
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    83
     *               of the caller.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    84
     * @param invokedType Stacked automatically by VM; the signature of the invoked method, which includes the
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    85
     *                    expected static type of the returned lambda object, and the static types of the captured
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    86
     *                    arguments for the lambda.  In the event that the implementation method is an instance method,
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    87
     *                    the first argument in the invocation signature will correspond to the receiver.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    88
     * @param samMethod The primary method in the functional interface to which the lambda or method reference is
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    89
     *                  being converted, represented as a method handle.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    90
     * @param implMethod The implementation method which should be called (with suitable adaptation of argument
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    91
     *                   types, return types, and adjustment for captured arguments) when methods of the resulting
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    92
     *                   functional interface instance are invoked.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    93
     * @param instantiatedMethodType The signature of the primary functional interface method after type variables
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    94
     *                               are substituted with their instantiation from the capture site
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    95
     * @param flags A bitmask containing flags that may influence the translation of this lambda expression.  Defined
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    96
     *              fields include FLAG_SERIALIZABLE.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    97
     * @param markerInterfaces Additional interfaces which the lambda object should implement.
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    98
     * @throws ReflectiveOperationException
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    99
     * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   100
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   101
    public InnerClassLambdaMetafactory(MethodHandles.Lookup caller,
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   102
                                       MethodType invokedType,
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   103
                                       MethodHandle samMethod,
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   104
                                       MethodHandle implMethod,
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   105
                                       MethodType instantiatedMethodType,
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   106
                                       int flags,
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   107
                                       Class<?>[] markerInterfaces)
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   108
            throws ReflectiveOperationException, LambdaConversionException {
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   109
        super(caller, invokedType, samMethod, implMethod, instantiatedMethodType, flags, markerInterfaces);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   110
        implMethodClassName = implDefiningClass.getName().replace('.', '/');
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   111
        implMethodName = implInfo.getName();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   112
        implMethodDesc = implMethodType.toMethodDescriptorString();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   113
        Type implMethodAsmType = Type.getMethodType(implMethodDesc);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   114
        implMethodArgumentTypes = implMethodAsmType.getArgumentTypes();
18556
0fe397a41c18 8016761: Lambda metafactory - incorrect type conversion of constructor method handle
rfield
parents: 18284
diff changeset
   115
        implMethodReturnType = (implKind == MethodHandleInfo.REF_newInvokeSpecial)
0fe397a41c18 8016761: Lambda metafactory - incorrect type conversion of constructor method handle
rfield
parents: 18284
diff changeset
   116
                ? Type.getObjectType(implMethodClassName)
0fe397a41c18 8016761: Lambda metafactory - incorrect type conversion of constructor method handle
rfield
parents: 18284
diff changeset
   117
                : implMethodAsmType.getReturnType();
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   118
        constructorType = invokedType.changeReturnType(Void.TYPE);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   119
        constructorDesc = constructorType.toMethodDescriptorString();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   120
        lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   121
        cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   122
        argTypes = Type.getArgumentTypes(constructorDesc);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   123
        argNames = new String[argTypes.length];
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   124
        for (int i = 0; i < argTypes.length; i++) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   125
            argNames[i] = "arg$" + (i + 1);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   126
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   127
        instantiatedArgumentTypes = Type.getArgumentTypes(instantiatedMethodType.toMethodDescriptorString());
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   128
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   129
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   130
    /**
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   131
     * Build the CallSite. Generate a class file which implements the functional
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   132
     * interface, define the class, if there are no parameters create an instance
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   133
     * of the class which the CallSite will return, otherwise, generate handles
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   134
     * which will call the class' constructor.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   135
     *
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   136
     * @return a CallSite, which, when invoked, will return an instance of the
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   137
     * functional interface
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   138
     * @throws ReflectiveOperationException
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   139
     * @throws LambdaConversionException If properly formed functional interface is not found
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   140
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   141
    @Override
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   142
    CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   143
        final Class<?> innerClass = spinInnerClass();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   144
        if (invokedType.parameterCount() == 0) {
14762
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   145
            final Constructor[] ctrs = AccessController.doPrivileged(
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   146
                    new PrivilegedAction<Constructor[]>() {
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   147
                @Override
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   148
                public Constructor[] run() {
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   149
                    return innerClass.getDeclaredConstructors();
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   150
                }
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   151
            });
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   152
            if (ctrs.length != 1) {
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   153
                throw new ReflectiveOperationException("Expected one lambda constructor for "
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   154
                        + innerClass.getCanonicalName() + ", got " + ctrs.length);
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   155
            }
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   156
            // The lambda implementing inner class constructor is private, set
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   157
            // it accessible (by us) before creating the constant sole instance
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   158
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   159
                @Override
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   160
                public Void run() {
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   161
                    ctrs[0].setAccessible(true);
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   162
                    return null;
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   163
                }
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   164
            });
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   165
            Object inst = ctrs[0].newInstance();
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   166
            return new ConstantCallSite(MethodHandles.constant(samBase, inst));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   167
        } else {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   168
            return new ConstantCallSite(
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   169
                    MethodHandles.Lookup.IMPL_LOOKUP
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   170
                                        .findConstructor(innerClass, constructorType)
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   171
                                        .asType(constructorType.changeReturnType(samBase)));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   172
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   173
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   174
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   175
    /**
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   176
     * Generate a class file which implements the functional
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   177
     * interface, define and return the class.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   178
     *
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   179
     * @return a Class which implements the functional interface
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   180
     * @throws LambdaConversionException If properly formed functional interface is not found
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   181
     */
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   182
    private Class<?> spinInnerClass() throws LambdaConversionException {
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   183
        String samName = samBase.getName().replace('.', '/');
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   184
        String[] interfaces = new String[markerInterfaces.length + 1];
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   185
        interfaces[0] = samName;
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   186
        for (int i=0; i<markerInterfaces.length; i++) {
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   187
            interfaces[i+1] = markerInterfaces[i].getName().replace('.', '/');
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   188
        }
16859
45fbee947921 8012028: Metafactory-generated lambda classes should be final
rfield
parents: 16854
diff changeset
   189
        cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   190
                 lambdaClassName, null,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   191
                 NAME_MAGIC_ACCESSOR_IMPL, interfaces);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   192
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   193
        // Generate final fields to be filled in by constructor
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   194
        for (int i = 0; i < argTypes.length; i++) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   195
            FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, argNames[i], argTypes[i].getDescriptor(),
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   196
                                            null, null);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   197
            fv.visitEnd();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   198
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   199
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   200
        generateConstructor();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   201
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   202
        MethodAnalyzer ma = new MethodAnalyzer();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   203
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   204
        // Forward the SAM method
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   205
        if (ma.getSamMethod() == null) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   206
            throw new LambdaConversionException(String.format("Functional interface method not found: %s", samMethodType));
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   207
        } else {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   208
            generateForwardingMethod(ma.getSamMethod(), false);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   209
        }
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   210
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   211
        // Forward the bridges
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   212
        // @@@ The commented-out code is temporary, pending the VM's ability to bridge all methods on request
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   213
        // @@@ Once the VM can do fail-over, uncomment the !ma.wasDefaultMethodFound() test, and emit the appropriate
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   214
        // @@@ classfile attribute to request custom bridging.  See 8002092.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   215
        if (!ma.getMethodsToBridge().isEmpty() /* && !ma.conflictFoundBetweenDefaultAndBridge() */ ) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   216
            for (Method m : ma.getMethodsToBridge()) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   217
                generateForwardingMethod(m, true);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   218
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   219
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   220
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   221
        if (isSerializable) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   222
            generateWriteReplace();
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   223
        }
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   224
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   225
        cw.visitEnd();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   226
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   227
        // Define the generated class in this VM.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   228
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   229
        final byte[] classBytes = cw.toByteArray();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   230
14762
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   231
        /*** Uncomment to dump the generated file
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   232
            System.out.printf("Loaded: %s (%d bytes) %n", lambdaClassName, classBytes.length);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   233
            try (FileOutputStream fos = new FileOutputStream(lambdaClassName.replace('/', '.') + ".class")) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   234
                fos.write(classBytes);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   235
            } catch (IOException ex) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   236
                PlatformLogger.getLogger(InnerClassLambdaMetafactory.class.getName()).severe(ex.getMessage(), ex);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   237
            }
14762
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   238
        ***/
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   239
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   240
        ClassLoader loader = targetClass.getClassLoader();
14762
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   241
        ProtectionDomain pd = (loader == null)
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   242
            ? null
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   243
            : AccessController.doPrivileged(
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   244
            new PrivilegedAction<ProtectionDomain>() {
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   245
                @Override
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   246
                public ProtectionDomain run() {
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   247
                    return targetClass.getProtectionDomain();
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   248
                }
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   249
            }
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   250
        );
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   251
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   252
        return (Class<?>) Unsafe.getUnsafe().defineClass(lambdaClassName, classBytes, 0, classBytes.length,
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   253
                                                                   loader, pd);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   254
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   255
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   256
    /**
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   257
     * Generate the constructor for the class
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   258
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   259
    private void generateConstructor() {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   260
        // Generate constructor
14762
34956da26ceb 8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents: 14680
diff changeset
   261
        MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, constructorDesc, null, null);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   262
        ctor.visitCode();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   263
        ctor.visitVarInsn(ALOAD, 0);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   264
        ctor.visitMethodInsn(INVOKESPECIAL, NAME_MAGIC_ACCESSOR_IMPL, NAME_CTOR, METHOD_DESCRIPTOR_VOID);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   265
        int lvIndex = 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   266
        for (int i = 0; i < argTypes.length; i++) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   267
            ctor.visitVarInsn(ALOAD, 0);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   268
            ctor.visitVarInsn(argTypes[i].getOpcode(ILOAD), lvIndex + 1);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   269
            lvIndex += argTypes[i].getSize();
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   270
            ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor());
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   271
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   272
        ctor.visitInsn(RETURN);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   273
        ctor.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   274
        ctor.visitEnd();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   275
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   276
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   277
    /**
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   278
     * Generate the writeReplace method (if needed for serialization)
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   279
     */
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   280
    private void generateWriteReplace() {
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   281
        TypeConvertingMethodAdapter mv
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   282
                = new TypeConvertingMethodAdapter(cw.visitMethod(ACC_PRIVATE + ACC_FINAL,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   283
                                                                 NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   284
                                                                 null, null));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   285
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   286
        mv.visitCode();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   287
        mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA);
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   288
        mv.visitInsn(DUP);;
16034
cb5fbea1ecec 8008770: SerializedLambda incorrect class loader for lambda deserializing class
rfield
parents: 16001
diff changeset
   289
        mv.visitLdcInsn(Type.getType(targetClass));
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   290
        mv.visitLdcInsn(samInfo.getReferenceKind());
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   291
        mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/'));
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   292
        mv.visitLdcInsn(samInfo.getName());
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   293
        mv.visitLdcInsn(samInfo.getMethodType().toMethodDescriptorString());
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   294
        mv.visitLdcInsn(implInfo.getReferenceKind());
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   295
        mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/'));
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   296
        mv.visitLdcInsn(implInfo.getName());
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   297
        mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString());
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   298
        mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString());
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   299
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   300
        mv.iconst(argTypes.length);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   301
        mv.visitTypeInsn(ANEWARRAY, NAME_OBJECT);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   302
        for (int i = 0; i < argTypes.length; i++) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   303
            mv.visitInsn(DUP);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   304
            mv.iconst(i);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   305
            mv.visitVarInsn(ALOAD, 0);
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   306
            mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor());
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   307
            mv.boxIfTypePrimitive(argTypes[i]);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   308
            mv.visitInsn(AASTORE);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   309
        }
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   310
        mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   311
                DESCR_CTOR_SERIALIZED_LAMBDA);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   312
        mv.visitInsn(ARETURN);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   313
        mv.visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   314
        mv.visitEnd();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   315
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   316
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   317
    /**
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   318
     * Generate a method which calls the lambda implementation method,
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   319
     * converting arguments, as needed.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   320
     * @param m The method whose signature should be generated
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   321
     * @param isBridge True if this methods should be flagged as a bridge
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   322
     */
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   323
    private void generateForwardingMethod(Method m, boolean isBridge) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   324
        Class<?>[] exceptionTypes = m.getExceptionTypes();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   325
        String[] exceptionNames = new String[exceptionTypes.length];
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   326
        for (int i = 0; i < exceptionTypes.length; i++) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   327
            exceptionNames[i] = exceptionTypes[i].getName().replace('.', '/');
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   328
        }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   329
        String methodDescriptor = Type.getMethodDescriptor(m);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   330
        int access = isBridge? ACC_PUBLIC | ACC_BRIDGE : ACC_PUBLIC;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   331
        MethodVisitor mv = cw.visitMethod(access, m.getName(), methodDescriptor, null, exceptionNames);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   332
        new ForwardingMethodGenerator(mv).generate(m);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   333
    }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   334
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   335
    /**
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   336
     * This class generates a method body which calls the lambda implementation
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   337
     * method, converting arguments, as needed.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   338
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   339
    private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   340
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   341
        ForwardingMethodGenerator(MethodVisitor mv) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   342
            super(mv);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   343
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   344
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   345
        void generate(Method m) throws InternalError {
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   346
            visitCode();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   347
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   348
            if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   349
                visitTypeInsn(NEW, implMethodClassName);
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   350
                visitInsn(DUP);;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   351
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   352
            for (int i = 0; i < argTypes.length; i++) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   353
                visitVarInsn(ALOAD, 0);
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   354
                visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argTypes[i].getDescriptor());
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   355
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   356
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   357
            convertArgumentTypes(Type.getArgumentTypes(m));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   358
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   359
            // Invoke the method we want to forward to
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   360
            visitMethodInsn(invocationOpcode(), implMethodClassName, implMethodName, implMethodDesc);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   361
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   362
            // Convert the return value (if any) and return it
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   363
            // Note: if adapting from non-void to void, the 'return' instruction will pop the unneeded result
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   364
            Type samReturnType = Type.getReturnType(m);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   365
            convertType(implMethodReturnType, samReturnType, samReturnType);
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   366
            visitInsn(samReturnType.getOpcode(Opcodes.IRETURN));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   367
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   368
            visitMaxs(-1, -1); // Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   369
            visitEnd();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   370
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   371
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   372
        private void convertArgumentTypes(Type[] samArgumentTypes) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   373
            int lvIndex = 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   374
            boolean samIncludesReceiver = implIsInstanceMethod && argTypes.length == 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   375
            int samReceiverLength = samIncludesReceiver ? 1 : 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   376
            if (samIncludesReceiver) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   377
                // push receiver
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   378
                Type rcvrType = samArgumentTypes[0];
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   379
                Type instantiatedRcvrType = instantiatedArgumentTypes[0];
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   380
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   381
                visitVarInsn(rcvrType.getOpcode(ILOAD), lvIndex + 1);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   382
                lvIndex += rcvrType.getSize();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   383
                convertType(rcvrType, Type.getType(implDefiningClass), instantiatedRcvrType);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   384
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   385
            int argOffset = implMethodArgumentTypes.length - samArgumentTypes.length;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   386
            for (int i = samReceiverLength; i < samArgumentTypes.length; i++) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   387
                Type argType = samArgumentTypes[i];
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   388
                Type targetType = implMethodArgumentTypes[argOffset + i];
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   389
                Type instantiatedArgType = instantiatedArgumentTypes[i];
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   390
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14762
diff changeset
   391
                visitVarInsn(argType.getOpcode(ILOAD), lvIndex + 1);
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   392
                lvIndex += argType.getSize();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   393
                convertType(argType, targetType, instantiatedArgType);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   394
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   395
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   396
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   397
        private void convertType(Type argType, Type targetType, Type functionalType) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   398
            convertType(argType.getDescriptor(), targetType.getDescriptor(), functionalType.getDescriptor());
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   399
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   400
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   401
        private int invocationOpcode() throws InternalError {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   402
            switch (implKind) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   403
                case MethodHandleInfo.REF_invokeStatic:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   404
                    return INVOKESTATIC;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   405
                case MethodHandleInfo.REF_newInvokeSpecial:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   406
                    return INVOKESPECIAL;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   407
                 case MethodHandleInfo.REF_invokeVirtual:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   408
                    return INVOKEVIRTUAL;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   409
                case MethodHandleInfo.REF_invokeInterface:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   410
                    return INVOKEINTERFACE;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   411
                case MethodHandleInfo.REF_invokeSpecial:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   412
                    return INVOKESPECIAL;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   413
                default:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   414
                    throw new InternalError("Unexpected invocation kind: " + implKind);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   415
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   416
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   417
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   418
}