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. |
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 |
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 |