author | shade |
Tue, 17 May 2016 22:28:00 +0300 | |
changeset 38372 | 017d7578731c |
parent 37781 | 71ed5645f17c |
child 43702 | 699ccfe75625 |
permissions | -rw-r--r-- |
14323 | 1 |
/* |
21618
6632680b0683
8027232: Update j.l.invoke code generating class files to use ASM enhancements for invocation of non-abstract methods on ifaces
ksrini
parents:
21425
diff
changeset
|
2 |
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
14323 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package java.lang.invoke; |
|
27 |
||
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
28 |
import jdk.internal.org.objectweb.asm.*; |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
29 |
import sun.invoke.util.BytecodeDescriptor; |
33674
566777f73c32
8140606: Update library code to use internal Unsafe
chegar
parents:
33525
diff
changeset
|
30 |
import jdk.internal.misc.Unsafe; |
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
31 |
import sun.security.action.GetPropertyAction; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
32 |
|
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
33 |
import java.io.FilePermission; |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
34 |
import java.io.Serializable; |
18284 | 35 |
import java.lang.reflect.Constructor; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
36 |
import java.security.AccessController; |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
37 |
import java.security.PrivilegedAction; |
21353
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
38 |
import java.util.LinkedHashSet; |
18284 | 39 |
import java.util.concurrent.atomic.AtomicInteger; |
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
40 |
import java.util.PropertyPermission; |
21353
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
41 |
import java.util.Set; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
42 |
|
18284 | 43 |
import static jdk.internal.org.objectweb.asm.Opcodes.*; |
14323 | 44 |
|
45 |
/** |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
46 |
* Lambda metafactory implementation which dynamically creates an |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
47 |
* inner-class-like class per lambda callsite. |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
48 |
* |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
49 |
* @see LambdaMetafactory |
14323 | 50 |
*/ |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
51 |
/* package */ final class InnerClassLambdaMetafactory extends AbstractValidatingLambdaMetafactory { |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
52 |
private static final Unsafe UNSAFE = Unsafe.getUnsafe(); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
53 |
|
21618
6632680b0683
8027232: Update j.l.invoke code generating class files to use ASM enhancements for invocation of non-abstract methods on ifaces
ksrini
parents:
21425
diff
changeset
|
54 |
private static final int CLASSFILE_VERSION = 52; |
14323 | 55 |
private static final String METHOD_DESCRIPTOR_VOID = Type.getMethodDescriptor(Type.VOID_TYPE); |
21300 | 56 |
private static final String JAVA_LANG_OBJECT = "java/lang/Object"; |
14323 | 57 |
private static final String NAME_CTOR = "<init>"; |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
58 |
private static final String NAME_FACTORY = "get$Lambda"; |
14323 | 59 |
|
60 |
//Serialization support |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
61 |
private static final String NAME_SERIALIZED_LAMBDA = "java/lang/invoke/SerializedLambda"; |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
62 |
private static final String NAME_NOT_SERIALIZABLE_EXCEPTION = "java/io/NotSerializableException"; |
14323 | 63 |
private static final String DESCR_METHOD_WRITE_REPLACE = "()Ljava/lang/Object;"; |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
64 |
private static final String DESCR_METHOD_WRITE_OBJECT = "(Ljava/io/ObjectOutputStream;)V"; |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
65 |
private static final String DESCR_METHOD_READ_OBJECT = "(Ljava/io/ObjectInputStream;)V"; |
14323 | 66 |
private static final String NAME_METHOD_WRITE_REPLACE = "writeReplace"; |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
67 |
private static final String NAME_METHOD_READ_OBJECT = "readObject"; |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
68 |
private static final String NAME_METHOD_WRITE_OBJECT = "writeObject"; |
33525
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
69 |
|
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
70 |
private static final String DESCR_CLASS = "Ljava/lang/Class;"; |
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
71 |
private static final String DESCR_STRING = "Ljava/lang/String;"; |
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
72 |
private static final String DESCR_OBJECT = "Ljava/lang/Object;"; |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
73 |
private static final String DESCR_CTOR_SERIALIZED_LAMBDA |
33525
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
74 |
= "(" + DESCR_CLASS + DESCR_STRING + DESCR_STRING + DESCR_STRING + "I" |
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
75 |
+ DESCR_STRING + DESCR_STRING + DESCR_STRING + DESCR_STRING + "[" + DESCR_OBJECT + ")V"; |
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
76 |
|
3058b44fd282
8141539: Avoid calculating string constants in InnerClassLambdaMetaFactory
redestad
parents:
29986
diff
changeset
|
77 |
private static final String DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION = "(Ljava/lang/String;)V"; |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
78 |
private static final String[] SER_HOSTILE_EXCEPTIONS = new String[] {NAME_NOT_SERIALIZABLE_EXCEPTION}; |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
79 |
|
14323 | 80 |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
81 |
private static final String[] EMPTY_STRING_ARRAY = new String[0]; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
82 |
|
14323 | 83 |
// Used to ensure that each spun class name is unique |
84 |
private static final AtomicInteger counter = new AtomicInteger(0); |
|
85 |
||
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
86 |
// For dumping generated classes to disk, for debugging purposes |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
87 |
private static final ProxyClassesDumper dumper; |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
88 |
|
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
89 |
static { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
90 |
final String key = "jdk.internal.lambda.dumpProxyClasses"; |
37781
71ed5645f17c
8155775: Re-examine naming of privileged methods to access System properties
redestad
parents:
37593
diff
changeset
|
91 |
String path = GetPropertyAction.privilegedGetProperty(key); |
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
92 |
dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
93 |
} |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
94 |
|
14323 | 95 |
// See context values in AbstractValidatingLambdaMetafactory |
96 |
private final String implMethodClassName; // Name of type containing implementation "CC" |
|
97 |
private final String implMethodName; // Name of implementation method "impl" |
|
98 |
private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;" |
|
25979 | 99 |
private final Class<?> implMethodReturnClass; // class for implementation method return type "Ljava/lang/String;" |
14323 | 100 |
private final MethodType constructorType; // Generated class constructor type "(CC)void" |
101 |
private final ClassWriter cw; // ASM class writer |
|
102 |
private final String[] argNames; // Generated names for the constructor arguments |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
103 |
private final String[] argDescs; // Type descriptors for the constructor arguments |
14323 | 104 |
private final String lambdaClassName; // Generated name for the generated class "X$$Lambda$1" |
105 |
||
106 |
/** |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
107 |
* General meta-factory constructor, supporting both standard cases and |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
108 |
* allowing for uncommon options such as serialization or bridging. |
14323 | 109 |
* |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
110 |
* @param caller Stacked automatically by VM; represents a lookup context |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
111 |
* with the accessibility privileges of the caller. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
112 |
* @param invokedType Stacked automatically by VM; the signature of the |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
113 |
* invoked method, which includes the expected static |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
114 |
* type of the returned lambda object, and the static |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
115 |
* types of the captured arguments for the lambda. In |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
116 |
* the event that the implementation method is an |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
117 |
* instance method, the first argument in the invocation |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
118 |
* signature will correspond to the receiver. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
119 |
* @param samMethodName Name of the method in the functional interface to |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
120 |
* which the lambda or method reference is being |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
121 |
* converted, represented as a String. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
122 |
* @param samMethodType Type of the method in the functional interface to |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
123 |
* which the lambda or method reference is being |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
124 |
* converted, represented as a MethodType. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
125 |
* @param implMethod The implementation method which should be called (with |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
126 |
* suitable adaptation of argument types, return types, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
127 |
* and adjustment for captured arguments) when methods of |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
128 |
* the resulting functional interface instance are invoked. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
129 |
* @param instantiatedMethodType The signature of the primary functional |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
130 |
* interface method after type variables are |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
131 |
* substituted with their instantiation from |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
132 |
* the capture site |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
133 |
* @param isSerializable Should the lambda be made serializable? If set, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
134 |
* either the target type or one of the additional SAM |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
135 |
* types must extend {@code Serializable}. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
136 |
* @param markerInterfaces Additional interfaces which the lambda object |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
137 |
* should implement. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
138 |
* @param additionalBridges Method types for additional signatures to be |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
139 |
* bridged to the implementation method |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
140 |
* @throws LambdaConversionException If any of the meta-factory protocol |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
141 |
* invariants are violated |
14323 | 142 |
*/ |
143 |
public InnerClassLambdaMetafactory(MethodHandles.Lookup caller, |
|
144 |
MethodType invokedType, |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
145 |
String samMethodName, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
146 |
MethodType samMethodType, |
14323 | 147 |
MethodHandle implMethod, |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
148 |
MethodType instantiatedMethodType, |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
149 |
boolean isSerializable, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
150 |
Class<?>[] markerInterfaces, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
151 |
MethodType[] additionalBridges) |
21360
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
152 |
throws LambdaConversionException { |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
153 |
super(caller, invokedType, samMethodName, samMethodType, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
154 |
implMethod, instantiatedMethodType, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
155 |
isSerializable, markerInterfaces, additionalBridges); |
14323 | 156 |
implMethodClassName = implDefiningClass.getName().replace('.', '/'); |
157 |
implMethodName = implInfo.getName(); |
|
158 |
implMethodDesc = implMethodType.toMethodDescriptorString(); |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
159 |
implMethodReturnClass = (implKind == MethodHandleInfo.REF_newInvokeSpecial) |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
160 |
? implDefiningClass |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
161 |
: implMethodType.returnType(); |
14323 | 162 |
constructorType = invokedType.changeReturnType(Void.TYPE); |
163 |
lambdaClassName = targetClass.getName().replace('.', '/') + "$$Lambda$" + counter.incrementAndGet(); |
|
164 |
cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
165 |
int parameterCount = invokedType.parameterCount(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
166 |
if (parameterCount > 0) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
167 |
argNames = new String[parameterCount]; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
168 |
argDescs = new String[parameterCount]; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
169 |
for (int i = 0; i < parameterCount; i++) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
170 |
argNames[i] = "arg$" + (i + 1); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
171 |
argDescs[i] = BytecodeDescriptor.unparse(invokedType.parameterType(i)); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
172 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
173 |
} else { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
174 |
argNames = argDescs = EMPTY_STRING_ARRAY; |
14323 | 175 |
} |
176 |
} |
|
177 |
||
178 |
/** |
|
179 |
* Build the CallSite. Generate a class file which implements the functional |
|
180 |
* interface, define the class, if there are no parameters create an instance |
|
181 |
* of the class which the CallSite will return, otherwise, generate handles |
|
182 |
* which will call the class' constructor. |
|
183 |
* |
|
184 |
* @return a CallSite, which, when invoked, will return an instance of the |
|
185 |
* functional interface |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
186 |
* @throws ReflectiveOperationException |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
187 |
* @throws LambdaConversionException If properly formed functional interface |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
188 |
* is not found |
14323 | 189 |
*/ |
190 |
@Override |
|
21360
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
191 |
CallSite buildCallSite() throws LambdaConversionException { |
14323 | 192 |
final Class<?> innerClass = spinInnerClass(); |
193 |
if (invokedType.parameterCount() == 0) { |
|
22297 | 194 |
final Constructor<?>[] ctrs = AccessController.doPrivileged( |
29986
97167d851fc4
8078467: Update core libraries to use diamond with anonymous classes
darcy
parents:
28972
diff
changeset
|
195 |
new PrivilegedAction<>() { |
14762
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
196 |
@Override |
22297 | 197 |
public Constructor<?>[] run() { |
21425
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
198 |
Constructor<?>[] ctrs = innerClass.getDeclaredConstructors(); |
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
199 |
if (ctrs.length == 1) { |
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
200 |
// The lambda implementing inner class constructor is private, set |
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
201 |
// it accessible (by us) before creating the constant sole instance |
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
202 |
ctrs[0].setAccessible(true); |
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
203 |
} |
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
204 |
return ctrs; |
14762
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
205 |
} |
21425
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
206 |
}); |
14762
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
207 |
if (ctrs.length != 1) { |
21360
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
208 |
throw new LambdaConversionException("Expected one lambda constructor for " |
14762
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
209 |
+ innerClass.getCanonicalName() + ", got " + ctrs.length); |
34956da26ceb
8003881: Prevent lambda implementing inner classes from allowing the creation of new instances
rfield
parents:
14680
diff
changeset
|
210 |
} |
21425
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
211 |
|
21360
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
212 |
try { |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
213 |
Object inst = ctrs[0].newInstance(); |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
214 |
return new ConstantCallSite(MethodHandles.constant(samBase, inst)); |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
215 |
} |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
216 |
catch (ReflectiveOperationException e) { |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
217 |
throw new LambdaConversionException("Exception instantiating lambda object", e); |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
218 |
} |
14323 | 219 |
} else { |
21360
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
220 |
try { |
21425
2d49fa63ac15
8024633: Lambda linkage performance - initialize generated class earlier
briangoetz
parents:
21424
diff
changeset
|
221 |
UNSAFE.ensureClassInitialized(innerClass); |
21360
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
222 |
return new ConstantCallSite( |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
223 |
MethodHandles.Lookup.IMPL_LOOKUP |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
224 |
.findStatic(innerClass, NAME_FACTORY, invokedType)); |
21360
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
225 |
} |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
226 |
catch (ReflectiveOperationException e) { |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
227 |
throw new LambdaConversionException("Exception finding constructor", e); |
2c2f062cf52f
8019646: Clarify javadoc contract of LambdaMetafactory
briangoetz
parents:
21353
diff
changeset
|
228 |
} |
14323 | 229 |
} |
230 |
} |
|
231 |
||
232 |
/** |
|
233 |
* Generate a class file which implements the functional |
|
234 |
* interface, define and return the class. |
|
235 |
* |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
236 |
* @implNote The class that is generated does not include signature |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
237 |
* information for exceptions that may be present on the SAM method. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
238 |
* This is to reduce classfile size, and is harmless as checked exceptions |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
239 |
* are erased anyway, no one will ever compile against this classfile, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
240 |
* and we make no guarantees about the reflective properties of lambda |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
241 |
* objects. |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
242 |
* |
14323 | 243 |
* @return a Class which implements the functional interface |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
244 |
* @throws LambdaConversionException If properly formed functional interface |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
245 |
* is not found |
14323 | 246 |
*/ |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
247 |
private Class<?> spinInnerClass() throws LambdaConversionException { |
21353
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
248 |
String[] interfaces; |
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
249 |
String samIntf = samBase.getName().replace('.', '/'); |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
250 |
boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase); |
21353
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
251 |
if (markerInterfaces.length == 0) { |
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
252 |
interfaces = new String[]{samIntf}; |
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
253 |
} else { |
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
254 |
// Assure no duplicate interfaces (ClassFormatError) |
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
255 |
Set<String> itfs = new LinkedHashSet<>(markerInterfaces.length + 1); |
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
256 |
itfs.add(samIntf); |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
257 |
for (Class<?> markerInterface : markerInterfaces) { |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
258 |
itfs.add(markerInterface.getName().replace('.', '/')); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
259 |
accidentallySerializable |= !isSerializable && Serializable.class.isAssignableFrom(markerInterface); |
21353
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
260 |
} |
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
261 |
interfaces = itfs.toArray(new String[itfs.size()]); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
262 |
} |
21353
9792667abbf2
8025868: Several lang/LMBD JCK tests fail with java.lang.BootstrapMethodError
rfield
parents:
21300
diff
changeset
|
263 |
|
16859
45fbee947921
8012028: Metafactory-generated lambda classes should be final
rfield
parents:
16854
diff
changeset
|
264 |
cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC, |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
265 |
lambdaClassName, null, |
21300 | 266 |
JAVA_LANG_OBJECT, interfaces); |
14323 | 267 |
|
268 |
// Generate final fields to be filled in by constructor |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
269 |
for (int i = 0; i < argDescs.length; i++) { |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
270 |
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
271 |
argNames[i], |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
272 |
argDescs[i], |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
273 |
null, null); |
14323 | 274 |
fv.visitEnd(); |
275 |
} |
|
276 |
||
277 |
generateConstructor(); |
|
278 |
||
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
279 |
if (invokedType.parameterCount() != 0) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
280 |
generateFactory(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
281 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
282 |
|
14323 | 283 |
// Forward the SAM method |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
284 |
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, samMethodName, |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
285 |
samMethodType.toMethodDescriptorString(), null, null); |
28972 | 286 |
mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
287 |
new ForwardingMethodGenerator(mv).generate(samMethodType); |
14323 | 288 |
|
289 |
// Forward the bridges |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
290 |
if (additionalBridges != null) { |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
291 |
for (MethodType mt : additionalBridges) { |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
292 |
mv = cw.visitMethod(ACC_PUBLIC|ACC_BRIDGE, samMethodName, |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
293 |
mt.toMethodDescriptorString(), null, null); |
28972 | 294 |
mv.visitAnnotation("Ljava/lang/invoke/LambdaForm$Hidden;", true); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
295 |
new ForwardingMethodGenerator(mv).generate(mt); |
14323 | 296 |
} |
297 |
} |
|
298 |
||
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
299 |
if (isSerializable) |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
300 |
generateSerializationFriendlyMethods(); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
301 |
else if (accidentallySerializable) |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
302 |
generateSerializationHostileMethods(); |
14323 | 303 |
|
304 |
cw.visitEnd(); |
|
305 |
||
306 |
// Define the generated class in this VM. |
|
307 |
||
308 |
final byte[] classBytes = cw.toByteArray(); |
|
309 |
||
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
310 |
// If requested, dump out to a file for debugging purposes |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
311 |
if (dumper != null) { |
29986
97167d851fc4
8078467: Update core libraries to use diamond with anonymous classes
darcy
parents:
28972
diff
changeset
|
312 |
AccessController.doPrivileged(new PrivilegedAction<>() { |
20748
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
313 |
@Override |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
314 |
public Void run() { |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
315 |
dumper.dumpClass(lambdaClassName, classBytes); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
316 |
return null; |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
317 |
} |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
318 |
}, null, |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
319 |
new FilePermission("<<ALL FILES>>", "read, write"), |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
320 |
// createDirectories may need it |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
321 |
new PropertyPermission("user.dir", "read")); |
fbf53402134d
8023524: Mechanism to dump generated lambda classes / log lambda code generation
henryjen
parents:
18716
diff
changeset
|
322 |
} |
14323 | 323 |
|
21300 | 324 |
return UNSAFE.defineAnonymousClass(targetClass, classBytes, null); |
14323 | 325 |
} |
326 |
||
327 |
/** |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
328 |
* Generate the factory method for the class |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
329 |
*/ |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
330 |
private void generateFactory() { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
331 |
MethodVisitor m = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, NAME_FACTORY, invokedType.toMethodDescriptorString(), null, null); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
332 |
m.visitCode(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
333 |
m.visitTypeInsn(NEW, lambdaClassName); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
334 |
m.visitInsn(Opcodes.DUP); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
335 |
int parameterCount = invokedType.parameterCount(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
336 |
for (int typeIndex = 0, varIndex = 0; typeIndex < parameterCount; typeIndex++) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
337 |
Class<?> argType = invokedType.parameterType(typeIndex); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
338 |
m.visitVarInsn(getLoadOpcode(argType), varIndex); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
339 |
varIndex += getParameterSize(argType); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
340 |
} |
22297 | 341 |
m.visitMethodInsn(INVOKESPECIAL, lambdaClassName, NAME_CTOR, constructorType.toMethodDescriptorString(), false); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
342 |
m.visitInsn(ARETURN); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
343 |
m.visitMaxs(-1, -1); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
344 |
m.visitEnd(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
345 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
346 |
|
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
347 |
/** |
14323 | 348 |
* Generate the constructor for the class |
349 |
*/ |
|
350 |
private void generateConstructor() { |
|
351 |
// Generate constructor |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
352 |
MethodVisitor ctor = cw.visitMethod(ACC_PRIVATE, NAME_CTOR, |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
353 |
constructorType.toMethodDescriptorString(), null, null); |
14323 | 354 |
ctor.visitCode(); |
355 |
ctor.visitVarInsn(ALOAD, 0); |
|
21300 | 356 |
ctor.visitMethodInsn(INVOKESPECIAL, JAVA_LANG_OBJECT, NAME_CTOR, |
22297 | 357 |
METHOD_DESCRIPTOR_VOID, false); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
358 |
int parameterCount = invokedType.parameterCount(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
359 |
for (int i = 0, lvIndex = 0; i < parameterCount; i++) { |
14323 | 360 |
ctor.visitVarInsn(ALOAD, 0); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
361 |
Class<?> argType = invokedType.parameterType(i); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
362 |
ctor.visitVarInsn(getLoadOpcode(argType), lvIndex + 1); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
363 |
lvIndex += getParameterSize(argType); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
364 |
ctor.visitFieldInsn(PUTFIELD, lambdaClassName, argNames[i], argDescs[i]); |
14323 | 365 |
} |
366 |
ctor.visitInsn(RETURN); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
367 |
// Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
368 |
ctor.visitMaxs(-1, -1); |
14323 | 369 |
ctor.visitEnd(); |
370 |
} |
|
371 |
||
372 |
/** |
|
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
373 |
* Generate a writeReplace method that supports serialization |
14323 | 374 |
*/ |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
375 |
private void generateSerializationFriendlyMethods() { |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
376 |
TypeConvertingMethodAdapter mv |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
377 |
= new TypeConvertingMethodAdapter( |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
378 |
cw.visitMethod(ACC_PRIVATE + ACC_FINAL, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
379 |
NAME_METHOD_WRITE_REPLACE, DESCR_METHOD_WRITE_REPLACE, |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
380 |
null, null)); |
14323 | 381 |
|
382 |
mv.visitCode(); |
|
383 |
mv.visitTypeInsn(NEW, NAME_SERIALIZED_LAMBDA); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
384 |
mv.visitInsn(DUP); |
16034
cb5fbea1ecec
8008770: SerializedLambda incorrect class loader for lambda deserializing class
rfield
parents:
16001
diff
changeset
|
385 |
mv.visitLdcInsn(Type.getType(targetClass)); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
386 |
mv.visitLdcInsn(invokedType.returnType().getName().replace('.', '/')); |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
387 |
mv.visitLdcInsn(samMethodName); |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
388 |
mv.visitLdcInsn(samMethodType.toMethodDescriptorString()); |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
389 |
mv.visitLdcInsn(implInfo.getReferenceKind()); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
390 |
mv.visitLdcInsn(implInfo.getDeclaringClass().getName().replace('.', '/')); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
391 |
mv.visitLdcInsn(implInfo.getName()); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
392 |
mv.visitLdcInsn(implInfo.getMethodType().toMethodDescriptorString()); |
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
393 |
mv.visitLdcInsn(instantiatedMethodType.toMethodDescriptorString()); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
394 |
mv.iconst(argDescs.length); |
21300 | 395 |
mv.visitTypeInsn(ANEWARRAY, JAVA_LANG_OBJECT); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
396 |
for (int i = 0; i < argDescs.length; i++) { |
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
397 |
mv.visitInsn(DUP); |
14323 | 398 |
mv.iconst(i); |
399 |
mv.visitVarInsn(ALOAD, 0); |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
400 |
mv.visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
401 |
mv.boxIfTypePrimitive(Type.getType(argDescs[i])); |
14323 | 402 |
mv.visitInsn(AASTORE); |
403 |
} |
|
16001
fd4c8d3becf8
8004970: Implement serialization in the lambda metafactory
rfield
parents:
14762
diff
changeset
|
404 |
mv.visitMethodInsn(INVOKESPECIAL, NAME_SERIALIZED_LAMBDA, NAME_CTOR, |
22297 | 405 |
DESCR_CTOR_SERIALIZED_LAMBDA, false); |
14323 | 406 |
mv.visitInsn(ARETURN); |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
407 |
// Maxs computed by ClassWriter.COMPUTE_MAXS, these arguments ignored |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
408 |
mv.visitMaxs(-1, -1); |
14323 | 409 |
mv.visitEnd(); |
410 |
} |
|
411 |
||
412 |
/** |
|
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
413 |
* Generate a readObject/writeObject method that is hostile to serialization |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
414 |
*/ |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
415 |
private void generateSerializationHostileMethods() { |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
416 |
MethodVisitor mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL, |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
417 |
NAME_METHOD_WRITE_OBJECT, DESCR_METHOD_WRITE_OBJECT, |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
418 |
null, SER_HOSTILE_EXCEPTIONS); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
419 |
mv.visitCode(); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
420 |
mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
421 |
mv.visitInsn(DUP); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
422 |
mv.visitLdcInsn("Non-serializable lambda"); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
423 |
mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR, |
22297 | 424 |
DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
425 |
mv.visitInsn(ATHROW); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
426 |
mv.visitMaxs(-1, -1); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
427 |
mv.visitEnd(); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
428 |
|
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
429 |
mv = cw.visitMethod(ACC_PRIVATE + ACC_FINAL, |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
430 |
NAME_METHOD_READ_OBJECT, DESCR_METHOD_READ_OBJECT, |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
431 |
null, SER_HOSTILE_EXCEPTIONS); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
432 |
mv.visitCode(); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
433 |
mv.visitTypeInsn(NEW, NAME_NOT_SERIALIZABLE_EXCEPTION); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
434 |
mv.visitInsn(DUP); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
435 |
mv.visitLdcInsn("Non-serializable lambda"); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
436 |
mv.visitMethodInsn(INVOKESPECIAL, NAME_NOT_SERIALIZABLE_EXCEPTION, NAME_CTOR, |
22297 | 437 |
DESCR_CTOR_NOT_SERIALIZABLE_EXCEPTION, false); |
21417
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
438 |
mv.visitInsn(ATHROW); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
439 |
mv.visitMaxs(-1, -1); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
440 |
mv.visitEnd(); |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
441 |
} |
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
442 |
|
58b329cea7f2
8027318: Lambda Metafactory: generate serialization-hostile read/writeObject methods for non-serializable lambdas
briangoetz
parents:
21360
diff
changeset
|
443 |
/** |
14323 | 444 |
* This class generates a method body which calls the lambda implementation |
445 |
* method, converting arguments, as needed. |
|
446 |
*/ |
|
447 |
private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter { |
|
448 |
||
449 |
ForwardingMethodGenerator(MethodVisitor mv) { |
|
450 |
super(mv); |
|
451 |
} |
|
452 |
||
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
453 |
void generate(MethodType methodType) { |
14323 | 454 |
visitCode(); |
455 |
||
456 |
if (implKind == MethodHandleInfo.REF_newInvokeSpecial) { |
|
457 |
visitTypeInsn(NEW, implMethodClassName); |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
458 |
visitInsn(DUP); |
14323 | 459 |
} |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
460 |
for (int i = 0; i < argNames.length; i++) { |
14323 | 461 |
visitVarInsn(ALOAD, 0); |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
462 |
visitFieldInsn(GETFIELD, lambdaClassName, argNames[i], argDescs[i]); |
14323 | 463 |
} |
464 |
||
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
465 |
convertArgumentTypes(methodType); |
14323 | 466 |
|
467 |
// Invoke the method we want to forward to |
|
21618
6632680b0683
8027232: Update j.l.invoke code generating class files to use ASM enhancements for invocation of non-abstract methods on ifaces
ksrini
parents:
21425
diff
changeset
|
468 |
visitMethodInsn(invocationOpcode(), implMethodClassName, |
6632680b0683
8027232: Update j.l.invoke code generating class files to use ASM enhancements for invocation of non-abstract methods on ifaces
ksrini
parents:
21425
diff
changeset
|
469 |
implMethodName, implMethodDesc, |
6632680b0683
8027232: Update j.l.invoke code generating class files to use ASM enhancements for invocation of non-abstract methods on ifaces
ksrini
parents:
21425
diff
changeset
|
470 |
implDefiningClass.isInterface()); |
14323 | 471 |
|
472 |
// Convert the return value (if any) and return it |
|
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
473 |
// Note: if adapting from non-void to void, the 'return' |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
474 |
// instruction will pop the unneeded result |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
475 |
Class<?> samReturnClass = methodType.returnType(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
476 |
convertType(implMethodReturnClass, samReturnClass, samReturnClass); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
477 |
visitInsn(getReturnOpcode(samReturnClass)); |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
478 |
// Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored |
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
479 |
visitMaxs(-1, -1); |
14323 | 480 |
visitEnd(); |
481 |
} |
|
482 |
||
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
483 |
private void convertArgumentTypes(MethodType samType) { |
14323 | 484 |
int lvIndex = 0; |
18716
9723e722b955
8016281: The SAM method should be passed to the metafactory as a MethodType not a MethodHandle
mcimadamore
parents:
18556
diff
changeset
|
485 |
boolean samIncludesReceiver = implIsInstanceMethod && |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
486 |
invokedType.parameterCount() == 0; |
14323 | 487 |
int samReceiverLength = samIncludesReceiver ? 1 : 0; |
488 |
if (samIncludesReceiver) { |
|
489 |
// push receiver |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
490 |
Class<?> rcvrType = samType.parameterType(0); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
491 |
visitVarInsn(getLoadOpcode(rcvrType), lvIndex + 1); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
492 |
lvIndex += getParameterSize(rcvrType); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
493 |
convertType(rcvrType, implDefiningClass, instantiatedMethodType.parameterType(0)); |
14323 | 494 |
} |
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
495 |
int samParametersLength = samType.parameterCount(); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
496 |
int argOffset = implMethodType.parameterCount() - samParametersLength; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
497 |
for (int i = samReceiverLength; i < samParametersLength; i++) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
498 |
Class<?> argType = samType.parameterType(i); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
499 |
visitVarInsn(getLoadOpcode(argType), lvIndex + 1); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
500 |
lvIndex += getParameterSize(argType); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
501 |
convertType(argType, implMethodType.parameterType(argOffset + i), instantiatedMethodType.parameterType(i)); |
14323 | 502 |
} |
503 |
} |
|
504 |
||
505 |
private int invocationOpcode() throws InternalError { |
|
506 |
switch (implKind) { |
|
507 |
case MethodHandleInfo.REF_invokeStatic: |
|
508 |
return INVOKESTATIC; |
|
509 |
case MethodHandleInfo.REF_newInvokeSpecial: |
|
510 |
return INVOKESPECIAL; |
|
511 |
case MethodHandleInfo.REF_invokeVirtual: |
|
512 |
return INVOKEVIRTUAL; |
|
513 |
case MethodHandleInfo.REF_invokeInterface: |
|
514 |
return INVOKEINTERFACE; |
|
515 |
case MethodHandleInfo.REF_invokeSpecial: |
|
516 |
return INVOKESPECIAL; |
|
517 |
default: |
|
518 |
throw new InternalError("Unexpected invocation kind: " + implKind); |
|
519 |
} |
|
520 |
} |
|
521 |
} |
|
21424
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
522 |
|
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
523 |
static int getParameterSize(Class<?> c) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
524 |
if (c == Void.TYPE) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
525 |
return 0; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
526 |
} else if (c == Long.TYPE || c == Double.TYPE) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
527 |
return 2; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
528 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
529 |
return 1; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
530 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
531 |
|
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
532 |
static int getLoadOpcode(Class<?> c) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
533 |
if(c == Void.TYPE) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
534 |
throw new InternalError("Unexpected void type of load opcode"); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
535 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
536 |
return ILOAD + getOpcodeOffset(c); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
537 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
538 |
|
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
539 |
static int getReturnOpcode(Class<?> c) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
540 |
if(c == Void.TYPE) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
541 |
return RETURN; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
542 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
543 |
return IRETURN + getOpcodeOffset(c); |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
544 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
545 |
|
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
546 |
private static int getOpcodeOffset(Class<?> c) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
547 |
if (c.isPrimitive()) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
548 |
if (c == Long.TYPE) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
549 |
return 1; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
550 |
} else if (c == Float.TYPE) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
551 |
return 2; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
552 |
} else if (c == Double.TYPE) { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
553 |
return 3; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
554 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
555 |
return 0; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
556 |
} else { |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
557 |
return 4; |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
558 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
559 |
} |
47236f604347
8024637: Lambda linkage performance - use reflection instead of ASM to manipulate parameter types
briangoetz
parents:
21417
diff
changeset
|
560 |
|
14323 | 561 |
} |