CompilerConstants.java revision 1687:809ef81502ed
1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.codegen;
27
28import static jdk.nashorn.internal.lookup.Lookup.MH;
29
30import java.lang.invoke.MethodHandle;
31import java.lang.invoke.MethodHandles;
32import java.util.HashSet;
33import java.util.Iterator;
34import java.util.Set;
35import jdk.internal.org.objectweb.asm.MethodVisitor;
36import jdk.internal.org.objectweb.asm.Opcodes;
37import jdk.nashorn.internal.codegen.types.Type;
38import jdk.nashorn.internal.runtime.ScriptFunction;
39import jdk.nashorn.internal.runtime.ScriptObject;
40import jdk.nashorn.internal.runtime.Source;
41
42/**
43 * This class represents constant names of variables, methods and fields in
44 * the compiler
45 */
46
47public enum CompilerConstants {
48    /** the __FILE__ variable */
49    __FILE__,
50
51    /** the __DIR__ variable */
52    __DIR__,
53
54    /** the __LINE__ variable */
55    __LINE__,
56
57    /** constructor name */
58    INIT("<init>"),
59
60    /** static initializer name */
61    CLINIT("<clinit>"),
62
63    /** eval name */
64    EVAL("eval"),
65
66    /** source name and class */
67    SOURCE("source", Source.class),
68
69    /** constants name and class */
70    CONSTANTS("constants", Object[].class),
71
72    /** strict mode field name and type */
73    STRICT_MODE("strictMode", boolean.class),
74
75    /** default script name */
76    DEFAULT_SCRIPT_NAME("Script"),
77
78    /** function prefix for anonymous functions */
79    ANON_FUNCTION_PREFIX("L:"),
80
81    /** separator for method names of nested functions */
82    NESTED_FUNCTION_SEPARATOR("#"),
83
84    /** separator for making method names unique by appending numeric ids */
85    ID_FUNCTION_SEPARATOR("-"),
86
87    /** method name for Java method that is the program entry point */
88    PROGRAM(":program"),
89
90    /** method name for Java method that creates the script function for the program */
91    CREATE_PROGRAM_FUNCTION(":createProgramFunction"),
92
93    /**
94     * "this" name symbol for a parameter representing ECMAScript "this" in static methods that are compiled
95     * representations of ECMAScript functions. It is not assigned a slot, as its position in the method signature is
96     * dependent on other factors (most notably, callee can precede it).
97     */
98    THIS("this", Object.class),
99
100    /** this debugger symbol */
101    THIS_DEBUGGER(":this"),
102
103    /** scope name, type and slot */
104    SCOPE(":scope", ScriptObject.class, 2),
105
106    /** the return value variable name were intermediate results are stored for scripts */
107    RETURN(":return"),
108
109    /** the callee value variable when necessary */
110    CALLEE(":callee", ScriptFunction.class),
111
112    /** the varargs variable when necessary */
113    VARARGS(":varargs", Object[].class),
114
115    /** the arguments variable (visible to function body). Initially set to ARGUMENTS, but can be reassigned by code in
116     * the function body.*/
117    ARGUMENTS_VAR("arguments", Object.class),
118
119    /** the internal arguments object, when necessary (not visible to scripts, can't be reassigned). */
120    ARGUMENTS(":arguments", ScriptObject.class),
121
122    /** prefix for apply-to-call exploded arguments */
123    EXPLODED_ARGUMENT_PREFIX(":xarg"),
124
125    /** prefix for iterators for for (x in ...) */
126    ITERATOR_PREFIX(":i", Iterator.class),
127
128    /** prefix for tag variable used for switch evaluation */
129    SWITCH_TAG_PREFIX(":s"),
130
131    /** prefix for JVM exceptions */
132    EXCEPTION_PREFIX(":e", Throwable.class),
133
134    /** prefix for quick slots generated in Store */
135    QUICK_PREFIX(":q"),
136
137    /** prefix for temporary variables */
138    TEMP_PREFIX(":t"),
139
140    /** prefix for literals */
141    LITERAL_PREFIX(":l"),
142
143    /** prefix for regexps */
144    REGEX_PREFIX(":r"),
145
146    /** "this" used in non-static Java methods; always in slot 0 */
147    JAVA_THIS(null, 0),
148
149    /** Map parameter in scope object constructors; always in slot 1 */
150    INIT_MAP(null, 1),
151
152    /** Parent scope parameter in scope object constructors; always in slot 2 */
153    INIT_SCOPE(null, 2),
154
155    /** Arguments parameter in scope object constructors; in slot 3 when present */
156    INIT_ARGUMENTS(null, 3),
157
158    /** prefix for all ScriptObject subclasses with dual object/primitive fields, see {@link ObjectClassGenerator} */
159    JS_OBJECT_DUAL_FIELD_PREFIX("JD"),
160
161    /** prefix for all ScriptObject subclasses with object fields only, see {@link ObjectClassGenerator} */
162    JS_OBJECT_SINGLE_FIELD_PREFIX("JO"),
163
164    /** name for allocate method in JO objects */
165    ALLOCATE("allocate"),
166
167    /** prefix for split methods, @see Splitter */
168    SPLIT_PREFIX(":split"),
169
170    /** prefix for split array method and slot */
171    SPLIT_ARRAY_ARG(":split_array", 3),
172
173    /** get string from constant pool */
174    GET_STRING(":getString"),
175
176    /** get map */
177    GET_MAP(":getMap"),
178
179    /** set map */
180    SET_MAP(":setMap"),
181
182    /** get array prefix */
183    GET_ARRAY_PREFIX(":get"),
184
185    /** get array suffix */
186    GET_ARRAY_SUFFIX("$array");
187
188    /** To save memory - intern the compiler constant symbol names, as they are frequently reused */
189    static {
190        for (final CompilerConstants c : values()) {
191            final String symbolName = c.symbolName();
192            if (symbolName != null) {
193                symbolName.intern();
194            }
195        }
196    }
197
198    private static Set<String> symbolNames;
199
200    /**
201     * Prefix used for internal methods generated in script classes.
202     */
203    private static final String INTERNAL_METHOD_PREFIX = ":";
204
205    private final String symbolName;
206    private final Class<?> type;
207    private final int slot;
208
209    private CompilerConstants() {
210        this.symbolName = name();
211        this.type = null;
212        this.slot = -1;
213    }
214
215    private CompilerConstants(final String symbolName) {
216        this(symbolName, -1);
217    }
218
219    private CompilerConstants(final String symbolName, final int slot) {
220        this(symbolName, null, slot);
221    }
222
223    private CompilerConstants(final String symbolName, final Class<?> type) {
224        this(symbolName, type, -1);
225    }
226
227    private CompilerConstants(final String symbolName, final Class<?> type, final int slot) {
228        this.symbolName = symbolName;
229        this.type       = type;
230        this.slot       = slot;
231    }
232
233    /**
234     * Check whether a name is that of a reserved compiler constant
235     * @param name name
236     * @return true if compiler constant name
237     */
238    public static boolean isCompilerConstant(final String name) {
239        ensureSymbolNames();
240        return symbolNames.contains(name);
241    }
242
243    private static void ensureSymbolNames() {
244        if(symbolNames == null) {
245            symbolNames = new HashSet<>();
246            for(final CompilerConstants cc: CompilerConstants.values()) {
247                symbolNames.add(cc.symbolName);
248            }
249        }
250    }
251
252    /**
253     * Return the tag for this compile constant. Deliberately avoiding "name" here
254     * not to conflate with enum implementation. This is the master string for the
255     * constant - every constant has one.
256     *
257     * @return the tag
258     */
259    public final String symbolName() {
260        return symbolName;
261    }
262
263    /**
264     * Return the type for this compile constant
265     *
266     * @return type for this constant's instances, or null if N/A
267     */
268    public final Class<?> type() {
269        return type;
270    }
271
272    /**
273     * Return the slot for this compile constant
274     *
275     * @return byte code slot where constant is stored or -1 if N/A
276     */
277    public final int slot() {
278        return slot;
279    }
280
281    /**
282     * Return a descriptor for this compile constant. Only relevant if it has
283     * a type
284     *
285     * @return descriptor the descriptor
286     */
287    public final String descriptor() {
288        assert type != null : " asking for descriptor of typeless constant";
289        return typeDescriptor(type);
290    }
291
292    /**
293     * Get the internal class name for a type
294     *
295     * @param type a type
296     * @return  the internal name for this type
297     */
298    public static String className(final Class<?> type) {
299        return Type.getInternalName(type);
300    }
301
302    /**
303     * Get the method descriptor for a given method type collection
304     *
305     * @param rtype  return type
306     * @param ptypes parameter types
307     *
308     * @return internal descriptor for this method
309     */
310    public static String methodDescriptor(final Class<?> rtype, final Class<?>... ptypes) {
311        return Type.getMethodDescriptor(rtype, ptypes);
312    }
313
314    /**
315     * Get the type descriptor for a type
316     *
317     * @param clazz a type
318     *
319     * @return the internal descriptor for this type
320     */
321    public static String typeDescriptor(final Class<?> clazz) {
322        return Type.typeFor(clazz).getDescriptor();
323    }
324
325    /**
326     * Create a call representing a void constructor for a given type. Don't
327     * attempt to look this up at compile time
328     *
329     * @param clazz the class
330     *
331     * @return Call representing void constructor for type
332     */
333    public static Call constructorNoLookup(final Class<?> clazz) {
334        return specialCallNoLookup(clazz, INIT.symbolName(), void.class);
335    }
336
337    /**
338     * Create a call representing a constructor for a given type. Don't
339     * attempt to look this up at compile time
340     *
341     * @param className the type class name
342     * @param ptypes    the parameter types for the constructor
343     *
344     * @return Call representing constructor for type
345     */
346    public static Call constructorNoLookup(final String className, final Class<?>... ptypes) {
347        return specialCallNoLookup(className, INIT.symbolName(), methodDescriptor(void.class, ptypes));
348    }
349
350    /**
351     * Create a call representing a constructor for a given type. Don't
352     * attempt to look this up at compile time
353     *
354     * @param clazz  the class name
355     * @param ptypes the parameter types for the constructor
356     *
357     * @return Call representing constructor for type
358     */
359    public static Call constructorNoLookup(final Class<?> clazz, final Class<?>... ptypes) {
360        return specialCallNoLookup(clazz, INIT.symbolName(), void.class, ptypes);
361    }
362
363    /**
364     * Create a call representing an invokespecial to a given method. Don't
365     * attempt to look this up at compile time
366     *
367     * @param className the class name
368     * @param name      the method name
369     * @param desc      the descriptor
370     *
371     * @return Call representing specified invokespecial call
372     */
373    public static Call specialCallNoLookup(final String className, final String name, final String desc) {
374        return new Call(null, className, name, desc) {
375            @Override
376            MethodEmitter invoke(final MethodEmitter method) {
377                return method.invokespecial(className, name, descriptor);
378            }
379
380            @Override
381            public void invoke(final MethodVisitor mv) {
382                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, desc, false);
383            }
384        };
385    }
386
387    /**
388     * Create a call representing an invokespecial to a given method. Don't
389     * attempt to look this up at compile time
390     *
391     * @param clazz  the class
392     * @param name   the method name
393     * @param rtype  the return type
394     * @param ptypes the parameter types
395     *
396     * @return Call representing specified invokespecial call
397     */
398    public static Call specialCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
399        return specialCallNoLookup(className(clazz), name, methodDescriptor(rtype, ptypes));
400    }
401
402    /**
403     * Create a call representing an invokestatic to a given method. Don't
404     * attempt to look this up at compile time
405     *
406     * @param className the class name
407     * @param name      the method name
408     * @param desc      the descriptor
409     *
410     * @return Call representing specified invokestatic call
411     */
412    public static Call staticCallNoLookup(final String className, final String name, final String desc) {
413        return new Call(null, className, name, desc) {
414            @Override
415            MethodEmitter invoke(final MethodEmitter method) {
416                return method.invokestatic(className, name, descriptor);
417            }
418
419            @Override
420            public void invoke(final MethodVisitor mv) {
421                mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, desc, false);
422            }
423        };
424    }
425
426    /**
427     * Create a call representing an invokestatic to a given method. Don't
428     * attempt to look this up at compile time
429     *
430     * @param clazz  the class
431     * @param name   the method name
432     * @param rtype  the return type
433     * @param ptypes the parameter types
434     *
435     * @return Call representing specified invokestatic call
436     */
437    public static Call staticCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
438        return staticCallNoLookup(className(clazz), name, methodDescriptor(rtype, ptypes));
439    }
440
441    /**
442     * Create a call representing an invokevirtual to a given method. Don't
443     * attempt to look this up at compile time
444     *
445     * @param clazz  the class
446     * @param name   the method name
447     * @param rtype  the return type
448     * @param ptypes the parameter types
449     *
450     * @return Call representing specified invokevirtual call
451     */
452    public static Call virtualCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
453        return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
454            @Override
455            MethodEmitter invoke(final MethodEmitter method) {
456                return method.invokevirtual(className, name, descriptor);
457            }
458
459            @Override
460            public void invoke(final MethodVisitor mv) {
461                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false);
462            }
463        };
464    }
465
466    /**
467     * Create a call representing an invokeinterface to a given method. Don't
468     * attempt to look this up at compile time
469     *
470     * @param clazz  the class
471     * @param name   the method name
472     * @param rtype  the return type
473     * @param ptypes the parameter types
474     *
475     * @return Call representing specified invokeinterface call
476     */
477    public static Call interfaceCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
478        return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
479            @Override
480            MethodEmitter invoke(final MethodEmitter method) {
481                return method.invokeinterface(className, name, descriptor);
482            }
483
484            @Override
485            public void invoke(final MethodVisitor mv) {
486                mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, className, name, descriptor, true);
487            }
488        };
489    }
490
491    /**
492     * Create a FieldAccess representing a virtual field, that can be subject to put
493     * or get operations
494     *
495     * @param className name of the class where the field is a member
496     * @param name      name of the field
497     * @param desc      type descriptor of the field
498     *
499     * @return a field access object giving access code generation method for the virtual field
500     */
501    public static FieldAccess virtualField(final String className, final String name, final String desc) {
502        return new FieldAccess(className, name, desc) {
503            @Override
504            public MethodEmitter get(final MethodEmitter method) {
505                return method.getField(className, name, descriptor);
506            }
507
508            @Override
509            public void put(final MethodEmitter method) {
510                method.putField(className, name, descriptor);
511            }
512        };
513    }
514
515    /**
516     * Create a FieldAccess representing a virtual field, that can be subject to put
517     * or get operations
518     *
519     * @param clazz class where the field is a member
520     * @param name  name of the field
521     * @param type  type of the field
522     *
523     * @return a field access object giving access code generation method for the virtual field
524     */
525    public static FieldAccess virtualField(final Class<?> clazz, final String name, final Class<?> type) {
526        return virtualField(className(clazz), name, typeDescriptor(type));
527    }
528
529    /**
530     * Create a FieldAccess representing a static field, that can be subject to put
531     * or get operations
532     *
533     * @param className name of the class where the field is a member
534     * @param name      name of the field
535     * @param desc      type descriptor of the field
536     *
537     * @return a field access object giving access code generation method for the static field
538     */
539    public static FieldAccess staticField(final String className, final String name, final String desc) {
540        return new FieldAccess(className, name, desc) {
541            @Override
542            public MethodEmitter get(final MethodEmitter method) {
543                return method.getStatic(className, name, descriptor);
544            }
545
546            @Override
547            public void put(final MethodEmitter method) {
548                method.putStatic(className, name, descriptor);
549            }
550        };
551    }
552
553    /**
554     * Create a FieldAccess representing a static field, that can be subject to put
555     * or get operations
556     *
557     * @param clazz class where the field is a member
558     * @param name  name of the field
559     * @param type  type of the field
560     *
561     * @return a field access object giving access code generation method for the virtual field
562     */
563    public static FieldAccess staticField(final Class<?> clazz, final String name, final Class<?> type) {
564        return staticField(className(clazz), name, typeDescriptor(type));
565    }
566
567    /**
568     * Create a static call, given an explicit lookup, looking up the method handle for it at the same time
569     *
570     * @param lookup the lookup
571     * @param clazz  the class
572     * @param name   the name of the method
573     * @param rtype  the return type
574     * @param ptypes the parameter types
575     *
576     * @return the call object representing the static call
577     */
578    public static Call staticCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
579        return new Call(MH.findStatic(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
580            @Override
581            MethodEmitter invoke(final MethodEmitter method) {
582                return method.invokestatic(className, name, descriptor);
583            }
584
585            @Override
586            public void invoke(final MethodVisitor mv) {
587                mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, descriptor, false);
588            }
589        };
590    }
591
592    /**
593     * Create a virtual call, given an explicit lookup, looking up the method handle for it at the same time
594     *
595     * @param lookup the lookup
596     * @param clazz  the class
597     * @param name   the name of the method
598     * @param rtype  the return type
599     * @param ptypes the parameter types
600     *
601     * @return the call object representing the virtual call
602     */
603    public static Call virtualCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
604        return new Call(MH.findVirtual(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
605            @Override
606            MethodEmitter invoke(final MethodEmitter method) {
607                return method.invokevirtual(className, name, descriptor);
608            }
609
610            @Override
611            public void invoke(final MethodVisitor mv) {
612                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false);
613            }
614        };
615    }
616
617    /**
618     * Create a special call, given an explicit lookup, looking up the method handle for it at the same time.
619     * clazz is used as this class
620     *
621     * @param lookup    the lookup
622     * @param clazz     the class
623     * @param name      the name of the method
624     * @param rtype     the return type
625     * @param ptypes    the parameter types
626     *
627     * @return the call object representing the virtual call
628     */
629    public static Call specialCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
630        return new Call(MH.findSpecial(lookup, clazz, name, MH.type(rtype, ptypes), clazz), className(clazz), name, methodDescriptor(rtype, ptypes)) {
631            @Override
632            MethodEmitter invoke(final MethodEmitter method) {
633                return method.invokespecial(className, name, descriptor);
634            }
635
636            @Override
637            public void invoke(final MethodVisitor mv) {
638                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, descriptor, false);
639            }
640        };
641    }
642
643    /**
644     * Returns true if the passed string looks like a method name of an internally generated Nashorn method. Basically,
645     * if it starts with a colon character {@code :} but is not the name of the program method {@code :program}.
646     * Program function is not considered internal as we want it to show up in exception stack traces.
647     * @param methodName the name of a method
648     * @return true if it looks like an internal Nashorn method name.
649     * @throws NullPointerException if passed null
650     */
651    public static boolean isInternalMethodName(final String methodName) {
652        return methodName.startsWith(INTERNAL_METHOD_PREFIX) && !methodName.equals(PROGRAM.symbolName);
653     }
654
655    /**
656     * Private class representing an access. This can generate code into a method code or
657     * a field access.
658     */
659    private abstract static class Access {
660        protected final MethodHandle methodHandle;
661        protected final String       className;
662        protected final String       name;
663        protected final String       descriptor;
664
665        /**
666         * Constructor
667         *
668         * @param methodHandle methodHandle or null if none
669         * @param className    class name for access
670         * @param name         field or method name for access
671         * @param descriptor   descriptor for access field or method
672         */
673        protected Access(final MethodHandle methodHandle, final String className, final String name, final String descriptor) {
674            this.methodHandle = methodHandle;
675            this.className    = className;
676            this.name         = name;
677            this.descriptor   = descriptor;
678        }
679
680        /**
681         * Get the method handle, or null if access hasn't been looked up
682         *
683         * @return method handle
684         */
685        public MethodHandle methodHandle() {
686            return methodHandle;
687        }
688
689        /**
690         * Get the class name of the access
691         *
692         * @return the class name
693         */
694        public String className() {
695            return className;
696        }
697
698        /**
699         * Get the field name or method name of the access
700         *
701         * @return the name
702         */
703        public String name() {
704            return name;
705        }
706
707        /**
708         * Get the descriptor of the method or field of the access
709         *
710         * @return the descriptor
711         */
712        public String descriptor() {
713            return descriptor;
714        }
715    }
716
717    /**
718     * Field access - this can be used for generating code for static or
719     * virtual field accesses
720     */
721    public abstract static class FieldAccess extends Access {
722        /**
723         * Constructor
724         *
725         * @param className  name of the class where the field is
726         * @param name       name of the field
727         * @param descriptor descriptor of the field
728         */
729        protected FieldAccess(final String className, final String name, final String descriptor) {
730            super(null, className, name, descriptor);
731        }
732
733        /**
734         * Generate get code for the field
735         *
736         * @param emitter a method emitter
737         *
738         * @return the method emitter
739         */
740        protected abstract MethodEmitter get(final MethodEmitter emitter);
741
742        /**
743         * Generate put code for the field
744         *
745         * @param emitter a method emitter
746         */
747        protected abstract void put(final MethodEmitter emitter);
748    }
749
750    /**
751     * Call - this can be used for generating code for different types of calls
752     */
753    public abstract static class Call extends Access {
754
755        /**
756         * Constructor
757         *
758         * @param className  class name for the method of the call
759         * @param name       method name
760         * @param descriptor method descriptor
761         */
762        protected Call(final String className, final String name, final String descriptor) {
763            super(null, className, name, descriptor);
764        }
765
766        /**
767         * Constructor
768         *
769         * @param methodHandle method handle for the call if resolved
770         * @param className    class name for the method of the call
771         * @param name         method name
772         * @param descriptor   method descriptor
773         */
774        protected Call(final MethodHandle methodHandle, final String className, final String name, final String descriptor) {
775            super(methodHandle, className, name, descriptor);
776        }
777
778        /**
779         * Generate invocation code for the method
780         *
781         * @param emitter a method emitter
782         *
783         * @return the method emitter
784         */
785        abstract MethodEmitter invoke(final MethodEmitter emitter);
786
787        /**
788         * Generate invocation code for the method
789         *
790         * @param mv a method visitor
791         */
792        public abstract void invoke(final MethodVisitor mv);
793    }
794
795}
796