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