jdk/src/share/classes/java/lang/invoke/BoundMethodHandle.java
changeset 24572 5c9e5961d21c
parent 23918 5f40f1d88890
equal deleted inserted replaced
24571:e1cabb2a72ed 24572:5c9e5961d21c
    24  */
    24  */
    25 
    25 
    26 package java.lang.invoke;
    26 package java.lang.invoke;
    27 
    27 
    28 import static jdk.internal.org.objectweb.asm.Opcodes.*;
    28 import static jdk.internal.org.objectweb.asm.Opcodes.*;
    29 import static java.lang.invoke.LambdaForm.basicTypes;
    29 import static java.lang.invoke.LambdaForm.*;
    30 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
    30 import static java.lang.invoke.LambdaForm.BasicType.*;
    31 import static java.lang.invoke.MethodHandleStatics.*;
    31 import static java.lang.invoke.MethodHandleStatics.*;
    32 
    32 
    33 import java.lang.invoke.LambdaForm.Name;
       
    34 import java.lang.invoke.LambdaForm.NamedFunction;
    33 import java.lang.invoke.LambdaForm.NamedFunction;
    35 import java.lang.invoke.MethodHandles.Lookup;
    34 import java.lang.invoke.MethodHandles.Lookup;
    36 import java.lang.reflect.Field;
    35 import java.lang.reflect.Field;
    37 import java.util.Arrays;
    36 import java.util.Arrays;
    38 import java.util.HashMap;
    37 import java.util.HashMap;
    59 
    58 
    60     //
    59     //
    61     // BMH API and internals
    60     // BMH API and internals
    62     //
    61     //
    63 
    62 
    64     static MethodHandle bindSingle(MethodType type, LambdaForm form, char xtype, Object x) {
    63     static MethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
    65         // for some type signatures, there exist pre-defined concrete BMH classes
    64         // for some type signatures, there exist pre-defined concrete BMH classes
    66         try {
    65         try {
    67             switch (xtype) {
    66             switch (xtype) {
    68             case 'L':
    67             case L_TYPE:
    69                 if (true)  return bindSingle(type, form, x);  // Use known fast path.
    68                 if (true)  return bindSingle(type, form, x);  // Use known fast path.
    70                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('L').constructor[0].invokeBasic(type, form, x);
    69                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(L_TYPE).constructor[0].invokeBasic(type, form, x);
    71             case 'I':
    70             case I_TYPE:
    72                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('I').constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
    71                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x));
    73             case 'J':
    72             case J_TYPE:
    74                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('J').constructor[0].invokeBasic(type, form, (long) x);
    73                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor[0].invokeBasic(type, form, (long) x);
    75             case 'F':
    74             case F_TYPE:
    76                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('F').constructor[0].invokeBasic(type, form, (float) x);
    75                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor[0].invokeBasic(type, form, (float) x);
    77             case 'D':
    76             case D_TYPE:
    78                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWithType('D').constructor[0].invokeBasic(type, form, (double) x);
    77                 return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor[0].invokeBasic(type, form, (double) x);
    79             default : throw new InternalError("unexpected xtype: " + xtype);
    78             default : throw newInternalError("unexpected xtype: " + xtype);
    80             }
    79             }
    81         } catch (Throwable t) {
    80         } catch (Throwable t) {
    82             throw newInternalError(t);
    81             throw newInternalError(t);
    83         }
    82         }
    84     }
    83     }
    85 
    84 
    86     static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
    85     static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) {
    87             return new Species_L(type, form, x);
    86             return new Species_L(type, form, x);
    88     }
    87     }
    89 
    88 
    90     MethodHandle cloneExtend(MethodType type, LambdaForm form, char xtype, Object x) {
    89     MethodHandle cloneExtend(MethodType type, LambdaForm form, BasicType xtype, Object x) {
    91         try {
    90         try {
    92             switch (xtype) {
    91             switch (xtype) {
    93             case 'L': return cloneExtendL(type, form, x);
    92             case L_TYPE: return copyWithExtendL(type, form, x);
    94             case 'I': return cloneExtendI(type, form, ValueConversions.widenSubword(x));
    93             case I_TYPE: return copyWithExtendI(type, form, ValueConversions.widenSubword(x));
    95             case 'J': return cloneExtendJ(type, form, (long) x);
    94             case J_TYPE: return copyWithExtendJ(type, form, (long) x);
    96             case 'F': return cloneExtendF(type, form, (float) x);
    95             case F_TYPE: return copyWithExtendF(type, form, (float) x);
    97             case 'D': return cloneExtendD(type, form, (double) x);
    96             case D_TYPE: return copyWithExtendD(type, form, (double) x);
    98             }
    97             }
    99         } catch (Throwable t) {
    98         } catch (Throwable t) {
   100             throw newInternalError(t);
    99             throw newInternalError(t);
   101         }
   100         }
   102         throw new InternalError("unexpected type: " + xtype);
   101         throw newInternalError("unexpected type: " + xtype);
   103     }
   102     }
   104 
   103 
   105     @Override
   104     @Override
   106     MethodHandle bindArgument(int pos, char basicType, Object value) {
   105     MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
   107         MethodType type = type().dropParameterTypes(pos, pos+1);
   106         MethodType type = type().dropParameterTypes(pos, pos+1);
   108         LambdaForm form = internalForm().bind(1+pos, speciesData());
   107         LambdaForm form = internalForm().bind(1+pos, speciesData());
   109         return cloneExtend(type, form, basicType, value);
   108         return cloneExtend(type, form, basicType, value);
   110     }
   109     }
   111 
   110 
   112     @Override
   111     @Override
   113     MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
   112     MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
   114         LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
   113         LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos + drops));
   115         try {
   114         try {
   116              return clone(srcType, form);
   115              return copyWith(srcType, form);
   117          } catch (Throwable t) {
   116          } catch (Throwable t) {
   118              throw newInternalError(t);
   117              throw newInternalError(t);
   119          }
   118          }
   120     }
   119     }
   121 
   120 
   122     @Override
   121     @Override
   123     MethodHandle permuteArguments(MethodType newType, int[] reorder) {
   122     MethodHandle permuteArguments(MethodType newType, int[] reorder) {
   124         try {
   123         try {
   125              return clone(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
   124              return copyWith(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList())));
   126          } catch (Throwable t) {
   125          } catch (Throwable t) {
   127              throw newInternalError(t);
   126              throw newInternalError(t);
   128          }
   127          }
   129     }
       
   130 
       
   131     static final String EXTENSION_TYPES = "LIJFD";
       
   132     static final byte INDEX_L = 0, INDEX_I = 1, INDEX_J = 2, INDEX_F = 3, INDEX_D = 4;
       
   133     static byte extensionIndex(char type) {
       
   134         int i = EXTENSION_TYPES.indexOf(type);
       
   135         if (i < 0)  throw new InternalError();
       
   136         return (byte) i;
       
   137     }
   128     }
   138 
   129 
   139     /**
   130     /**
   140      * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
   131      * Return the {@link SpeciesData} instance representing this BMH species. All subclasses must provide a
   141      * static field containing this value, and they must accordingly implement this method.
   132      * static field containing this value, and they must accordingly implement this method.
   142      */
   133      */
   143     /*non-public*/ abstract SpeciesData speciesData();
   134     /*non-public*/ abstract SpeciesData speciesData();
   144 
   135 
       
   136     /**
       
   137      * Return the number of fields in this BMH.  Equivalent to speciesData().fieldCount().
       
   138      */
       
   139     /*non-public*/ abstract int fieldCount();
       
   140 
   145     @Override
   141     @Override
   146     final Object internalProperties() {
   142     final Object internalProperties() {
   147         return "/BMH="+internalValues();
   143         return "/BMH="+internalValues();
   148     }
   144     }
   149 
   145 
   157     }
   153     }
   158 
   154 
   159     /*non-public*/ final Object arg(int i) {
   155     /*non-public*/ final Object arg(int i) {
   160         try {
   156         try {
   161             switch (speciesData().fieldType(i)) {
   157             switch (speciesData().fieldType(i)) {
   162             case 'L': return argL(i);
   158             case L_TYPE: return          speciesData().getters[i].invokeBasic(this);
   163             case 'I': return argI(i);
   159             case I_TYPE: return (int)    speciesData().getters[i].invokeBasic(this);
   164             case 'F': return argF(i);
   160             case J_TYPE: return (long)   speciesData().getters[i].invokeBasic(this);
   165             case 'D': return argD(i);
   161             case F_TYPE: return (float)  speciesData().getters[i].invokeBasic(this);
   166             case 'J': return argJ(i);
   162             case D_TYPE: return (double) speciesData().getters[i].invokeBasic(this);
   167             }
   163             }
   168         } catch (Throwable ex) {
   164         } catch (Throwable ex) {
   169             throw newInternalError(ex);
   165             throw newInternalError(ex);
   170         }
   166         }
   171         throw new InternalError("unexpected type: " + speciesData().types+"."+i);
   167         throw new InternalError("unexpected type: " + speciesData().typeChars+"."+i);
   172     }
   168     }
   173     /*non-public*/ final Object argL(int i) throws Throwable { return          speciesData().getters[i].invokeBasic(this); }
       
   174     /*non-public*/ final int    argI(int i) throws Throwable { return (int)    speciesData().getters[i].invokeBasic(this); }
       
   175     /*non-public*/ final float  argF(int i) throws Throwable { return (float)  speciesData().getters[i].invokeBasic(this); }
       
   176     /*non-public*/ final double argD(int i) throws Throwable { return (double) speciesData().getters[i].invokeBasic(this); }
       
   177     /*non-public*/ final long   argJ(int i) throws Throwable { return (long)   speciesData().getters[i].invokeBasic(this); }
       
   178 
   169 
   179     //
   170     //
   180     // cloning API
   171     // cloning API
   181     //
   172     //
   182 
   173 
   183     /*non-public*/ abstract BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable;
   174     /*non-public*/ abstract BoundMethodHandle copyWith(MethodType mt, LambdaForm lf);
   184     /*non-public*/ abstract BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable;
   175     /*non-public*/ abstract BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg);
   185     /*non-public*/ abstract BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int    narg) throws Throwable;
   176     /*non-public*/ abstract BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int    narg);
   186     /*non-public*/ abstract BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long   narg) throws Throwable;
   177     /*non-public*/ abstract BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long   narg);
   187     /*non-public*/ abstract BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float  narg) throws Throwable;
   178     /*non-public*/ abstract BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float  narg);
   188     /*non-public*/ abstract BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable;
   179     /*non-public*/ abstract BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg);
   189 
   180 
   190     // The following is a grossly irregular hack:
   181     // The following is a grossly irregular hack:
   191     @Override MethodHandle reinvokerTarget() {
   182     @Override MethodHandle reinvokerTarget() {
   192         try {
   183         try {
   193             return (MethodHandle) argL(0);
   184             return (MethodHandle) arg(0);
   194         } catch (Throwable ex) {
   185         } catch (Throwable ex) {
   195             throw newInternalError(ex);
   186             throw newInternalError(ex);
   196         }
   187         }
   197     }
   188     }
   198 
   189 
   201     //
   192     //
   202 
   193 
   203     private  // make it private to force users to access the enclosing class first
   194     private  // make it private to force users to access the enclosing class first
   204     static final class Species_L extends BoundMethodHandle {
   195     static final class Species_L extends BoundMethodHandle {
   205         final Object argL0;
   196         final Object argL0;
   206         /*non-public*/ Species_L(MethodType mt, LambdaForm lf, Object argL0) {
   197         private Species_L(MethodType mt, LambdaForm lf, Object argL0) {
   207             super(mt, lf);
   198             super(mt, lf);
   208             this.argL0 = argL0;
   199             this.argL0 = argL0;
   209         }
   200         }
   210         // The following is a grossly irregular hack:
   201         // The following is a grossly irregular hack:
   211         @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
   202         @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; }
   212         @Override
   203         @Override
   213         /*non-public*/ SpeciesData speciesData() {
   204         /*non-public*/ SpeciesData speciesData() {
   214             return SPECIES_DATA;
   205             return SPECIES_DATA;
   215         }
   206         }
       
   207         @Override
       
   208         /*non-public*/ int fieldCount() {
       
   209             return 1;
       
   210         }
   216         /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("L", Species_L.class);
   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         }
   217         @Override
   215         @Override
   218         /*non-public*/ final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
   216         /*non-public*/ final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
   219             return new Species_L(mt, lf, argL0);
   217             return new Species_L(mt, lf, argL0);
   220         }
   218         }
   221         @Override
   219         @Override
   222         /*non-public*/ final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
   220         /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
   223             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, 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             }
   224         }
   226         }
   225         @Override
   227         @Override
   226         /*non-public*/ final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
   228         /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
   227             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, 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             }
   228         }
   234         }
   229         @Override
   235         @Override
   230         /*non-public*/ final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
   236         /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
   231             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, 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             }
   232         }
   242         }
   233         @Override
   243         @Override
   234         /*non-public*/ final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
   244         /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
   235             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, 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             }
   236         }
   250         }
   237         @Override
   251         @Override
   238         /*non-public*/ final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
   252         /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
   239             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, narg);
   253             try {
   240         }
   254                 return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg);
   241     }
   255             } catch (Throwable ex) {
   242 
   256                 throw uncaughtException(ex);
   243 /*
   257             }
   244     static final class Species_LL extends BoundMethodHandle {
   258         }
   245         final Object argL0;
   259     }
   246         final Object argL1;
       
   247         public Species_LL(MethodType mt, LambdaForm lf, Object argL0, Object argL1) {
       
   248             super(mt, lf);
       
   249             this.argL0 = argL0;
       
   250             this.argL1 = argL1;
       
   251         }
       
   252         @Override
       
   253         public SpeciesData speciesData() {
       
   254             return SPECIES_DATA;
       
   255         }
       
   256         public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LL", Species_LL.class);
       
   257         @Override
       
   258         public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
       
   259             return new Species_LL(mt, lf, argL0, argL1);
       
   260         }
       
   261         @Override
       
   262         public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
       
   263             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
       
   264         }
       
   265         @Override
       
   266         public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
       
   267             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
       
   268         }
       
   269         @Override
       
   270         public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
       
   271             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
       
   272         }
       
   273         @Override
       
   274         public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
       
   275             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
       
   276         }
       
   277         @Override
       
   278         public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
       
   279             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, narg);
       
   280         }
       
   281     }
       
   282 
       
   283     static final class Species_JL extends BoundMethodHandle {
       
   284         final long argJ0;
       
   285         final Object argL1;
       
   286         public Species_JL(MethodType mt, LambdaForm lf, long argJ0, Object argL1) {
       
   287             super(mt, lf);
       
   288             this.argJ0 = argJ0;
       
   289             this.argL1 = argL1;
       
   290         }
       
   291         @Override
       
   292         public SpeciesData speciesData() {
       
   293             return SPECIES_DATA;
       
   294         }
       
   295         public static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("JL", Species_JL.class);
       
   296         @Override public final long   argJ0() { return argJ0; }
       
   297         @Override public final Object argL1() { return argL1; }
       
   298         @Override
       
   299         public final BoundMethodHandle clone(MethodType mt, LambdaForm lf) throws Throwable {
       
   300             return new Species_JL(mt, lf, argJ0, argL1);
       
   301         }
       
   302         @Override
       
   303         public final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) throws Throwable {
       
   304             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
       
   305         }
       
   306         @Override
       
   307         public final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) throws Throwable {
       
   308             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
       
   309         }
       
   310         @Override
       
   311         public final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) throws Throwable {
       
   312             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
       
   313         }
       
   314         @Override
       
   315         public final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) throws Throwable {
       
   316             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
       
   317         }
       
   318         @Override
       
   319         public final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) throws Throwable {
       
   320             return (BoundMethodHandle) SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argJ0, argL1, narg);
       
   321         }
       
   322     }
       
   323 */
       
   324 
   260 
   325     //
   261     //
   326     // BMH species meta-data
   262     // BMH species meta-data
   327     //
   263     //
   328 
   264 
   329     /**
   265     /**
   330      * Meta-data wrapper for concrete BMH classes.
   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.
   331      */
   272      */
   332     static class SpeciesData {
   273     static class SpeciesData {
   333         final String                             types;
   274         final String                             typeChars;
       
   275         final BasicType[]                        typeCodes;
   334         final Class<? extends BoundMethodHandle> clazz;
   276         final Class<? extends BoundMethodHandle> clazz;
   335         // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
   277         // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH
   336         // Therefore, we need a non-final link in the chain.  Use array elements.
   278         // Therefore, we need a non-final link in the chain.  Use array elements.
   337         final MethodHandle[]                     constructor;
   279         final MethodHandle[]                     constructor;
   338         final MethodHandle[]                     getters;
   280         final MethodHandle[]                     getters;
       
   281         final NamedFunction[]                    nominalGetters;
   339         final SpeciesData[]                      extensions;
   282         final SpeciesData[]                      extensions;
   340 
   283 
   341         /*non-public*/ int fieldCount() {
   284         /*non-public*/ int fieldCount() {
   342             return types.length();
   285             return typeCodes.length;
   343         }
   286         }
   344         /*non-public*/ char fieldType(int i) {
   287         /*non-public*/ BasicType fieldType(int i) {
   345             return types.charAt(i);
   288             return typeCodes[i];
       
   289         }
       
   290         /*non-public*/ char fieldTypeChar(int i) {
       
   291             return typeChars.charAt(i);
   346         }
   292         }
   347 
   293 
   348         public String toString() {
   294         public String toString() {
   349             return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+types+"]";
   295             return "SpeciesData["+(isPlaceholder() ? "<placeholder>" : clazz.getSimpleName())+":"+typeChars+"]";
   350         }
   296         }
   351 
   297 
   352         /**
   298         /**
   353          * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
   299          * Return a {@link LambdaForm.Name} containing a {@link LambdaForm.NamedFunction} that
   354          * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
   300          * represents a MH bound to a generic invoker, which in turn forwards to the corresponding
   355          * getter.
   301          * getter.
   356          */
   302          */
   357         Name getterName(Name mhName, int i) {
       
   358             MethodHandle mh = getters[i];
       
   359             assert(mh != null) : this+"."+i;
       
   360             return new Name(mh, mhName);
       
   361         }
       
   362 
       
   363         NamedFunction getterFunction(int i) {
   303         NamedFunction getterFunction(int i) {
   364             return new NamedFunction(getters[i]);
   304             return nominalGetters[i];
   365         }
   305         }
   366 
   306 
   367         static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
   307         static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class);
   368 
   308 
   369         private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
   309         private SpeciesData(String types, Class<? extends BoundMethodHandle> clazz) {
   370             this.types = types;
   310             this.typeChars = types;
       
   311             this.typeCodes = basicTypes(types);
   371             this.clazz = clazz;
   312             this.clazz = clazz;
   372             if (!INIT_DONE) {
   313             if (!INIT_DONE) {
   373                 this.constructor = new MethodHandle[1];
   314                 this.constructor = new MethodHandle[1];  // only one ctor
   374                 this.getters = new MethodHandle[types.length()];
   315                 this.getters = new MethodHandle[types.length()];
       
   316                 this.nominalGetters = new NamedFunction[types.length()];
   375             } else {
   317             } else {
   376                 this.constructor = Factory.makeCtors(clazz, types, null);
   318                 this.constructor = Factory.makeCtors(clazz, types, null);
   377                 this.getters = Factory.makeGetters(clazz, types, null);
   319                 this.getters = Factory.makeGetters(clazz, types, null);
   378             }
   320                 this.nominalGetters = Factory.makeNominalGetters(types, null, this.getters);
   379             this.extensions = new SpeciesData[EXTENSION_TYPES.length()];
   321             }
       
   322             this.extensions = new SpeciesData[ARG_TYPE_LIMIT];
   380         }
   323         }
   381 
   324 
   382         private void initForBootstrap() {
   325         private void initForBootstrap() {
   383             assert(!INIT_DONE);
   326             assert(!INIT_DONE);
   384             if (constructor[0] == null) {
   327             if (constructor[0] == null) {
       
   328                 String types = typeChars;
   385                 Factory.makeCtors(clazz, types, this.constructor);
   329                 Factory.makeCtors(clazz, types, this.constructor);
   386                 Factory.makeGetters(clazz, types, this.getters);
   330                 Factory.makeGetters(clazz, types, this.getters);
   387             }
   331                 Factory.makeNominalGetters(types, this.nominalGetters, this.getters);
   388         }
   332             }
   389 
   333         }
   390         private SpeciesData(String types) {
   334 
       
   335         private SpeciesData(String typeChars) {
   391             // Placeholder only.
   336             // Placeholder only.
   392             this.types = types;
   337             this.typeChars = typeChars;
       
   338             this.typeCodes = basicTypes(typeChars);
   393             this.clazz = null;
   339             this.clazz = null;
   394             this.constructor = null;
   340             this.constructor = null;
   395             this.getters = null;
   341             this.getters = null;
       
   342             this.nominalGetters = null;
   396             this.extensions = null;
   343             this.extensions = null;
   397         }
   344         }
   398         private boolean isPlaceholder() { return clazz == null; }
   345         private boolean isPlaceholder() { return clazz == null; }
   399 
   346 
   400         private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
   347         private static final HashMap<String, SpeciesData> CACHE = new HashMap<>();
   401         static { CACHE.put("", EMPTY); }  // make bootstrap predictable
   348         static { CACHE.put("", EMPTY); }  // make bootstrap predictable
   402         private static final boolean INIT_DONE;  // set after <clinit> finishes...
   349         private static final boolean INIT_DONE;  // set after <clinit> finishes...
   403 
   350 
   404         SpeciesData extendWithType(char type) {
   351         SpeciesData extendWith(byte type) {
   405             int i = extensionIndex(type);
   352             return extendWith(BasicType.basicType(type));
   406             SpeciesData d = extensions[i];
   353         }
       
   354 
       
   355         SpeciesData extendWith(BasicType type) {
       
   356             int ord = type.ordinal();
       
   357             SpeciesData d = extensions[ord];
   407             if (d != null)  return d;
   358             if (d != null)  return d;
   408             extensions[i] = d = get(types+type);
   359             extensions[ord] = d = get(typeChars+type.basicTypeChar());
   409             return d;
       
   410         }
       
   411 
       
   412         SpeciesData extendWithIndex(byte index) {
       
   413             SpeciesData d = extensions[index];
       
   414             if (d != null)  return d;
       
   415             extensions[index] = d = get(types+EXTENSION_TYPES.charAt(index));
       
   416             return d;
   360             return d;
   417         }
   361         }
   418 
   362 
   419         private static SpeciesData get(String types) {
   363         private static SpeciesData get(String types) {
   420             // Acquire cache lock for query.
   364             // Acquire cache lock for query.
   454         }
   398         }
   455 
   399 
   456         static {
   400         static {
   457             // pre-fill the BMH speciesdata cache with BMH's inner classes
   401             // pre-fill the BMH speciesdata cache with BMH's inner classes
   458             final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
   402             final Class<BoundMethodHandle> rootCls = BoundMethodHandle.class;
   459             SpeciesData d0 = BoundMethodHandle.SPECIES_DATA;  // trigger class init
       
   460             assert(d0 == null || d0 == lookupCache("")) : d0;
       
   461             try {
   403             try {
   462                 for (Class<?> c : rootCls.getDeclaredClasses()) {
   404                 for (Class<?> c : rootCls.getDeclaredClasses()) {
   463                     if (rootCls.isAssignableFrom(c)) {
   405                     if (rootCls.isAssignableFrom(c)) {
   464                         final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
   406                         final Class<? extends BoundMethodHandle> cbmh = c.asSubclass(BoundMethodHandle.class);
   465                         SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
   407                         SpeciesData d = Factory.speciesDataFromConcreteBMHClass(cbmh);
   466                         assert(d != null) : cbmh.getName();
   408                         assert(d != null) : cbmh.getName();
   467                         assert(d.clazz == cbmh);
   409                         assert(d.clazz == cbmh);
   468                         assert(d == lookupCache(d.types));
   410                         assert(d == lookupCache(d.typeChars));
   469                     }
   411                     }
   470                 }
   412                 }
   471             } catch (Throwable e) {
   413             } catch (Throwable e) {
   472                 throw newInternalError(e);
   414                 throw newInternalError(e);
   473             }
   415             }
   514 
   456 
   515         static final String BMHSPECIES_DATA_EWI_SIG = "(B)" + SPECIES_DATA_SIG;
   457         static final String BMHSPECIES_DATA_EWI_SIG = "(B)" + SPECIES_DATA_SIG;
   516         static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG;
   458         static final String BMHSPECIES_DATA_GFC_SIG = "(" + JLS_SIG + JLC_SIG + ")" + SPECIES_DATA_SIG;
   517         static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG;
   459         static final String MYSPECIES_DATA_SIG = "()" + SPECIES_DATA_SIG;
   518         static final String VOID_SIG   = "()V";
   460         static final String VOID_SIG   = "()V";
       
   461         static final String INT_SIG    = "()I";
   519 
   462 
   520         static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
   463         static final String SIG_INCIPIT = "(Ljava/lang/invoke/MethodType;Ljava/lang/invoke/LambdaForm;";
   521 
       
   522         static final Class<?>[] TYPES = new Class<?>[] { Object.class, int.class, long.class, float.class, double.class };
       
   523 
   464 
   524         static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
   465         static final String[] E_THROWABLE = new String[] { "java/lang/Throwable" };
   525 
   466 
   526         /**
   467         /**
   527          * Generate a concrete subclass of BMH for a given combination of bound types.
   468          * Generate a concrete subclass of BMH for a given combination of bound types.
   549          * class BoundMethodHandle { ... private static
   490          * class BoundMethodHandle { ... private static
   550          * final class Species_LLI extends BoundMethodHandle {
   491          * final class Species_LLI extends BoundMethodHandle {
   551          *     final Object argL0;
   492          *     final Object argL0;
   552          *     final Object argL1;
   493          *     final Object argL1;
   553          *     final int argI2;
   494          *     final int argI2;
   554          *     Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
   495          *     private Species_LLI(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
   555          *         super(mt, lf);
   496          *         super(mt, lf);
   556          *         this.argL0 = argL0;
   497          *         this.argL0 = argL0;
   557          *         this.argL1 = argL1;
   498          *         this.argL1 = argL1;
   558          *         this.argI2 = argI2;
   499          *         this.argI2 = argI2;
   559          *     }
   500          *     }
   560          *     final SpeciesData speciesData() { return SPECIES_DATA; }
   501          *     final SpeciesData speciesData() { return SPECIES_DATA; }
       
   502          *     final int fieldCount() { return 3; }
   561          *     static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
   503          *     static final SpeciesData SPECIES_DATA = SpeciesData.getForClass("LLI", Species_LLI.class);
   562          *     final BoundMethodHandle clone(MethodType mt, LambdaForm lf) {
   504          *     static BoundMethodHandle make(MethodType mt, LambdaForm lf, Object argL0, Object argL1, int argI2) {
   563          *         return SPECIES_DATA.constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2);
   505          *         return new Species_LLI(mt, lf, argL0, argL1, argI2);
   564          *     }
   506          *     }
   565          *     final BoundMethodHandle cloneExtendL(MethodType mt, LambdaForm lf, Object narg) {
   507          *     final BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
   566          *         return SPECIES_DATA.extendWithIndex(INDEX_L).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   508          *         return new Species_LLI(mt, lf, argL0, argL1, argI2);
   567          *     }
   509          *     }
   568          *     final BoundMethodHandle cloneExtendI(MethodType mt, LambdaForm lf, int narg) {
   510          *     final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
   569          *         return SPECIES_DATA.extendWithIndex(INDEX_I).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   511          *         return SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   570          *     }
   512          *     }
   571          *     final BoundMethodHandle cloneExtendJ(MethodType mt, LambdaForm lf, long narg) {
   513          *     final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
   572          *         return SPECIES_DATA.extendWithIndex(INDEX_J).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   514          *         return SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   573          *     }
   515          *     }
   574          *     final BoundMethodHandle cloneExtendF(MethodType mt, LambdaForm lf, float narg) {
   516          *     final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
   575          *         return SPECIES_DATA.extendWithIndex(INDEX_F).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   517          *         return SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg);
   576          *     }
   518          *     }
   577          *     final BoundMethodHandle cloneExtendD(MethodType mt, LambdaForm lf, double narg) {
   519          *     final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
   578          *         return SPECIES_DATA.extendWithIndex(INDEX_D).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, 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);
   579          *     }
   524          *     }
   580          * }
   525          * }
   581          * </pre>
   526          * </pre>
   582          *
   527          *
   583          * @param types the type signature, wherein reference types are erased to 'L'
   528          * @param types the type signature, wherein reference types are erased to 'L'
   584          * @return the generated concrete BMH class
   529          * @return the generated concrete BMH class
   585          */
   530          */
   586         static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
   531         static Class<? extends BoundMethodHandle> generateConcreteBMHClass(String types) {
   587             final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
   532             final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS + ClassWriter.COMPUTE_FRAMES);
   588 
   533 
   589             final String className  = SPECIES_PREFIX_PATH + types;
   534             String shortTypes = LambdaForm.shortenSignature(types);
   590             final String sourceFile = SPECIES_PREFIX_NAME + types;
   535             final String className  = SPECIES_PREFIX_PATH + shortTypes;
       
   536             final String sourceFile = SPECIES_PREFIX_NAME + shortTypes;
   591             final int NOT_ACC_PUBLIC = 0;  // not ACC_PUBLIC
   537             final int NOT_ACC_PUBLIC = 0;  // not ACC_PUBLIC
   592             cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
   538             cw.visit(V1_6, NOT_ACC_PUBLIC + ACC_FINAL + ACC_SUPER, className, null, BMH, null);
   593             cw.visitSource(sourceFile, null);
   539             cw.visitSource(sourceFile, null);
   594 
   540 
   595             // emit static types and SPECIES_DATA fields
   541             // emit static types and SPECIES_DATA fields
   604             }
   550             }
   605 
   551 
   606             MethodVisitor mv;
   552             MethodVisitor mv;
   607 
   553 
   608             // emit constructor
   554             // emit constructor
   609             mv = cw.visitMethod(NOT_ACC_PUBLIC, "<init>", makeSignature(types, true), null, null);
   555             mv = cw.visitMethod(ACC_PRIVATE, "<init>", makeSignature(types, true), null, null);
   610             mv.visitCode();
   556             mv.visitCode();
   611             mv.visitVarInsn(ALOAD, 0);
   557             mv.visitVarInsn(ALOAD, 0); // this
   612             mv.visitVarInsn(ALOAD, 1);
   558             mv.visitVarInsn(ALOAD, 1); // type
   613             mv.visitVarInsn(ALOAD, 2);
   559             mv.visitVarInsn(ALOAD, 2); // form
   614 
   560 
   615             mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
   561             mv.visitMethodInsn(INVOKESPECIAL, BMH, "<init>", makeSignature("", true), false);
   616 
   562 
   617             for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
   563             for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
   618                 // i counts the arguments, j counts corresponding argument slots
   564                 // i counts the arguments, j counts corresponding argument slots
   645             mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   591             mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   646             mv.visitInsn(ARETURN);
   592             mv.visitInsn(ARETURN);
   647             mv.visitMaxs(0, 0);
   593             mv.visitMaxs(0, 0);
   648             mv.visitEnd();
   594             mv.visitEnd();
   649 
   595 
   650             // emit clone()
   596             // emit implementation of fieldCount()
   651             mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "clone", makeSignature("", false), null, E_THROWABLE);
   597             mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "fieldCount", INT_SIG, null, null);
   652             mv.visitCode();
   598             mv.visitCode();
   653             // return speciesData().constructor[0].invokeBasic(mt, lf, argL0, ...)
   599             int fc = types.length();
   654             // obtain constructor
   600             if (fc <= (ICONST_5 - ICONST_0)) {
   655             mv.visitVarInsn(ALOAD, 0);
   601                 mv.visitInsn(ICONST_0 + fc);
   656             mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   602             } else {
   657             mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
   603                 mv.visitIntInsn(SIPUSH, fc);
   658             mv.visitInsn(ICONST_0);
   604             }
   659             mv.visitInsn(AALOAD);
   605             mv.visitInsn(IRETURN);
       
   606             mv.visitMaxs(0, 0);
       
   607             mv.visitEnd();
       
   608             // emit make()  ...factory method wrapping constructor
       
   609             mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_STATIC, "make", makeSignature(types, false), null, null);
       
   610             mv.visitCode();
       
   611             // make instance
       
   612             mv.visitTypeInsn(NEW, className);
       
   613             mv.visitInsn(DUP);
       
   614             // load mt, lf
       
   615             mv.visitVarInsn(ALOAD, 0);  // type
       
   616             mv.visitVarInsn(ALOAD, 1);  // form
       
   617             // load factory method arguments
       
   618             for (int i = 0, j = 0; i < types.length(); ++i, ++j) {
       
   619                 // i counts the arguments, j counts corresponding argument slots
       
   620                 char t = types.charAt(i);
       
   621                 mv.visitVarInsn(typeLoadOp(t), j + 2); // parameters start at 3
       
   622                 if (t == 'J' || t == 'D') {
       
   623                     ++j; // adjust argument register access
       
   624                 }
       
   625             }
       
   626 
       
   627             // finally, invoke the constructor and return
       
   628             mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
       
   629             mv.visitInsn(ARETURN);
       
   630             mv.visitMaxs(0, 0);
       
   631             mv.visitEnd();
       
   632 
       
   633             // emit copyWith()
       
   634             mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWith", makeSignature("", false), null, null);
       
   635             mv.visitCode();
       
   636             // make instance
       
   637             mv.visitTypeInsn(NEW, className);
       
   638             mv.visitInsn(DUP);
   660             // load mt, lf
   639             // load mt, lf
   661             mv.visitVarInsn(ALOAD, 1);
   640             mv.visitVarInsn(ALOAD, 1);
   662             mv.visitVarInsn(ALOAD, 2);
   641             mv.visitVarInsn(ALOAD, 2);
   663             // put fields on the stack
   642             // put fields on the stack
   664             emitPushFields(types, className, mv);
   643             emitPushFields(types, className, mv);
   665             // finally, invoke the constructor and return
   644             // finally, invoke the constructor and return
   666             mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types, false), false);
   645             mv.visitMethodInsn(INVOKESPECIAL, className, "<init>", makeSignature(types, true), false);
   667             mv.visitInsn(ARETURN);
   646             mv.visitInsn(ARETURN);
   668             mv.visitMaxs(0, 0);
   647             mv.visitMaxs(0, 0);
   669             mv.visitEnd();
   648             mv.visitEnd();
   670 
   649 
   671             // for each type, emit cloneExtendT()
   650             // for each type, emit copyWithExtendT()
   672             for (Class<?> c : TYPES) {
   651             for (BasicType type : BasicType.ARG_TYPES) {
   673                 char t = Wrapper.basicTypeChar(c);
   652                 int ord = type.ordinal();
   674                 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "cloneExtend" + t, makeSignature(String.valueOf(t), false), null, E_THROWABLE);
   653                 char btChar = type.basicTypeChar();
       
   654                 mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE);
   675                 mv.visitCode();
   655                 mv.visitCode();
   676                 // return SPECIES_DATA.extendWithIndex(extensionIndex(t)).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
   656                 // return SPECIES_DATA.extendWith(t).constructor[0].invokeBasic(mt, lf, argL0, ..., narg)
   677                 // obtain constructor
   657                 // obtain constructor
   678                 mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   658                 mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG);
   679                 int iconstInsn = ICONST_0 + extensionIndex(t);
   659                 int iconstInsn = ICONST_0 + ord;
   680                 assert(iconstInsn <= ICONST_5);
   660                 assert(iconstInsn <= ICONST_5);
   681                 mv.visitInsn(iconstInsn);
   661                 mv.visitInsn(iconstInsn);
   682                 mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWithIndex", BMHSPECIES_DATA_EWI_SIG, false);
   662                 mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false);
   683                 mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
   663                 mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG);
   684                 mv.visitInsn(ICONST_0);
   664                 mv.visitInsn(ICONST_0);
   685                 mv.visitInsn(AALOAD);
   665                 mv.visitInsn(AALOAD);
   686                 // load mt, lf
   666                 // load mt, lf
   687                 mv.visitVarInsn(ALOAD, 1);
   667                 mv.visitVarInsn(ALOAD, 1);
   688                 mv.visitVarInsn(ALOAD, 2);
   668                 mv.visitVarInsn(ALOAD, 2);
   689                 // put fields on the stack
   669                 // put fields on the stack
   690                 emitPushFields(types, className, mv);
   670                 emitPushFields(types, className, mv);
   691                 // put narg on stack
   671                 // put narg on stack
   692                 mv.visitVarInsn(typeLoadOp(t), 3);
   672                 mv.visitVarInsn(typeLoadOp(btChar), 3);
   693                 // finally, invoke the constructor and return
   673                 // finally, invoke the constructor and return
   694                 mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + t, false), false);
   674                 mv.visitMethodInsn(INVOKEVIRTUAL, MH, "invokeBasic", makeSignature(types + btChar, false), false);
   695                 mv.visitInsn(ARETURN);
   675                 mv.visitInsn(ARETURN);
   696                 mv.visitMaxs(0, 0);
   676                 mv.visitMaxs(0, 0);
   697                 mv.visitEnd();
   677                 mv.visitEnd();
   698             }
   678             }
   699 
   679 
   728             case 'L': return ALOAD;
   708             case 'L': return ALOAD;
   729             case 'I': return ILOAD;
   709             case 'I': return ILOAD;
   730             case 'J': return LLOAD;
   710             case 'J': return LLOAD;
   731             case 'F': return FLOAD;
   711             case 'F': return FLOAD;
   732             case 'D': return DLOAD;
   712             case 'D': return DLOAD;
   733             default : throw new InternalError("unrecognized type " + t);
   713             default : throw newInternalError("unrecognized type " + t);
   734             }
   714             }
   735         }
   715         }
   736 
   716 
   737         private static void emitPushFields(String types, String className, MethodVisitor mv) {
   717         private static void emitPushFields(String types, String className, MethodVisitor mv) {
   738             for (int i = 0; i < types.length(); ++i) {
   718             for (int i = 0; i < types.length(); ++i) {
   769             return mhs;
   749             return mhs;
   770         }
   750         }
   771 
   751 
   772         static MethodHandle[] makeCtors(Class<? extends BoundMethodHandle> cbmh, String types, MethodHandle mhs[]) {
   752         static MethodHandle[] makeCtors(Class<? extends BoundMethodHandle> cbmh, String types, MethodHandle mhs[]) {
   773             if (mhs == null)  mhs = new MethodHandle[1];
   753             if (mhs == null)  mhs = new MethodHandle[1];
       
   754             if (types.equals(""))  return mhs;  // hack for empty BMH species
   774             mhs[0] = makeCbmhCtor(cbmh, types);
   755             mhs[0] = makeCbmhCtor(cbmh, types);
   775             return mhs;
   756             return mhs;
       
   757         }
       
   758 
       
   759         static NamedFunction[] makeNominalGetters(String types, NamedFunction[] nfs, MethodHandle[] getters) {
       
   760             if (nfs == null)  nfs = new NamedFunction[types.length()];
       
   761             for (int i = 0; i < nfs.length; ++i) {
       
   762                 nfs[i] = new NamedFunction(getters[i]);
       
   763             }
       
   764             return nfs;
   776         }
   765         }
   777 
   766 
   778         //
   767         //
   779         // Auxiliary methods.
   768         // Auxiliary methods.
   780         //
   769         //
   806             return buf.append(')').append(ctor ? "V" : BMH_SIG).toString();
   795             return buf.append(')').append(ctor ? "V" : BMH_SIG).toString();
   807         }
   796         }
   808 
   797 
   809         static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
   798         static MethodHandle makeCbmhCtor(Class<? extends BoundMethodHandle> cbmh, String types) {
   810             try {
   799             try {
   811                 return linkConstructor(LOOKUP.findConstructor(cbmh, MethodType.fromMethodDescriptorString(makeSignature(types, true), null)));
   800                 return LOOKUP.findStatic(cbmh, "make", MethodType.fromMethodDescriptorString(makeSignature(types, false), null));
   812             } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
   801             } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | TypeNotPresentException e) {
   813                 throw newInternalError(e);
   802                 throw newInternalError(e);
   814             }
   803             }
   815         }
   804         }
   816 
       
   817         /**
       
   818          * Wrap a constructor call in a {@link LambdaForm}.
       
   819          *
       
   820          * If constructors ({@code <init>} methods) are called in LFs, problems might arise if the LFs
       
   821          * are turned into bytecode, because the call to the allocator is routed through an MH, and the
       
   822          * verifier cannot find a {@code NEW} instruction preceding the {@code INVOKESPECIAL} to
       
   823          * {@code <init>}. To avoid this, we add an indirection by invoking {@code <init>} through
       
   824          * {@link MethodHandle#linkToSpecial}.
       
   825          *
       
   826          * The last {@link LambdaForm.Name Name} in the argument's form is expected to be the {@code void}
       
   827          * result of the {@code <init>} invocation. This entry is replaced.
       
   828          */
       
   829         private static MethodHandle linkConstructor(MethodHandle cmh) {
       
   830             final LambdaForm lf = cmh.form;
       
   831             final int initNameIndex = lf.names.length - 1;
       
   832             final Name initName = lf.names[initNameIndex];
       
   833             final MemberName ctorMN = initName.function.member;
       
   834             final MethodType ctorMT = ctorMN.getInvocationType();
       
   835 
       
   836             // obtain function member (call target)
       
   837             // linker method type replaces initial parameter (BMH species) with BMH to avoid naming a species (anonymous class!)
       
   838             final MethodType linkerMT = ctorMT.changeParameterType(0, BoundMethodHandle.class).appendParameterTypes(MemberName.class);
       
   839             MemberName linkerMN = new MemberName(MethodHandle.class, "linkToSpecial", linkerMT, REF_invokeStatic);
       
   840             try {
       
   841                 linkerMN = MemberName.getFactory().resolveOrFail(REF_invokeStatic, linkerMN, null, NoSuchMethodException.class);
       
   842                 assert(linkerMN.isStatic());
       
   843             } catch (ReflectiveOperationException ex) {
       
   844                 throw newInternalError(ex);
       
   845             }
       
   846             // extend arguments array
       
   847             Object[] newArgs = Arrays.copyOf(initName.arguments, initName.arguments.length + 1);
       
   848             newArgs[newArgs.length - 1] = ctorMN;
       
   849             // replace function
       
   850             final NamedFunction nf = new NamedFunction(linkerMN);
       
   851             final Name linkedCtor = new Name(nf, newArgs);
       
   852             linkedCtor.initIndex(initNameIndex);
       
   853             lf.names[initNameIndex] = linkedCtor;
       
   854             return cmh;
       
   855         }
       
   856 
       
   857     }
   805     }
   858 
   806 
   859     private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
   807     private static final Lookup LOOKUP = Lookup.IMPL_LOOKUP;
   860 
   808 
   861     /**
   809     /**