jdk/src/share/classes/java/lang/invoke/AbstractValidatingLambdaMetafactory.java
author chegar
Wed, 19 Jun 2013 11:47:14 +0100
changeset 18284 e281a0a2583e
parent 18182 a86f1b828425
child 18716 9723e722b955
permissions -rw-r--r--
8017044: anti-delta fix for 8015402 Reviewed-by: alanb
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
package java.lang.invoke;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    26
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    27
import java.io.Serializable;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    28
import java.lang.reflect.Method;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    29
import java.lang.reflect.Modifier;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    30
import java.util.ArrayList;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    31
import java.util.Arrays;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    32
import java.util.List;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    33
import sun.invoke.util.Wrapper;
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    34
import static sun.invoke.util.Wrapper.*;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    35
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    36
/**
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    37
 * Abstract implementation of a lambda metafactory which provides parameter unrolling and input validation.
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    38
 *
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    39
 * @see LambdaMetafactory
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    40
 */
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    41
/* package */ abstract class AbstractValidatingLambdaMetafactory {
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    42
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    43
    /*
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    44
     * For context, the comments for the following fields are marked in quotes with their values, given this program:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    45
     * interface II<T> {  Object foo(T x); }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    46
     * interface JJ<R extends Number> extends II<R> { }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    47
     * class CC {  String impl(int i) { return "impl:"+i; }}
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    48
     * class X {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    49
     *     public static void main(String[] args) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    50
     *         JJ<Integer> iii = (new CC())::impl;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    51
     *         System.out.printf(">>> %s\n", iii.foo(44));
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    52
     * }}
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    53
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    54
    final Class<?> targetClass;               // The class calling the meta-factory via invokedynamic "class X"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    55
    final MethodType invokedType;             // The type of the invoked method "(CC)II"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    56
    final Class<?> samBase;                   // The type of the returned instance "interface JJ"
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    57
    final MethodHandle samMethod;             // Raw method handle for the functional interface method
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    58
    final MethodHandleInfo samInfo;           // Info about the SAM method handle "MethodHandleInfo[9 II.foo(Object)Object]"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    59
    final Class<?> samClass;                  // Interface containing the SAM method "interface II"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    60
    final MethodType samMethodType;           // Type of the SAM method "(Object)Object"
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    61
    final MethodHandle implMethod;            // Raw method handle for the implementation method
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    62
    final MethodHandleInfo implInfo;          // Info about the implementation method handle "MethodHandleInfo[5 CC.impl(int)String]"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    63
    final int implKind;                       // Invocation kind for implementation "5"=invokevirtual
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    64
    final boolean implIsInstanceMethod;       // Is the implementation an instance method "true"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    65
    final Class<?> implDefiningClass;         // Type defining the implementation "class CC"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    66
    final MethodType implMethodType;          // Type of the implementation method "(int)String"
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    67
    final MethodType instantiatedMethodType;  // Instantiated erased functional interface method type "(Integer)Object"
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    68
    final boolean isSerializable;             // Should the returned instance be serializable
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    69
    final Class<?>[] markerInterfaces;        // Additional marker interfaces to be implemented
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    70
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    71
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    72
    /**
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    73
     * Meta-factory constructor.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    74
     *
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    75
     * @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
    76
     *               of the caller.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    77
     * @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
    78
     *                    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
    79
     *                    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
    80
     *                    the first argument in the invocation signature will correspond to the receiver.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    81
     * @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
    82
     *                  being converted, represented as a method handle.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    83
     * @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
    84
     *                   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
    85
     *                   functional interface instance are invoked.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    86
     * @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
    87
     *                               are substituted with their instantiation from the capture site
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    88
     * @throws ReflectiveOperationException
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    89
     * @throws LambdaConversionException If any of the meta-factory protocol invariants are violated
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    90
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    91
    AbstractValidatingLambdaMetafactory(MethodHandles.Lookup caller,
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    92
                                       MethodType invokedType,
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    93
                                       MethodHandle samMethod,
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    94
                                       MethodHandle implMethod,
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    95
                                       MethodType instantiatedMethodType,
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    96
                                       int flags,
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
    97
                                       Class<?>[] markerInterfaces)
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
    98
            throws ReflectiveOperationException, LambdaConversionException {
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
    99
        this.targetClass = caller.lookupClass();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   100
        this.invokedType = invokedType;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   101
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   102
        this.samBase = invokedType.returnType();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   103
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   104
        this.samMethod = samMethod;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   105
        this.samInfo = new MethodHandleInfo(samMethod);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   106
        this.samClass = samInfo.getDeclaringClass();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   107
        this.samMethodType  = samInfo.getMethodType();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   108
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   109
        this.implMethod = implMethod;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   110
        this.implInfo = new MethodHandleInfo(implMethod);
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   111
        // @@@ Temporary work-around pending resolution of 8005119
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   112
        this.implKind = (implInfo.getReferenceKind() == MethodHandleInfo.REF_invokeSpecial)
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   113
                        ? MethodHandleInfo.REF_invokeVirtual
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   114
                        : implInfo.getReferenceKind();
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   115
        this.implIsInstanceMethod =
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   116
                implKind == MethodHandleInfo.REF_invokeVirtual ||
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   117
                implKind == MethodHandleInfo.REF_invokeSpecial ||
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   118
                implKind == MethodHandleInfo.REF_invokeInterface;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   119
        this.implDefiningClass = implInfo.getDeclaringClass();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   120
        this.implMethodType = implInfo.getMethodType();
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   121
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   122
        this.instantiatedMethodType = instantiatedMethodType;
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   123
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   124
        if (!samClass.isInterface()) {
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   125
            throw new LambdaConversionException(String.format(
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   126
                    "Functional interface %s is not an interface",
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   127
                    samClass.getName()));
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   128
        }
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   129
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   130
        boolean foundSerializableSupertype = Serializable.class.isAssignableFrom(samBase);
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   131
        for (Class<?> c : markerInterfaces) {
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   132
            if (!c.isInterface()) {
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   133
                throw new LambdaConversionException(String.format(
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   134
                        "Marker interface %s is not an interface",
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   135
                        c.getName()));
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   136
            }
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   137
            foundSerializableSupertype |= Serializable.class.isAssignableFrom(c);
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   138
        }
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   139
        this.isSerializable = ((flags & LambdaMetafactory.FLAG_SERIALIZABLE) != 0)
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   140
                              || foundSerializableSupertype;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   141
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   142
        if (isSerializable && !foundSerializableSupertype) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   143
            markerInterfaces = Arrays.copyOf(markerInterfaces, markerInterfaces.length + 1);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   144
            markerInterfaces[markerInterfaces.length-1] = Serializable.class;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   145
        }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   146
        this.markerInterfaces = markerInterfaces;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   147
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   148
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   149
    /**
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   150
     * Build the CallSite.
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   151
     *
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   152
     * @return a CallSite, which, when invoked, will return an instance of the
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   153
     * functional interface
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   154
     * @throws ReflectiveOperationException
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   155
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   156
    abstract CallSite buildCallSite() throws ReflectiveOperationException, LambdaConversionException;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   157
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   158
    /**
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   159
     * Check the meta-factory arguments for errors
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   160
     * @throws LambdaConversionException if there are improper conversions
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   161
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   162
    void validateMetafactoryArgs() throws LambdaConversionException {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   163
        // Check target type is a subtype of class where SAM method is defined
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   164
        if (!samClass.isAssignableFrom(samBase)) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   165
            throw new LambdaConversionException(
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   166
                    String.format("Invalid target type %s for lambda conversion; not a subtype of functional interface %s",
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   167
                                  samBase.getName(), samClass.getName()));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   168
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   169
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   170
        switch (implKind) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   171
            case MethodHandleInfo.REF_invokeInterface:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   172
            case MethodHandleInfo.REF_invokeVirtual:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   173
            case MethodHandleInfo.REF_invokeStatic:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   174
            case MethodHandleInfo.REF_newInvokeSpecial:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   175
            case MethodHandleInfo.REF_invokeSpecial:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   176
                break;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   177
            default:
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   178
                throw new LambdaConversionException(String.format("Unsupported MethodHandle kind: %s", implInfo));
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   179
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   180
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   181
        // Check arity: optional-receiver + captured + SAM == impl
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   182
        final int implArity = implMethodType.parameterCount();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   183
        final int receiverArity = implIsInstanceMethod ? 1 : 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   184
        final int capturedArity = invokedType.parameterCount();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   185
        final int samArity = samMethodType.parameterCount();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   186
        final int instantiatedArity = instantiatedMethodType.parameterCount();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   187
        if (implArity + receiverArity != capturedArity + samArity) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   188
            throw new LambdaConversionException(
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   189
                    String.format("Incorrect number of parameters for %s method %s; %d captured parameters, %d functional interface method parameters, %d implementation parameters",
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   190
                                  implIsInstanceMethod ? "instance" : "static", implInfo,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   191
                                  capturedArity, samArity, implArity));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   192
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   193
        if (instantiatedArity != samArity) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   194
            throw new LambdaConversionException(
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   195
                    String.format("Incorrect number of parameters for %s method %s; %d instantiated parameters, %d functional interface method parameters",
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   196
                                  implIsInstanceMethod ? "instance" : "static", implInfo,
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   197
                                  instantiatedArity, samArity));
14323
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
        // If instance: first captured arg (receiver) must be subtype of class where impl method is defined
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   201
        final int capturedStart;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   202
        final int samStart;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   203
        if (implIsInstanceMethod) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   204
            final Class<?> receiverClass;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   205
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   206
            // implementation is an instance method, adjust for receiver in captured variables / SAM arguments
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   207
            if (capturedArity == 0) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   208
                // receiver is function parameter
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   209
                capturedStart = 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   210
                samStart = 1;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   211
                receiverClass = instantiatedMethodType.parameterType(0);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   212
            } else {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   213
                // receiver is a captured variable
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   214
                capturedStart = 1;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   215
                samStart = 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   216
                receiverClass = invokedType.parameterType(0);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   217
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   218
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   219
            // check receiver type
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   220
            if (!implDefiningClass.isAssignableFrom(receiverClass)) {
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   221
                throw new LambdaConversionException(
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   222
                        String.format("Invalid receiver type %s; not a subtype of implementation type %s",
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   223
                                      receiverClass, implDefiningClass));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   224
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   225
        } else {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   226
            // no receiver
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   227
            capturedStart = 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   228
            samStart = 0;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   229
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   230
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   231
        // Check for exact match on non-receiver captured arguments
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   232
        final int implFromCaptured = capturedArity - capturedStart;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   233
        for (int i=0; i<implFromCaptured; i++) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   234
            Class<?> implParamType = implMethodType.parameterType(i);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   235
            Class<?> capturedParamType = invokedType.parameterType(i + capturedStart);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   236
            if (!capturedParamType.equals(implParamType)) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   237
                throw new LambdaConversionException(
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   238
                        String.format("Type mismatch in captured lambda parameter %d: expecting %s, found %s",
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   239
                                      i, capturedParamType, implParamType));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   240
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   241
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   242
        // Check for adaptation match on SAM arguments
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   243
        final int samOffset = samStart - implFromCaptured;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   244
        for (int i=implFromCaptured; i<implArity; i++) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   245
            Class<?> implParamType = implMethodType.parameterType(i);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   246
            Class<?> instantiatedParamType = instantiatedMethodType.parameterType(i + samOffset);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   247
            if (!isAdaptableTo(instantiatedParamType, implParamType, true)) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   248
                throw new LambdaConversionException(
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   249
                        String.format("Type mismatch for lambda argument %d: %s is not convertible to %s",
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   250
                                      i, instantiatedParamType, implParamType));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   251
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   252
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   253
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   254
        // Adaptation match: return type
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   255
        Class<?> expectedType = instantiatedMethodType.returnType();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   256
        Class<?> actualReturnType =
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   257
                (implKind == MethodHandleInfo.REF_newInvokeSpecial)
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   258
                  ? implDefiningClass
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   259
                  : implMethodType.returnType();
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   260
        if (!isAdaptableToAsReturn(actualReturnType, expectedType)) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   261
            throw new LambdaConversionException(
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   262
                    String.format("Type mismatch for lambda return: %s is not convertible to %s",
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   263
                                  actualReturnType, expectedType));
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   264
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   265
     }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   266
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   267
    /**
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   268
     * Check type adaptability
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   269
     * @param fromType
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   270
     * @param toType
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   271
     * @param strict If true, do strict checks, else allow that fromType may be parameterized
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   272
     * @return True if 'fromType' can be passed to an argument of 'toType'
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   273
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   274
    private boolean isAdaptableTo(Class<?> fromType, Class<?> toType, boolean strict) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   275
        if (fromType.equals(toType)) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   276
            return true;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   277
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   278
        if (fromType.isPrimitive()) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   279
            Wrapper wfrom = forPrimitiveType(fromType);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   280
            if (toType.isPrimitive()) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   281
                // both are primitive: widening
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   282
                Wrapper wto = forPrimitiveType(toType);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   283
                return wto.isConvertibleFrom(wfrom);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   284
            } else {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   285
                // from primitive to reference: boxing
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   286
                return toType.isAssignableFrom(wfrom.wrapperType());
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   287
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   288
        } else {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   289
            if (toType.isPrimitive()) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   290
                // from reference to primitive: unboxing
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   291
                Wrapper wfrom;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   292
                if (isWrapperType(fromType) && (wfrom = forWrapperType(fromType)).primitiveType().isPrimitive()) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   293
                    // fromType is a primitive wrapper; unbox+widen
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   294
                    Wrapper wto = forPrimitiveType(toType);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   295
                    return wto.isConvertibleFrom(wfrom);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   296
                } else {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   297
                    // must be convertible to primitive
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   298
                    return !strict;
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   299
                }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   300
            } else {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   301
                // both are reference types: fromType should be a superclass of toType.
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   302
                return strict? toType.isAssignableFrom(fromType) : true;
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   303
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   304
        }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   305
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   306
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   307
    /**
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   308
     * Check type adaptability for return types -- special handling of void type) and parameterized fromType
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   309
     * @param fromType
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   310
     * @param toType
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   311
     * @return True if 'fromType' can be converted to 'toType'
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   312
     */
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   313
    private boolean isAdaptableToAsReturn(Class<?> fromType, Class<?> toType) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   314
        return toType.equals(void.class)
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   315
               || !fromType.equals(void.class) && isAdaptableTo(fromType, toType, false);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   316
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   317
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   318
16001
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   319
    /*********** Logging support -- for debugging only, uncomment as needed
fd4c8d3becf8 8004970: Implement serialization in the lambda metafactory
rfield
parents: 14323
diff changeset
   320
    static final Executor logPool = Executors.newSingleThreadExecutor();
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   321
    protected static void log(final String s) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   322
        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   323
            @Override
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   324
            public void run() {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   325
                System.out.println(s);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   326
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   327
        });
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   328
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   329
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   330
    protected static void log(final String s, final Throwable e) {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   331
        MethodHandleProxyLambdaMetafactory.logPool.execute(new Runnable() {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   332
            @Override
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   333
            public void run() {
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   334
                System.out.println(s);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   335
                e.printStackTrace(System.out);
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   336
            }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   337
        });
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   338
    }
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   339
    ***********************/
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   340
18284
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   341
    /**
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   342
     * Find the functional interface method and corresponding abstract methods
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   343
     * which should be bridged. The functional interface method and those to be
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   344
     * bridged will have the same name and number of parameters. Check for
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   345
     * matching default methods (non-abstract), the VM will create bridges for
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   346
     * default methods; We don't have enough readily available type information
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   347
     * to distinguish between where the functional interface method should be
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   348
     * bridged and where the default method should be bridged; This situation is
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   349
     * flagged.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   350
     */
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   351
    class MethodAnalyzer {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   352
        private final Method[] methods = samBase.getMethods();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   353
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   354
        private Method samMethod = null;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   355
        private final List<Method> methodsToBridge = new ArrayList<>(methods.length);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   356
        private boolean conflictFoundBetweenDefaultAndBridge = false;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   357
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   358
        MethodAnalyzer() {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   359
            String samMethodName = samInfo.getName();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   360
            Class<?>[] samParamTypes = samMethodType.parameterArray();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   361
            int samParamLength = samParamTypes.length;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   362
            Class<?> samReturnType = samMethodType.returnType();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   363
            Class<?> objectClass = Object.class;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   364
            List<Method> defaultMethods = new ArrayList<>(methods.length);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   365
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   366
            for (Method m : methods) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   367
                if (m.getName().equals(samMethodName) && m.getDeclaringClass() != objectClass) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   368
                    Class<?>[] mParamTypes = m.getParameterTypes();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   369
                    if (mParamTypes.length == samParamLength) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   370
                        // Method matches name and parameter length -- and is not Object
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   371
                        if (Modifier.isAbstract(m.getModifiers())) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   372
                            // Method is abstract
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   373
                            if (m.getReturnType().equals(samReturnType)
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   374
                                    && Arrays.equals(mParamTypes, samParamTypes)) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   375
                                // Exact match, this is the SAM method signature
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   376
                                samMethod = m;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   377
                            } else if (!hasMatchingBridgeSignature(m)) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   378
                                // Record bridges, exclude methods with duplicate signatures
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   379
                                methodsToBridge.add(m);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   380
                            }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   381
                        } else {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   382
                            // Record default methods for conflict testing
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   383
                            defaultMethods.add(m);
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   384
                        }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   385
                    }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   386
                }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   387
            }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   388
            for (Method dm : defaultMethods) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   389
                if (hasMatchingBridgeSignature(dm)) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   390
                    conflictFoundBetweenDefaultAndBridge = true;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   391
                    break;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   392
                }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   393
            }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   394
        }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   395
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   396
        Method getSamMethod() {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   397
            return samMethod;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   398
        }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   399
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   400
        List<Method> getMethodsToBridge() {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   401
            return methodsToBridge;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   402
        }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   403
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   404
        boolean conflictFoundBetweenDefaultAndBridge() {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   405
            return conflictFoundBetweenDefaultAndBridge;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   406
        }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   407
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   408
        /**
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   409
         * Search the list of previously found bridge methods to determine if there is a method with the same signature
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   410
         * (return and parameter types) as the specified method.
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   411
         *
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   412
         * @param m The method to match
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   413
         * @return True if the method was found, False otherwise
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   414
         */
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   415
        private boolean hasMatchingBridgeSignature(Method m) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   416
            Class<?>[] ptypes = m.getParameterTypes();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   417
            Class<?> rtype = m.getReturnType();
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   418
            for (Method md : methodsToBridge) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   419
                if (md.getReturnType().equals(rtype) && Arrays.equals(ptypes, md.getParameterTypes())) {
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   420
                    return true;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   421
                }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   422
            }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   423
                    return false;
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   424
                }
e281a0a2583e 8017044: anti-delta fix for 8015402
chegar
parents: 18182
diff changeset
   425
            }
14323
5acca3d1f124 8000806: Implement runtime lambda metafactory
rfield
parents:
diff changeset
   426
}