379
380 SpeciesData extendWith(byte type) {
381 return extendWith(BasicType.basicType(type));
382 }
383
384 SpeciesData extendWith(BasicType type) {
385 int ord = type.ordinal();
386 SpeciesData d = extensions[ord];
387 if (d != null) return d;
388 extensions[ord] = d = get(typeChars+type.basicTypeChar());
389 return d;
390 }
391
392 private static SpeciesData get(String types) {
393 // Acquire cache lock for query.
394 SpeciesData d = lookupCache(types);
395 if (!d.isPlaceholder())
396 return d;
397 synchronized (d) {
398 // Use synch. on the placeholder to prevent multiple instantiation of one species.
399 // Creating this class forces a recursive call to getForClass.
400 if (lookupCache(types).isPlaceholder())
401 Factory.generateConcreteBMHClass(types);
402 }
403 // Reacquire cache lock.
404 d = lookupCache(types);
405 // Class loading must have upgraded the cache.
406 assert(d != null && !d.isPlaceholder());
407 return d;
408 }
409 static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
410 // clazz is a new class which is initializing its SPECIES_DATA field
411 return updateCache(types, new SpeciesData(types, clazz));
412 }
413 private static synchronized SpeciesData lookupCache(String types) {
414 SpeciesData d = CACHE.get(types);
415 if (d != null) return d;
416 d = new SpeciesData(types);
417 assert(d.isPlaceholder());
418 CACHE.put(types, d);
419 return d;
420 }
421 private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
422 SpeciesData d2;
423 assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
424 assert(!d.isPlaceholder());
425 CACHE.put(types, d);
426 return d;
427 }
428
429 static {
430 // pre-fill the BMH speciesdata cache with BMH's inner classes
431 final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
432 try {
433 for (Class<?> c : rootCls.getDeclaredClasses()) {
434 if (rootCls.isAssignableFrom(c)) {
435 final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
436 SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
437 assert(d != null) : cbmh.getName();
438 assert(d.clazz == cbmh);
439 assert(d == lookupCache(d.typeChars));
440 }
441 }
442 } catch (Throwable e) {
443 throw newInternalError(e);
444 }
445
446 for (SpeciesData d : CACHE.values()) {
447 d.initForBootstrap();
448 }
449 // Note: Do not simplify this, because INIT_DONE must not be
450 // a compile-time constant during bootstrapping.
451 INIT_DONE = Boolean.TRUE;
452 }
453 }
454
455 static SpeciesData getSpeciesData(String types) {
456 return SpeciesData.get(types);
457 }
458
459 /**
569
570 // emit static types and SPECIES_DATA fields
571 cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
572
573 // emit bound argument fields
574 for (int i = 0; i < types.length(); ++i) {
575 final char t = types.charAt(i);
576 final String fieldName = makeFieldName(types, i);
577 final String fieldDesc = t == 'L' ? JLO_SIG : String.valueOf(t);
578 cw.visitField(ACC_FINAL, fieldName, fieldDesc, null, null).visitEnd();
579 }
580
581 MethodVisitor mv;
582
583 // emit constructor
584 mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null);
585 mv.visitCode();
586 mv.visitVarInsn(ALOAD, 0); // this
587 mv.visitVarInsn(ALOAD, 1); // type
588 mv.visitVarInsn(ALOAD, 2); // form
589
590 mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
591
592 for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
593 // i counts the arguments, j counts corresponding argument slots
594 char t = types.charAt(i);
595 mv.visitVarInsn(ALOAD, 0);
596 mv.visitVarInsn(typeLoadOp(t), j + 3); // parameters start at 3
597 mv.visitFieldInsn(PUTFIELD, className, makeFieldName(types, i), typeSig(t));
598 if (t == 'J' || t == 'D') {
599 ++j; // adjust argument register access
600 }
601 }
602
603 mv.visitInsn(RETURN);
604 mv.visitMaxs(0, 0);
605 mv.visitEnd();
606
607 // emit implementation of speciesData()
608 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
609 mv.visitCode();
610 mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
611 mv.visitInsn(ARETURN);
612 mv.visitMaxs(0, 0);
613 mv.visitEnd();
614
615 // emit implementation of fieldCount()
616 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null);
617 mv.visitCode();
618 int fc = types.length();
619 if (fc <= (ICONST_5 - ICONST_0)) {
620 mv.visitInsn(ICONST_0 + fc);
621 } else {
622 mv.visitIntInsn(SIPUSH, fc);
623 }
624 mv.visitInsn(IRETURN);
625 mv.visitMaxs(0, 0);
626 mv.visitEnd();
627 // emit make() ...factory method wrapping constructor
628 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null);
629 mv.visitCode();
630 // make instance
631 mv.visitTypeInsn(NEW, className);
632 mv.visitInsn(DUP);
633 // load mt, lf
634 mv.visitVarInsn(ALOAD, 0); // type
635 mv.visitVarInsn(ALOAD, 1); // form
636 // load factory method arguments
637 for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
638 // i counts the arguments, j counts corresponding argument slots
639 char t = types.charAt(i);
640 mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3
641 if (t == 'J' || t == 'D') {
642 ++j; // adjust argument register access
643 }
644 }
645
646 // finally, invoke the constructor and return
647 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
648 mv.visitInsn(ARETURN);
649 mv.visitMaxs(0, 0);
650 mv.visitEnd();
651
652 // emit copyWith()
653 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null);
654 mv.visitCode();
655 // make instance
656 mv.visitTypeInsn(NEW, className);
657 mv.visitInsn(DUP);
658 // load mt, lf
659 mv.visitVarInsn(ALOAD, 1);
660 mv.visitVarInsn(ALOAD, 2);
661 // put fields on the stack
662 emitPushFields(types, className, mv);
663 // finally, invoke the constructor and return
664 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
665 mv.visitInsn(ARETURN);
|
379
380 SpeciesData extendWith(byte type) {
381 return extendWith(BasicType.basicType(type));
382 }
383
384 SpeciesData extendWith(BasicType type) {
385 int ord = type.ordinal();
386 SpeciesData d = extensions[ord];
387 if (d != null) return d;
388 extensions[ord] = d = get(typeChars+type.basicTypeChar());
389 return d;
390 }
391
392 private static SpeciesData get(String types) {
393 // Acquire cache lock for query.
394 SpeciesData d = lookupCache(types);
395 if (!d.isPlaceholder())
396 return d;
397 synchronized (d) {
398 // Use synch. on the placeholder to prevent multiple instantiation of one species.
399 SpeciesData d2 = lookupCache(types);
400 if (d2.isPlaceholder()) {
401 Class<? extends BoundMethodHandle> bmhcl = Factory.generateConcreteBMHClass(types);
402 // install new SpeciesData into cache
403 d2 = Factory.speciesDataFromConcreteBMHClass(bmhcl);
404 assert(!d2.isPlaceholder());
405 updateCache(d2.typeChars, d2);
406 }
407 d = d2;
408 }
409 return d;
410 }
411 static SpeciesData getForClass(String types, Class<? extends BoundMethodHandle> clazz) {
412 // clazz is a new class which is initializing its SPECIES_DATA field
413 return new SpeciesData(types, clazz);
414 }
415 private static synchronized SpeciesData lookupCache(String types) {
416 SpeciesData d = CACHE.get(types);
417 if (d != null) return d;
418 d = new SpeciesData(types);
419 assert(d.isPlaceholder());
420 CACHE.put(types, d);
421 return d;
422 }
423 private static synchronized SpeciesData updateCache(String types, SpeciesData d) {
424 SpeciesData d2;
425 assert((d2 = CACHE.get(types)) == null || d2.isPlaceholder());
426 assert(!d.isPlaceholder());
427 CACHE.put(types, d);
428 return d;
429 }
430
431 static {
432 // pre-fill the BMH speciesdata cache with BMH's inner classes
433 final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
434 try {
435 for (Class<?> c : rootCls.getDeclaredClasses()) {
436 if (rootCls.isAssignableFrom(c)) {
437 final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
438 SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
439 assert(d != null) : cbmh.getName();
440 assert(d.clazz == cbmh);
441 updateCache(d.typeChars, d);
442 }
443 }
444 } catch (Throwable e) {
445 throw newInternalError(e);
446 }
447
448 for (SpeciesData d : CACHE.values()) {
449 d.initForBootstrap();
450 }
451 // Note: Do not simplify this, because INIT_DONE must not be
452 // a compile-time constant during bootstrapping.
453 INIT_DONE = Boolean.TRUE;
454 }
455 }
456
457 static SpeciesData getSpeciesData(String types) {
458 return SpeciesData.get(types);
459 }
460
461 /**
571
572 // emit static types and SPECIES_DATA fields
573 cw.visitField(NOT_ACC_PUBLIC + ACC_STATIC, "SPECIES_DATA", SPECIES_DATA_SIG, null, null).visitEnd();
574
575 // emit bound argument fields
576 for (int i = 0; i < types.length(); ++i) {
577 final char t = types.charAt(i);
578 final String fieldName = makeFieldName(types, i);
579 final String fieldDesc = t == 'L' ? JLO_SIG : String.valueOf(t);
580 cw.visitField(ACC_FINAL, fieldName, fieldDesc, null, null).visitEnd();
581 }
582
583 MethodVisitor mv;
584
585 // emit constructor
586 mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null);
587 mv.visitCode();
588 mv.visitVarInsn(ALOAD, 0); // this
589 mv.visitVarInsn(ALOAD, 1); // type
590 mv.visitVarInsn(ALOAD, 2); // form
591 mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
592 for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
593 // i counts the arguments, j counts corresponding argument slots
594 char t = types.charAt(i);
595 mv.visitVarInsn(ALOAD, 0);
596 mv.visitVarInsn(typeLoadOp(t), j + 3); // parameters start at 3
597 mv.visitFieldInsn(PUTFIELD, className, makeFieldName(types, i), typeSig(t));
598 if (t == 'J' || t == 'D') {
599 ++j; // adjust argument register access
600 }
601 }
602 mv.visitInsn(RETURN);
603 mv.visitMaxs(0, 0);
604 mv.visitEnd();
605
606 // emit implementation of speciesData()
607 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null);
608 mv.visitCode();
609 mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
610 mv.visitInsn(ARETURN);
611 mv.visitMaxs(0, 0);
612 mv.visitEnd();
613
614 // emit implementation of fieldCount()
615 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null);
616 mv.visitCode();
617 int fc = types.length();
618 if (fc <= (ICONST_5 - ICONST_0)) {
619 mv.visitInsn(ICONST_0 + fc);
620 } else {
621 mv.visitIntInsn(SIPUSH, fc);
622 }
623 mv.visitInsn(IRETURN);
624 mv.visitMaxs(0, 0);
625 mv.visitEnd();
626
627 // emit make() ...factory method wrapping constructor
628 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null);
629 mv.visitCode();
630 // make instance
631 mv.visitTypeInsn(NEW, className);
632 mv.visitInsn(DUP);
633 // load mt, lf
634 mv.visitVarInsn(ALOAD, 0); // type
635 mv.visitVarInsn(ALOAD, 1); // form
636 // load factory method arguments
637 for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
638 // i counts the arguments, j counts corresponding argument slots
639 char t = types.charAt(i);
640 mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3
641 if (t == 'J' || t == 'D') {
642 ++j; // adjust argument register access
643 }
644 }
645 // finally, invoke the constructor and return
646 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
647 mv.visitInsn(ARETURN);
648 mv.visitMaxs(0, 0);
649 mv.visitEnd();
650
651 // emit copyWith()
652 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null);
653 mv.visitCode();
654 // make instance
655 mv.visitTypeInsn(NEW, className);
656 mv.visitInsn(DUP);
657 // load mt, lf
658 mv.visitVarInsn(ALOAD, 1);
659 mv.visitVarInsn(ALOAD, 2);
660 // put fields on the stack
661 emitPushFields(types, className, mv);
662 // finally, invoke the constructor and return
663 mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
664 mv.visitInsn(ARETURN);
|