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