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