49 * when the handle is created, not when it is invoked.
50 *
51 * All bound arguments are encapsulated in dedicated species.
52 */
53 /* non-public */ abstract class BoundMethodHandle extends MethodHandle {
54
55 /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) {
56 super(type, form);
57 }
58
59 //
60 // BMH API and internals
61 //
62
63 static MethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
64 // for some type signatures, there exist pre-defined concrete BMH classes
65 try {
66 switch (xtype) {
67 case L_TYPE:
68 if (true) return bindSingle(type, form, x); // Use known fast path.
69 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(L_TYPE).constructor[0].invokeBasic(type, form, x);
70 case I_TYPE:
71 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
72 case J_TYPE:
73 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor[0].invokeBasic(type, form, (long) x);
74 case F_TYPE:
75 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor[0].invokeBasic(type, form, (float) x);
76 case D_TYPE:
77 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor[0].invokeBasic(type, form, (double) x);
78 default : throw newInternalError("unexpected xtype: " + xtype);
79 }
80 } catch (Throwable t) {
81 throw newInternalError(t);
82 }
83 }
84
85 static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
86 return new Species_L(type, form, x);
87 }
88
89 MethodHandle cloneExtend(MethodType type, LambdaForm form, BasicType xtype, Object x) {
90 try {
91 switch (xtype) {
92 case L_TYPE: return copyWithExtendL(type, form, x);
93 case I_TYPE: return copyWithExtendI(type, form, ValueConversions.widenSubword(x));
94 case J_TYPE: return copyWithExtendJ(type, form, (long) x);
95 case F_TYPE: return copyWithExtendF(type, form, (float) x);
96 case D_TYPE: return copyWithExtendD(type, form, (double) x);
97 }
202 @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
203 @Override
204 /*non-public*/ SpeciesData speciesData() {
205 return SPECIES_DATA;
206 }
207 @Override
208 /*non-public*/ int fieldCount() {
209 return 1;
210 }
211 /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
212 /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
213 return new Species_L(mt, lf, argL0);
214 }
215 @Override
216 /*non-public*/ final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
217 return new Species_L(mt, lf, argL0);
218 }
219 @Override
220 /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
221 try {
222 return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
223 } catch (Throwable ex) {
224 throw uncaughtException(ex);
225 }
226 }
227 @Override
228 /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
229 try {
230 return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
231 } catch (Throwable ex) {
232 throw uncaughtException(ex);
233 }
234 }
235 @Override
236 /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
237 try {
238 return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
239 } catch (Throwable ex) {
240 throw uncaughtException(ex);
241 }
242 }
243 @Override
244 /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
245 try {
246 return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
247 } catch (Throwable ex) {
248 throw uncaughtException(ex);
249 }
250 }
251 @Override
252 /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
253 try {
254 return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
255 } catch (Throwable ex) {
256 throw uncaughtException(ex);
257 }
258 }
259 }
260
261 //
262 // BMH species meta-data
263 //
264
265 /**
266 * Meta-data wrapper for concrete BMH types.
267 * Each BMH type corresponds to a given sequence of basic field types (LIJFD).
268 * The fields are immutable; their values are fully specified at object construction.
269 * Each BMH type supplies an array of getter functions which may be used in lambda forms.
270 * A BMH is constructed by cloning a shorter BMH and adding one or more new field values.
271 * As a degenerate and common case, the "shorter BMH" can be missing, and contributes zero prior fields.
272 */
273 static class SpeciesData {
274 final String typeChars;
287 /*non-public*/ BasicType fieldType(int i) {
288 return typeCodes[i];
289 }
290 /*non-public*/ char fieldTypeChar(int i) {
291 return typeChars.charAt(i);
292 }
293
294 public String toString() {
295 return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+typeChars+"]";
296 }
297
298 /**
299 * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
300 * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
301 * getter.
302 */
303 NamedFunction getterFunction(int i) {
304 return nominalGetters[i];
305 }
306
307 static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
308
309 private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
310 this.typeChars = types;
311 this.typeCodes = basicTypes(types);
312 this.clazz = clazz;
313 if (!INIT_DONE) {
314 this.constructor = new MethodHandle[1]; // only one ctor
315 this.getters = new MethodHandle[types.length()];
316 this.nominalGetters = new NamedFunction[types.length()];
317 } else {
318 this.constructor = Factory.makeCtors(clazz, types, null);
319 this.getters = Factory.makeGetters(clazz, types, null);
320 this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters);
321 }
322 this.extensions = new SpeciesData[ARG_TYPE_LIMIT];
323 }
324
325 private void initForBootstrap() {
326 assert(!INIT_DONE);
327 if (constructor[0] == null) {
328 String types = typeChars;
329 Factory.makeCtors(clazz, types, this.constructor);
330 Factory.makeGetters(clazz, types, this.getters);
331 Factory.makeNominalGetters(types, this.nominalGetters, this.getters);
332 }
333 }
334
335 private SpeciesData(String typeChars) {
336 // Placeholder only.
337 this.typeChars = typeChars;
338 this.typeCodes = basicTypes(typeChars);
339 this.clazz = null;
340 this.constructor = null;
341 this.getters = null;
342 this.nominalGetters = null;
343 this.extensions = null;
344 }
345 private boolean isPlaceholder() { return clazz == null; }
346
347 private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
491 * final class Species_LLI extends BoundMethodHandle {
492 * final Object argL0;
493 * final Object argL1;
494 * final int argI2;
495 * private Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
496 * super(mt, lf);
497 * this.argL0 = argL0;
498 * this.argL1 = argL1;
499 * this.argI2 = argI2;
500 * }
501 * final SpeciesData speciesData() { return SPECIES_DATA; }
502 * final int fieldCount() { return 3; }
503 * static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
504 * static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
505 * return new Species_LLI(mt, lf, argL0, argL1, argI2);
506 * }
507 * final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
508 * return new Species_LLI(mt, lf, argL0, argL1, argI2);
509 * }
510 * final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
511 * return SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
512 * }
513 * final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
514 * return SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
515 * }
516 * final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
517 * return SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
518 * }
519 * final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
520 * return SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
521 * }
522 * public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
523 * return SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
524 * }
525 * }
526 * </pre>
527 *
528 * @param types the type signature, wherein reference types are erased to 'L'
529 * @return the generated concrete BMH class
530 */
531 static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
532 final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
533
534 String shortTypes = LambdaForm.shortenSignature(types);
535 final String className = SPECIES_PREFIX_PATH + shortTypes;
536 final String sourceFile = SPECIES_PREFIX_NAME + shortTypes;
537 final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC
538 cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
539 cw.visitSource(sourceFile, null);
540
541 // emit static types and SPECIES_DATA fields
542 cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
543
636 // make instance
637 mv.visitTypeInsn(NEW, className);
638 mv.visitInsn(DUP);
639 // load mt, lf
640 mv.visitVarInsn(ALOAD, 1);
641 mv.visitVarInsn(ALOAD, 2);
642 // put fields on the stack
643 emitPushFields(types, className, mv);
644 // finally, invoke the constructor and return
645 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
646 mv.visitInsn(ARETURN);
647 mv.visitMaxs(0, 0);
648 mv.visitEnd();
649
650 // for each type, emit copyWithExtendT()
651 for (BasicType type : BasicType.ARG_TYPES) {
652 int ord = type.ordinal();
653 char btChar = type.basicTypeChar();
654 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE);
655 mv.visitCode();
656 // return SPECIES_DATA.extendWith(t).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
657 // obtain constructor
658 mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
659 int iconstInsn = ICONST_0 + ord;
660 assert(iconstInsn <= ICONST_5);
661 mv.visitInsn(iconstInsn);
662 mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false);
663 mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
664 mv.visitInsn(ICONST_0);
665 mv.visitInsn(AALOAD);
666 // load mt, lf
667 mv.visitVarInsn(ALOAD, 1);
668 mv.visitVarInsn(ALOAD, 2);
669 // put fields on the stack
670 emitPushFields(types, className, mv);
671 // put narg on stack
672 mv.visitVarInsn(typeLoadOp(btChar), 3);
673 // finally, invoke the constructor and return
674 mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false);
675 mv.visitInsn(ARETURN);
676 mv.visitMaxs(0, 0);
677 mv.visitEnd();
678 }
679
680 // emit class initializer
681 mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
682 mv.visitCode();
683 mv.visitLdcInsn(types);
684 mv.visitLdcInsn(Type.getObjectType(className));
685 mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false);
|
49 * when the handle is created, not when it is invoked.
50 *
51 * All bound arguments are encapsulated in dedicated species.
52 */
53 /* non-public */ abstract class BoundMethodHandle extends MethodHandle {
54
55 /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) {
56 super(type, form);
57 }
58
59 //
60 // BMH API and internals
61 //
62
63 static MethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
64 // for some type signatures, there exist pre-defined concrete BMH classes
65 try {
66 switch (xtype) {
67 case L_TYPE:
68 if (true) return bindSingle(type, form, x); // Use known fast path.
69 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(L_TYPE).constructor().invokeBasic(type, form, x);
70 case I_TYPE:
71 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x));
72 case J_TYPE:
73 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x);
74 case F_TYPE:
75 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x);
76 case D_TYPE:
77 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x);
78 default : throw newInternalError("unexpected xtype: " + xtype);
79 }
80 } catch (Throwable t) {
81 throw newInternalError(t);
82 }
83 }
84
85 static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
86 return new Species_L(type, form, x);
87 }
88
89 MethodHandle cloneExtend(MethodType type, LambdaForm form, BasicType xtype, Object x) {
90 try {
91 switch (xtype) {
92 case L_TYPE: return copyWithExtendL(type, form, x);
93 case I_TYPE: return copyWithExtendI(type, form, ValueConversions.widenSubword(x));
94 case J_TYPE: return copyWithExtendJ(type, form, (long) x);
95 case F_TYPE: return copyWithExtendF(type, form, (float) x);
96 case D_TYPE: return copyWithExtendD(type, form, (double) x);
97 }
202 @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
203 @Override
204 /*non-public*/ SpeciesData speciesData() {
205 return SPECIES_DATA;
206 }
207 @Override
208 /*non-public*/ int fieldCount() {
209 return 1;
210 }
211 /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
212 /*non-public*/ static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0) {
213 return new Species_L(mt, lf, argL0);
214 }
215 @Override
216 /*non-public*/ final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
217 return new Species_L(mt, lf, argL0);
218 }
219 @Override
220 /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
221 try {
222 return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
223 } catch (Throwable ex) {
224 throw uncaughtException(ex);
225 }
226 }
227 @Override
228 /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
229 try {
230 return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
231 } catch (Throwable ex) {
232 throw uncaughtException(ex);
233 }
234 }
235 @Override
236 /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
237 try {
238 return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
239 } catch (Throwable ex) {
240 throw uncaughtException(ex);
241 }
242 }
243 @Override
244 /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
245 try {
246 return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
247 } catch (Throwable ex) {
248 throw uncaughtException(ex);
249 }
250 }
251 @Override
252 /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
253 try {
254 return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, narg);
255 } catch (Throwable ex) {
256 throw uncaughtException(ex);
257 }
258 }
259 }
260
261 //
262 // BMH species meta-data
263 //
264
265 /**
266 * Meta-data wrapper for concrete BMH types.
267 * Each BMH type corresponds to a given sequence of basic field types (LIJFD).
268 * The fields are immutable; their values are fully specified at object construction.
269 * Each BMH type supplies an array of getter functions which may be used in lambda forms.
270 * A BMH is constructed by cloning a shorter BMH and adding one or more new field values.
271 * As a degenerate and common case, the "shorter BMH" can be missing, and contributes zero prior fields.
272 */
273 static class SpeciesData {
274 final String typeChars;
287 /*non-public*/ BasicType fieldType(int i) {
288 return typeCodes[i];
289 }
290 /*non-public*/ char fieldTypeChar(int i) {
291 return typeChars.charAt(i);
292 }
293
294 public String toString() {
295 return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+typeChars+"]";
296 }
297
298 /**
299 * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
300 * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
301 * getter.
302 */
303 NamedFunction getterFunction(int i) {
304 return nominalGetters[i];
305 }
306
307 MethodHandle constructor() {
308 return constructor[0];
309 }
310
311 static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
312
313 private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
314 this.typeChars = types;
315 this.typeCodes = basicTypes(types);
316 this.clazz = clazz;
317 if (!INIT_DONE) {
318 this.constructor = new MethodHandle[1]; // only one ctor
319 this.getters = new MethodHandle[types.length()];
320 this.nominalGetters = new NamedFunction[types.length()];
321 } else {
322 this.constructor = Factory.makeCtors(clazz, types, null);
323 this.getters = Factory.makeGetters(clazz, types, null);
324 this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters);
325 }
326 this.extensions = new SpeciesData[ARG_TYPE_LIMIT];
327 }
328
329 private void initForBootstrap() {
330 assert(!INIT_DONE);
331 if (constructor() == null) {
332 String types = typeChars;
333 Factory.makeCtors(clazz, types, this.constructor);
334 Factory.makeGetters(clazz, types, this.getters);
335 Factory.makeNominalGetters(types, this.nominalGetters, this.getters);
336 }
337 }
338
339 private SpeciesData(String typeChars) {
340 // Placeholder only.
341 this.typeChars = typeChars;
342 this.typeCodes = basicTypes(typeChars);
343 this.clazz = null;
344 this.constructor = null;
345 this.getters = null;
346 this.nominalGetters = null;
347 this.extensions = null;
348 }
349 private boolean isPlaceholder() { return clazz == null; }
350
351 private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
495 * final class Species_LLI extends BoundMethodHandle {
496 * final Object argL0;
497 * final Object argL1;
498 * final int argI2;
499 * private Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
500 * super(mt, lf);
501 * this.argL0 = argL0;
502 * this.argL1 = argL1;
503 * this.argI2 = argI2;
504 * }
505 * final SpeciesData speciesData() { return SPECIES_DATA; }
506 * final int fieldCount() { return 3; }
507 * static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
508 * static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
509 * return new Species_LLI(mt, lf, argL0, argL1, argI2);
510 * }
511 * final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
512 * return new Species_LLI(mt, lf, argL0, argL1, argI2);
513 * }
514 * final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
515 * return SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
516 * }
517 * final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
518 * return SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
519 * }
520 * final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
521 * return SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
522 * }
523 * final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
524 * return SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
525 * }
526 * public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
527 * return SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg);
528 * }
529 * }
530 * </pre>
531 *
532 * @param types the type signature, wherein reference types are erased to 'L'
533 * @return the generated concrete BMH class
534 */
535 static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
536 final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
537
538 String shortTypes = LambdaForm.shortenSignature(types);
539 final String className = SPECIES_PREFIX_PATH + shortTypes;
540 final String sourceFile = SPECIES_PREFIX_NAME + shortTypes;
541 final int NOT_ACC_PUBLIC = 0; // not ACC_PUBLIC
542 cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
543 cw.visitSource(sourceFile, null);
544
545 // emit static types and SPECIES_DATA fields
546 cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
547
640 // make instance
641 mv.visitTypeInsn(NEW, className);
642 mv.visitInsn(DUP);
643 // load mt, lf
644 mv.visitVarInsn(ALOAD, 1);
645 mv.visitVarInsn(ALOAD, 2);
646 // put fields on the stack
647 emitPushFields(types, className, mv);
648 // finally, invoke the constructor and return
649 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
650 mv.visitInsn(ARETURN);
651 mv.visitMaxs(0, 0);
652 mv.visitEnd();
653
654 // for each type, emit copyWithExtendT()
655 for (BasicType type : BasicType.ARG_TYPES) {
656 int ord = type.ordinal();
657 char btChar = type.basicTypeChar();
658 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE);
659 mv.visitCode();
660 // return SPECIES_DATA.extendWith(t).constructor().invokeBasic(mt, lf, argL0, ..., narg)
661 // obtain constructor
662 mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
663 int iconstInsn = ICONST_0 + ord;
664 assert(iconstInsn <= ICONST_5);
665 mv.visitInsn(iconstInsn);
666 mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false);
667 mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "constructor", "()" + MH_SIG, false);
668 // load mt, lf
669 mv.visitVarInsn(ALOAD, 1);
670 mv.visitVarInsn(ALOAD, 2);
671 // put fields on the stack
672 emitPushFields(types, className, mv);
673 // put narg on stack
674 mv.visitVarInsn(typeLoadOp(btChar), 3);
675 // finally, invoke the constructor and return
676 mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false);
677 mv.visitInsn(ARETURN);
678 mv.visitMaxs(0, 0);
679 mv.visitEnd();
680 }
681
682 // emit class initializer
683 mv = cw.visitMethod(NOT_ACC_PUBLIC | ACC_STATIC, "<clinit>", VOID_SIG, null, null);
684 mv.visitCode();
685 mv.visitLdcInsn(types);
686 mv.visitLdcInsn(Type.getObjectType(className));
687 mv.visitMethodInsn(INVOKESTATIC, SPECIES_DATA, "getForClass", BMHSPECIES_DATA_GFC_SIG, false);
|