997 if (member.equals(target.internalMemberName())) |
1028 if (member.equals(target.internalMemberName())) |
998 return target; |
1029 return target; |
999 return new WrappedMember(target, target.type(), member, null); |
1030 return new WrappedMember(target, target.type(), member, null); |
1000 } |
1031 } |
1001 |
1032 |
|
1033 /// Collection of multiple arguments. |
|
1034 |
|
1035 private static MethodHandle findCollector(String name, int nargs, Class<?> rtype, Class<?>... ptypes) { |
|
1036 MethodType type = MethodType.genericMethodType(nargs) |
|
1037 .changeReturnType(rtype) |
|
1038 .insertParameterTypes(0, ptypes); |
|
1039 try { |
|
1040 return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type); |
|
1041 } catch (ReflectiveOperationException ex) { |
|
1042 return null; |
|
1043 } |
|
1044 } |
|
1045 |
|
1046 private static final Object[] NO_ARGS_ARRAY = {}; |
|
1047 private static Object[] makeArray(Object... args) { return args; } |
|
1048 private static Object[] array() { return NO_ARGS_ARRAY; } |
|
1049 private static Object[] array(Object a0) |
|
1050 { return makeArray(a0); } |
|
1051 private static Object[] array(Object a0, Object a1) |
|
1052 { return makeArray(a0, a1); } |
|
1053 private static Object[] array(Object a0, Object a1, Object a2) |
|
1054 { return makeArray(a0, a1, a2); } |
|
1055 private static Object[] array(Object a0, Object a1, Object a2, Object a3) |
|
1056 { return makeArray(a0, a1, a2, a3); } |
|
1057 private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1058 Object a4) |
|
1059 { return makeArray(a0, a1, a2, a3, a4); } |
|
1060 private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1061 Object a4, Object a5) |
|
1062 { return makeArray(a0, a1, a2, a3, a4, a5); } |
|
1063 private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1064 Object a4, Object a5, Object a6) |
|
1065 { return makeArray(a0, a1, a2, a3, a4, a5, a6); } |
|
1066 private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1067 Object a4, Object a5, Object a6, Object a7) |
|
1068 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } |
|
1069 private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1070 Object a4, Object a5, Object a6, Object a7, |
|
1071 Object a8) |
|
1072 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } |
|
1073 private static Object[] array(Object a0, Object a1, Object a2, Object a3, |
|
1074 Object a4, Object a5, Object a6, Object a7, |
|
1075 Object a8, Object a9) |
|
1076 { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } |
|
1077 private static MethodHandle[] makeArrays() { |
|
1078 ArrayList<MethodHandle> mhs = new ArrayList<>(); |
|
1079 for (;;) { |
|
1080 MethodHandle mh = findCollector("array", mhs.size(), Object[].class); |
|
1081 if (mh == null) break; |
|
1082 mhs.add(mh); |
|
1083 } |
|
1084 assert(mhs.size() == 11); // current number of methods |
|
1085 return mhs.toArray(new MethodHandle[MAX_ARITY+1]); |
|
1086 } |
|
1087 private static final MethodHandle[] ARRAYS = makeArrays(); |
|
1088 |
|
1089 // filling versions of the above: |
|
1090 // using Integer len instead of int len and no varargs to avoid bootstrapping problems |
|
1091 private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) { |
|
1092 Object[] a = new Object[len]; |
|
1093 fillWithArguments(a, 0, args); |
|
1094 return a; |
|
1095 } |
|
1096 private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) { |
|
1097 Object[] a = Arrays.copyOf(example, len); |
|
1098 fillWithArguments(a, 0, args); |
|
1099 return a; |
|
1100 } |
|
1101 private static void fillWithArguments(Object[] a, int pos, Object... args) { |
|
1102 System.arraycopy(args, 0, a, pos, args.length); |
|
1103 } |
|
1104 // using Integer pos instead of int pos to avoid bootstrapping problems |
|
1105 private static Object[] fillArray(Integer pos, Object[] a, Object a0) |
|
1106 { fillWithArguments(a, pos, a0); return a; } |
|
1107 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1) |
|
1108 { fillWithArguments(a, pos, a0, a1); return a; } |
|
1109 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2) |
|
1110 { fillWithArguments(a, pos, a0, a1, a2); return a; } |
|
1111 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3) |
|
1112 { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } |
|
1113 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, |
|
1114 Object a4) |
|
1115 { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } |
|
1116 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, |
|
1117 Object a4, Object a5) |
|
1118 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } |
|
1119 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, |
|
1120 Object a4, Object a5, Object a6) |
|
1121 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } |
|
1122 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, |
|
1123 Object a4, Object a5, Object a6, Object a7) |
|
1124 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } |
|
1125 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, |
|
1126 Object a4, Object a5, Object a6, Object a7, |
|
1127 Object a8) |
|
1128 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } |
|
1129 private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, |
|
1130 Object a4, Object a5, Object a6, Object a7, |
|
1131 Object a8, Object a9) |
|
1132 { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } |
|
1133 private static MethodHandle[] makeFillArrays() { |
|
1134 ArrayList<MethodHandle> mhs = new ArrayList<>(); |
|
1135 mhs.add(null); // there is no empty fill; at least a0 is required |
|
1136 for (;;) { |
|
1137 MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class); |
|
1138 if (mh == null) break; |
|
1139 mhs.add(mh); |
|
1140 } |
|
1141 assert(mhs.size() == 11); // current number of methods |
|
1142 return mhs.toArray(new MethodHandle[0]); |
|
1143 } |
|
1144 private static final MethodHandle[] FILL_ARRAYS = makeFillArrays(); |
|
1145 |
|
1146 private static Object[] copyAsReferenceArray(Class<? extends Object[]> arrayType, Object... a) { |
|
1147 return Arrays.copyOf(a, a.length, arrayType); |
|
1148 } |
|
1149 private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { |
|
1150 Object a = w.makeArray(boxes.length); |
|
1151 w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length); |
|
1152 return a; |
|
1153 } |
|
1154 |
|
1155 /** Return a method handle that takes the indicated number of Object |
|
1156 * arguments and returns an Object array of them, as if for varargs. |
|
1157 */ |
|
1158 static MethodHandle varargsArray(int nargs) { |
|
1159 MethodHandle mh = ARRAYS[nargs]; |
|
1160 if (mh != null) return mh; |
|
1161 mh = findCollector("array", nargs, Object[].class); |
|
1162 if (mh != null) return ARRAYS[nargs] = mh; |
|
1163 mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs); |
|
1164 assert(assertCorrectArity(mh, nargs)); |
|
1165 return ARRAYS[nargs] = mh; |
|
1166 } |
|
1167 |
|
1168 private static boolean assertCorrectArity(MethodHandle mh, int arity) { |
|
1169 assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh; |
|
1170 return true; |
|
1171 } |
|
1172 |
|
1173 // Array identity function (used as Lazy.MH_arrayIdentity). |
|
1174 static <T> T[] identity(T[] x) { |
|
1175 return x; |
|
1176 } |
|
1177 |
|
1178 private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) { |
|
1179 // Build up the result mh as a sequence of fills like this: |
|
1180 // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23)) |
|
1181 // The various fill(_,10*I,___*[J]) are reusable. |
|
1182 int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately |
|
1183 int rightLen = nargs - leftLen; |
|
1184 MethodHandle leftCollector = newArray.bindTo(nargs); |
|
1185 leftCollector = leftCollector.asCollector(Object[].class, leftLen); |
|
1186 MethodHandle mh = finisher; |
|
1187 if (rightLen > 0) { |
|
1188 MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen); |
|
1189 if (mh == Lazy.MH_arrayIdentity) |
|
1190 mh = rightFiller; |
|
1191 else |
|
1192 mh = MethodHandles.collectArguments(mh, 0, rightFiller); |
|
1193 } |
|
1194 if (mh == Lazy.MH_arrayIdentity) |
|
1195 mh = leftCollector; |
|
1196 else |
|
1197 mh = MethodHandles.collectArguments(mh, 0, leftCollector); |
|
1198 return mh; |
|
1199 } |
|
1200 |
|
1201 private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1); |
|
1202 private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; |
|
1203 /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) |
|
1204 * fills a[L]..a[N-1] with corresponding arguments, |
|
1205 * and then returns a. The value L is a global constant (LEFT_ARGS). |
|
1206 */ |
|
1207 private static MethodHandle fillToRight(int nargs) { |
|
1208 MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs]; |
|
1209 if (filler != null) return filler; |
|
1210 filler = buildFiller(nargs); |
|
1211 assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1)); |
|
1212 return FILL_ARRAY_TO_RIGHT[nargs] = filler; |
|
1213 } |
|
1214 private static MethodHandle buildFiller(int nargs) { |
|
1215 if (nargs <= LEFT_ARGS) |
|
1216 return Lazy.MH_arrayIdentity; // no args to fill; return the array unchanged |
|
1217 // we need room for both mh and a in mh.invoke(a, arg*[nargs]) |
|
1218 final int CHUNK = LEFT_ARGS; |
|
1219 int rightLen = nargs % CHUNK; |
|
1220 int midLen = nargs - rightLen; |
|
1221 if (rightLen == 0) { |
|
1222 midLen = nargs - (rightLen = CHUNK); |
|
1223 if (FILL_ARRAY_TO_RIGHT[midLen] == null) { |
|
1224 // build some precursors from left to right |
|
1225 for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) |
|
1226 if (j > LEFT_ARGS) fillToRight(j); |
|
1227 } |
|
1228 } |
|
1229 if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); |
|
1230 assert(rightLen > 0); |
|
1231 MethodHandle midFill = fillToRight(midLen); // recursive fill |
|
1232 MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] |
|
1233 assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); |
|
1234 assert(rightFill.type().parameterCount() == 1 + rightLen); |
|
1235 |
|
1236 // Combine the two fills: |
|
1237 // right(mid(a, x10..x19), x20..x23) |
|
1238 // The final product will look like this: |
|
1239 // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23) |
|
1240 if (midLen == LEFT_ARGS) |
|
1241 return rightFill; |
|
1242 else |
|
1243 return MethodHandles.collectArguments(rightFill, 0, midFill); |
|
1244 } |
|
1245 |
|
1246 // Type-polymorphic version of varargs maker. |
|
1247 private static final ClassValue<MethodHandle[]> TYPED_COLLECTORS |
|
1248 = new ClassValue<MethodHandle[]>() { |
|
1249 @Override |
|
1250 protected MethodHandle[] computeValue(Class<?> type) { |
|
1251 return new MethodHandle[256]; |
|
1252 } |
|
1253 }; |
|
1254 |
|
1255 static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM |
|
1256 |
|
1257 /** Return a method handle that takes the indicated number of |
|
1258 * typed arguments and returns an array of them. |
|
1259 * The type argument is the array type. |
|
1260 */ |
|
1261 static MethodHandle varargsArray(Class<?> arrayType, int nargs) { |
|
1262 Class<?> elemType = arrayType.getComponentType(); |
|
1263 if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); |
|
1264 // FIXME: Need more special casing and caching here. |
|
1265 if (nargs >= MAX_JVM_ARITY/2 - 1) { |
|
1266 int slots = nargs; |
|
1267 final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH |
|
1268 if (arrayType == double[].class || arrayType == long[].class) |
|
1269 slots *= 2; |
|
1270 if (slots > MAX_ARRAY_SLOTS) |
|
1271 throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs); |
|
1272 } |
|
1273 if (elemType == Object.class) |
|
1274 return varargsArray(nargs); |
|
1275 // other cases: primitive arrays, subtypes of Object[] |
|
1276 MethodHandle cache[] = TYPED_COLLECTORS.get(elemType); |
|
1277 MethodHandle mh = nargs < cache.length ? cache[nargs] : null; |
|
1278 if (mh != null) return mh; |
|
1279 if (elemType.isPrimitive()) { |
|
1280 MethodHandle builder = Lazy.MH_fillNewArray; |
|
1281 MethodHandle producer = buildArrayProducer(arrayType); |
|
1282 mh = buildVarargsArray(builder, producer, nargs); |
|
1283 } else { |
|
1284 @SuppressWarnings("unchecked") |
|
1285 Class<? extends Object[]> objArrayType = (Class<? extends Object[]>) arrayType; |
|
1286 Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType); |
|
1287 MethodHandle builder = Lazy.MH_fillNewTypedArray.bindTo(example); |
|
1288 MethodHandle producer = Lazy.MH_arrayIdentity; |
|
1289 mh = buildVarargsArray(builder, producer, nargs); |
|
1290 } |
|
1291 mh = mh.asType(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType))); |
|
1292 assert(assertCorrectArity(mh, nargs)); |
|
1293 if (nargs < cache.length) |
|
1294 cache[nargs] = mh; |
|
1295 return mh; |
|
1296 } |
|
1297 |
|
1298 private static MethodHandle buildArrayProducer(Class<?> arrayType) { |
|
1299 Class<?> elemType = arrayType.getComponentType(); |
|
1300 if (elemType.isPrimitive()) |
|
1301 return Lazy.MH_copyAsPrimitiveArray.bindTo(Wrapper.forPrimitiveType(elemType)); |
|
1302 else |
|
1303 return Lazy.MH_copyAsReferenceArray.bindTo(arrayType); |
|
1304 } |
1002 } |
1305 } |