--- old/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilerConstants.java 2020-04-15 18:47:04.000000000 +0530 +++ /dev/null 2020-04-15 18:47:04.000000000 +0530 @@ -1,795 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.nashorn.internal.codegen; - -import static jdk.nashorn.internal.lookup.Lookup.MH; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.nashorn.internal.codegen.types.Type; -import jdk.nashorn.internal.runtime.ScriptFunction; -import jdk.nashorn.internal.runtime.ScriptObject; -import jdk.nashorn.internal.runtime.Source; - -/** - * This class represents constant names of variables, methods and fields in - * the compiler - */ - -public enum CompilerConstants { - /** the __FILE__ variable */ - __FILE__, - - /** the __DIR__ variable */ - __DIR__, - - /** the __LINE__ variable */ - __LINE__, - - /** constructor name */ - INIT(""), - - /** static initializer name */ - CLINIT(""), - - /** eval name */ - EVAL("eval"), - - /** source name and class */ - SOURCE("source", Source.class), - - /** constants name and class */ - CONSTANTS("constants", Object[].class), - - /** strict mode field name and type */ - STRICT_MODE("strictMode", boolean.class), - - /** default script name */ - DEFAULT_SCRIPT_NAME("Script"), - - /** function prefix for anonymous functions */ - ANON_FUNCTION_PREFIX("L:"), - - /** separator for method names of nested functions */ - NESTED_FUNCTION_SEPARATOR("#"), - - /** separator for making method names unique by appending numeric ids */ - ID_FUNCTION_SEPARATOR("-"), - - /** method name for Java method that is the program entry point */ - PROGRAM(":program"), - - /** method name for Java method that creates the script function for the program */ - CREATE_PROGRAM_FUNCTION(":createProgramFunction"), - - /** - * "this" name symbol for a parameter representing ECMAScript "this" in static methods that are compiled - * representations of ECMAScript functions. It is not assigned a slot, as its position in the method signature is - * dependent on other factors (most notably, callee can precede it). - */ - THIS("this", Object.class), - - /** this debugger symbol */ - THIS_DEBUGGER(":this"), - - /** scope name, type and slot */ - SCOPE(":scope", ScriptObject.class, 2), - - /** the return value variable name were intermediate results are stored for scripts */ - RETURN(":return"), - - /** the callee value variable when necessary */ - CALLEE(":callee", ScriptFunction.class), - - /** the varargs variable when necessary */ - VARARGS(":varargs", Object[].class), - - /** the arguments variable (visible to function body). Initially set to ARGUMENTS, but can be reassigned by code in - * the function body.*/ - ARGUMENTS_VAR("arguments", Object.class), - - /** the internal arguments object, when necessary (not visible to scripts, can't be reassigned). */ - ARGUMENTS(":arguments", ScriptObject.class), - - /** prefix for apply-to-call exploded arguments */ - EXPLODED_ARGUMENT_PREFIX(":xarg"), - - /** prefix for iterators for for (x in ...) */ - ITERATOR_PREFIX(":i", Iterator.class), - - /** prefix for tag variable used for switch evaluation */ - SWITCH_TAG_PREFIX(":s"), - - /** prefix for JVM exceptions */ - EXCEPTION_PREFIX(":e", Throwable.class), - - /** prefix for quick slots generated in Store */ - QUICK_PREFIX(":q"), - - /** prefix for temporary variables */ - TEMP_PREFIX(":t"), - - /** prefix for literals */ - LITERAL_PREFIX(":l"), - - /** prefix for regexps */ - REGEX_PREFIX(":r"), - - /** "this" used in non-static Java methods; always in slot 0 */ - JAVA_THIS(null, 0), - - /** Map parameter in scope object constructors; always in slot 1 */ - INIT_MAP(null, 1), - - /** Parent scope parameter in scope object constructors; always in slot 2 */ - INIT_SCOPE(null, 2), - - /** Arguments parameter in scope object constructors; in slot 3 when present */ - INIT_ARGUMENTS(null, 3), - - /** prefix for all ScriptObject subclasses with dual object/primitive fields, see {@link ObjectClassGenerator} */ - JS_OBJECT_DUAL_FIELD_PREFIX("JD"), - - /** prefix for all ScriptObject subclasses with object fields only, see {@link ObjectClassGenerator} */ - JS_OBJECT_SINGLE_FIELD_PREFIX("JO"), - - /** name for allocate method in JO objects */ - ALLOCATE("allocate"), - - /** prefix for split methods, @see Splitter */ - SPLIT_PREFIX(":split"), - - /** prefix for split array method and slot */ - SPLIT_ARRAY_ARG(":split_array", 3), - - /** get string from constant pool */ - GET_STRING(":getString"), - - /** get map */ - GET_MAP(":getMap"), - - /** set map */ - SET_MAP(":setMap"), - - /** get array prefix */ - GET_ARRAY_PREFIX(":get"), - - /** get array suffix */ - GET_ARRAY_SUFFIX("$array"); - - /** To save memory - intern the compiler constant symbol names, as they are frequently reused */ - static { - for (final CompilerConstants c : values()) { - final String symbolName = c.symbolName(); - if (symbolName != null) { - symbolName.intern(); - } - } - } - - private static Set symbolNames; - - /** - * Prefix used for internal methods generated in script classes. - */ - private static final String INTERNAL_METHOD_PREFIX = ":"; - - private final String symbolName; - private final Class type; - private final int slot; - - private CompilerConstants() { - this.symbolName = name(); - this.type = null; - this.slot = -1; - } - - private CompilerConstants(final String symbolName) { - this(symbolName, -1); - } - - private CompilerConstants(final String symbolName, final int slot) { - this(symbolName, null, slot); - } - - private CompilerConstants(final String symbolName, final Class type) { - this(symbolName, type, -1); - } - - private CompilerConstants(final String symbolName, final Class type, final int slot) { - this.symbolName = symbolName; - this.type = type; - this.slot = slot; - } - - /** - * Check whether a name is that of a reserved compiler constant - * @param name name - * @return true if compiler constant name - */ - public static boolean isCompilerConstant(final String name) { - ensureSymbolNames(); - return symbolNames.contains(name); - } - - private static void ensureSymbolNames() { - if(symbolNames == null) { - symbolNames = new HashSet<>(); - for(final CompilerConstants cc: CompilerConstants.values()) { - symbolNames.add(cc.symbolName); - } - } - } - - /** - * Return the tag for this compile constant. Deliberately avoiding "name" here - * not to conflate with enum implementation. This is the master string for the - * constant - every constant has one. - * - * @return the tag - */ - public final String symbolName() { - return symbolName; - } - - /** - * Return the type for this compile constant - * - * @return type for this constant's instances, or null if N/A - */ - public final Class type() { - return type; - } - - /** - * Return the slot for this compile constant - * - * @return byte code slot where constant is stored or -1 if N/A - */ - public final int slot() { - return slot; - } - - /** - * Return a descriptor for this compile constant. Only relevant if it has - * a type - * - * @return descriptor the descriptor - */ - public final String descriptor() { - assert type != null : " asking for descriptor of typeless constant"; - return typeDescriptor(type); - } - - /** - * Get the internal class name for a type - * - * @param type a type - * @return the internal name for this type - */ - public static String className(final Class type) { - return Type.getInternalName(type); - } - - /** - * Get the method descriptor for a given method type collection - * - * @param rtype return type - * @param ptypes parameter types - * - * @return internal descriptor for this method - */ - public static String methodDescriptor(final Class rtype, final Class... ptypes) { - return Type.getMethodDescriptor(rtype, ptypes); - } - - /** - * Get the type descriptor for a type - * - * @param clazz a type - * - * @return the internal descriptor for this type - */ - public static String typeDescriptor(final Class clazz) { - return Type.typeFor(clazz).getDescriptor(); - } - - /** - * Create a call representing a void constructor for a given type. Don't - * attempt to look this up at compile time - * - * @param clazz the class - * - * @return Call representing void constructor for type - */ - public static Call constructorNoLookup(final Class clazz) { - return specialCallNoLookup(clazz, INIT.symbolName(), void.class); - } - - /** - * Create a call representing a constructor for a given type. Don't - * attempt to look this up at compile time - * - * @param className the type class name - * @param ptypes the parameter types for the constructor - * - * @return Call representing constructor for type - */ - public static Call constructorNoLookup(final String className, final Class... ptypes) { - return specialCallNoLookup(className, INIT.symbolName(), methodDescriptor(void.class, ptypes)); - } - - /** - * Create a call representing a constructor for a given type. Don't - * attempt to look this up at compile time - * - * @param clazz the class name - * @param ptypes the parameter types for the constructor - * - * @return Call representing constructor for type - */ - public static Call constructorNoLookup(final Class clazz, final Class... ptypes) { - return specialCallNoLookup(clazz, INIT.symbolName(), void.class, ptypes); - } - - /** - * Create a call representing an invokespecial to a given method. Don't - * attempt to look this up at compile time - * - * @param className the class name - * @param name the method name - * @param desc the descriptor - * - * @return Call representing specified invokespecial call - */ - public static Call specialCallNoLookup(final String className, final String name, final String desc) { - return new Call(null, className, name, desc) { - @Override - MethodEmitter invoke(final MethodEmitter method) { - return method.invokespecial(className, name, descriptor); - } - - @Override - public void invoke(final MethodVisitor mv) { - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, desc, false); - } - }; - } - - /** - * Create a call representing an invokespecial to a given method. Don't - * attempt to look this up at compile time - * - * @param clazz the class - * @param name the method name - * @param rtype the return type - * @param ptypes the parameter types - * - * @return Call representing specified invokespecial call - */ - public static Call specialCallNoLookup(final Class clazz, final String name, final Class rtype, final Class... ptypes) { - return specialCallNoLookup(className(clazz), name, methodDescriptor(rtype, ptypes)); - } - - /** - * Create a call representing an invokestatic to a given method. Don't - * attempt to look this up at compile time - * - * @param className the class name - * @param name the method name - * @param desc the descriptor - * - * @return Call representing specified invokestatic call - */ - public static Call staticCallNoLookup(final String className, final String name, final String desc) { - return new Call(null, className, name, desc) { - @Override - MethodEmitter invoke(final MethodEmitter method) { - return method.invokestatic(className, name, descriptor); - } - - @Override - public void invoke(final MethodVisitor mv) { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, desc, false); - } - }; - } - - /** - * Create a call representing an invokestatic to a given method. Don't - * attempt to look this up at compile time - * - * @param clazz the class - * @param name the method name - * @param rtype the return type - * @param ptypes the parameter types - * - * @return Call representing specified invokestatic call - */ - public static Call staticCallNoLookup(final Class clazz, final String name, final Class rtype, final Class... ptypes) { - return staticCallNoLookup(className(clazz), name, methodDescriptor(rtype, ptypes)); - } - - /** - * Create a call representing an invokevirtual to a given method. Don't - * attempt to look this up at compile time - * - * @param clazz the class - * @param name the method name - * @param rtype the return type - * @param ptypes the parameter types - * - * @return Call representing specified invokevirtual call - */ - public static Call virtualCallNoLookup(final Class clazz, final String name, final Class rtype, final Class... ptypes) { - return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) { - @Override - MethodEmitter invoke(final MethodEmitter method) { - return method.invokevirtual(className, name, descriptor); - } - - @Override - public void invoke(final MethodVisitor mv) { - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false); - } - }; - } - - /** - * Create a call representing an invokeinterface to a given method. Don't - * attempt to look this up at compile time - * - * @param clazz the class - * @param name the method name - * @param rtype the return type - * @param ptypes the parameter types - * - * @return Call representing specified invokeinterface call - */ - public static Call interfaceCallNoLookup(final Class clazz, final String name, final Class rtype, final Class... ptypes) { - return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) { - @Override - MethodEmitter invoke(final MethodEmitter method) { - return method.invokeinterface(className, name, descriptor); - } - - @Override - public void invoke(final MethodVisitor mv) { - mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, className, name, descriptor, true); - } - }; - } - - /** - * Create a FieldAccess representing a virtual field, that can be subject to put - * or get operations - * - * @param className name of the class where the field is a member - * @param name name of the field - * @param desc type descriptor of the field - * - * @return a field access object giving access code generation method for the virtual field - */ - public static FieldAccess virtualField(final String className, final String name, final String desc) { - return new FieldAccess(className, name, desc) { - @Override - public MethodEmitter get(final MethodEmitter method) { - return method.getField(className, name, descriptor); - } - - @Override - public void put(final MethodEmitter method) { - method.putField(className, name, descriptor); - } - }; - } - - /** - * Create a FieldAccess representing a virtual field, that can be subject to put - * or get operations - * - * @param clazz class where the field is a member - * @param name name of the field - * @param type type of the field - * - * @return a field access object giving access code generation method for the virtual field - */ - public static FieldAccess virtualField(final Class clazz, final String name, final Class type) { - return virtualField(className(clazz), name, typeDescriptor(type)); - } - - /** - * Create a FieldAccess representing a static field, that can be subject to put - * or get operations - * - * @param className name of the class where the field is a member - * @param name name of the field - * @param desc type descriptor of the field - * - * @return a field access object giving access code generation method for the static field - */ - public static FieldAccess staticField(final String className, final String name, final String desc) { - return new FieldAccess(className, name, desc) { - @Override - public MethodEmitter get(final MethodEmitter method) { - return method.getStatic(className, name, descriptor); - } - - @Override - public void put(final MethodEmitter method) { - method.putStatic(className, name, descriptor); - } - }; - } - - /** - * Create a FieldAccess representing a static field, that can be subject to put - * or get operations - * - * @param clazz class where the field is a member - * @param name name of the field - * @param type type of the field - * - * @return a field access object giving access code generation method for the virtual field - */ - public static FieldAccess staticField(final Class clazz, final String name, final Class type) { - return staticField(className(clazz), name, typeDescriptor(type)); - } - - /** - * Create a static call, given an explicit lookup, looking up the method handle for it at the same time - * - * @param lookup the lookup - * @param clazz the class - * @param name the name of the method - * @param rtype the return type - * @param ptypes the parameter types - * - * @return the call object representing the static call - */ - public static Call staticCall(final MethodHandles.Lookup lookup, final Class clazz, final String name, final Class rtype, final Class... ptypes) { - return new Call(MH.findStatic(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) { - @Override - MethodEmitter invoke(final MethodEmitter method) { - return method.invokestatic(className, name, descriptor); - } - - @Override - public void invoke(final MethodVisitor mv) { - mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, descriptor, false); - } - }; - } - - /** - * Create a virtual call, given an explicit lookup, looking up the method handle for it at the same time - * - * @param lookup the lookup - * @param clazz the class - * @param name the name of the method - * @param rtype the return type - * @param ptypes the parameter types - * - * @return the call object representing the virtual call - */ - public static Call virtualCall(final MethodHandles.Lookup lookup, final Class clazz, final String name, final Class rtype, final Class... ptypes) { - return new Call(MH.findVirtual(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) { - @Override - MethodEmitter invoke(final MethodEmitter method) { - return method.invokevirtual(className, name, descriptor); - } - - @Override - public void invoke(final MethodVisitor mv) { - mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false); - } - }; - } - - /** - * Create a special call, given an explicit lookup, looking up the method handle for it at the same time. - * clazz is used as this class - * - * @param lookup the lookup - * @param clazz the class - * @param name the name of the method - * @param rtype the return type - * @param ptypes the parameter types - * - * @return the call object representing the virtual call - */ - public static Call specialCall(final MethodHandles.Lookup lookup, final Class clazz, final String name, final Class rtype, final Class... ptypes) { - return new Call(MH.findSpecial(lookup, clazz, name, MH.type(rtype, ptypes), clazz), className(clazz), name, methodDescriptor(rtype, ptypes)) { - @Override - MethodEmitter invoke(final MethodEmitter method) { - return method.invokespecial(className, name, descriptor); - } - - @Override - public void invoke(final MethodVisitor mv) { - mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, descriptor, false); - } - }; - } - - /** - * Returns true if the passed string looks like a method name of an internally generated Nashorn method. Basically, - * if it starts with a colon character {@code :} but is not the name of the program method {@code :program}. - * Program function is not considered internal as we want it to show up in exception stack traces. - * @param methodName the name of a method - * @return true if it looks like an internal Nashorn method name. - * @throws NullPointerException if passed null - */ - public static boolean isInternalMethodName(final String methodName) { - return methodName.startsWith(INTERNAL_METHOD_PREFIX) && !methodName.equals(PROGRAM.symbolName); - } - - /** - * Private class representing an access. This can generate code into a method code or - * a field access. - */ - private abstract static class Access { - protected final MethodHandle methodHandle; - protected final String className; - protected final String name; - protected final String descriptor; - - /** - * Constructor - * - * @param methodHandle methodHandle or null if none - * @param className class name for access - * @param name field or method name for access - * @param descriptor descriptor for access field or method - */ - protected Access(final MethodHandle methodHandle, final String className, final String name, final String descriptor) { - this.methodHandle = methodHandle; - this.className = className; - this.name = name; - this.descriptor = descriptor; - } - - /** - * Get the method handle, or null if access hasn't been looked up - * - * @return method handle - */ - public MethodHandle methodHandle() { - return methodHandle; - } - - /** - * Get the class name of the access - * - * @return the class name - */ - public String className() { - return className; - } - - /** - * Get the field name or method name of the access - * - * @return the name - */ - public String name() { - return name; - } - - /** - * Get the descriptor of the method or field of the access - * - * @return the descriptor - */ - public String descriptor() { - return descriptor; - } - } - - /** - * Field access - this can be used for generating code for static or - * virtual field accesses - */ - public abstract static class FieldAccess extends Access { - /** - * Constructor - * - * @param className name of the class where the field is - * @param name name of the field - * @param descriptor descriptor of the field - */ - protected FieldAccess(final String className, final String name, final String descriptor) { - super(null, className, name, descriptor); - } - - /** - * Generate get code for the field - * - * @param emitter a method emitter - * - * @return the method emitter - */ - protected abstract MethodEmitter get(final MethodEmitter emitter); - - /** - * Generate put code for the field - * - * @param emitter a method emitter - */ - protected abstract void put(final MethodEmitter emitter); - } - - /** - * Call - this can be used for generating code for different types of calls - */ - public abstract static class Call extends Access { - - /** - * Constructor - * - * @param className class name for the method of the call - * @param name method name - * @param descriptor method descriptor - */ - protected Call(final String className, final String name, final String descriptor) { - super(null, className, name, descriptor); - } - - /** - * Constructor - * - * @param methodHandle method handle for the call if resolved - * @param className class name for the method of the call - * @param name method name - * @param descriptor method descriptor - */ - protected Call(final MethodHandle methodHandle, final String className, final String name, final String descriptor) { - super(methodHandle, className, name, descriptor); - } - - /** - * Generate invocation code for the method - * - * @param emitter a method emitter - * - * @return the method emitter - */ - abstract MethodEmitter invoke(final MethodEmitter emitter); - - /** - * Generate invocation code for the method - * - * @param mv a method visitor - */ - public abstract void invoke(final MethodVisitor mv); - } - -}