17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import java.lang.annotation.*;
29 import java.lang.reflect.Method;
30 import java.util.Map;
31 import java.util.List;
32 import java.util.Arrays;
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.concurrent.ConcurrentHashMap;
36 import sun.invoke.util.Wrapper;
37 import static java.lang.invoke.MethodHandleStatics.*;
38 import static java.lang.invoke.MethodHandleNatives.Constants.*;
39 import java.lang.reflect.Field;
40 import java.util.Objects;
41
42 /**
43 * The symbolic, non-executable form of a method handle's invocation semantics.
44 * It consists of a series of names.
45 * The first N (N=arity) names are parameters,
46 * while any remaining names are temporary values.
47 * Each temporary specifies the application of a function to some arguments.
48 * The functions are method handles, while the arguments are mixes of
49 * constant values and local names.
50 * The result of the lambda is defined as one of the names, often the last one.
51 * <p>
52 * Here is an approximate grammar:
53 * <pre>
54 * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
55 * ArgName = "a" N ":" T
56 * TempName = "t" N ":" T "=" Function "(" Argument* ");"
103 * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
104 * t3:L = MethodHandle#invoke(t2, a1);
105 * t4:L = FilterMethodHandle#target(a0);
106 * t5:L = MethodHandle#invoke(t4, t3); t5 }
107 * == general invoker for unary filterArgument combination
108 * (a0:L, a1:L)=>{ ...(same as previous example)...
109 * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
110 * == general invoker for unary/unary foldArgument combination
111 * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
112 * == invoker for identity method handle which performs i2l
113 * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
114 * t3:L = Class#cast(t2,a1); t3 }
115 * == invoker for identity method handle which performs cast
116 * </pre>
117 * <p>
118 * @author John Rose, JSR 292 EG
119 */
120 class LambdaForm {
121 final int arity;
122 final int result;
123 final Name[] names;
124 final String debugName;
125 MemberName vmentry; // low-level behavior, or null if not yet prepared
126 private boolean isCompiled;
127
128 // Caches for common structural transforms:
129 LambdaForm[] bindCache;
130
131 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
132
133 LambdaForm(String debugName,
134 int arity, Name[] names, int result) {
135 assert(namesOK(arity, names));
136 this.arity = arity;
137 this.result = fixResult(result, names);
138 this.names = names.clone();
139 this.debugName = debugName;
140 normalize();
141 }
142
143 LambdaForm(String debugName,
954 for (int k = i+1; k < names2.length; k++) {
955 names2[k] = names2[k].replaceName(n, n2);
956 }
957 }
958 }
959 return new LambdaForm(debugName, arity2, names2, result2);
960 }
961
962 static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) {
963 int inTypes = types.length;
964 int outArgs = reorder.length;
965 for (int i = 0; i < outArgs; i++) {
966 assert(names[skip+i].isParam());
967 assert(names[skip+i].type == types[reorder[i]]);
968 }
969 return true;
970 }
971
972 static class NamedFunction {
973 final MemberName member;
974 MethodHandle resolvedHandle;
975 MethodHandle invoker;
976
977 NamedFunction(MethodHandle resolvedHandle) {
978 this(resolvedHandle.internalMemberName(), resolvedHandle);
979 }
980 NamedFunction(MemberName member, MethodHandle resolvedHandle) {
981 this.member = member;
982 //resolvedHandle = eraseSubwordTypes(resolvedHandle);
983 this.resolvedHandle = resolvedHandle;
984 }
985
986 // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
987 // Any LambdaForm containing such a member is not interpretable.
988 // This is OK, since all such LFs are prepared with special primitive vmentry points.
989 // And even without the resolvedHandle, the name can still be compiled and optimized.
990 NamedFunction(Method method) {
991 this(new MemberName(method));
992 }
993 NamedFunction(Field field) {
994 this(new MemberName(field));
995 }
1250 btypes[i] = basicType(types.get(i));
1251 }
1252 return btypes;
1253 }
1254 public static String basicTypeSignature(MethodType type) {
1255 char[] sig = new char[type.parameterCount() + 2];
1256 int sigp = 0;
1257 for (Class<?> pt : type.parameterList()) {
1258 sig[sigp++] = basicType(pt);
1259 }
1260 sig[sigp++] = '_';
1261 sig[sigp++] = basicType(type.returnType());
1262 assert(sigp == sig.length);
1263 return String.valueOf(sig);
1264 }
1265
1266 static final class Name {
1267 final char type;
1268 private short index;
1269 final NamedFunction function;
1270 final Object[] arguments;
1271
1272 private Name(int index, char type, NamedFunction function, Object[] arguments) {
1273 this.index = (short)index;
1274 this.type = type;
1275 this.function = function;
1276 this.arguments = arguments;
1277 assert(this.index == index);
1278 }
1279 Name(MethodHandle function, Object... arguments) {
1280 this(new NamedFunction(function), arguments);
1281 }
1282 Name(MemberName function, Object... arguments) {
1283 this(new NamedFunction(function), arguments);
1284 }
1285 Name(NamedFunction function, Object... arguments) {
1286 this(-1, function.returnType(), function, arguments = arguments.clone());
1287 assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
1288 for (int i = 0; i < arguments.length; i++)
1289 assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
1290 }
|
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.invoke;
27
28 import java.lang.annotation.*;
29 import java.lang.reflect.Method;
30 import java.util.Map;
31 import java.util.List;
32 import java.util.Arrays;
33 import java.util.ArrayList;
34 import java.util.HashMap;
35 import java.util.concurrent.ConcurrentHashMap;
36 import sun.invoke.util.Wrapper;
37 import sun.invoke.Stable;
38 import static java.lang.invoke.MethodHandleStatics.*;
39 import static java.lang.invoke.MethodHandleNatives.Constants.*;
40 import java.lang.reflect.Field;
41 import java.util.Objects;
42
43 /**
44 * The symbolic, non-executable form of a method handle's invocation semantics.
45 * It consists of a series of names.
46 * The first N (N=arity) names are parameters,
47 * while any remaining names are temporary values.
48 * Each temporary specifies the application of a function to some arguments.
49 * The functions are method handles, while the arguments are mixes of
50 * constant values and local names.
51 * The result of the lambda is defined as one of the names, often the last one.
52 * <p>
53 * Here is an approximate grammar:
54 * <pre>
55 * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
56 * ArgName = "a" N ":" T
57 * TempName = "t" N ":" T "=" Function "(" Argument* ");"
104 * (a0:L, a1:L)=>{ t2:L = FilterMethodHandle#filter(a0);
105 * t3:L = MethodHandle#invoke(t2, a1);
106 * t4:L = FilterMethodHandle#target(a0);
107 * t5:L = MethodHandle#invoke(t4, t3); t5 }
108 * == general invoker for unary filterArgument combination
109 * (a0:L, a1:L)=>{ ...(same as previous example)...
110 * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
111 * == general invoker for unary/unary foldArgument combination
112 * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
113 * == invoker for identity method handle which performs i2l
114 * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
115 * t3:L = Class#cast(t2,a1); t3 }
116 * == invoker for identity method handle which performs cast
117 * </pre>
118 * <p>
119 * @author John Rose, JSR 292 EG
120 */
121 class LambdaForm {
122 final int arity;
123 final int result;
124 @Stable final Name[] names;
125 final String debugName;
126 MemberName vmentry; // low-level behavior, or null if not yet prepared
127 private boolean isCompiled;
128
129 // Caches for common structural transforms:
130 LambdaForm[] bindCache;
131
132 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
133
134 LambdaForm(String debugName,
135 int arity, Name[] names, int result) {
136 assert(namesOK(arity, names));
137 this.arity = arity;
138 this.result = fixResult(result, names);
139 this.names = names.clone();
140 this.debugName = debugName;
141 normalize();
142 }
143
144 LambdaForm(String debugName,
955 for (int k = i+1; k < names2.length; k++) {
956 names2[k] = names2[k].replaceName(n, n2);
957 }
958 }
959 }
960 return new LambdaForm(debugName, arity2, names2, result2);
961 }
962
963 static boolean permutedTypesMatch(int[] reorder, char[] types, Name[] names, int skip) {
964 int inTypes = types.length;
965 int outArgs = reorder.length;
966 for (int i = 0; i < outArgs; i++) {
967 assert(names[skip+i].isParam());
968 assert(names[skip+i].type == types[reorder[i]]);
969 }
970 return true;
971 }
972
973 static class NamedFunction {
974 final MemberName member;
975 @Stable MethodHandle resolvedHandle;
976 @Stable MethodHandle invoker;
977
978 NamedFunction(MethodHandle resolvedHandle) {
979 this(resolvedHandle.internalMemberName(), resolvedHandle);
980 }
981 NamedFunction(MemberName member, MethodHandle resolvedHandle) {
982 this.member = member;
983 //resolvedHandle = eraseSubwordTypes(resolvedHandle);
984 this.resolvedHandle = resolvedHandle;
985 }
986
987 // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc.
988 // Any LambdaForm containing such a member is not interpretable.
989 // This is OK, since all such LFs are prepared with special primitive vmentry points.
990 // And even without the resolvedHandle, the name can still be compiled and optimized.
991 NamedFunction(Method method) {
992 this(new MemberName(method));
993 }
994 NamedFunction(Field field) {
995 this(new MemberName(field));
996 }
1251 btypes[i] = basicType(types.get(i));
1252 }
1253 return btypes;
1254 }
1255 public static String basicTypeSignature(MethodType type) {
1256 char[] sig = new char[type.parameterCount() + 2];
1257 int sigp = 0;
1258 for (Class<?> pt : type.parameterList()) {
1259 sig[sigp++] = basicType(pt);
1260 }
1261 sig[sigp++] = '_';
1262 sig[sigp++] = basicType(type.returnType());
1263 assert(sigp == sig.length);
1264 return String.valueOf(sig);
1265 }
1266
1267 static final class Name {
1268 final char type;
1269 private short index;
1270 final NamedFunction function;
1271 @Stable final Object[] arguments;
1272
1273 private Name(int index, char type, NamedFunction function, Object[] arguments) {
1274 this.index = (short)index;
1275 this.type = type;
1276 this.function = function;
1277 this.arguments = arguments;
1278 assert(this.index == index);
1279 }
1280 Name(MethodHandle function, Object... arguments) {
1281 this(new NamedFunction(function), arguments);
1282 }
1283 Name(MemberName function, Object... arguments) {
1284 this(new NamedFunction(function), arguments);
1285 }
1286 Name(NamedFunction function, Object... arguments) {
1287 this(-1, function.returnType(), function, arguments = arguments.clone());
1288 assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString();
1289 for (int i = 0; i < arguments.length; i++)
1290 assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString();
1291 }
|