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     ANON_FUNCTION_PREFIX("L:"),
  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 }