24 */
25
26 package java.lang.invoke;
27
28 import jdk.internal.perf.PerfCounter;
29 import jdk.internal.vm.annotation.DontInline;
30 import jdk.internal.vm.annotation.Stable;
31 import sun.invoke.util.Wrapper;
32
33 import java.lang.annotation.ElementType;
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.lang.annotation.Target;
37 import java.lang.reflect.Method;
38 import java.util.Arrays;
39 import java.util.HashMap;
40
41 import static java.lang.invoke.LambdaForm.BasicType.*;
42 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
43 import static java.lang.invoke.MethodHandleStatics.*;
44
45 /**
46 * The symbolic, non-executable form of a method handle's invocation semantics.
47 * It consists of a series of names.
48 * The first N (N=arity) names are parameters,
49 * while any remaining names are temporary values.
50 * Each temporary specifies the application of a function to some arguments.
51 * The functions are method handles, while the arguments are mixes of
52 * constant values and local names.
53 * The result of the lambda is defined as one of the names, often the last one.
54 * <p>
55 * Here is an approximate grammar:
56 * <blockquote><pre>{@code
57 * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
58 * ArgName = "a" N ":" T
59 * TempName = "t" N ":" T "=" Function "(" Argument* ");"
60 * Function = ConstantValue
61 * Argument = NameRef | ConstantValue
62 * Result = NameRef | "void"
63 * NameRef = "a" N | "t" N
110 * == general invoker for unary filterArgument combination
111 * (a0:L, a1:L)=>{ ...(same as previous example)...
112 * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
113 * == general invoker for unary/unary foldArgument combination
114 * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
115 * == invoker for identity method handle which performs i2l
116 * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
117 * t3:L = Class#cast(t2,a1); t3 }
118 * == invoker for identity method handle which performs cast
119 * }</pre></blockquote>
120 * <p>
121 * @author John Rose, JSR 292 EG
122 */
123 class LambdaForm {
124 final int arity;
125 final int result;
126 final boolean forceInline;
127 final MethodHandle customized;
128 @Stable final Name[] names;
129 final String debugName;
130 MemberName vmentry; // low-level behavior, or null if not yet prepared
131 private boolean isCompiled;
132
133 // Either a LambdaForm cache (managed by LambdaFormEditor) or a link to uncustomized version (for customized LF)
134 volatile Object transformCache;
135
136 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
137
138 enum BasicType {
139 L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types
140 I_TYPE('I', int.class, Wrapper.INT),
141 J_TYPE('J', long.class, Wrapper.LONG),
142 F_TYPE('F', float.class, Wrapper.FLOAT),
143 D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
144 V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
145
146 static final BasicType[] ALL_TYPES = BasicType.values();
147 static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
148
149 static final int ARG_TYPE_LIMIT = ARG_TYPES.length;
249 }
250 static boolean isArgBasicTypeChar(char c) {
251 return "LIJFD".indexOf(c) >= 0;
252 }
253
254 static { assert(checkBasicType()); }
255 private static boolean checkBasicType() {
256 for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
257 assert ARG_TYPES[i].ordinal() == i;
258 assert ARG_TYPES[i] == ALL_TYPES[i];
259 }
260 for (int i = 0; i < TYPE_LIMIT; i++) {
261 assert ALL_TYPES[i].ordinal() == i;
262 }
263 assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
264 assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
265 return true;
266 }
267 }
268
269 LambdaForm(String debugName,
270 int arity, Name[] names, int result) {
271 this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null);
272 }
273 LambdaForm(String debugName,
274 int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {
275 assert(namesOK(arity, names));
276 this.arity = arity;
277 this.result = fixResult(result, names);
278 this.names = names.clone();
279 this.debugName = fixDebugName(debugName);
280 this.forceInline = forceInline;
281 this.customized = customized;
282 int maxOutArity = normalize();
283 if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
284 // Cannot use LF interpreter on very high arity expressions.
285 assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
286 compileToBytecode();
287 }
288 }
289 LambdaForm(String debugName,
290 int arity, Name[] names) {
291 this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
292 }
293 LambdaForm(String debugName,
294 int arity, Name[] names, boolean forceInline) {
295 this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null);
296 }
297 LambdaForm(String debugName,
298 Name[] formals, Name[] temps, Name result) {
299 this(debugName,
300 formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
301 }
302 LambdaForm(String debugName,
303 Name[] formals, Name[] temps, Name result, boolean forceInline) {
304 this(debugName,
305 formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline, /*customized=*/null);
306 }
307
308 private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
309 int arity = formals.length;
310 int length = arity + temps.length + (result == null ? 0 : 1);
311 Name[] names = Arrays.copyOf(formals, length);
312 System.arraycopy(temps, 0, names, arity, temps.length);
313 if (result != null)
314 names[length - 1] = result;
315 return names;
316 }
317
318 private LambdaForm(MethodType mt) {
319 // Make a blank lambda form, which returns a constant zero or null.
320 // It is used as a template for managing the invocation of similar forms that are non-empty.
321 // Called only from getPreparedForm.
322 this.arity = mt.parameterCount();
323 this.result = (mt.returnType() == void.class || mt.returnType() == Void.class) ? -1 : arity;
324 this.names = buildEmptyNames(arity, mt, result == -1);
325 this.debugName = "LF.zero";
326 this.forceInline = true;
327 this.customized = null;
328 assert(nameRefsAreLegal());
329 assert(isEmpty());
330 String sig = null;
331 assert(isValidSignature(sig = basicTypeSignature()));
332 assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
333 }
334
335 private static Name[] buildEmptyNames(int arity, MethodType mt, boolean isVoid) {
336 Name[] names = arguments(isVoid ? 0 : 1, mt);
337 if (!isVoid) {
338 Name zero = new Name(constantZero(basicType(mt.returnType())));
339 names[arity] = zero.newIndex(arity);
340 }
341 return names;
342 }
343
344 private static int fixResult(int result, Name[] names) {
345 if (result == LAST_RESULT)
346 result = names.length - 1; // might still be void
347 if (result >= 0 && names[result].type == V_TYPE)
378 }
379 return buf.toString();
380 }
381 return debugName;
382 }
383
384 private static boolean namesOK(int arity, Name[] names) {
385 for (int i = 0; i < names.length; i++) {
386 Name n = names[i];
387 assert(n != null) : "n is null";
388 if (i < arity)
389 assert( n.isParam()) : n + " is not param at " + i;
390 else
391 assert(!n.isParam()) : n + " is param at " + i;
392 }
393 return true;
394 }
395
396 /** Customize LambdaForm for a particular MethodHandle */
397 LambdaForm customize(MethodHandle mh) {
398 LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh);
399 if (COMPILE_THRESHOLD >= 0 && isCompiled) {
400 // If shared LambdaForm has been compiled, compile customized version as well.
401 customForm.compileToBytecode();
402 }
403 customForm.transformCache = this; // LambdaFormEditor should always use uncustomized form.
404 return customForm;
405 }
406
407 /** Get uncustomized flavor of the LambdaForm */
408 LambdaForm uncustomize() {
409 if (customized == null) {
410 return this;
411 }
412 assert(transformCache != null); // Customized LambdaForm should always has a link to uncustomized version.
413 LambdaForm uncustomizedForm = (LambdaForm)transformCache;
414 if (COMPILE_THRESHOLD >= 0 && isCompiled) {
415 // If customized LambdaForm has been compiled, compile uncustomized version as well.
416 uncustomizedForm.compileToBytecode();
417 }
418 return uncustomizedForm;
753 if (vmentry != null && isCompiled) {
754 return; // already compiled somehow
755 }
756 MethodType invokerType = methodType();
757 assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
758 try {
759 vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
760 if (TRACE_INTERPRETER)
761 traceInterpreter("compileToBytecode", this);
762 isCompiled = true;
763 } catch (InvokerBytecodeGenerator.BytecodeGenerationException bge) {
764 // bytecode generation failed - mark this LambdaForm as to be run in interpretation mode only
765 invocationCounter = -1;
766 failedCompilationCounter().increment();
767 if (LOG_LF_COMPILATION_FAILURE) {
768 System.out.println("LambdaForm compilation failed: " + this);
769 bge.printStackTrace(System.out);
770 }
771 } catch (Error | Exception e) {
772 throw newInternalError(this.toString(), e);
773 }
774 }
775
776 /**
777 * Generate optimizable bytecode for this form after first looking for a
778 * pregenerated version in a specified class.
779 */
780 void compileToBytecode(Class<?> lookupClass) {
781 if (vmentry != null && isCompiled) {
782 return; // already compiled somehow
783 }
784 MethodType invokerType = methodType();
785 assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
786 int dot = debugName.indexOf('.');
787 String methodName = (dot > 0) ? debugName.substring(dot + 1) : debugName;
788 MemberName member = new MemberName(lookupClass, methodName, invokerType, REF_invokeStatic);
789 MemberName resolvedMember = MemberName.getFactory().resolveOrNull(REF_invokeStatic, member, lookupClass);
790 if (resolvedMember != null) {
791 vmentry = resolvedMember;
792 isCompiled = true;
793 } else {
794 compileToBytecode();
795 }
796 }
797
798 private static void computeInitialPreparedForms() {
799 // Find all predefined invokers and associate them with canonical empty lambda forms.
800 for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
801 if (!m.isStatic() || !m.isPackage()) continue;
802 MethodType mt = m.getMethodType();
803 if (mt.parameterCount() > 0 &&
804 mt.parameterType(0) == MethodHandle.class &&
805 m.getName().startsWith("interpret_")) {
806 String sig = null;
807 assert((sig = basicTypeSignature(mt)) != null &&
808 m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
809 LambdaForm form = new LambdaForm(mt);
810 form.vmentry = m;
811 form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
812 }
813 }
814 }
|
24 */
25
26 package java.lang.invoke;
27
28 import jdk.internal.perf.PerfCounter;
29 import jdk.internal.vm.annotation.DontInline;
30 import jdk.internal.vm.annotation.Stable;
31 import sun.invoke.util.Wrapper;
32
33 import java.lang.annotation.ElementType;
34 import java.lang.annotation.Retention;
35 import java.lang.annotation.RetentionPolicy;
36 import java.lang.annotation.Target;
37 import java.lang.reflect.Method;
38 import java.util.Arrays;
39 import java.util.HashMap;
40
41 import static java.lang.invoke.LambdaForm.BasicType.*;
42 import static java.lang.invoke.MethodHandleNatives.Constants.REF_invokeStatic;
43 import static java.lang.invoke.MethodHandleStatics.*;
44 import java.util.Objects;
45
46 /**
47 * The symbolic, non-executable form of a method handle's invocation semantics.
48 * It consists of a series of names.
49 * The first N (N=arity) names are parameters,
50 * while any remaining names are temporary values.
51 * Each temporary specifies the application of a function to some arguments.
52 * The functions are method handles, while the arguments are mixes of
53 * constant values and local names.
54 * The result of the lambda is defined as one of the names, often the last one.
55 * <p>
56 * Here is an approximate grammar:
57 * <blockquote><pre>{@code
58 * LambdaForm = "(" ArgName* ")=>{" TempName* Result "}"
59 * ArgName = "a" N ":" T
60 * TempName = "t" N ":" T "=" Function "(" Argument* ");"
61 * Function = ConstantValue
62 * Argument = NameRef | ConstantValue
63 * Result = NameRef | "void"
64 * NameRef = "a" N | "t" N
111 * == general invoker for unary filterArgument combination
112 * (a0:L, a1:L)=>{ ...(same as previous example)...
113 * t5:L = MethodHandle#invoke(t4, t3, a1); t5 }
114 * == general invoker for unary/unary foldArgument combination
115 * (a0:L, a1:I)=>{ t2:I = identity(long).asType((int)->long)(a1); t2 }
116 * == invoker for identity method handle which performs i2l
117 * (a0:L, a1:L)=>{ t2:L = BoundMethodHandle#argument(a0);
118 * t3:L = Class#cast(t2,a1); t3 }
119 * == invoker for identity method handle which performs cast
120 * }</pre></blockquote>
121 * <p>
122 * @author John Rose, JSR 292 EG
123 */
124 class LambdaForm {
125 final int arity;
126 final int result;
127 final boolean forceInline;
128 final MethodHandle customized;
129 @Stable final Name[] names;
130 final String debugName;
131 final Kind kind;
132 MemberName vmentry; // low-level behavior, or null if not yet prepared
133 private boolean isCompiled;
134
135 // Either a LambdaForm cache (managed by LambdaFormEditor) or a link to uncustomized version (for customized LF)
136 volatile Object transformCache;
137
138 public static final int VOID_RESULT = -1, LAST_RESULT = -2;
139
140 enum BasicType {
141 L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types
142 I_TYPE('I', int.class, Wrapper.INT),
143 J_TYPE('J', long.class, Wrapper.LONG),
144 F_TYPE('F', float.class, Wrapper.FLOAT),
145 D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
146 V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
147
148 static final BasicType[] ALL_TYPES = BasicType.values();
149 static final BasicType[] ARG_TYPES = Arrays.copyOf(ALL_TYPES, ALL_TYPES.length-1);
150
151 static final int ARG_TYPE_LIMIT = ARG_TYPES.length;
251 }
252 static boolean isArgBasicTypeChar(char c) {
253 return "LIJFD".indexOf(c) >= 0;
254 }
255
256 static { assert(checkBasicType()); }
257 private static boolean checkBasicType() {
258 for (int i = 0; i < ARG_TYPE_LIMIT; i++) {
259 assert ARG_TYPES[i].ordinal() == i;
260 assert ARG_TYPES[i] == ALL_TYPES[i];
261 }
262 for (int i = 0; i < TYPE_LIMIT; i++) {
263 assert ALL_TYPES[i].ordinal() == i;
264 }
265 assert ALL_TYPES[TYPE_LIMIT - 1] == V_TYPE;
266 assert !Arrays.asList(ARG_TYPES).contains(V_TYPE);
267 return true;
268 }
269 }
270
271 enum Kind {
272 GENERIC(""),
273 BOUND_REINVOKER("BMH.reinvoke"),
274 REINVOKER("MH.reinvoke"),
275 DELEGATE("MH.delegate"),
276 DIRECT_INVOKE_VIRTUAL("DMH.invokeVirtual"),
277 DIRECT_INVOKE_SPECIAL("DMH.invokeSpecial"),
278 DIRECT_INVOKE_STATIC("DMH.invokeStatic"),
279 DIRECT_NEW_INVOKE_SPECIAL("DMH.newInvokeSpecial"),
280 DIRECT_INVOKE_INTERFACE("DMH.invokeInterface"),
281 DIRECT_INVOKE_STATIC_INIT("DMH.invokeStaticInit");
282
283 final String defaultLambdaName;
284 final String methodName;
285
286 private Kind(String defaultLambdaName) {
287 this.defaultLambdaName = defaultLambdaName;
288 int p = defaultLambdaName.indexOf('.');
289 if (p > -1) {
290 this.methodName = defaultLambdaName.substring(p + 1);
291 } else {
292 this.methodName = defaultLambdaName;
293 }
294 }
295 }
296
297 LambdaForm(String debugName,
298 int arity, Name[] names, int result) {
299 this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
300 }
301 LambdaForm(String debugName,
302 int arity, Name[] names, int result, Kind kind) {
303 this(debugName, arity, names, result, /*forceInline=*/true, /*customized=*/null, kind);
304 }
305 LambdaForm(String debugName,
306 int arity, Name[] names, int result, boolean forceInline, MethodHandle customized) {
307 this(debugName, arity, names, result, forceInline, customized, Kind.GENERIC);
308 }
309 LambdaForm(String debugName,
310 int arity, Name[] names, int result, boolean forceInline, MethodHandle customized, Kind kind) {
311 assert(namesOK(arity, names));
312 this.arity = arity;
313 this.result = fixResult(result, names);
314 this.names = names.clone();
315 this.debugName = fixDebugName(debugName);
316 this.forceInline = forceInline;
317 this.customized = customized;
318 this.kind = kind;
319 int maxOutArity = normalize();
320 if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) {
321 // Cannot use LF interpreter on very high arity expressions.
322 assert(maxOutArity <= MethodType.MAX_JVM_ARITY);
323 compileToBytecode();
324 }
325 }
326 LambdaForm(String debugName,
327 int arity, Name[] names) {
328 this(debugName, arity, names, LAST_RESULT, /*forceInline=*/true, /*customized=*/null, Kind.GENERIC);
329 }
330 LambdaForm(String debugName,
331 int arity, Name[] names, boolean forceInline) {
332 this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, Kind.GENERIC);
333 }
334 LambdaForm(String debugName,
335 int arity, Name[] names, boolean forceInline, Kind kind) {
336 this(debugName, arity, names, LAST_RESULT, forceInline, /*customized=*/null, kind);
337 }
338 LambdaForm(String debugName,
339 Name[] formals, Name[] temps, Name result) {
340 this(debugName,
341 formals.length, buildNames(formals, temps, result), LAST_RESULT, /*forceInline=*/true, /*customized=*/null);
342 }
343 LambdaForm(String debugName,
344 Name[] formals, Name[] temps, Name result, boolean forceInline) {
345 this(debugName,
346 formals.length, buildNames(formals, temps, result), LAST_RESULT, forceInline, /*customized=*/null);
347 }
348
349 private static Name[] buildNames(Name[] formals, Name[] temps, Name result) {
350 int arity = formals.length;
351 int length = arity + temps.length + (result == null ? 0 : 1);
352 Name[] names = Arrays.copyOf(formals, length);
353 System.arraycopy(temps, 0, names, arity, temps.length);
354 if (result != null)
355 names[length - 1] = result;
356 return names;
357 }
358
359 private LambdaForm(MethodType mt) {
360 // Make a blank lambda form, which returns a constant zero or null.
361 // It is used as a template for managing the invocation of similar forms that are non-empty.
362 // Called only from getPreparedForm.
363 this.arity = mt.parameterCount();
364 this.result = (mt.returnType() == void.class || mt.returnType() == Void.class) ? -1 : arity;
365 this.names = buildEmptyNames(arity, mt, result == -1);
366 this.debugName = "LF.zero";
367 this.forceInline = true;
368 this.customized = null;
369 this.kind = Kind.GENERIC;
370 assert(nameRefsAreLegal());
371 assert(isEmpty());
372 String sig = null;
373 assert(isValidSignature(sig = basicTypeSignature()));
374 assert(sig.equals(basicTypeSignature())) : sig + " != " + basicTypeSignature();
375 }
376
377 private static Name[] buildEmptyNames(int arity, MethodType mt, boolean isVoid) {
378 Name[] names = arguments(isVoid ? 0 : 1, mt);
379 if (!isVoid) {
380 Name zero = new Name(constantZero(basicType(mt.returnType())));
381 names[arity] = zero.newIndex(arity);
382 }
383 return names;
384 }
385
386 private static int fixResult(int result, Name[] names) {
387 if (result == LAST_RESULT)
388 result = names.length - 1; // might still be void
389 if (result >= 0 && names[result].type == V_TYPE)
420 }
421 return buf.toString();
422 }
423 return debugName;
424 }
425
426 private static boolean namesOK(int arity, Name[] names) {
427 for (int i = 0; i < names.length; i++) {
428 Name n = names[i];
429 assert(n != null) : "n is null";
430 if (i < arity)
431 assert( n.isParam()) : n + " is not param at " + i;
432 else
433 assert(!n.isParam()) : n + " is param at " + i;
434 }
435 return true;
436 }
437
438 /** Customize LambdaForm for a particular MethodHandle */
439 LambdaForm customize(MethodHandle mh) {
440 LambdaForm customForm = new LambdaForm(debugName, arity, names, result, forceInline, mh, kind);
441 if (COMPILE_THRESHOLD >= 0 && isCompiled) {
442 // If shared LambdaForm has been compiled, compile customized version as well.
443 customForm.compileToBytecode();
444 }
445 customForm.transformCache = this; // LambdaFormEditor should always use uncustomized form.
446 return customForm;
447 }
448
449 /** Get uncustomized flavor of the LambdaForm */
450 LambdaForm uncustomize() {
451 if (customized == null) {
452 return this;
453 }
454 assert(transformCache != null); // Customized LambdaForm should always has a link to uncustomized version.
455 LambdaForm uncustomizedForm = (LambdaForm)transformCache;
456 if (COMPILE_THRESHOLD >= 0 && isCompiled) {
457 // If customized LambdaForm has been compiled, compile uncustomized version as well.
458 uncustomizedForm.compileToBytecode();
459 }
460 return uncustomizedForm;
795 if (vmentry != null && isCompiled) {
796 return; // already compiled somehow
797 }
798 MethodType invokerType = methodType();
799 assert(vmentry == null || vmentry.getMethodType().basicType().equals(invokerType));
800 try {
801 vmentry = InvokerBytecodeGenerator.generateCustomizedCode(this, invokerType);
802 if (TRACE_INTERPRETER)
803 traceInterpreter("compileToBytecode", this);
804 isCompiled = true;
805 } catch (InvokerBytecodeGenerator.BytecodeGenerationException bge) {
806 // bytecode generation failed - mark this LambdaForm as to be run in interpretation mode only
807 invocationCounter = -1;
808 failedCompilationCounter().increment();
809 if (LOG_LF_COMPILATION_FAILURE) {
810 System.out.println("LambdaForm compilation failed: " + this);
811 bge.printStackTrace(System.out);
812 }
813 } catch (Error | Exception e) {
814 throw newInternalError(this.toString(), e);
815 }
816 }
817
818 private static void computeInitialPreparedForms() {
819 // Find all predefined invokers and associate them with canonical empty lambda forms.
820 for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) {
821 if (!m.isStatic() || !m.isPackage()) continue;
822 MethodType mt = m.getMethodType();
823 if (mt.parameterCount() > 0 &&
824 mt.parameterType(0) == MethodHandle.class &&
825 m.getName().startsWith("interpret_")) {
826 String sig = null;
827 assert((sig = basicTypeSignature(mt)) != null &&
828 m.getName().equals("interpret" + sig.substring(sig.indexOf('_'))));
829 LambdaForm form = new LambdaForm(mt);
830 form.vmentry = m;
831 form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form);
832 }
833 }
834 }
|