1
25
26 package java.lang.invoke;
27
28 import jdk.internal.vm.annotation.Stable;
29 import sun.invoke.util.ValueConversions;
30
31 import java.util.ArrayList;
32 import java.util.List;
33
34 import static java.lang.invoke.LambdaForm.BasicType;
35 import static java.lang.invoke.LambdaForm.BasicType.*;
36 import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM;
37 import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM;
38 import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM;
39 import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
40 import static java.lang.invoke.MethodHandleNatives.Constants.*;
41 import static java.lang.invoke.MethodHandleStatics.newInternalError;
42 import static java.lang.invoke.MethodHandleStatics.uncaughtException;
43
44
51 abstract class BoundMethodHandle extends MethodHandle {
52
53 BoundMethodHandle(MethodType type, LambdaForm form) {
54 super(type, form);
55 assert(speciesData() == speciesDataFor(form));
56 }
57
58
59
60
61
62 static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
63
64 try {
65 switch (xtype) {
66 case L_TYPE:
67 return bindSingle(type, form, x);
68 case I_TYPE:
69 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(I_TYPE_NUM).factory().invokeBasic(type, form, ValueConversions.widenSubword(x));
70 case J_TYPE:
71 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(J_TYPE_NUM).factory().invokeBasic(type, form, (long) x);
72 case F_TYPE:
73 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(F_TYPE_NUM).factory().invokeBasic(type, form, (float) x);
74 case D_TYPE:
75 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(D_TYPE_NUM).factory().invokeBasic(type, form, (double) x);
76 default : throw newInternalError("unexpected xtype: " + xtype);
77 }
78 } catch (Throwable t) {
79 throw uncaughtException(t);
80 }
81 }
82
83
84 LambdaFormEditor editor() {
85 return form.editor();
86 }
87
88 static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
89 return Species_L.make(type, form, x);
90 }
91
92 @Override
93
94 BoundMethodHandle bindArgumentL(int pos, Object value) {
95 return editor().bindArgumentL(this, pos, value);
96 }
97
98
99 BoundMethodHandle bindArgumentI(int pos, int value) {
100 return editor().bindArgumentI(this, pos, value);
101 }
102
103 BoundMethodHandle bindArgumentJ(int pos, long value) {
104 return editor().bindArgumentJ(this, pos, value);
105 }
106
107 BoundMethodHandle bindArgumentF(int pos, float value) {
108 return editor().bindArgumentF(this, pos, value);
109 }
110
111 BoundMethodHandle bindArgumentD(int pos, double value) {
112 return editor().bindArgumentD(this, pos, value);
113 }
114 @Override
115 BoundMethodHandle rebind() {
116 if (!tooComplex()) {
117 return this;
118 }
119 return makeReinvoker(this);
120 }
121
122 private boolean tooComplex() {
123 return (fieldCount() > FIELD_COUNT_THRESHOLD ||
124 form.expressionCount() > FORM_EXPRESSION_THRESHOLD);
125 }
126 private static final int FIELD_COUNT_THRESHOLD = 12;
127 private static final int FORM_EXPRESSION_THRESHOLD = 24;
128
129
133 static BoundMethodHandle makeReinvoker(MethodHandle target) {
134 LambdaForm form = DelegatingMethodHandle.makeReinvokerForm(
135 target, MethodTypeForm.LF_REBIND,
136 Species_L.BMH_SPECIES, Species_L.BMH_SPECIES.getterFunction(0));
137 return Species_L.make(target.type(), form, target);
138 }
139
140
144 abstract BoundMethodHandle.SpeciesData speciesData();
145
146 static BoundMethodHandle.SpeciesData speciesDataFor(LambdaForm form) {
147 Object c = form.names[0].constraint;
148 if (c instanceof SpeciesData) {
149 return (SpeciesData) c;
150 }
151
152 return SPECIALIZER.topSpecies();
153 }
154
155
158 final int fieldCount() { return speciesData().fieldCount(); }
159
160 @Override
161 Object internalProperties() {
162 return "\n& BMH="+internalValues();
163 }
164
165 @Override
166 final String internalValues() {
167 int count = fieldCount();
168 if (count == 1) {
169 return "[" + arg(0) + "]";
170 }
171 StringBuilder sb = new StringBuilder("[");
172 for (int i = 0; i < count; ++i) {
173 sb.append("\n ").append(i).append(": ( ").append(arg(i)).append(" )");
174 }
175 return sb.append("\n]").toString();
176 }
177
178 final Object arg(int i) {
179 try {
180 Class<?> fieldType = speciesData().fieldTypes().get(i);
181 switch (BasicType.basicType(fieldType)) {
182 case L_TYPE: return speciesData().getter(i).invokeBasic(this);
183 case I_TYPE: return (int) speciesData().getter(i).invokeBasic(this);
184 case J_TYPE: return (long) speciesData().getter(i).invokeBasic(this);
185 case F_TYPE: return (float) speciesData().getter(i).invokeBasic(this);
186 case D_TYPE: return (double) speciesData().getter(i).invokeBasic(this);
187 }
188 } catch (Throwable ex) {
189 throw uncaughtException(ex);
190 }
191 throw new InternalError("unexpected type: " + speciesData().key()+"."+i);
192 }
193
194
195
196
197
198 abstract BoundMethodHandle copyWith(MethodType mt, LambdaForm lf);
199 abstract BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg);
200 abstract BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg);
201 abstract BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg);
202 abstract BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg);
203 abstract BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg);
204
205
206
207
208
209 private
210 static final class Species_L extends BoundMethodHandle {
211
212 final Object argL0;
213
214 private Species_L(MethodType mt, LambdaForm lf, Object argL0) {
215 super(mt, lf);
216 this.argL0 = argL0;
217 }
218
219 @Override
220 SpeciesData speciesData() {
221 return BMH_SPECIES;
222 }
223
224 static @Stable SpeciesData BMH_SPECIES;
225
226 static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
227 return new Species_L(mt, lf, argL0);
228 }
229 @Override
230 final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
231 return new Species_L(mt, lf, argL0);
232 }
233 @Override
234 final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
235 try {
236 return (BoundMethodHandle) BMH_SPECIES.extendWith(L_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
237 } catch (Throwable ex) {
238 throw uncaughtException(ex);
239 }
240 }
241 @Override
242 final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
243 try {
244 return (BoundMethodHandle) BMH_SPECIES.extendWith(I_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
245 } catch (Throwable ex) {
246 throw uncaughtException(ex);
247 }
248 }
249 @Override
250 final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
251 try {
252 return (BoundMethodHandle) BMH_SPECIES.extendWith(J_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
253 } catch (Throwable ex) {
254 throw uncaughtException(ex);
255 }
256 }
257 @Override
258 final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
259 try {
260 return (BoundMethodHandle) BMH_SPECIES.extendWith(F_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
261 } catch (Throwable ex) {
262 throw uncaughtException(ex);
263 }
264 }
265 @Override
266 final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
267 try {
268 return (BoundMethodHandle) BMH_SPECIES.extendWith(D_TYPE_NUM).factory().invokeBasic(mt, lf, argL0, narg);
269 } catch (Throwable ex) {
270 throw uncaughtException(ex);
271 }
272 }
273 }
274
275
276
277
278
279
280 static final class SpeciesData extends ClassSpecializer<BoundMethodHandle, String, SpeciesData>.SpeciesData {
281
282 @Stable final private SpeciesData[] extensions = new SpeciesData[ARG_TYPE_LIMIT];
283
284 public SpeciesData(Specializer outer, String key) {
285 outer.super(key);
286 }
287
288 @Override
289 protected String deriveClassName() {
290 String typeString = deriveTypeString();
291 if (typeString.isEmpty()) {
292 return SimpleMethodHandle.class.getName();
293 }
294 return BoundMethodHandle.class.getName() + "$Species_" + typeString;
295 }
296
297 @Override
298 protected List<Class<?>> deriveFieldTypes(String key) {
299 ArrayList<Class<?>> types = new ArrayList<>(key.length());
300 for (int i = 0; i < key.length(); i++) {
301 types.add(basicType(key.charAt(i)).basicTypeClass());
302 }
303 return types;
304 }
305
306 @Override
307 protected String deriveTypeString() {
308
309 return key();
310 }
311
312 @Override
313 protected MethodHandle deriveTransformHelper(MemberName transform, int whichtm) {
314 if (whichtm == Specializer.TN_COPY_NO_EXTEND) {
315 return factory();
316 } else if (whichtm < ARG_TYPE_LIMIT) {
317 return extendWith((byte) whichtm).factory();
318 } else {
319 throw newInternalError("bad transform");
320 }
321 }
322
323 @Override
324 protected <X> List<X> deriveTransformHelperArguments(MemberName transform, int whichtm, List<X> args, List<X> fields) {
325 assert(verifyTHAargs(transform, whichtm, args, fields));
326
327
328 args.addAll(2, fields);
329 return args;
330 }
331
332 private boolean verifyTHAargs(MemberName transform, int whichtm, List<?> args, List<?> fields) {
333 assert(transform == Specializer.BMH_TRANSFORMS.get(whichtm));
334 assert(args.size() == transform.getMethodType().parameterCount());
335 assert(fields.size() == this.fieldCount());
336 final int MH_AND_LF = 2;
337 if (whichtm == Specializer.TN_COPY_NO_EXTEND) {
338 assert(transform.getMethodType().parameterCount() == MH_AND_LF);
339 } else if (whichtm < ARG_TYPE_LIMIT) {
340 assert(transform.getMethodType().parameterCount() == MH_AND_LF+1);
341 final BasicType type = basicType((byte) whichtm);
342 assert(transform.getParameterTypes()[MH_AND_LF] == type.basicTypeClass());
343 } else {
344 return false;
345 }
346 return true;
347 }
348
349 SpeciesData extendWith(byte typeNum) {
350 SpeciesData sd = extensions[typeNum];
351 if (sd != null) return sd;
352 sd = SPECIALIZER.findSpecies(key() + BasicType.basicType(typeNum).basicTypeChar());
353 extensions[typeNum] = sd;
354 return sd;
355 }
356 }
357
358
359 static final Specializer SPECIALIZER = new Specializer();
360 static {
361 SimpleMethodHandle.BMH_SPECIES = BoundMethodHandle.SPECIALIZER.findSpecies("");
362 Species_L.BMH_SPECIES = BoundMethodHandle.SPECIALIZER.findSpecies("L");
363 }
364
365
366 static final class Specializer extends ClassSpecializer<BoundMethodHandle, String, SpeciesData> {
367
368 private static final MemberName SPECIES_DATA_ACCESSOR;
369
370 static {
371 try {
372 SPECIES_DATA_ACCESSOR = IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BoundMethodHandle.class,
373 "speciesData", MethodType.methodType(BoundMethodHandle.SpeciesData.class));
374 } catch (ReflectiveOperationException ex) {
375 throw newInternalError("Bootstrap link error", ex);
376 }
377 }
378
379 private Specializer() {
380 super(
381 BoundMethodHandle.class, String.class, BoundMethodHandle.SpeciesData.class,
382
383 MethodType.methodType(void.class, MethodType.class, LambdaForm.class),
384
385 SPECIES_DATA_ACCESSOR,
386 "BMH_SPECIES",
387 BMH_TRANSFORMS);
388 }
389
390 @Override
391 protected String topSpeciesKey() {
392 return "";
393 }
394
395 @Override
396 protected BoundMethodHandle.SpeciesData newSpeciesData(String key) {
397 return new BoundMethodHandle.SpeciesData(this, key);
398 }
399
400 static final List<MemberName> BMH_TRANSFORMS;
401 static final int TN_COPY_NO_EXTEND = V_TYPE_NUM;
402 static {
403 final Class<BoundMethodHandle> BMH = BoundMethodHandle.class;
404
405 try {
406 BMH_TRANSFORMS = List.of(
407 IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendL", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, Object.class)),
408 IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendI", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, int.class)),
409 IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendJ", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, long.class)),
410 IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendF", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, float.class)),
411 IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWithExtendD", MethodType.methodType(BMH, MethodType.class, LambdaForm.class, double.class)),
412 IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, BMH, "copyWith", MethodType.methodType(BMH, MethodType.class, LambdaForm.class))
413 );
414 } catch (ReflectiveOperationException ex) {
415 throw newInternalError("Failed resolving copyWith methods", ex);
416 }
417
418
419 assert(BMH_TRANSFORMS.size() == TYPE_LIMIT);
420 }
421
422
434 class Factory extends ClassSpecializer<BoundMethodHandle, String, BoundMethodHandle.SpeciesData>.Factory {
435 @Override
436 protected String chooseFieldName(Class<?> type, int index) {
437 return "arg" + super.chooseFieldName(type, index);
438 }
439 }
440
441 @Override
442 protected Factory makeFactory() {
443 return new Factory();
444 }
445 }
446
447 static SpeciesData speciesData_L() { return Species_L.BMH_SPECIES; }
448 static SpeciesData speciesData_LL() { return SPECIALIZER.findSpecies("LL"); }
449 static SpeciesData speciesData_LLL() { return SPECIALIZER.findSpecies("LLL"); }
450 static SpeciesData speciesData_LLLL() { return SPECIALIZER.findSpecies("LLLL"); }
451 static SpeciesData speciesData_LLLLL() { return SPECIALIZER.findSpecies("LLLLL"); }
452 }
453