Mercurial > hg > shenandoah-preopenjdk-archive > openjdk8 > nashorn
changeset 95:e478708faa22
8008239: Unpublicized parts of the code generator package that were only package internal.
Reviewed-by: hannesw, attila
line wrap: on
line diff
--- a/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,14 +25,14 @@ package jdk.nashorn.internal.codegen; -import static jdk.nashorn.internal.codegen.MethodEmitter.Condition.EQ; -import static jdk.nashorn.internal.codegen.MethodEmitter.Condition.GE; -import static jdk.nashorn.internal.codegen.MethodEmitter.Condition.GT; -import static jdk.nashorn.internal.codegen.MethodEmitter.Condition.LE; -import static jdk.nashorn.internal.codegen.MethodEmitter.Condition.LT; -import static jdk.nashorn.internal.codegen.MethodEmitter.Condition.NE; +import static jdk.nashorn.internal.codegen.Condition.EQ; +import static jdk.nashorn.internal.codegen.Condition.GE; +import static jdk.nashorn.internal.codegen.Condition.GT; +import static jdk.nashorn.internal.codegen.Condition.LE; +import static jdk.nashorn.internal.codegen.Condition.LT; +import static jdk.nashorn.internal.codegen.Condition.NE; -import jdk.nashorn.internal.codegen.MethodEmitter.Label; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Node;
--- a/src/jdk/nashorn/internal/codegen/ClassEmitter.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/ClassEmitter.java Fri Feb 15 09:44:15 2013 +0100 @@ -62,6 +62,7 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; +import jdk.nashorn.internal.codegen.Emitter; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.runtime.Context; @@ -102,7 +103,6 @@ * detect if this is not true * * @see Compiler - * @see CodeGenerator */ public class ClassEmitter implements Emitter { @@ -156,7 +156,7 @@ * @param superClassName super class name for class * @param interfaceNames names of interfaces implemented by this class, or null if none */ - public ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) { + ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) { this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)); cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, interfaceNames); } @@ -363,7 +363,7 @@ * @param bytecode byte array representing bytecode * @return disassembly as human readable string */ - public static String disassemble(final byte[] bytecode) { + static String disassemble(final byte[] bytecode) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (final PrintWriter pw = new PrintWriter(baos)) { new ClassReader(bytecode).accept(new TraceClassVisitor(pw), 0); @@ -411,7 +411,7 @@ * * @return method emitter to use for weaving this method */ - public MethodEmitter method(final String methodName, final Class<?> rtype, final Class<?>... ptypes) { + MethodEmitter method(final String methodName, final Class<?> rtype, final Class<?>... ptypes) { return method(DEFAULT_METHOD_FLAGS, methodName, rtype, ptypes); //TODO why public default ? } @@ -425,7 +425,7 @@ * * @return method emitter to use for weaving this method */ - public MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) { + MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) { return new MethodEmitter(this, cw.visitMethod(Flag.getValue(methodFlags), methodName, methodDescriptor(rtype, ptypes), null, null)); } @@ -437,7 +437,7 @@ * * @return method emitter to use for weaving this method */ - public MethodEmitter method(final String methodName, final String descriptor) { + MethodEmitter method(final String methodName, final String descriptor) { return method(DEFAULT_METHOD_FLAGS, methodName, descriptor); } @@ -450,7 +450,7 @@ * * @return method emitter to use for weaving this method */ - public MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final String descriptor) { + MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final String descriptor) { return new MethodEmitter(this, cw.visitMethod(Flag.getValue(methodFlags), methodName, descriptor, null, null)); } @@ -460,7 +460,7 @@ * @param functionNode the function node to generate a method for * @return method emitter to use for weaving this method */ - public MethodEmitter method(final FunctionNode functionNode) { + MethodEmitter method(final FunctionNode functionNode) { final MethodVisitor mv = cw.visitMethod( ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0), functionNode.getName(), @@ -476,7 +476,7 @@ * * @return method emitter to use for weaving <clinit> */ - public MethodEmitter clinit() { + MethodEmitter clinit() { return method(EnumSet.of(Flag.STATIC), CLINIT.tag(), void.class); } @@ -485,7 +485,7 @@ * * @return method emitter to use for weaving <init>()V */ - public MethodEmitter init() { + MethodEmitter init() { return method(INIT.tag(), void.class); } @@ -495,7 +495,7 @@ * @param ptypes parameter types for constructor * @return method emitter to use for weaving <init>()V */ - public MethodEmitter init(final Class<?>... ptypes) { + MethodEmitter init(final Class<?>... ptypes) { return method(INIT.tag(), void.class, ptypes); } @@ -507,7 +507,7 @@ * * @return method emitter to use for weaving <init>(...)V */ - public MethodEmitter init(final EnumSet<Flag> flags, final Class<?>... ptypes) { + MethodEmitter init(final EnumSet<Flag> flags, final Class<?>... ptypes) { return method(flags, INIT.tag(), void.class, ptypes); } @@ -521,7 +521,7 @@ * * @see ClassEmitter.Flag */ - public final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType, final Object value) { + final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType, final Object value) { cw.visitField(Flag.getValue(fieldFlags), fieldName, typeDescriptor(fieldType), null, value).visitEnd(); } @@ -534,7 +534,7 @@ * * @see ClassEmitter.Flag */ - public final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType) { + final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType) { field(fieldFlags, fieldName, fieldType, null); } @@ -544,7 +544,7 @@ * @param fieldName name of field * @param fieldType type of field */ - public final void field(final String fieldName, final Class<?> fieldType) { + final void field(final String fieldName, final Class<?> fieldType) { field(EnumSet.of(Flag.PUBLIC), fieldName, fieldType, null); } @@ -554,7 +554,7 @@ * * @return byte code array for generated class, null if class generation hasn't been ended with {@link ClassEmitter#end()} */ - public byte[] toByteArray() { + byte[] toByteArray() { assert classEnded; if (!classEnded) { return null; @@ -572,7 +572,7 @@ * Flags are provided for method handles, protection levels, static/virtual * fields/methods. */ - public static enum Flag { + static enum Flag { /** method handle with static access */ HANDLE_STATIC(H_INVOKESTATIC), /** method handle with new invoke special access */ @@ -603,7 +603,7 @@ * Get the value of this flag * @return the int value */ - public int getValue() { + int getValue() { return value; } @@ -613,7 +613,7 @@ * @param flags enum set of flags * @return an integer value representing the flags intrinsic values or:ed together */ - public static int getValue(final EnumSet<Flag> flags) { + static int getValue(final EnumSet<Flag> flags) { int v = 0; for (final Flag flag : flags) { v |= flag.getValue(); @@ -621,5 +621,4 @@ return v; } } - }
--- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Feb 15 09:44:15 2013 +0100 @@ -63,13 +63,7 @@ import java.util.TreeMap; import jdk.nashorn.internal.codegen.ClassEmitter.Flag; import jdk.nashorn.internal.codegen.CompilerConstants.Call; -import jdk.nashorn.internal.codegen.MethodEmitter.Condition; -import jdk.nashorn.internal.codegen.MethodEmitter.Label; import jdk.nashorn.internal.codegen.RuntimeCallSite.SpecializedRuntimeNode; -import jdk.nashorn.internal.codegen.objects.FieldObjectCreator; -import jdk.nashorn.internal.codegen.objects.MapCreator; -import jdk.nashorn.internal.codegen.objects.ObjectCreator; -import jdk.nashorn.internal.codegen.objects.ObjectMapCreator; import jdk.nashorn.internal.codegen.types.ArrayType; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.AccessNode; @@ -118,6 +112,7 @@ import jdk.nashorn.internal.runtime.CodeInstaller; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ECMAException; +import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.Scope; import jdk.nashorn.internal.runtime.ScriptFunction; @@ -147,7 +142,7 @@ * The CodeGenerator visits nodes only once, tags them as resolved and emits * bytecode for them. */ -public final class CodeGenerator extends NodeOperatorVisitor { +final class CodeGenerator extends NodeOperatorVisitor { /** Name of the Global object, cannot be referred to as .class, @see CodeGenerator */ private static final String GLOBAL_OBJECT = Compiler.OBJECTS_PACKAGE + '/' + "Global"; @@ -189,7 +184,7 @@ * * @return the correct flags for a call site in the current function */ - public int getCallSiteFlags() { + int getCallSiteFlags() { return getCurrentFunctionNode().isStrictMode() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags; } @@ -302,7 +297,7 @@ * * @return the method emitter used */ - public MethodEmitter load(final Node node) { + MethodEmitter load(final Node node) { return load(node, false); } @@ -661,9 +656,8 @@ } else { // get global from scope (which is the self) globalInstance(); } - loadArgs(args, signature, isVarArg, argCount); - method.invokeStatic(callee.getCompileUnit().getUnitClassName(), callee.getName(), signature); + method.invokestatic(callee.getCompileUnit().getUnitClassName(), callee.getName(), signature); assert method.peekType().equals(callee.getReturnType()) : method.peekType() + " != " + callee.getReturnType(); return null; @@ -1138,7 +1132,7 @@ savedMethod.swap(); savedMethod.loadScope(); savedMethod.swap(); - savedMethod.invokeStatic(className, name, signature); + savedMethod.invokestatic(className, name, signature); } } finally { setCurrentCompileUnit(savedCompileUnit); @@ -1191,13 +1185,13 @@ * * @param string string to load */ - public void loadConstant(final String string) { + void loadConstant(final String string) { final String unitClassName = getCurrentCompileUnit().getUnitClassName(); final ClassEmitter classEmitter = getCurrentCompileUnit().getClassEmitter(); final int index = compiler.getConstantData().add(string); method.load(index); - method.invokeStatic(unitClassName, GET_STRING.tag(), methodDescriptor(String.class, int.class)); + method.invokestatic(unitClassName, GET_STRING.tag(), methodDescriptor(String.class, int.class)); classEmitter.needGetConstantMethod(String.class); } @@ -1207,7 +1201,7 @@ * * @param object object to load */ - public void loadConstant(final Object object) { + void loadConstant(final Object object) { final String unitClassName = getCurrentCompileUnit().getUnitClassName(); final ClassEmitter classEmitter = getCurrentCompileUnit().getClassEmitter(); final int index = compiler.getConstantData().add(object); @@ -1215,12 +1209,12 @@ if (cls == PropertyMap.class) { method.load(index); - method.invokeStatic(unitClassName, GET_MAP.tag(), methodDescriptor(PropertyMap.class, int.class)); + method.invokestatic(unitClassName, GET_MAP.tag(), methodDescriptor(PropertyMap.class, int.class)); classEmitter.needGetConstantMethod(PropertyMap.class); } else if (cls.isArray()) { method.load(index); final String methodName = ClassEmitter.getArrayMethodName(cls); - method.invokeStatic(unitClassName, methodName, methodDescriptor(cls, int.class)); + method.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class)); classEmitter.needGetConstantMethod(cls); } else { method.loadConstants(unitClassName).load(index).arrayload(); @@ -1363,7 +1357,12 @@ */ @Override protected MapCreator newMapCreator(final Class<?> fieldObjectClass) { - return new ObjectMapCreator(fieldObjectClass, keys, symbols); + return new MapCreator(fieldObjectClass, keys, symbols) { + @Override + protected int getPropertyFlags(final Symbol symbol, final boolean isVarArg) { + return super.getPropertyFlags(symbol, isVarArg) | Property.IS_ALWAYS_OBJECT; + } + }; } }.makeObject(method); @@ -1487,7 +1486,7 @@ method.label(falseLabel); load(rhs); - method.invokeStatic(CompilerConstants.className(ScriptRuntime.class), request.toString(), signature); + method.invokestatic(CompilerConstants.className(ScriptRuntime.class), request.toString(), signature); method._goto(endLabel); method.label(trueLabel); @@ -1628,7 +1627,7 @@ load(arg).convert(Type.OBJECT); //TODO this should not be necessary below Lower } - method.invokeStatic( + method.invokestatic( CompilerConstants.className(ScriptRuntime.class), runtimeNode.getRequest().toString(), new FunctionSignature( @@ -1746,7 +1745,7 @@ labels[i] = new Label("split_state_" + i); } - caller.tableSwitch(low, targetCount, breakLabel, labels); + caller.tableswitch(low, targetCount, breakLabel, labels); for (int i = low; i <= targetCount; i++) { caller.label(labels[i - low]); if (i == 0) { @@ -1853,7 +1852,7 @@ table[value - lo] = labels[i]; } - method.tableSwitch(lo, hi, defaultLabel, table); + method.tableswitch(lo, hi, defaultLabel, table); } else { final int[] ints = new int[size]; @@ -1861,7 +1860,7 @@ ints[i] = values[i]; } - method.lookupSwitch(defaultLabel, ints, labels); + method.lookupswitch(defaultLabel, ints, labels); } } else { load(expression); @@ -1869,7 +1868,7 @@ if (expression.getType().isInteger()) { method.convert(Type.NUMBER).dup(); method.store(tag); - method.conditionalJump(MethodEmitter.Condition.NE, true, defaultLabel); + method.conditionalJump(Condition.NE, true, defaultLabel); } else { method.store(tag); } @@ -3245,7 +3244,7 @@ new ObjectCreator(this, new ArrayList<String>(), new ArrayList<Symbol>(), false, false) { @Override - public void makeObject(final MethodEmitter method) { + protected void makeObject(final MethodEmitter method) { final String className = isLazy ? SCRIPTFUNCTION_TRAMPOLINE_OBJECT : SCRIPTFUNCTION_IMPL_OBJECT; method._new(className).dup(); @@ -3286,36 +3285,36 @@ * is from the code pipeline is Global */ private MethodEmitter globalInstance() { - return method.invokeStatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';'); + return method.invokestatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';'); } private MethodEmitter globalObjectPrototype() { - return method.invokeStatic(GLOBAL_OBJECT, "objectPrototype", methodDescriptor(ScriptObject.class)); + return method.invokestatic(GLOBAL_OBJECT, "objectPrototype", methodDescriptor(ScriptObject.class)); } private MethodEmitter globalAllocateArguments() { - return method.invokeStatic(GLOBAL_OBJECT, "allocateArguments", methodDescriptor(ScriptObject.class, Object[].class, Object.class, int.class)); + return method.invokestatic(GLOBAL_OBJECT, "allocateArguments", methodDescriptor(ScriptObject.class, Object[].class, Object.class, int.class)); } private MethodEmitter globalNewRegExp() { - return method.invokeStatic(GLOBAL_OBJECT, "newRegExp", methodDescriptor(Object.class, String.class, String.class)); + return method.invokestatic(GLOBAL_OBJECT, "newRegExp", methodDescriptor(Object.class, String.class, String.class)); } private MethodEmitter globalRegExpCopy() { - return method.invokeStatic(GLOBAL_OBJECT, "regExpCopy", methodDescriptor(Object.class, Object.class)); + return method.invokestatic(GLOBAL_OBJECT, "regExpCopy", methodDescriptor(Object.class, Object.class)); } private MethodEmitter globalAllocateArray(final ArrayType type) { //make sure the native array is treated as an array type - return method.invokeStatic(GLOBAL_OBJECT, "allocate", "(" + type.getDescriptor() + ")Ljdk/nashorn/internal/objects/NativeArray;"); + return method.invokestatic(GLOBAL_OBJECT, "allocate", "(" + type.getDescriptor() + ")Ljdk/nashorn/internal/objects/NativeArray;"); } private MethodEmitter globalIsEval() { - return method.invokeStatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class)); + return method.invokestatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class)); } private MethodEmitter globalDirectEval() { - return method.invokeStatic(GLOBAL_OBJECT, "directEval", + return method.invokestatic(GLOBAL_OBJECT, "directEval", methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class)); } }
--- a/src/jdk/nashorn/internal/codegen/CompilationPhase.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/CompilationPhase.java Fri Feb 15 09:44:15 2013 +0100 @@ -76,18 +76,7 @@ CONSTANT_FOLDING_PHASE(EnumSet.of(INITIALIZED), CONSTANT_FOLDED) { @Override boolean transform(final Compiler compiler, final FunctionNode fn) { - final Context context = compiler.getContext(); - - if (context._print_ast) { - context.getErr().println(new ASTWriter(fn)); - } - - if (context._print_parse) { - context.getErr().println(new PrintVisitor(fn)); - } - fn.accept(new FoldConstants()); - return true; } @@ -137,7 +126,7 @@ if (context._print_lower_parse) { context.getErr().println(new PrintVisitor(fn)); - } + } } }
--- a/src/jdk/nashorn/internal/codegen/CompilerConstants.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/CompilerConstants.java Fri Feb 15 09:44:15 2013 +0100 @@ -320,7 +320,7 @@ return new Call(null, className, name, desc) { @Override public MethodEmitter invoke(final MethodEmitter method) { - return method.invokeSpecial(className, name, descriptor); + return method.invokespecial(className, name, descriptor); } }; } @@ -354,7 +354,7 @@ return new Call(null, className, name, desc) { @Override public MethodEmitter invoke(final MethodEmitter method) { - return method.invokeStatic(className, name, descriptor); + return method.invokestatic(className, name, descriptor); } }; } @@ -389,7 +389,7 @@ return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) { @Override public MethodEmitter invoke(final MethodEmitter method) { - return method.invokeVirtual(className, name, descriptor); + return method.invokevirtual(className, name, descriptor); } }; } @@ -409,7 +409,7 @@ return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) { @Override public MethodEmitter invoke(final MethodEmitter method) { - return method.invokeInterface(className, name, descriptor); + return method.invokeinterface(className, name, descriptor); } }; } @@ -519,7 +519,7 @@ return new Call(MH.findStatic(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) { @Override public MethodEmitter invoke(final MethodEmitter method) { - return method.invokeStatic(className, name, descriptor); + return method.invokestatic(className, name, descriptor); } }; } @@ -553,7 +553,7 @@ return new Call(MH.findVirtual(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) { @Override public MethodEmitter invoke(final MethodEmitter method) { - return method.invokeVirtual(className, name, descriptor); + return method.invokevirtual(className, name, descriptor); } }; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/Condition.java Fri Feb 15 09:44:15 2013 +0100 @@ -0,0 +1,107 @@ +/* + * 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.internal.org.objectweb.asm.Opcodes.IFEQ; +import static jdk.internal.org.objectweb.asm.Opcodes.IFGE; +import static jdk.internal.org.objectweb.asm.Opcodes.IFGT; +import static jdk.internal.org.objectweb.asm.Opcodes.IFLE; +import static jdk.internal.org.objectweb.asm.Opcodes.IFLT; +import static jdk.internal.org.objectweb.asm.Opcodes.IFNE; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPEQ; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPNE; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPEQ; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGT; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLE; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLT; +import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPNE; +import jdk.nashorn.internal.ir.RuntimeNode; + +/** + * Condition enum used for all kinds of jumps, regardless of type + */ +enum Condition { + EQ, + NE, + LE, + LT, + GE, + GT; + + static Condition forRuntimeRequest(final RuntimeNode.Request request) { + try { + final String reqString = request.toString().replace("_STRICT", ""); + return Condition.valueOf(reqString); + } catch (final IllegalArgumentException e) { + return null; + } + } + + static int toUnary(final Condition c) { + switch (c) { + case EQ: + return IFEQ; + case NE: + return IFNE; + case LE: + return IFLE; + case LT: + return IFLT; + case GE: + return IFGE; + case GT: + return IFGT; + default: + assert false; + return -1; + } + } + + static int toBinary(final Condition c) { + return toBinary(c, false); + } + + static int toBinary(final Condition c, final boolean isObject) { + switch (c) { + case EQ: + return isObject ? IF_ACMPEQ : IF_ICMPEQ; + case NE: + return isObject ? IF_ACMPNE : IF_ICMPNE; + case LE: + return IF_ICMPLE; + case LT: + return IF_ICMPLT; + case GE: + return IF_ICMPGE; + case GT: + return IF_ICMPGT; + default: + assert false; + return -1; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java Fri Feb 15 09:44:15 2013 +0100 @@ -0,0 +1,191 @@ +/* + * 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.codegen.CompilerConstants.ARGUMENTS; +import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; +import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; +import static jdk.nashorn.internal.codegen.types.Type.OBJECT; + +import java.util.Iterator; +import java.util.List; +import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.ir.Symbol; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.arrays.ArrayIndex; + +/** + * Analyze an object's characteristics for appropriate code generation. This + * is used for functions and for objects. A field object take a set of values which + * to assign to the various fields in the object. This is done by the generated code + * + * @param <T> the value type for the fields being written on object creation, e.g. Node + * @see jdk.nashorn.internal.ir.Node + */ +public abstract class FieldObjectCreator<T> extends ObjectCreator { + /** array of corresponding values to symbols (null for no values) */ + private final List<T> values; + + /** call site flags to be used for invocations */ + private final int callSiteFlags; + + /** + * Constructor + * + * @param codegen code generator + * @param keys keys for fields in object + * @param symbols symbols for fields in object + * @param values list of values corresponding to keys + */ + FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values) { + this(codegen, keys, symbols, values, false, false); + } + + /** + * Constructor + * + * @param codegen code generator + * @param keys keys for fields in object + * @param symbols symbols for fields in object + * @param values values (or null where no value) to be written to the fields + * @param isScope is this a scope object + * @param hasArguments does the created object have an "arguments" property + */ + FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values, final boolean isScope, final boolean hasArguments) { + super(codegen, keys, symbols, isScope, hasArguments); + this.values = values; + this.callSiteFlags = codegen.getCallSiteFlags(); + } + + /** + * Loads the scope on the stack through the passed method emitter. + * @param method the method emitter to use + */ + protected void loadScope(final MethodEmitter method) { + method.loadScope(); + } + + /** + * Construct an object. + * + * @param method the method emitter + */ + @Override + protected void makeObject(final MethodEmitter method) { + makeMap(); + + method._new(getClassName()).dup(); // create instance + loadMap(method); //load the map + + if (isScope()) { + loadScope(method); + + if (hasArguments()) { + method.loadArguments(); + method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class, ARGUMENTS.type())); + } else { + method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class)); + } + } else { + method.invoke(constructorNoLookup(getClassName(), PropertyMap.class)); + } + + // Set values. + final Iterator<Symbol> symbolIter = symbols.iterator(); + final Iterator<String> keyIter = keys.iterator(); + final Iterator<T> valueIter = values.iterator(); + + while (symbolIter.hasNext()) { + final Symbol symbol = symbolIter.next(); + final String key = keyIter.next(); + final T value = valueIter.next(); + + if (symbol != null && value != null) { + final int index = ArrayIndex.getArrayIndexNoThrow(key); + + if (index < 0) { + putField(method, key, symbol.getFieldIndex(), value); + } else { + putSlot(method, index, value); + } + } + } + } + + /** + * Technique for loading an initial value. Defined by anonymous subclasses in code gen. + * + * @param value Value to load. + */ + protected abstract void loadValue(T value); + + /** + * Determine the type of a value. Defined by anonymous subclasses in code gen. + * + * @param value Value to inspect. + * + * @return Value type. + */ + protected abstract Type getValueType(T value); + + /** + * Store a value in a field of the generated class object. + * + * @param method Script method. + * @param key Property key. + * @param fieldIndex Field number. + * @param value Value to store. + */ + private void putField(final MethodEmitter method, final String key, final int fieldIndex, final T value) { + method.dup(); + + loadValue(value); + + final Type valueType = getValueType(value); + // for example when we have a with scope + if (valueType.isObject() || valueType.isBoolean()) { + method.convert(OBJECT); + } + + method.convert(OBJECT); + method.putField(getClassName(), ObjectClassGenerator.getFieldName(fieldIndex, Type.OBJECT), typeDescriptor(Object.class)); + } + + /** + * Store a value in an indexed slot of a generated class object. + * + * @param method Script method. + * @param index Slot index. + * @param value Value to store. + */ + private void putSlot(final MethodEmitter method, final int index, final T value) { + method.dup(); + method.load(index); + loadValue(value); + method.dynamicSetIndex(callSiteFlags); + } +}
--- a/src/jdk/nashorn/internal/codegen/FunctionSignature.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/FunctionSignature.java Fri Feb 15 09:44:15 2013 +0100 @@ -202,7 +202,6 @@ return methodType; } - private static Type[] objectArgs(final int nArgs) { final Type[] array = new Type[nArgs]; for (int i = 0; i < nArgs; i++) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/Label.java Fri Feb 15 09:44:15 2013 +0100 @@ -0,0 +1,83 @@ +/* + * 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 java.util.ArrayDeque; + +import jdk.nashorn.internal.codegen.types.Type; + +/** + * Abstraction for labels, separating a label from the underlying + * byte code emitter. Also augmenting label with e.g. a name + * for easier debugging and reading code + * + * see -Dnashorn.codegen.debug, --log=codegen + */ +public class Label extends jdk.internal.org.objectweb.asm.Label { + /** Name of this label */ + private final String name; + + /** Type stack at this label */ + private ArrayDeque<Type> stack; + + /** + * Constructor + * + * @param name name of this label + */ + public Label(final String name) { + super(); + this.name = name; + } + + /** + * Copy constructor + * + * @param label a label to clone + */ + public Label(final Label label) { + super(); + this.name = label.name; + } + + ArrayDeque<Type> getStack() { + return stack; + } + + void setStack(final ArrayDeque<Type> stack) { + this.stack = stack; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + String s = super.toString(); + s = s.substring(1, s.length()); + sb.append(name).append('_').append(Long.toHexString(Long.parseLong(s))); + + return sb.toString(); + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/MapCreator.java Fri Feb 15 09:44:15 2013 +0100 @@ -0,0 +1,122 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; +import jdk.nashorn.internal.ir.Symbol; +import jdk.nashorn.internal.runtime.AccessorProperty; +import jdk.nashorn.internal.runtime.Property; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.arrays.ArrayIndex; + +/** + * Class that creates PropertyMap sent to script object constructors. + */ +public class MapCreator { + /** Object structure for objects associated with this map */ + private final Class<?> structure; + + /** key set for object map */ + private final String[] keys; + + /** corresponding symbol set for object map */ + private final Symbol[] symbols; + + /** + * Constructor + * + * @param structure structure to generate map for (a JO$ subclass) + * @param keys list of keys for map + * @param symbols list of symbols for map + */ + MapCreator(final Class<?> structure, final List<String> keys, final List<Symbol> symbols) { + final int size = keys.size(); + + this.structure = structure; + this.keys = keys.toArray(new String[size]); + this.symbols = symbols.toArray(new Symbol[size]); + } + + /** + * Constructs a property map based on a set of fields. + * + * @param hasArguments does the created object have an "arguments" property + * + * @return New map populated with accessor properties. + */ + PropertyMap makeMap(final boolean hasArguments) { + final List<Property> properties = new ArrayList<>(); + + assert keys != null; + + for (int i = 0; i < keys.length; i++) { + final String key = keys[i]; + final Symbol symbol = symbols[i]; + + if (symbol != null && !ArrayIndex.isIndexKey(key)) { + properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex())); + } + } + + return PropertyMap.newMap(structure, properties); + } + + /** + * Compute property flags given local state of a field. May be overridden and extended, + * + * @param symbol symbol to check + * @param hasArguments does the created object have an "arguments" property + * + * @return flags to use for fields + */ + protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) { + int flags = 0; + + if (symbol.isParam()) { + flags |= Property.IS_ALWAYS_OBJECT | Property.IS_PARAMETER; + } + + if (hasArguments) { + flags |= Property.IS_ALWAYS_OBJECT | Property.HAS_ARGUMENTS; + } + + if (symbol.isScope()) { + flags |= Property.NOT_CONFIGURABLE; + } + + if (symbol.canBePrimitive()) { + flags |= Property.CAN_BE_PRIMITIVE; + } + + if (symbol.canBeUndefined()) { + flags |= Property.CAN_BE_UNDEFINED; + } + + return flags; + } + +}
--- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Fri Feb 15 09:44:15 2013 +0100 @@ -43,10 +43,6 @@ import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPEQ; import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPNE; import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPEQ; -import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE; -import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGT; -import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLE; -import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLT; import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPNE; import static jdk.internal.org.objectweb.asm.Opcodes.INSTANCEOF; import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE; @@ -114,7 +110,7 @@ private final MethodVisitor method; /** Current type stack for current evaluation */ - protected ArrayDeque<Type> stack; + private ArrayDeque<Type> stack; /** Parent classEmitter representing the class of this method */ private final ClassEmitter classEmitter; @@ -287,7 +283,7 @@ * * @return the type at position "pos" on the stack */ - public final Type peekType(final int pos) { + final Type peekType(final int pos) { final Iterator<Type> iter = stack.iterator(); for (int i = 0; i < pos; i++) { iter.next(); @@ -300,7 +296,7 @@ * * @return the type at the top of the stack */ - public final Type peekType() { + final Type peekType() { return stack.peek(); } @@ -312,7 +308,7 @@ * * @return the method emitter */ - public MethodEmitter _new(final String classDescriptor) { + MethodEmitter _new(final String classDescriptor) { debug("new", classDescriptor); method.visitTypeInsn(NEW, classDescriptor); pushType(Type.OBJECT); @@ -327,7 +323,7 @@ * * @return the method emitter */ - public MethodEmitter _new(final Class<?> clazz) { + MethodEmitter _new(final Class<?> clazz) { return _new(className(clazz)); } @@ -338,7 +334,7 @@ * * @return the method emitter */ - public MethodEmitter newInstance(final Class<?> clazz) { + MethodEmitter newInstance(final Class<?> clazz) { return invoke(constructorNoLookup(clazz)); } @@ -352,7 +348,7 @@ * @return the method emitter, or null if depth is illegal and * has no instruction equivalent. */ - public MethodEmitter dup(final int depth) { + MethodEmitter dup(final int depth) { if (peekType().dup(method, depth) == null) { return null; } @@ -396,7 +392,7 @@ * * @return the method emitter */ - public MethodEmitter dup2() { + MethodEmitter dup2() { debug("dup2"); if (peekType().isCategory2()) { @@ -417,7 +413,7 @@ * * @return the method emitter */ - public MethodEmitter dup() { + MethodEmitter dup() { return dup(0); } @@ -426,7 +422,7 @@ * * @return the method emitter */ - public MethodEmitter pop() { + MethodEmitter pop() { debug("pop", peekType()); popType().pop(method); return this; @@ -438,7 +434,7 @@ * * @return the method emitter */ - public MethodEmitter pop2() { + MethodEmitter pop2() { if (peekType().isCategory2()) { popType(); } else { @@ -453,7 +449,7 @@ * * @return the method emitter */ - public MethodEmitter swap() { + MethodEmitter swap() { debug("swap"); final Type p0 = popType(); @@ -473,7 +469,7 @@ * @param start start of scope * @param end end of scope */ - public void localVariable(final Symbol symbol, final Label start, final Label end) { + void localVariable(final Symbol symbol, final Label start, final Label end) { if (!symbol.hasSlot()) { return; } @@ -492,7 +488,7 @@ * * @return the method emitter */ - public MethodEmitter newStringBuilder() { + MethodEmitter newStringBuilder() { return invoke(constructorNoLookup(StringBuilder.class)).dup(); } @@ -503,7 +499,7 @@ * * @return the method emitter */ - public MethodEmitter stringBuilderAppend() { + MethodEmitter stringBuilderAppend() { convert(Type.STRING); return invoke(virtualCallNoLookup(StringBuilder.class, "append", StringBuilder.class, String.class)); } @@ -515,7 +511,7 @@ * @param start start * @param end end */ - public void markerVariable(final String name, final Label start, final Label end) { + void markerVariable(final String name, final Label start, final Label end) { method.visitLocalVariable(name, Type.OBJECT.getDescriptor(), null, start, end, 0); } @@ -525,7 +521,7 @@ * * @return the method emitter */ - public MethodEmitter and() { + MethodEmitter and() { debug("and"); pushType(get2i().and(method)); return this; @@ -537,7 +533,7 @@ * * @return the method emitter */ - public MethodEmitter or() { + MethodEmitter or() { debug("or"); pushType(get2i().or(method)); return this; @@ -549,7 +545,7 @@ * * @return the method emitter */ - public MethodEmitter xor() { + MethodEmitter xor() { debug("xor"); pushType(get2i().xor(method)); return this; @@ -561,7 +557,7 @@ * * @return the method emitter */ - public MethodEmitter shr() { + MethodEmitter shr() { debug("shr"); popType(Type.INT); pushType(popInteger().shr(method)); @@ -574,7 +570,7 @@ * * @return the method emitter */ - public MethodEmitter shl() { + MethodEmitter shl() { debug("shl"); popType(Type.INT); pushType(popInteger().shl(method)); @@ -587,7 +583,7 @@ * * @return the method emitter */ - public MethodEmitter sar() { + MethodEmitter sar() { debug("sar"); popType(Type.INT); pushType(popInteger().sar(method)); @@ -599,7 +595,7 @@ * * @return the method emitter */ - public MethodEmitter neg() { + MethodEmitter neg() { debug("neg"); pushType(popNumeric().neg(method)); return this; @@ -611,7 +607,7 @@ * * @param recovery label pointing to start of catch block */ - public void _catch(final Label recovery) { + void _catch(final Label recovery) { stack.clear(); stack.push(Type.OBJECT); label(recovery); @@ -625,7 +621,7 @@ * @param recovery start label for catch * @param typeDescriptor type descriptor for exception */ - public void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor) { + void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor) { method.visitTryCatchBlock(entry, exit, recovery, typeDescriptor); } @@ -637,7 +633,7 @@ * @param recovery start label for catch * @param clazz exception class */ - public void _try(final Label entry, final Label exit, final Label recovery, final Class<?> clazz) { + void _try(final Label entry, final Label exit, final Label recovery, final Class<?> clazz) { method.visitTryCatchBlock(entry, exit, recovery, CompilerConstants.className(clazz)); } @@ -648,7 +644,7 @@ * @param exit end label for try * @param recovery start label for catch */ - public void _try(final Label entry, final Label exit, final Label recovery) { + void _try(final Label entry, final Label exit, final Label recovery) { _try(entry, exit, recovery, (String)null); } @@ -658,7 +654,7 @@ * @param unitClassName name of the compile unit from which to load constants * @return this method emitter */ - public MethodEmitter loadConstants(final String unitClassName) { + MethodEmitter loadConstants(final String unitClassName) { getStatic(unitClassName, CONSTANTS.tag(), CONSTANTS.descriptor()); assert peekType().isArray() : peekType(); return this; @@ -673,7 +669,7 @@ * @param type the type for which to push UNDEFINED * @return the method emitter */ - public MethodEmitter loadUndefined(final Type type) { + MethodEmitter loadUndefined(final Type type) { debug("load undefined " + type); pushType(type.loadUndefined(method)); return this; @@ -685,7 +681,7 @@ * @param type the type * @return the method emitter */ - public MethodEmitter loadEmpty(final Type type) { + MethodEmitter loadEmpty(final Type type) { debug("load empty " + type); pushType(type.loadEmpty(method)); return this; @@ -696,7 +692,7 @@ * * @return the method emitter */ - public MethodEmitter loadNull() { + MethodEmitter loadNull() { debug("aconst_null"); pushType(Type.OBJECT.ldc(method, null)); return this; @@ -709,7 +705,7 @@ * * @return the method emitter */ - public MethodEmitter loadType(final String className) { + MethodEmitter loadType(final String className) { debug("load type", className); method.visitLdcInsn(jdk.internal.org.objectweb.asm.Type.getObjectType(className)); pushType(Type.OBJECT); @@ -723,7 +719,7 @@ * * @return the method emitter */ - public MethodEmitter load(final boolean b) { + MethodEmitter load(final boolean b) { debug("load boolean", b); pushType(Type.BOOLEAN.ldc(method, b)); return this; @@ -736,7 +732,7 @@ * * @return the method emitter */ - public MethodEmitter load(final int i) { + MethodEmitter load(final int i) { debug("load int", i); pushType(Type.INT.ldc(method, i)); return this; @@ -749,7 +745,7 @@ * * @return the method emitter */ - public MethodEmitter load(final double d) { + MethodEmitter load(final double d) { debug("load double", d); pushType(Type.NUMBER.ldc(method, d)); return this; @@ -762,7 +758,7 @@ * * @return the method emitter */ - public MethodEmitter load(final long l) { + MethodEmitter load(final long l) { debug("load long", l); pushType(Type.LONG.ldc(method, l)); return this; @@ -772,7 +768,7 @@ * Fetch the length of an array. * @return Array length. */ - public MethodEmitter arraylength() { + MethodEmitter arraylength() { debug("arraylength"); popType(Type.OBJECT); pushType(Type.OBJECT_ARRAY.arraylength(method)); @@ -786,7 +782,7 @@ * * @return the method emitter */ - public MethodEmitter load(final String s) { + MethodEmitter load(final String s) { debug("load string", s); if (s == null) { @@ -826,7 +822,7 @@ * * @return the method emitter */ - public MethodEmitter load(final Symbol symbol) { + MethodEmitter load(final Symbol symbol) { assert symbol != null; if (symbol.hasSlot()) { final int slot = symbol.getSlot(); @@ -837,7 +833,7 @@ assert !symbol.isScope(); assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters"; final int index = symbol.getFieldIndex(); - if(functionNode.needsArguments()) { + if (functionNode.needsArguments()) { // ScriptObject.getArgument(int) on arguments debug("load symbol", symbol.getName(), " arguments index=", index); loadArguments(); @@ -864,7 +860,7 @@ * * @return the method emitter */ - public MethodEmitter load(final Type type, final int slot) { + MethodEmitter load(final Type type, final int slot) { debug("explicit load", type, slot); final Type loadType = type.load(method, slot); pushType(loadType == Type.OBJECT && isThisSlot(slot) ? Type.THIS : loadType); @@ -886,7 +882,7 @@ * * @return the method emitter */ - public MethodEmitter loadThis() { + MethodEmitter loadThis() { load(functionNode.getThisNode().getSymbol()); return this; } @@ -896,7 +892,7 @@ * * @return the method emitter */ - public MethodEmitter loadScope() { + MethodEmitter loadScope() { if (peekType() == Type.SCOPE) { dup(); return this; @@ -910,7 +906,7 @@ * * @return the method emitter */ - public MethodEmitter loadResult() { + MethodEmitter loadResult() { load(functionNode.getResultNode().getSymbol()); return this; } @@ -924,11 +920,9 @@ * @param descName descriptor * @param flags flags that describe this handle, e.g. invokespecial new, or invoke virtual * - * @see ClassEmitter.Flag - * * @return the method emitter */ - public MethodEmitter loadHandle(final String className, final String methodName, final String descName, final EnumSet<Flag> flags) { + MethodEmitter loadHandle(final String className, final String methodName, final String descName, final EnumSet<Flag> flags) { debug("load handle "); pushType(Type.OBJECT.ldc(method, new Handle(Flag.getValue(flags), className, methodName, descName))); return this; @@ -939,7 +933,7 @@ * * @return the method emitter */ - public MethodEmitter loadVarArgs() { + MethodEmitter loadVarArgs() { debug("load var args " + functionNode.getVarArgsNode().getSymbol()); return load(functionNode.getVarArgsNode().getSymbol()); } @@ -949,7 +943,7 @@ * * @return the method emitter */ - public MethodEmitter loadArguments() { + MethodEmitter loadArguments() { debug("load arguments ", functionNode.getArgumentsNode().getSymbol()); assert functionNode.getArgumentsNode().getSymbol().getSlot() != 0; return load(functionNode.getArgumentsNode().getSymbol()); @@ -960,7 +954,7 @@ * * @return the method emitter */ - public MethodEmitter loadCallee() { + MethodEmitter loadCallee() { final Symbol calleeSymbol = functionNode.getCalleeNode().getSymbol(); debug("load callee ", calleeSymbol); assert calleeSymbol.getSlot() == 0 : "callee has wrong slot " + calleeSymbol.getSlot() + " in " + functionNode.getName(); @@ -971,7 +965,7 @@ /** * Pop the scope from the stack and store it in its predefined slot */ - public void storeScope() { + void storeScope() { debug("store scope"); store(functionNode.getScopeNode().getSymbol()); } @@ -979,7 +973,7 @@ /** * Pop the return from the stack and store it in its predefined slot */ - public void storeResult() { + void storeResult() { debug("store result"); store(functionNode.getResultNode().getSymbol()); } @@ -987,7 +981,7 @@ /** * Pop the arguments array from the stack and store it in its predefined slot */ - public void storeArguments() { + void storeArguments() { debug("store arguments"); store(functionNode.getArgumentsNode().getSymbol()); } @@ -996,7 +990,7 @@ * Load an element from an array, determining type automatically * @return the method emitter */ - public MethodEmitter arrayload() { + MethodEmitter arrayload() { debug("Xaload"); popType(Type.INT); pushType(popArray().aload(method)); @@ -1007,7 +1001,7 @@ * Pop a value, an index and an array from the stack and store * the value at the given index in the array. */ - public void arraystore() { + void arraystore() { debug("Xastore"); final Type value = popType(); final Type index = popType(Type.INT); @@ -1025,7 +1019,7 @@ * * @param symbol symbol to store stack to */ - public void store(final Symbol symbol) { + void store(final Symbol symbol) { assert symbol != null : "No symbol to store"; if (symbol.hasSlot()) { final int slot = symbol.getSlot(); @@ -1035,7 +1029,7 @@ assert !symbol.isScope(); assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters"; final int index = symbol.getFieldIndex(); - if(functionNode.needsArguments()) { + if (functionNode.needsArguments()) { debug("store symbol", symbol.getName(), " arguments index=", index); loadArguments(); load(index); @@ -1057,7 +1051,7 @@ * @param type the type to pop * @param slot the slot */ - public void store(final Type type, final int slot) { + void store(final Type type, final int slot) { popType(type); type.store(method, slot); } @@ -1068,7 +1062,7 @@ * @param slot the int slot * @param increment the amount to increment */ - public void iinc(final int slot, final int increment) { + void iinc(final int slot, final int increment) { debug("iinc"); method.visitIincInsn(slot, increment); } @@ -1094,7 +1088,7 @@ * * @return the method emitter */ - public MethodEmitter _instanceof(final String classDescriptor) { + MethodEmitter _instanceof(final String classDescriptor) { debug("instanceof", classDescriptor); popType(Type.OBJECT); method.visitTypeInsn(INSTANCEOF, classDescriptor); @@ -1111,7 +1105,7 @@ * * @return the method emitter */ - public MethodEmitter _instanceof(final Class<?> clazz) { + MethodEmitter _instanceof(final Class<?> clazz) { return _instanceof(CompilerConstants.className(clazz)); } @@ -1123,7 +1117,7 @@ * * @return the method emitter */ - public MethodEmitter checkcast(final String classDescriptor) { + MethodEmitter checkcast(final String classDescriptor) { debug("checkcast", classDescriptor); assert peekType().isObject(); method.visitTypeInsn(CHECKCAST, classDescriptor); @@ -1138,7 +1132,7 @@ * * @return the method emitter */ - public MethodEmitter checkcast(final Class<?> clazz) { + MethodEmitter checkcast(final Class<?> clazz) { return checkcast(CompilerConstants.className(clazz)); } @@ -1150,7 +1144,7 @@ * * @return the method emitter */ - public MethodEmitter newarray(final ArrayType arrayType) { + MethodEmitter newarray(final ArrayType arrayType) { debug("newarray ", "arrayType=" + arrayType); popType(Type.INT); //LENGTH pushType(arrayType.newarray(method)); @@ -1166,7 +1160,7 @@ * * @return the method emitter */ - public MethodEmitter multinewarray(final ArrayType arrayType, final int dims) { + MethodEmitter multinewarray(final ArrayType arrayType, final int dims) { debug("multianewarray ", arrayType, dims); for (int i = 0; i < dims; i++) { popType(Type.INT); //LENGTH @@ -1200,7 +1194,7 @@ * * @return the method emitter */ - public MethodEmitter invoke(final Call call) { + MethodEmitter invoke(final Call call) { return call.invoke(this); } @@ -1229,7 +1223,7 @@ * * @return the method emitter */ - public MethodEmitter invokeSpecial(final String className, final String methodName, final String methodDescriptor) { + MethodEmitter invokespecial(final String className, final String methodName, final String methodDescriptor) { debug("invokespecial", className + "." + methodName + methodDescriptor); return invoke(INVOKESPECIAL, className, methodName, methodDescriptor, true); } @@ -1243,7 +1237,7 @@ * * @return the method emitter */ - public MethodEmitter invokeVirtual(final String className, final String methodName, final String methodDescriptor) { + MethodEmitter invokevirtual(final String className, final String methodName, final String methodDescriptor) { debug("invokevirtual", className + "." + methodName + methodDescriptor + " " + stack); return invoke(INVOKEVIRTUAL, className, methodName, methodDescriptor, true); } @@ -1257,7 +1251,7 @@ * * @return the method emitter */ - public MethodEmitter invokeStatic(final String className, final String methodName, final String methodDescriptor) { + MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor) { debug("invokestatic", className + "." + methodName + methodDescriptor); invoke(INVOKESTATIC, className, methodName, methodDescriptor, false); return this; @@ -1274,8 +1268,8 @@ * * @return the method emitter */ - public MethodEmitter invokeStatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) { - invokeStatic(className, methodName, methodDescriptor); + MethodEmitter invokeStatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) { + invokestatic(className, methodName, methodDescriptor); popType(); pushType(returnType); return this; @@ -1290,7 +1284,7 @@ * * @return the method emitter */ - public MethodEmitter invokeInterface(final String className, final String methodName, final String methodDescriptor) { + MethodEmitter invokeinterface(final String className, final String methodName, final String methodDescriptor) { debug("invokeinterface", className + "." + methodName + methodDescriptor); return invoke(INVOKEINTERFACE, className, methodName, methodDescriptor, true); } @@ -1302,7 +1296,7 @@ * @param values case values for the table * @param table default label */ - public void lookupSwitch(final Label defaultLabel, final int[] values, final Label[] table) { + void lookupswitch(final Label defaultLabel, final int[] values, final Label[] table) { debug("lookupswitch", peekType()); popType(Type.INT); method.visitLookupSwitchInsn(defaultLabel, values, table); @@ -1315,7 +1309,7 @@ * @param defaultLabel default label * @param table label table */ - public void tableSwitch(final int lo, final int hi, final Label defaultLabel, final Label[] table) { + void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label[] table) { debug("tableswitch", peekType()); popType(Type.INT); method.visitTableSwitchInsn(lo, hi, defaultLabel, table); @@ -1357,7 +1351,7 @@ * * @param type the type for the return */ - public void _return(final Type type) { + void _return(final Type type) { debug("return", type); assert stack.size() == 1 : "Only return value on stack allowed at return point - depth=" + stack.size() + " stack = " + stack; final Type stackType = peekType(); @@ -1371,14 +1365,14 @@ /** * Perform a return using the stack top value as the guide for the type */ - public void _return() { + void _return() { _return(peekType()); } /** * Perform a void return. */ - public void returnVoid() { + void returnVoid() { debug("return [void]"); assert stack.isEmpty() : stack; method.visitInsn(RETURN); @@ -1392,7 +1386,7 @@ * * @param label destination label */ - public void splitAwareGoto(final Label label) { + void splitAwareGoto(final Label label) { if (splitNode != null) { final int index = splitNode.getExternalTargets().indexOf(label); @@ -1418,7 +1412,7 @@ * * @return the method emitter */ - public MethodEmitter cmp(final boolean isCmpG) { + MethodEmitter cmp(final boolean isCmpG) { pushType(get2n().cmp(method, isCmpG)); return this; } @@ -1443,7 +1437,7 @@ * * @param label label to true case */ - public void if_acmpeq(final Label label) { + void if_acmpeq(final Label label) { debug("if_acmpeq", label); jump(IF_ACMPEQ, label, 2); } @@ -1453,7 +1447,7 @@ * * @param label label to true case */ - public void if_acmpne(final Label label) { + void if_acmpne(final Label label) { debug("if_acmpne", label); jump(IF_ACMPNE, label, 2); } @@ -1463,7 +1457,7 @@ * * @param label label to true case */ - public void ifnull(final Label label) { + void ifnull(final Label label) { debug("ifnull", label); jump(IFNULL, label, 1); } @@ -1473,7 +1467,7 @@ * * @param label label to true case */ - public void ifnonnull(final Label label) { + void ifnonnull(final Label label) { debug("ifnonnull", label); jump(IFNONNULL, label, 1); } @@ -1483,7 +1477,7 @@ * * @param label label to true case */ - public void ifeq(final Label label) { + void ifeq(final Label label) { debug("ifeq ", label); jump(IFEQ, label, 1); } @@ -1493,7 +1487,7 @@ * * @param label label to true case */ - public void if_icmpeq(final Label label) { + void if_icmpeq(final Label label) { debug("if_icmpeq", label); jump(IF_ICMPEQ, label, 2); } @@ -1503,8 +1497,7 @@ * * @param label label to true case */ - - public void ifne(final Label label) { + void ifne(final Label label) { debug("ifne", label); jump(IFNE, label, 1); } @@ -1514,7 +1507,7 @@ * * @param label label to true case */ - public void if_icmpne(final Label label) { + void if_icmpne(final Label label) { debug("if_icmpne", label); jump(IF_ICMPNE, label, 2); } @@ -1524,7 +1517,7 @@ * * @param label label to true case */ - public void iflt(final Label label) { + void iflt(final Label label) { debug("iflt", label); jump(IFLT, label, 1); } @@ -1534,7 +1527,7 @@ * * @param label label to true case */ - public void ifle(final Label label) { + void ifle(final Label label) { debug("ifle", label); jump(IFLE, label, 1); } @@ -1544,7 +1537,7 @@ * * @param label label to true case */ - public void ifgt(final Label label) { + void ifgt(final Label label) { debug("ifgt", label); jump(IFGT, label, 1); } @@ -1554,7 +1547,7 @@ * * @param label label to true case */ - public void ifge(final Label label) { + void ifge(final Label label) { debug("ifge", label); jump(IFGE, label, 1); } @@ -1564,7 +1557,7 @@ * * @param label destination label */ - public void _goto(final Label label) { + void _goto(final Label label) { debug("goto", label); jump(GOTO, label, 0); stack = null; @@ -1617,7 +1610,7 @@ * * @param label the label */ - public void label(final Label label) { + void label(final Label label) { /* * If stack == null, this means that we came here not through a fallthrough. * E.g. a label after an athrow. Then we create a new stack if one doesn't exist @@ -1643,7 +1636,7 @@ * * @return the method emitter */ - public MethodEmitter convert(final Type to) { + MethodEmitter convert(final Type to) { final Type type = peekType().convert(method, to); if (type != null) { if (peekType() != to) { @@ -1696,7 +1689,7 @@ * * @return the method emitter */ - public MethodEmitter add() { + MethodEmitter add() { debug("add"); pushType(get2().add(method)); return this; @@ -1707,7 +1700,7 @@ * * @return the method emitter */ - public MethodEmitter sub() { + MethodEmitter sub() { debug("sub"); pushType(get2n().sub(method)); return this; @@ -1718,7 +1711,7 @@ * * @return the method emitter */ - public MethodEmitter mul() { + MethodEmitter mul() { debug("mul "); pushType(get2n().mul(method)); return this; @@ -1729,7 +1722,7 @@ * * @return the method emitter */ - public MethodEmitter div() { + MethodEmitter div() { debug("div"); pushType(get2n().div(method)); return this; @@ -1740,7 +1733,7 @@ * * @return the method emitter */ - public MethodEmitter rem() { + MethodEmitter rem() { debug("rem"); pushType(get2n().rem(method)); return this; @@ -1795,7 +1788,7 @@ * * @return the method emitter */ - public MethodEmitter dynamicNew(final int argCount, final int flags) { + MethodEmitter dynamicNew(final int argCount, final int flags) { debug("dynamic_new", "argcount=" + argCount); final String signature = getDynamicSignature(Type.OBJECT, argCount); method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags); @@ -1812,7 +1805,7 @@ * * @return the method emitter */ - public MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) { + MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) { debug("dynamic_call", "args=" + argCount, "returnType=" + returnType); final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target) debug(" signature", signature); @@ -1831,7 +1824,7 @@ * * @return the method emitter */ - public MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) { + MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) { debug("dynamic_runtime_call", name, "args=" + request.getArity(), "returnType=" + returnType); final String signature = getDynamicSignature(returnType, request.getArity()); debug(" signature", signature); @@ -1851,7 +1844,7 @@ * * @return the method emitter */ - public MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) { + MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) { debug("dynamic_get", name, valueType); Type type = valueType; @@ -1877,7 +1870,7 @@ * @param name name of property * @param flags call site flags */ - public void dynamicSet(final Type valueType, final String name, final int flags) { + void dynamicSet(final Type valueType, final String name, final int flags) { debug("dynamic_set", name, peekType()); Type type = valueType; @@ -1902,7 +1895,7 @@ * * @return the method emitter */ - public MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) { + MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) { debug("dynamic_get_index", peekType(1) + "[" + peekType() + "]"); Type resultType = result; @@ -1938,7 +1931,7 @@ * * @param flags call site flags for setter */ - public void dynamicSetIndex(final int flags) { + void dynamicSetIndex(final int flags) { debug("dynamic_set_index", peekType(2) + "[" + peekType(1) + "] =", peekType()); Type value = peekType(); @@ -2015,7 +2008,7 @@ * * @return the method emitter */ - public MethodEmitter getField(final FieldAccess fa) { + MethodEmitter getField(final FieldAccess fa) { return fa.get(this); } @@ -2024,7 +2017,7 @@ * * @param fa the field access */ - public void putField(final FieldAccess fa) { + void putField(final FieldAccess fa) { fa.put(this); } @@ -2038,7 +2031,7 @@ * * @return the method emitter */ - public MethodEmitter getField(final String className, final String fieldName, final String fieldDescriptor) { + MethodEmitter getField(final String className, final String fieldName, final String fieldDescriptor) { debug("getfield", "receiver=" + peekType(), className + "." + fieldName + fieldDescriptor); final Type receiver = popType(); assert receiver.isObject(); @@ -2056,7 +2049,7 @@ * * @return the method emitter */ - public MethodEmitter getStatic(final String className, final String fieldName, final String fieldDescriptor) { + MethodEmitter getStatic(final String className, final String fieldName, final String fieldDescriptor) { debug("getstatic", className + "." + fieldName + "." + fieldDescriptor); method.visitFieldInsn(GETSTATIC, className, fieldName, fieldDescriptor); pushType(fieldType(fieldDescriptor)); @@ -2070,7 +2063,7 @@ * @param fieldName field name * @param fieldDescriptor field descriptor */ - public void putField(final String className, final String fieldName, final String fieldDescriptor) { + void putField(final String className, final String fieldName, final String fieldDescriptor) { debug("putfield", "receiver=" + peekType(1), "value=" + peekType()); popType(fieldType(fieldDescriptor)); popType(Type.OBJECT); @@ -2084,7 +2077,7 @@ * @param fieldName field name * @param fieldDescriptor field descriptor */ - public void putStatic(final String className, final String fieldName, final String fieldDescriptor) { + void putStatic(final String className, final String fieldName, final String fieldDescriptor) { debug("putfield", "value=" + peekType()); popType(fieldType(fieldDescriptor)); method.visitFieldInsn(PUTSTATIC, className, fieldName, fieldDescriptor); @@ -2096,7 +2089,7 @@ * @param line line number * @param label label */ - public void lineNumber(final int line, final Label label) { + void lineNumber(final int line, final Label label) { method.visitLineNumber(line, label); } @@ -2112,7 +2105,7 @@ /** * Emit a System.err.print statement of whatever is on top of the bytecode stack */ - public void print() { + void print() { getField(ERR_STREAM); swap(); convert(Type.OBJECT); @@ -2122,7 +2115,7 @@ /** * Emit a System.err.println statement of whatever is on top of the bytecode stack */ - public void println() { + void println() { getField(ERR_STREAM); swap(); convert(Type.OBJECT); @@ -2133,7 +2126,7 @@ * Emit a System.err.print statement * @param string string to print */ - public void print(final String string) { + void print(final String string) { getField(ERR_STREAM); load(string); invoke(PRINT); @@ -2143,7 +2136,7 @@ * Emit a System.err.println statement * @param string string to print */ - public void println(final String string) { + void println(final String string) { getField(ERR_STREAM); load(string); invoke(PRINTLN); @@ -2152,7 +2145,7 @@ /** * Print a stacktrace to S */ - public void stacktrace() { + void stacktrace() { _new(Throwable.class); dup(); invoke(constructorNoLookup(Throwable.class)); @@ -2254,130 +2247,11 @@ } } - - /** - * Abstraction for labels, separating a label from the underlying - * byte code emitter. Also augmenting label with e.g. a name - * for easier debugging and reading code - * - * see -Dnashorn.codegen.debug, --log=codegen - */ - public static class Label extends jdk.internal.org.objectweb.asm.Label { - /** Name of this label */ - private final String name; - - /** Type stack at this label */ - private ArrayDeque<Type> stack; - - /** - * Constructor - * - * @param name name of this label - */ - public Label(final String name) { - super(); - this.name = name; - } - - /** - * Copy constructor - * - * @param label a label to clone - */ - public Label(final Label label) { - super(); - name = label.name; - } - - ArrayDeque<Type> getStack() { - return stack; - } - - void setStack(final ArrayDeque<Type> stack) { - this.stack = stack; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - String s = super.toString(); - s = s.substring(1, s.length()); - sb.append(name).append('_').append(Long.toHexString(Long.parseLong(s))); - - return sb.toString(); - } - } - - /** - * Condition enum used for all kinds of jumps, regardless of type - */ - static enum Condition { - EQ, - NE, - LE, - LT, - GE, - GT; - - public static Condition forRuntimeRequest(final RuntimeNode.Request request) { - try { - final String reqString = request.toString().replace("_STRICT", ""); - return Condition.valueOf(reqString); - } catch (final IllegalArgumentException e) { - return null; - } - } - - public static int toUnary(final Condition c) { - switch (c) { - case EQ: - return IFEQ; - case NE: - return IFNE; - case LE: - return IFLE; - case LT: - return IFLT; - case GE: - return IFGE; - case GT: - return IFGT; - default: - assert false; - return -1; - } - } - - public static int toBinary(final Condition c) { - return toBinary(c, false); - } - - public static int toBinary(final Condition c, final boolean isObject) { - switch (c) { - case EQ: - return isObject ? IF_ACMPEQ : IF_ICMPEQ; - case NE: - return isObject ? IF_ACMPNE : IF_ICMPNE; - case LE: - return IF_ICMPLE; - case LT: - return IF_ICMPLT; - case GE: - return IF_ICMPGE; - case GT: - return IF_ICMPGT; - default: - assert false; - return -1; - } - } - } - /** * Set the current function node being emitted * @param functionNode the function node */ - public void setFunctionNode(final FunctionNode functionNode) { + void setFunctionNode(final FunctionNode functionNode) { this.functionNode = functionNode; } @@ -2387,7 +2261,7 @@ * * @return split node */ - public SplitNode getSplitNode() { + SplitNode getSplitNode() { return splitNode; } @@ -2395,7 +2269,7 @@ * Set the split node for this method emitter * @param splitNode split node */ - public void setSplitNode(final SplitNode splitNode) { + void setSplitNode(final SplitNode splitNode) { this.splitNode = splitNode; } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Fri Feb 15 09:44:15 2013 +0100 @@ -0,0 +1,760 @@ +/* + * 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.codegen.Compiler.SCRIPTS_PACKAGE; +import static jdk.nashorn.internal.codegen.CompilerConstants.ALLOCATE; +import static jdk.nashorn.internal.codegen.CompilerConstants.INIT_ARGUMENTS; +import static jdk.nashorn.internal.codegen.CompilerConstants.INIT_SCOPE; +import static jdk.nashorn.internal.codegen.CompilerConstants.JAVA_THIS; +import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_PREFIX; +import static jdk.nashorn.internal.codegen.CompilerConstants.MAP; +import static jdk.nashorn.internal.codegen.CompilerConstants.className; +import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; +import static jdk.nashorn.internal.runtime.linker.Lookup.MH; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import jdk.nashorn.internal.codegen.ClassEmitter.Flag; +import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.runtime.AccessorProperty; +import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.DebugLogger; +import jdk.nashorn.internal.runtime.FunctionScope; +import jdk.nashorn.internal.runtime.JSType; +import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; +import jdk.nashorn.internal.runtime.options.Options; + +/** + * Generates the ScriptObject subclass structure with fields for a user objects. + */ +public final class ObjectClassGenerator { + + /** + * Marker for scope parameters. + */ + static final String SCOPE_MARKER = "P"; + + /** + * Debug field logger + * Should we print debugging information for fields when they are generated and getters/setters are called? + */ + public static final DebugLogger LOG = new DebugLogger("fields", "nashorn.fields.debug"); + + /** + * is field debugging enabled. Several modules in codegen and properties use this, hence + * public access. + */ + public static final boolean DEBUG_FIELDS = LOG.isEnabled(); + + /** + * Should the runtime only use java.lang.Object slots for fields? If this is false, the representation + * will be a primitive 64-bit long value used for all primitives and a java.lang.Object for references. + * This introduces a larger number of method handles in the system, as we need to have different getters + * and setters for the different fields. Currently this introduces significant overhead in Hotspot. + * + * This is engineered to plug into the TaggedArray implementation, when it's done. + */ + public static final boolean OBJECT_FIELDS_ONLY = !Options.getBooleanProperty("nashorn.fields.dual"); + + /** The field types in the system */ + private static final List<Type> FIELD_TYPES = new LinkedList<>(); + + /** What type is the primitive type in dual representation */ + public static final Type PRIMITIVE_TYPE = Type.LONG; + + /** + * The list of field types that we support - one type creates one field. This is currently either + * LONG + OBJECT or just OBJECT for classic mode. + */ + static { + if (!OBJECT_FIELDS_ONLY) { + System.err.println("WARNING!!! Running with primitive fields - there is untested functionality!"); + FIELD_TYPES.add(PRIMITIVE_TYPE); + } + FIELD_TYPES.add(Type.OBJECT); + } + + /** The context */ + private final Context context; + + /** + * The list of available accessor types in width order. This order is used for type guesses narrow->wide + * in the dual--fields world + */ + public static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList( + Arrays.asList( + Type.INT, + Type.LONG, + Type.NUMBER, + Type.OBJECT)); + + //these are hard coded for speed and so that we can switch on them + private static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class); + private static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class); + private static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class); + private static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class); + + /** + * Constructor + * + * @param context a context + */ + public ObjectClassGenerator(final Context context) { + this.context = context; + assert context != null; + } + + /** + * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes()) + * + * @param type the type + * + * @return the accessor index, or -1 if no accessor of this type exists + */ + public static int getAccessorTypeIndex(final Type type) { + return getAccessorTypeIndex(type.getTypeClass()); + } + + /** + * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes()) + * + * Note that this is hardcoded with respect to the dynamic contents of the accessor + * types array for speed. Hotspot got stuck with this as 5% of the runtime in + * a benchmark when it looped over values and increased an index counter. :-( + * + * @param type the type + * + * @return the accessor index, or -1 if no accessor of this type exists + */ + public static int getAccessorTypeIndex(final Class<?> type) { + if (type == int.class) { + return 0; + } else if (type == long.class) { + return 1; + } else if (type == double.class) { + return 2; + } else if (!type.isPrimitive()) { + return 3; + } + return -1; + } + + /** + * Return the number of accessor types available. + * + * @return number of accessor types in system + */ + public static int getNumberOfAccessorTypes() { + return ACCESSOR_TYPES.size(); + } + + /** + * Return the accessor type based on its index in [0..getNumberOfAccessorTypes()) + * Indexes are ordered narrower->wider / optimistic->pessimistic. Invalidations always + * go to a type of higher index + * + * @param index accessor type index + * + * @return a type corresponding to the index. + */ + + public static Type getAccessorType(final int index) { + return ACCESSOR_TYPES.get(index); + } + + /** + * Returns the class name for JavaScript objects with fieldCount fields. + * + * @param fieldCount Number of fields to allocate. + * + * @return The class name. + */ + public static String getClassName(final int fieldCount) { + return fieldCount != 0 ? SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.tag() + fieldCount : + SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.tag(); + } + + /** + * Returns the class name for JavaScript scope with fieldCount fields and + * paramCount parameters. + * + * @param fieldCount Number of fields to allocate. + * @param paramCount Number of parameters to allocate + * + * @return The class name. + */ + public static String getClassName(final int fieldCount, final int paramCount) { + return SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.tag() + fieldCount + SCOPE_MARKER + paramCount; + } + + /** + * Returns the name of a field based on number and type. + * + * @param fieldIndex Ordinal of field. + * @param type Type of field. + * + * @return The field name. + */ + public static String getFieldName(final int fieldIndex, final Type type) { + return type.getDescriptor().substring(0, 1) + fieldIndex; + } + + /** + * In the world of Object fields, we also have no undefined SwitchPoint, to reduce as much potential + * MethodHandle overhead as possible. In that case, we explicitly need to assign undefined to fields + * when we initialize them. + * + * @param init constructor to generate code in + * @param className name of class + * @param fieldNames fields to initialize to undefined, where applicable + */ + private static void initializeToUndefined(final MethodEmitter init, final String className, final List<String> fieldNames) { + if (fieldNames.isEmpty()) { + return; + } + + // always initialize fields to undefined, even with --dual-fields. Then it's ok to + // remember things like "widest set type" in properties, and if it's object, don't + // add any special "return undefined" getters, saving an invalidation + init.load(Type.OBJECT, JAVA_THIS.slot()); + init.loadUndefined(Type.OBJECT); + + final Iterator<String> iter = fieldNames.iterator(); + while (iter.hasNext()) { + final String fieldName = iter.next(); + if (iter.hasNext()) { + init.dup2(); + } + init.putField(className, fieldName, Type.OBJECT.getDescriptor()); + } + } + + /** + * Generate the byte codes for a JavaScript object class or scope. + * Class name is a function of number of fields and number of param + * fields + * + * @param descriptor Descriptor pulled from class name. + * + * @return Byte codes for generated class. + */ + public byte[] generate(final String descriptor) { + final String[] counts = descriptor.split(SCOPE_MARKER); + final int fieldCount = Integer.valueOf(counts[0]); + + if (counts.length == 1) { + return generate(fieldCount); + } + + final int paramCount = Integer.valueOf(counts[1]); + + return generate(fieldCount, paramCount); + } + + /** + * Generate the byte codes for a JavaScript object class with fieldCount fields. + * + * @param fieldCount Number of fields in the JavaScript object. + * + * @return Byte codes for generated class. + */ + public byte[] generate(final int fieldCount) { + final String className = getClassName(fieldCount); + final String superName = className(ScriptObject.class); + final ClassEmitter classEmitter = newClassEmitter(className, superName); + final List<String> initFields = addFields(classEmitter, fieldCount); + + final MethodEmitter init = newInitMethod(classEmitter); + initializeToUndefined(init, className, initFields); + init.returnVoid(); + init.end(); + + newEmptyInit(classEmitter, className); + newAllocate(classEmitter, className); + + return toByteArray(classEmitter); + } + + /** + * Generate the byte codes for a JavaScript scope class with fieldCount fields + * and paramCount parameters. + * + * @param fieldCount Number of fields in the JavaScript scope. + * @param paramCount Number of parameters in the JavaScript scope + * . + * @return Byte codes for generated class. + */ + public byte[] generate(final int fieldCount, final int paramCount) { + final String className = getClassName(fieldCount, paramCount); + final String superName = className(FunctionScope.class); + final ClassEmitter classEmitter = newClassEmitter(className, superName); + final List<String> initFields = addFields(classEmitter, fieldCount); + + final MethodEmitter init = newInitScopeMethod(classEmitter); + initializeToUndefined(init, className, initFields); + init.returnVoid(); + init.end(); + + final MethodEmitter initWithArguments = newInitScopeWithArgumentsMethod(classEmitter); + initializeToUndefined(initWithArguments, className, initFields); + initWithArguments.returnVoid(); + initWithArguments.end(); + + return toByteArray(classEmitter); + } + + /** + * Generates the needed fields. + * + * @param classEmitter Open class emitter. + * @param fieldCount Number of fields. + * + * @return List fields that need to be initialized. + */ + private static List<String> addFields(final ClassEmitter classEmitter, final int fieldCount) { + final List<String> initFields = new LinkedList<>(); + + for (int i = 0; i < fieldCount; i++) { + for (final Type type : FIELD_TYPES) { + final String fieldName = getFieldName(i, type); + classEmitter.field(fieldName, type.getTypeClass()); + + if (type == Type.OBJECT) { + initFields.add(fieldName); + } + } + } + + return initFields; + } + + /** + * Allocate and initialize a new class emitter. + * + * @param className Name of JavaScript class. + * + * @return Open class emitter. + */ + private ClassEmitter newClassEmitter(final String className, final String superName) { + final ClassEmitter classEmitter = new ClassEmitter(context, className, superName); + classEmitter.begin(); + + return classEmitter; + } + + /** + * Allocate and initialize a new <init> method. + * + * @param classEmitter Open class emitter. + * + * @return Open method emitter. + */ + private static MethodEmitter newInitMethod(final ClassEmitter classEmitter) { + final MethodEmitter init = classEmitter.init(PropertyMap.class); + init.begin(); + init.load(Type.OBJECT, JAVA_THIS.slot()); + init.load(Type.OBJECT, MAP.slot()); + init.invoke(constructorNoLookup(ScriptObject.class, PropertyMap.class)); + + return init; + } + + /** + * Allocate and initialize a new <init> method for scopes. + * @param classEmitter Open class emitter. + * @return Open method emitter. + */ + private static MethodEmitter newInitScopeMethod(final ClassEmitter classEmitter) { + final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class); + init.begin(); + init.load(Type.OBJECT, JAVA_THIS.slot()); + init.load(Type.OBJECT, MAP.slot()); + init.load(Type.OBJECT, INIT_SCOPE.slot()); + init.invoke(constructorNoLookup(FunctionScope.class, PropertyMap.class, ScriptObject.class)); + + return init; + } + + /** + * Allocate and initialize a new <init> method for scopes with arguments. + * @param classEmitter Open class emitter. + * @return Open method emitter. + */ + private static MethodEmitter newInitScopeWithArgumentsMethod(final ClassEmitter classEmitter) { + final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class, Object.class); + init.begin(); + init.load(Type.OBJECT, JAVA_THIS.slot()); + init.load(Type.OBJECT, MAP.slot()); + init.load(Type.OBJECT, INIT_SCOPE.slot()); + init.load(Type.OBJECT, INIT_ARGUMENTS.slot()); + init.invoke(constructorNoLookup(FunctionScope.class, PropertyMap.class, ScriptObject.class, Object.class)); + + return init; + } + + /** + * Add an empty <init> method to the JavaScript class. + * + * @param classEmitter Open class emitter. + * @param className Name of JavaScript class. + */ + private static void newEmptyInit(final ClassEmitter classEmitter, final String className) { + final MethodEmitter emptyInit = classEmitter.init(); + emptyInit.begin(); + emptyInit.load(Type.OBJECT, JAVA_THIS.slot()); + emptyInit.loadNull(); + emptyInit.invoke(constructorNoLookup(className, PropertyMap.class)); + emptyInit.returnVoid(); + emptyInit.end(); + } + + /** + * Add an empty <init> method to the JavaScript class. + * + * @param classEmitter Open class emitter. + * @param className Name of JavaScript class. + */ + private static void newAllocate(final ClassEmitter classEmitter, final String className) { + final MethodEmitter allocate = classEmitter.method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), ALLOCATE.tag(), ScriptObject.class, PropertyMap.class); + allocate.begin(); + allocate._new(className); + allocate.dup(); + allocate.load(Type.typeFor(PropertyMap.class), 0); + allocate.invoke(constructorNoLookup(className, PropertyMap.class)); + allocate._return(); + allocate.end(); + } + + /** + * Collects the byte codes for a generated JavaScript class. + * + * @param classEmitter Open class emitter. + * @return Byte codes for the class. + */ + private byte[] toByteArray(final ClassEmitter classEmitter) { + classEmitter.end(); + + final byte[] code = classEmitter.toByteArray(); + + if (context != null && context._print_code) { + Context.getCurrentErr().println(ClassEmitter.disassemble(code)); + } + + if (context != null && context._verify_code) { + context.verify(code); + } + + return code; + } + + /** Double to long bits, used with --dual-fields for primitive double values */ + private static final MethodHandle PACK_DOUBLE = + MH.explicitCastArguments(MH.findStatic(MethodHandles.publicLookup(), Double.class, "doubleToRawLongBits", MH.type(long.class, double.class)), MH.type(long.class, double.class)); + + /** double bits to long, used with --dual-fields for primitive double values */ + private static MethodHandle UNPACK_DOUBLE = + MH.findStatic(MethodHandles.publicLookup(), Double.class, "longBitsToDouble", MH.type(double.class, long.class)); + + /** object conversion quickies with JS semantics - used for return value and parameter filter */ + private static MethodHandle[] CONVERT_OBJECT = { + JSType.TO_INT32.methodHandle(), + JSType.TO_UINT32.methodHandle(), + JSType.TO_NUMBER.methodHandle(), + null + }; + + /** + * Given a primitiveGetter (optional for non dual fields) and an objectSetter that retrieve + * the primitive and object version of a field respectively, return one with the correct + * method type and the correct filters. For example, if the value is stored as a double + * and we want an Object getter, in the dual fields world we'd pick the primitiveGetter, + * which reads a long, use longBitsToDouble on the result to unpack it, and then change the + * return type to Object, boxing it. In the objects only world there are only object fields, + * primtives are boxed when asked for them and we don't need to bother with primitive encoding + * (or even undefined, which if forType==null) representation, so we just return whatever is + * in the object field. The object field is always initiated to Undefined, so here, where we have + * the representation for Undefined in all our bits, this is not a problem. + * <p> + * Representing undefined in a primitive is hard, for an int there aren't enough bits, for a long + * we could limit the width of a representation, and for a double (as long as it is stored as long, + * as all NaNs will turn into QNaN on ia32, which is one bit pattern, we should use a special NaN). + * Naturally we could have special undefined values for all types which mean "go look in a wider field", + * but the guards needed on every getter took too much time. + * <p> + * To see how this is used, look for example in {@link AccessorProperty#getGetter} + * <p> + * @param forType representation of the underlying type in the field, null if undefined + * @param type type to retrieve it as + * @param primitiveGetter getter to read the primitive version of this field (null if Objects Only) + * @param objectGetter getter to read the object version of this field + * + * @return getter for the given representation that returns the given type + */ + public static MethodHandle createGetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter) { + final int fti = forType == null ? -1 : getAccessorTypeIndex(forType); + final int ti = getAccessorTypeIndex(type); + + if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) { + if (ti == TYPE_OBJECT_INDEX) { + return objectGetter; + } + + return MH.filterReturnValue(objectGetter, CONVERT_OBJECT[ti]); + } + + assert !OBJECT_FIELDS_ONLY; + if (forType == null) { + return GET_UNDEFINED[ti]; + } + + final MethodType pmt = primitiveGetter.type(); + + switch (fti) { + case TYPE_INT_INDEX: + case TYPE_LONG_INDEX: + switch (ti) { + case TYPE_INT_INDEX: + //get int while an int, truncating cast of long value + return MH.explicitCastArguments(primitiveGetter, pmt.changeReturnType(int.class)); + case TYPE_LONG_INDEX: + return primitiveGetter; + default: + return MH.asType(primitiveGetter, pmt.changeReturnType(type)); + } + case TYPE_DOUBLE_INDEX: + final MethodHandle getPrimitiveAsDouble = MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE); + switch (ti) { + case TYPE_INT_INDEX: + case TYPE_LONG_INDEX: + return MH.explicitCastArguments(getPrimitiveAsDouble, pmt.changeReturnType(type)); + case TYPE_DOUBLE_INDEX: + return getPrimitiveAsDouble; + default: + return MH.asType(getPrimitiveAsDouble, pmt.changeReturnType(Object.class)); + } + default: + assert false; + return null; + } + } + + private static final MethodHandle IS_TYPE_GUARD = findOwnMH("isType", boolean.class, Class.class, Object.class); + + @SuppressWarnings("unused") + private static boolean isType(final Class<?> boxedForType, final Object x) { + return x.getClass() == boxedForType; + } + + private static Class<? extends Number> getBoxedType(final Class<?> forType) { + if (forType == int.class) { + return Integer.class; + } + + if (forType == long.class) { + return Long.class; + } + + if (forType == double.class) { + return Double.class; + } + + assert false; + return null; + } + + /** + * If we are setting boxed types (because the compiler couldn't determine which they were) to + * a primitive field, we can reuse the primitive field getter, as long as we are setting an element + * of the same boxed type as the primitive type representation + * + * @param forType the current type + * @param primitiveSetter primitive setter for the current type with an element of the current type + * @param objectSetter the object setter + * + * @return method handle that checks if the element to be set is of the currenttype, even though it's boxed + * and instead of using the generic object setter, that would blow up the type and invalidate the map, + * unbox it and call the primitive setter instead + */ + public static MethodHandle createGuardBoxedPrimitiveSetter(final Class<?> forType, final MethodHandle primitiveSetter, final MethodHandle objectSetter) { + final Class<? extends Number> boxedForType = getBoxedType(forType); + //object setter that checks for primitive if current type is primitive + + return MH.guardWithTest( + MH.insertArguments( + MH.dropArguments( + IS_TYPE_GUARD, + 1, + Object.class), + 0, + boxedForType), + MH.asType( + primitiveSetter, + objectSetter.type()), + objectSetter); + } + + /** + * This is similar to the {@link ObjectClassGenerator#createGetter} function. Performs + * the necessary operations to massage a setter operand of type {@code type} to + * fit into the primitive field (if primitive and dual fields is enabled) or into + * the object field (box if primitive and dual fields is disabled) + * + * @param forType representation of the underlying object + * @param type representation of field to write, and setter signature + * @param primitiveSetter setter that writes to the primitive field (null if Objects Only) + * @param objectSetter setter that writes to the object field + * + * @return the setter for the given representation that takes a {@code type} + */ + public static MethodHandle createSetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveSetter, final MethodHandle objectSetter) { + assert forType != null; + + final int fti = getAccessorTypeIndex(forType); + final int ti = getAccessorTypeIndex(type); + + if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) { + if (ti == TYPE_OBJECT_INDEX) { + return objectSetter; + } + + return MH.asType(objectSetter, objectSetter.type().changeParameterType(1, type)); + } + + assert !OBJECT_FIELDS_ONLY; + + final MethodType pmt = primitiveSetter.type(); + + switch (fti) { + case TYPE_INT_INDEX: + case TYPE_LONG_INDEX: + switch (ti) { + case TYPE_INT_INDEX: + return MH.asType(primitiveSetter, pmt.changeParameterType(1, int.class)); + case TYPE_LONG_INDEX: + return primitiveSetter; + case TYPE_DOUBLE_INDEX: + return MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE); + default: + return objectSetter; + } + case TYPE_DOUBLE_INDEX: + if (ti == TYPE_OBJECT_INDEX) { + return objectSetter; + } + return MH.asType(MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE), pmt.changeParameterType(1, type)); + default: + assert false; + return null; + } + } + + // + // Provide generic getters and setters for undefined types. If a type is undefined, all + // and marshals the set to the correct setter depending on the type of the value being set. + // Note that there are no actual undefined versions of int, long and double in JavaScript, + // but executing toInt32, toLong and toNumber always returns a working result, 0, 0L or NaN + // + + /** The value of Undefined cast to an int32 */ + public static final int UNDEFINED_INT = 0; + /** The value of Undefined cast to a long */ + public static final long UNDEFINED_LONG = 0L; + /** The value of Undefined cast to a double */ + public static final double UNDEFINED_DOUBLE = Double.NaN; + + /** + * Compute type name for correct undefined getter + * @param type the type + * @return name of getter + */ + private static String typeName(final Type type) { + String name = type.getTypeClass().getName(); + final int dot = name.lastIndexOf('.'); + if (dot != -1) { + name = name.substring(dot + 1); + } + return Character.toUpperCase(name.charAt(0)) + name.substring(1); + } + + /** + * Handles for undefined getters of the different types + */ + private static final MethodHandle[] GET_UNDEFINED = new MethodHandle[ObjectClassGenerator.getNumberOfAccessorTypes()]; + + /** + * Used to wrap getters for undefined values, where this matters. Currently only in dual fields. + * If an object starts out as undefined it needs special getters until it has been assigned + * something the first time + * + * @param returnType type to cast the undefined to + * + * @return undefined as returnType + */ + public static MethodHandle getUndefined(final Class<?> returnType) { + return GET_UNDEFINED[ObjectClassGenerator.getAccessorTypeIndex(returnType)]; + } + + static { + int pos = 0; + for (final Type type : ACCESSOR_TYPES) { + GET_UNDEFINED[pos++] = findOwnMH("getUndefined" + typeName(type), type.getTypeClass(), Object.class); + } + } + + @SuppressWarnings("unused") + private static int getUndefinedInt(final Object obj) { + return UNDEFINED_INT; + } + + @SuppressWarnings("unused") + private static long getUndefinedLong(final Object obj) { + return UNDEFINED_LONG; + } + + @SuppressWarnings("unused") + private static double getUndefinedDouble(final Object obj) { + return UNDEFINED_DOUBLE; + } + + @SuppressWarnings("unused") + private static Object getUndefinedObject(final Object obj) { + return ScriptRuntime.UNDEFINED; + } + + private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { + return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/ObjectCreator.java Fri Feb 15 09:44:15 2013 +0100 @@ -0,0 +1,172 @@ +/* + * 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 java.util.List; +import jdk.nashorn.internal.ir.Symbol; +import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.PropertyMap; + +/** + * Base class for object creation code generation. + */ +public abstract class ObjectCreator { + + /** Compile unit for this ObjectCreator, see CompileUnit */ + protected final CompileUnit compileUnit; + + /** List of keys to initiate in this ObjectCreator */ + protected final List<String> keys; + + /** List of symbols to initiate in this ObjectCreator */ + protected final List<Symbol> symbols; + + /** Code generator */ + protected final CodeGenerator codegen; + + private final boolean isScope; + private final boolean hasArguments; + private int fieldCount; + private int paramCount; + private String fieldObjectClassName; + private Class<?> fieldObjectClass; + private PropertyMap propertyMap; + + /** + * Constructor + * + * @param codegen the code generator + * @param keys the keys + * @param symbols the symbols corresponding to keys, same index + * @param isScope is this object scope + * @param hasArguments does the created object have an "arguments" property + */ + protected ObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final boolean isScope, final boolean hasArguments) { + this.codegen = codegen; + this.compileUnit = codegen.getCurrentCompileUnit(); + this.keys = keys; + this.symbols = symbols; + this.isScope = isScope; + this.hasArguments = hasArguments; + + countFields(); + findClass(); + } + + /** + * Tally the number of fields and parameters. + */ + private void countFields() { + for (final Symbol symbol : this.symbols) { + if (symbol != null) { + if (hasArguments() && symbol.isParam()) { + symbol.setFieldIndex(paramCount++); + } else { + symbol.setFieldIndex(fieldCount++); + } + } + } + } + + /** + * Locate (or indirectly create) the object container class. + */ + private void findClass() { + fieldObjectClassName = isScope() ? + ObjectClassGenerator.getClassName(fieldCount, paramCount) : + ObjectClassGenerator.getClassName(fieldCount); + + try { + this.fieldObjectClass = Context.forStructureClass(Compiler.binaryName(fieldObjectClassName)); + } catch (final ClassNotFoundException e) { + throw new AssertionError("Nashorn has encountered an internal error. Structure can not be created."); + } + } + + /** + * Generate code for making the object. + * @param method Script method. + */ + protected abstract void makeObject(final MethodEmitter method); + + /** + * Create a new MapCreator + * @param clazz type of MapCreator + * @return map creator instantiated by type + */ + protected MapCreator newMapCreator(final Class<?> clazz) { + return new MapCreator(clazz, keys, symbols); + } + + /** + * Construct the property map appropriate for the object. + * @return the newly created property map + */ + protected PropertyMap makeMap() { + if (keys.isEmpty()) { //empty map + propertyMap = PropertyMap.newMap(fieldObjectClass); + } else { + propertyMap = newMapCreator(fieldObjectClass).makeMap(hasArguments()); + } + return propertyMap; + } + + /** + * Emit the correct map for the object. + * @param method method emitter + * @return the method emitter + */ + protected MethodEmitter loadMap(final MethodEmitter method) { + codegen.loadConstant(propertyMap); + return method; + } + + /** + * Get the class name for the object class, + * e.g. {@code com.nashorn.oracle.scripts.JO$2P0} + * + * @return script class name + */ + String getClassName() { + return fieldObjectClassName; + } + + /** + * Is this a scope object + * @return true if scope + */ + protected boolean isScope() { + return isScope; + } + + /** + * Does the created object have an "arguments" property + * @return true if has an "arguments" property + */ + protected boolean hasArguments() { + return hasArguments; + } +}
--- a/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/SharedScopeCall.java Fri Feb 15 09:44:15 2013 +0100 @@ -48,7 +48,7 @@ * <p>Scope calls must not be shared between normal callsites and callsites contained in a <tt>with</tt> * statement as this condition is not handled by current guards and will cause a runtime error.</p> */ -public class SharedScopeCall { +class SharedScopeCall { /** Threshold for using shared scope calls with fast scope access. */ public static final int FAST_SCOPE_CALL_THRESHOLD = 4; @@ -118,7 +118,7 @@ * @param method the method emitter */ public void generateInvoke(final MethodEmitter method) { - method.invokeStatic(compileUnit.getUnitClassName(), methodName, getStaticSignature()); + method.invokestatic(compileUnit.getUnitClassName(), methodName, getStaticSignature()); } /** @@ -138,8 +138,8 @@ // Load correct scope by calling getProto() on the scope argument as often as specified // by the second argument. - final MethodEmitter.Label parentLoopStart = new MethodEmitter.Label("parent_loop_start"); - final MethodEmitter.Label parentLoopDone = new MethodEmitter.Label("parent_loop_done"); + final Label parentLoopStart = new Label("parent_loop_start"); + final Label parentLoopDone = new Label("parent_loop_done"); method.load(Type.OBJECT, 0); method.label(parentLoopStart); method.load(Type.INT, 1);
--- a/src/jdk/nashorn/internal/codegen/Splitter.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/Splitter.java Fri Feb 15 09:44:15 2013 +0100 @@ -396,7 +396,7 @@ * @param targetNode the jump target node. * @param targetLabel the jump target label. */ - private void searchJumpTarget(final Node targetNode, final MethodEmitter.Label targetLabel) { + private void searchJumpTarget(final Node targetNode, final Label targetLabel) { final SplitNode targetSplit = targetNodes.get(targetNode); // Note that targetSplit may be null, indicating that targetNode is in top level method. @@ -406,7 +406,7 @@ if (split == targetSplit) { break; } - final List<MethodEmitter.Label> externalTargets = split.getExternalTargets(); + final List<Label> externalTargets = split.getExternalTargets(); if (!externalTargets.contains(targetLabel)) { split.addExternalTarget(targetLabel); }
--- a/src/jdk/nashorn/internal/codegen/objects/FieldObjectCreator.java Fri Feb 15 09:18:05 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +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.objects; - -import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; -import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; -import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; -import static jdk.nashorn.internal.codegen.types.Type.OBJECT; - -import java.util.Iterator; -import java.util.List; -import jdk.nashorn.internal.codegen.CodeGenerator; -import jdk.nashorn.internal.codegen.MethodEmitter; -import jdk.nashorn.internal.codegen.types.Type; -import jdk.nashorn.internal.ir.Symbol; -import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptObject; -import jdk.nashorn.internal.runtime.arrays.ArrayIndex; - -/** - * Analyze an object's characteristics for appropriate code generation. This - * is used for functions and for objects. A field object take a set of values which - * to assign to the various fields in the object. This is done by the generated code - * - * @param <T> the value type for the fields being written on object creation, e.g. Node - * @see jdk.nashorn.internal.ir.Node - */ -public abstract class FieldObjectCreator<T> extends ObjectCreator { - /** array of corresponding values to symbols (null for no values) */ - private final List<T> values; - - /** call site flags to be used for invocations */ - private final int callSiteFlags; - - /** - * Constructor - * - * @param codegen code generator - * @param keys keys for fields in object - * @param symbols symbols for fields in object - * @param values list of values corresponding to keys - */ - public FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values) { - this(codegen, keys, symbols, values, false, false); - } - - /** - * Constructor - * - * @param codegen code generator - * @param keys keys for fields in object - * @param symbols symbols for fields in object - * @param values values (or null where no value) to be written to the fields - * @param isScope is this a scope object - * @param hasArguments does the created object have an "arguments" property - */ - public FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values, final boolean isScope, final boolean hasArguments) { - super(codegen, keys, symbols, isScope, hasArguments); - this.values = values; - this.callSiteFlags = codegen.getCallSiteFlags(); - } - - /** - * Loads the scope on the stack through the passed method emitter. - * @param method the method emitter to use - */ - protected void loadScope(final MethodEmitter method) { - method.loadScope(); - } - - /** - * Construct an object. - * - * @param method the method emitter - */ - @Override - public void makeObject(final MethodEmitter method) { - makeMap(); - - method._new(getClassName()).dup(); // create instance - loadMap(method); //load the map - - if (isScope()) { - loadScope(method); - - if (hasArguments()) { - method.loadArguments(); - method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class, ARGUMENTS.type())); - } else { - method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class)); - } - } else { - method.invoke(constructorNoLookup(getClassName(), PropertyMap.class)); - } - - // Set values. - final Iterator<Symbol> symbolIter = symbols.iterator(); - final Iterator<String> keyIter = keys.iterator(); - final Iterator<T> valueIter = values.iterator(); - - while (symbolIter.hasNext()) { - final Symbol symbol = symbolIter.next(); - final String key = keyIter.next(); - final T value = valueIter.next(); - - if (symbol != null && value != null) { - final int index = ArrayIndex.getArrayIndexNoThrow(key); - - if (index < 0) { - putField(method, key, symbol.getFieldIndex(), value); - } else { - putSlot(method, index, value); - } - } - } - } - - /** - * Technique for loading an initial value. Defined by anonymous subclasses in code gen. - * - * @param value Value to load. - */ - protected abstract void loadValue(T value); - - /** - * Determine the type of a value. Defined by anonymous subclasses in code gen. - * - * @param value Value to inspect. - * - * @return Value type. - */ - protected abstract Type getValueType(T value); - - /** - * Store a value in a field of the generated class object. - * - * @param method Script method. - * @param key Property key. - * @param fieldIndex Field number. - * @param value Value to store. - */ - private void putField(final MethodEmitter method, final String key, final int fieldIndex, final T value) { - method.dup(); - - loadValue(value); - - final Type valueType = getValueType(value); - // for example when we have a with scope - if (valueType.isObject() || valueType.isBoolean()) { - method.convert(OBJECT); - } - - method.convert(OBJECT); - method.putField(getClassName(), ObjectClassGenerator.getFieldName(fieldIndex, Type.OBJECT), typeDescriptor(Object.class)); - } - - /** - * Store a value in an indexed slot of a generated class object. - * - * @param method Script method. - * @param index Slot index. - * @param value Value to store. - */ - private void putSlot(final MethodEmitter method, final int index, final T value) { - method.dup(); - method.load(index); - loadValue(value); - method.dynamicSetIndex(callSiteFlags); - } - -}
--- a/src/jdk/nashorn/internal/codegen/objects/MapCreator.java Fri Feb 15 09:18:05 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,123 +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.objects; - -import java.util.ArrayList; -import java.util.List; -import jdk.nashorn.internal.ir.Symbol; -import jdk.nashorn.internal.runtime.AccessorProperty; -import jdk.nashorn.internal.runtime.Property; -import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.arrays.ArrayIndex; - -/** - * Class that creates PropertyMap sent to script object constructors. - */ -public class MapCreator { - /** Object structure for objects associated with this map */ - private final Class<?> structure; - - /** key set for object map */ - private final String[] keys; - - /** corresponding symbol set for object map */ - private final Symbol[] symbols; - - /** - * Constructor - * - * @param structure structure to generate map for (a JO$ subclass) - * @param keys list of keys for map - * @param symbols list of symbols for map - */ - public MapCreator(final Class<?> structure, final List<String> keys, final List<Symbol> symbols) { - final int size = keys.size(); - - this.structure = structure; - this.keys = keys.toArray(new String[size]); - this.symbols = symbols.toArray(new Symbol[size]); - } - - /** - * Constructs a property map based on a set of fields. - * - * @param hasArguments does the created object have an "arguments" property - * - * @return New map populated with accessor properties. - */ - public PropertyMap makeMap(final boolean hasArguments) { - final List<Property> properties = new ArrayList<>(); - - assert keys != null; - - for (int i = 0; i < keys.length; i++) { - final String key = keys[i]; - final Symbol symbol = symbols[i]; - - if (symbol != null && !ArrayIndex.isIndexKey(key)) { - properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex())); - } - } - - return PropertyMap.newMap(structure, properties); - } - - /** - * Compute property flags given local state of a field. Maybe be overridden and extended, - * as is the case in {@link ObjectMapCreator} - * - * @param symbol symbol to check - * @param hasArguments does the created object have an "arguments" property - * - * @return flags to use for fields - */ - protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) { - int flags = 0; - - if (symbol.isParam()) { - flags |= Property.IS_ALWAYS_OBJECT | Property.IS_PARAMETER; - } - - if (hasArguments) { - flags |= Property.IS_ALWAYS_OBJECT | Property.HAS_ARGUMENTS; - } - - if (symbol.isScope()) { - flags |= Property.NOT_CONFIGURABLE; - } - - if (symbol.canBePrimitive()) { - flags |= Property.CAN_BE_PRIMITIVE; - } - - if (symbol.canBeUndefined()) { - flags |= Property.CAN_BE_UNDEFINED; - } - - return flags; - } - -}
--- a/src/jdk/nashorn/internal/codegen/objects/ObjectClassGenerator.java Fri Feb 15 09:18:05 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,762 +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.objects; - -import static jdk.nashorn.internal.codegen.Compiler.SCRIPTS_PACKAGE; -import static jdk.nashorn.internal.codegen.CompilerConstants.ALLOCATE; -import static jdk.nashorn.internal.codegen.CompilerConstants.INIT_ARGUMENTS; -import static jdk.nashorn.internal.codegen.CompilerConstants.INIT_SCOPE; -import static jdk.nashorn.internal.codegen.CompilerConstants.JAVA_THIS; -import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_PREFIX; -import static jdk.nashorn.internal.codegen.CompilerConstants.MAP; -import static jdk.nashorn.internal.codegen.CompilerConstants.className; -import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; -import static jdk.nashorn.internal.runtime.linker.Lookup.MH; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import jdk.nashorn.internal.codegen.ClassEmitter; -import jdk.nashorn.internal.codegen.ClassEmitter.Flag; -import jdk.nashorn.internal.codegen.MethodEmitter; -import jdk.nashorn.internal.codegen.types.Type; -import jdk.nashorn.internal.runtime.AccessorProperty; -import jdk.nashorn.internal.runtime.Context; -import jdk.nashorn.internal.runtime.DebugLogger; -import jdk.nashorn.internal.runtime.FunctionScope; -import jdk.nashorn.internal.runtime.JSType; -import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptObject; -import jdk.nashorn.internal.runtime.ScriptRuntime; -import jdk.nashorn.internal.runtime.options.Options; - -/** - * Generates the ScriptObject subclass structure with fields for a user objects. - */ -public final class ObjectClassGenerator { - - /** - * Marker for scope parameters. - */ - public static final String SCOPE_MARKER = "P"; - - /** - * Debug field logger - * Should we print debugging information for fields when they are generated and getters/setters are called? - */ - public static final DebugLogger LOG = new DebugLogger("fields", "nashorn.fields.debug"); - - /** - * is field debugging enabled. Several modules in codegen and properties use this, hence - * public access. - */ - public static final boolean DEBUG_FIELDS = LOG.isEnabled(); - - /** - * Should the runtime only use java.lang.Object slots for fields? If this is false, the representation - * will be a primitive 64-bit long value used for all primitives and a java.lang.Object for references. - * This introduces a larger number of method handles in the system, as we need to have different getters - * and setters for the different fields. Currently this introduces significant overhead in Hotspot. - * - * This is engineered to plug into the TaggedArray implementation, when it's done. - */ - public static final boolean OBJECT_FIELDS_ONLY = !Options.getBooleanProperty("nashorn.fields.dual"); - - /** The field types in the system */ - private static final List<Type> FIELD_TYPES = new LinkedList<>(); - - /** What type is the primitive type in dual representation */ - public static final Type PRIMITIVE_TYPE = Type.LONG; - - /** - * The list of field types that we support - one type creates one field. This is currently either - * LONG + OBJECT or just OBJECT for classic mode. - */ - static { - if (!OBJECT_FIELDS_ONLY) { - System.err.println("WARNING!!! Running with primitive fields - there is untested functionality!"); - FIELD_TYPES.add(PRIMITIVE_TYPE); - } - FIELD_TYPES.add(Type.OBJECT); - } - - /** The context */ - private final Context context; - - /** - * The list of available accessor types in width order. This order is used for type guesses narrow->wide - * in the dual--fields world - */ - public static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList( - Arrays.asList( - Type.INT, - Type.LONG, - Type.NUMBER, - Type.OBJECT)); - - //these are hard coded for speed and so that we can switch on them - private static final int TYPE_INT_INDEX = 0; //getAccessorTypeIndex(int.class); - private static final int TYPE_LONG_INDEX = 1; //getAccessorTypeIndex(long.class); - private static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class); - private static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class); - - /** - * Constructor - * - * @param context a context - */ - public ObjectClassGenerator(final Context context) { - this.context = context; - assert context != null; - } - - /** - * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes()) - * - * @param type the type - * - * @return the accessor index, or -1 if no accessor of this type exists - */ - public static int getAccessorTypeIndex(final Type type) { - return getAccessorTypeIndex(type.getTypeClass()); - } - - /** - * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes()) - * - * Note that this is hardcoded with respect to the dynamic contents of the accessor - * types array for speed. Hotspot got stuck with this as 5% of the runtime in - * a benchmark when it looped over values and increased an index counter. :-( - * - * @param type the type - * - * @return the accessor index, or -1 if no accessor of this type exists - */ - public static int getAccessorTypeIndex(final Class<?> type) { - if (type == int.class) { - return 0; - } else if (type == long.class) { - return 1; - } else if (type == double.class) { - return 2; - } else if (!type.isPrimitive()) { - return 3; - } - return -1; - } - - /** - * Return the number of accessor types available. - * - * @return number of accessor types in system - */ - public static int getNumberOfAccessorTypes() { - return ACCESSOR_TYPES.size(); - } - - /** - * Return the accessor type based on its index in [0..getNumberOfAccessorTypes()) - * Indexes are ordered narrower->wider / optimistic->pessimistic. Invalidations always - * go to a type of higher index - * - * @param index accessor type index - * - * @return a type corresponding to the index. - */ - - public static Type getAccessorType(final int index) { - return ACCESSOR_TYPES.get(index); - } - - /** - * Returns the class name for JavaScript objects with fieldCount fields. - * - * @param fieldCount Number of fields to allocate. - * - * @return The class name. - */ - public static String getClassName(final int fieldCount) { - return fieldCount != 0 ? SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.tag() + fieldCount : - SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.tag(); - } - - /** - * Returns the class name for JavaScript scope with fieldCount fields and - * paramCount parameters. - * - * @param fieldCount Number of fields to allocate. - * @param paramCount Number of parameters to allocate - * - * @return The class name. - */ - public static String getClassName(final int fieldCount, final int paramCount) { - return SCRIPTS_PACKAGE + '/' + JS_OBJECT_PREFIX.tag() + fieldCount + SCOPE_MARKER + paramCount; - } - - /** - * Returns the name of a field based on number and type. - * - * @param fieldIndex Ordinal of field. - * @param type Type of field. - * - * @return The field name. - */ - public static String getFieldName(final int fieldIndex, final Type type) { - return type.getDescriptor().substring(0, 1) + fieldIndex; - } - - /** - * In the world of Object fields, we also have no undefined SwitchPoint, to reduce as much potential - * MethodHandle overhead as possible. In that case, we explicitly need to assign undefined to fields - * when we initialize them. - * - * @param init constructor to generate code in - * @param className name of class - * @param fieldNames fields to initialize to undefined, where applicable - */ - private static void initializeToUndefined(final MethodEmitter init, final String className, final List<String> fieldNames) { - if (fieldNames.isEmpty()) { - return; - } - - // always initialize fields to undefined, even with --dual-fields. Then it's ok to - // remember things like "widest set type" in properties, and if it's object, don't - // add any special "return undefined" getters, saving an invalidation - init.load(Type.OBJECT, JAVA_THIS.slot()); - init.loadUndefined(Type.OBJECT); - - final Iterator<String> iter = fieldNames.iterator(); - while (iter.hasNext()) { - final String fieldName = iter.next(); - if (iter.hasNext()) { - init.dup2(); - } - init.putField(className, fieldName, Type.OBJECT.getDescriptor()); - } - } - - /** - * Generate the byte codes for a JavaScript object class or scope. - * Class name is a function of number of fields and number of param - * fields - * - * @param descriptor Descriptor pulled from class name. - * - * @return Byte codes for generated class. - */ - public byte[] generate(final String descriptor) { - final String[] counts = descriptor.split(SCOPE_MARKER); - final int fieldCount = Integer.valueOf(counts[0]); - - if (counts.length == 1) { - return generate(fieldCount); - } - - final int paramCount = Integer.valueOf(counts[1]); - - return generate(fieldCount, paramCount); - } - - /** - * Generate the byte codes for a JavaScript object class with fieldCount fields. - * - * @param fieldCount Number of fields in the JavaScript object. - * - * @return Byte codes for generated class. - */ - public byte[] generate(final int fieldCount) { - final String className = getClassName(fieldCount); - final String superName = className(ScriptObject.class); - final ClassEmitter classEmitter = newClassEmitter(className, superName); - final List<String> initFields = addFields(classEmitter, fieldCount); - - final MethodEmitter init = newInitMethod(classEmitter); - initializeToUndefined(init, className, initFields); - init.returnVoid(); - init.end(); - - newEmptyInit(classEmitter, className); - newAllocate(classEmitter, className); - - return toByteArray(classEmitter); - } - - /** - * Generate the byte codes for a JavaScript scope class with fieldCount fields - * and paramCount parameters. - * - * @param fieldCount Number of fields in the JavaScript scope. - * @param paramCount Number of parameters in the JavaScript scope - * . - * @return Byte codes for generated class. - */ - public byte[] generate(final int fieldCount, final int paramCount) { - final String className = getClassName(fieldCount, paramCount); - final String superName = className(FunctionScope.class); - final ClassEmitter classEmitter = newClassEmitter(className, superName); - final List<String> initFields = addFields(classEmitter, fieldCount); - - final MethodEmitter init = newInitScopeMethod(classEmitter); - initializeToUndefined(init, className, initFields); - init.returnVoid(); - init.end(); - - final MethodEmitter initWithArguments = newInitScopeWithArgumentsMethod(classEmitter); - initializeToUndefined(initWithArguments, className, initFields); - initWithArguments.returnVoid(); - initWithArguments.end(); - - return toByteArray(classEmitter); - } - - /** - * Generates the needed fields. - * - * @param classEmitter Open class emitter. - * @param fieldCount Number of fields. - * - * @return List fields that need to be initialized. - */ - private static List<String> addFields(final ClassEmitter classEmitter, final int fieldCount) { - final List<String> initFields = new LinkedList<>(); - - for (int i = 0; i < fieldCount; i++) { - for (final Type type : FIELD_TYPES) { - final String fieldName = getFieldName(i, type); - classEmitter.field(fieldName, type.getTypeClass()); - - if (type == Type.OBJECT) { - initFields.add(fieldName); - } - } - } - - return initFields; - } - - /** - * Allocate and initialize a new class emitter. - * - * @param className Name of JavaScript class. - * - * @return Open class emitter. - */ - private ClassEmitter newClassEmitter(final String className, final String superName) { - final ClassEmitter classEmitter = new ClassEmitter(context, className, superName); - classEmitter.begin(); - - return classEmitter; - } - - /** - * Allocate and initialize a new <init> method. - * - * @param classEmitter Open class emitter. - * - * @return Open method emitter. - */ - private static MethodEmitter newInitMethod(final ClassEmitter classEmitter) { - final MethodEmitter init = classEmitter.init(PropertyMap.class); - init.begin(); - init.load(Type.OBJECT, JAVA_THIS.slot()); - init.load(Type.OBJECT, MAP.slot()); - init.invoke(constructorNoLookup(ScriptObject.class, PropertyMap.class)); - - return init; - } - - /** - * Allocate and initialize a new <init> method for scopes. - * @param classEmitter Open class emitter. - * @return Open method emitter. - */ - private static MethodEmitter newInitScopeMethod(final ClassEmitter classEmitter) { - final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class); - init.begin(); - init.load(Type.OBJECT, JAVA_THIS.slot()); - init.load(Type.OBJECT, MAP.slot()); - init.load(Type.OBJECT, INIT_SCOPE.slot()); - init.invoke(constructorNoLookup(FunctionScope.class, PropertyMap.class, ScriptObject.class)); - - return init; - } - - /** - * Allocate and initialize a new <init> method for scopes with arguments. - * @param classEmitter Open class emitter. - * @return Open method emitter. - */ - private static MethodEmitter newInitScopeWithArgumentsMethod(final ClassEmitter classEmitter) { - final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class, Object.class); - init.begin(); - init.load(Type.OBJECT, JAVA_THIS.slot()); - init.load(Type.OBJECT, MAP.slot()); - init.load(Type.OBJECT, INIT_SCOPE.slot()); - init.load(Type.OBJECT, INIT_ARGUMENTS.slot()); - init.invoke(constructorNoLookup(FunctionScope.class, PropertyMap.class, ScriptObject.class, Object.class)); - - return init; - } - - /** - * Add an empty <init> method to the JavaScript class. - * - * @param classEmitter Open class emitter. - * @param className Name of JavaScript class. - */ - private static void newEmptyInit(final ClassEmitter classEmitter, final String className) { - final MethodEmitter emptyInit = classEmitter.init(); - emptyInit.begin(); - emptyInit.load(Type.OBJECT, JAVA_THIS.slot()); - emptyInit.loadNull(); - emptyInit.invoke(constructorNoLookup(className, PropertyMap.class)); - emptyInit.returnVoid(); - emptyInit.end(); - } - - /** - * Add an empty <init> method to the JavaScript class. - * - * @param classEmitter Open class emitter. - * @param className Name of JavaScript class. - */ - private static void newAllocate(final ClassEmitter classEmitter, final String className) { - final MethodEmitter allocate = classEmitter.method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), ALLOCATE.tag(), ScriptObject.class, PropertyMap.class); - allocate.begin(); - allocate._new(className); - allocate.dup(); - allocate.load(Type.typeFor(PropertyMap.class), 0); - allocate.invoke(constructorNoLookup(className, PropertyMap.class)); - allocate._return(); - allocate.end(); - } - - /** - * Collects the byte codes for a generated JavaScript class. - * - * @param classEmitter Open class emitter. - * @return Byte codes for the class. - */ - private byte[] toByteArray(final ClassEmitter classEmitter) { - classEmitter.end(); - - final byte[] code = classEmitter.toByteArray(); - - if (context != null && context._print_code) { - Context.getCurrentErr().println(ClassEmitter.disassemble(code)); - } - - if (context != null && context._verify_code) { - context.verify(code); - } - - return code; - } - - /** Double to long bits, used with --dual-fields for primitive double values */ - private static final MethodHandle PACK_DOUBLE = - MH.explicitCastArguments(MH.findStatic(MethodHandles.publicLookup(), Double.class, "doubleToRawLongBits", MH.type(long.class, double.class)), MH.type(long.class, double.class)); - - /** double bits to long, used with --dual-fields for primitive double values */ - private static MethodHandle UNPACK_DOUBLE = - MH.findStatic(MethodHandles.publicLookup(), Double.class, "longBitsToDouble", MH.type(double.class, long.class)); - - /** object conversion quickies with JS semantics - used for return value and parameter filter */ - private static MethodHandle[] CONVERT_OBJECT = { - JSType.TO_INT32.methodHandle(), - JSType.TO_UINT32.methodHandle(), - JSType.TO_NUMBER.methodHandle(), - null - }; - - /** - * Given a primitiveGetter (optional for non dual fields) and an objectSetter that retrieve - * the primitive and object version of a field respectively, return one with the correct - * method type and the correct filters. For example, if the value is stored as a double - * and we want an Object getter, in the dual fields world we'd pick the primitiveGetter, - * which reads a long, use longBitsToDouble on the result to unpack it, and then change the - * return type to Object, boxing it. In the objects only world there are only object fields, - * primtives are boxed when asked for them and we don't need to bother with primitive encoding - * (or even undefined, which if forType==null) representation, so we just return whatever is - * in the object field. The object field is always initiated to Undefined, so here, where we have - * the representation for Undefined in all our bits, this is not a problem. - * <p> - * Representing undefined in a primitive is hard, for an int there aren't enough bits, for a long - * we could limit the width of a representation, and for a double (as long as it is stored as long, - * as all NaNs will turn into QNaN on ia32, which is one bit pattern, we should use a special NaN). - * Naturally we could have special undefined values for all types which mean "go look in a wider field", - * but the guards needed on every getter took too much time. - * <p> - * To see how this is used, look for example in {@link AccessorProperty#getGetter} - * <p> - * @param forType representation of the underlying type in the field, null if undefined - * @param type type to retrieve it as - * @param primitiveGetter getter to read the primitive version of this field (null if Objects Only) - * @param objectGetter getter to read the object version of this field - * - * @return getter for the given representation that returns the given type - */ - public static MethodHandle createGetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter) { - final int fti = forType == null ? -1 : getAccessorTypeIndex(forType); - final int ti = getAccessorTypeIndex(type); - - if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) { - if (ti == TYPE_OBJECT_INDEX) { - return objectGetter; - } - - return MH.filterReturnValue(objectGetter, CONVERT_OBJECT[ti]); - } - - assert !OBJECT_FIELDS_ONLY; - if (forType == null) { - return GET_UNDEFINED[ti]; - } - - final MethodType pmt = primitiveGetter.type(); - - switch (fti) { - case TYPE_INT_INDEX: - case TYPE_LONG_INDEX: - switch (ti) { - case TYPE_INT_INDEX: - //get int while an int, truncating cast of long value - return MH.explicitCastArguments(primitiveGetter, pmt.changeReturnType(int.class)); - case TYPE_LONG_INDEX: - return primitiveGetter; - default: - return MH.asType(primitiveGetter, pmt.changeReturnType(type)); - } - case TYPE_DOUBLE_INDEX: - final MethodHandle getPrimitiveAsDouble = MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE); - switch (ti) { - case TYPE_INT_INDEX: - case TYPE_LONG_INDEX: - return MH.explicitCastArguments(getPrimitiveAsDouble, pmt.changeReturnType(type)); - case TYPE_DOUBLE_INDEX: - return getPrimitiveAsDouble; - default: - return MH.asType(getPrimitiveAsDouble, pmt.changeReturnType(Object.class)); - } - default: - assert false; - return null; - } - } - - private static final MethodHandle IS_TYPE_GUARD = findOwnMH("isType", boolean.class, Class.class, Object.class); - - @SuppressWarnings("unused") - private static boolean isType(final Class<?> boxedForType, final Object x) { - return x.getClass() == boxedForType; - } - - private static Class<? extends Number> getBoxedType(final Class<?> forType) { - if (forType == int.class) { - return Integer.class; - } - - if (forType == long.class) { - return Long.class; - } - - if (forType == double.class) { - return Double.class; - } - - assert false; - return null; - } - - /** - * If we are setting boxed types (because the compiler couldn't determine which they were) to - * a primitive field, we can reuse the primitive field getter, as long as we are setting an element - * of the same boxed type as the primitive type representation - * - * @param forType the current type - * @param primitiveSetter primitive setter for the current type with an element of the current type - * @param objectSetter the object setter - * - * @return method handle that checks if the element to be set is of the currenttype, even though it's boxed - * and instead of using the generic object setter, that would blow up the type and invalidate the map, - * unbox it and call the primitive setter instead - */ - public static MethodHandle createGuardBoxedPrimitiveSetter(final Class<?> forType, final MethodHandle primitiveSetter, final MethodHandle objectSetter) { - final Class<? extends Number> boxedForType = getBoxedType(forType); - //object setter that checks for primitive if current type is primitive - - return MH.guardWithTest( - MH.insertArguments( - MH.dropArguments( - IS_TYPE_GUARD, - 1, - Object.class), - 0, - boxedForType), - MH.asType( - primitiveSetter, - objectSetter.type()), - objectSetter); - } - - /** - * This is similar to the {@link ObjectClassGenerator#createGetter} function. Performs - * the necessary operations to massage a setter operand of type {@code type} to - * fit into the primitive field (if primitive and dual fields is enabled) or into - * the object field (box if primitive and dual fields is disabled) - * - * @param forType representation of the underlying object - * @param type representation of field to write, and setter signature - * @param primitiveSetter setter that writes to the primitive field (null if Objects Only) - * @param objectSetter setter that writes to the object field - * - * @return the setter for the given representation that takes a {@code type} - */ - public static MethodHandle createSetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveSetter, final MethodHandle objectSetter) { - assert forType != null; - - final int fti = getAccessorTypeIndex(forType); - final int ti = getAccessorTypeIndex(type); - - if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) { - if (ti == TYPE_OBJECT_INDEX) { - return objectSetter; - } - - return MH.asType(objectSetter, objectSetter.type().changeParameterType(1, type)); - } - - assert !OBJECT_FIELDS_ONLY; - - final MethodType pmt = primitiveSetter.type(); - - switch (fti) { - case TYPE_INT_INDEX: - case TYPE_LONG_INDEX: - switch (ti) { - case TYPE_INT_INDEX: - return MH.asType(primitiveSetter, pmt.changeParameterType(1, int.class)); - case TYPE_LONG_INDEX: - return primitiveSetter; - case TYPE_DOUBLE_INDEX: - return MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE); - default: - return objectSetter; - } - case TYPE_DOUBLE_INDEX: - if (ti == TYPE_OBJECT_INDEX) { - return objectSetter; - } - return MH.asType(MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE), pmt.changeParameterType(1, type)); - default: - assert false; - return null; - } - } - - // - // Provide generic getters and setters for undefined types. If a type is undefined, all - // and marshals the set to the correct setter depending on the type of the value being set. - // Note that there are no actual undefined versions of int, long and double in JavaScript, - // but executing toInt32, toLong and toNumber always returns a working result, 0, 0L or NaN - // - - /** The value of Undefined cast to an int32 */ - public static final int UNDEFINED_INT = 0; - /** The value of Undefined cast to a long */ - public static final long UNDEFINED_LONG = 0L; - /** The value of Undefined cast to a double */ - public static final double UNDEFINED_DOUBLE = Double.NaN; - - /** - * Compute type name for correct undefined getter - * @param type the type - * @return name of getter - */ - private static String typeName(final Type type) { - String name = type.getTypeClass().getName(); - final int dot = name.lastIndexOf('.'); - if (dot != -1) { - name = name.substring(dot + 1); - } - return Character.toUpperCase(name.charAt(0)) + name.substring(1); - } - - /** - * Handles for undefined getters of the different types - */ - private static final MethodHandle[] GET_UNDEFINED = new MethodHandle[ObjectClassGenerator.getNumberOfAccessorTypes()]; - - /** - * Used to wrap getters for undefined values, where this matters. Currently only in dual fields. - * If an object starts out as undefined it needs special getters until it has been assigned - * something the first time - * - * @param returnType type to cast the undefined to - * - * @return undefined as returnType - */ - public static MethodHandle getUndefined(final Class<?> returnType) { - return GET_UNDEFINED[ObjectClassGenerator.getAccessorTypeIndex(returnType)]; - } - - static { - int pos = 0; - for (final Type type : ACCESSOR_TYPES) { - GET_UNDEFINED[pos++] = findOwnMH("getUndefined" + typeName(type), type.getTypeClass(), Object.class); - } - } - - @SuppressWarnings("unused") - private static int getUndefinedInt(final Object obj) { - return UNDEFINED_INT; - } - - @SuppressWarnings("unused") - private static long getUndefinedLong(final Object obj) { - return UNDEFINED_LONG; - } - - @SuppressWarnings("unused") - private static double getUndefinedDouble(final Object obj) { - return UNDEFINED_DOUBLE; - } - - @SuppressWarnings("unused") - private static Object getUndefinedObject(final Object obj) { - return ScriptRuntime.UNDEFINED; - } - - private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { - return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types)); - } -}
--- a/src/jdk/nashorn/internal/codegen/objects/ObjectCreator.java Fri Feb 15 09:18:05 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,176 +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.objects; - -import java.util.List; -import jdk.nashorn.internal.codegen.CodeGenerator; -import jdk.nashorn.internal.codegen.CompileUnit; -import jdk.nashorn.internal.codegen.Compiler; -import jdk.nashorn.internal.codegen.MethodEmitter; -import jdk.nashorn.internal.ir.Symbol; -import jdk.nashorn.internal.runtime.Context; -import jdk.nashorn.internal.runtime.PropertyMap; - -/** - * Base class for object creation code generation. - */ -public abstract class ObjectCreator { - - /** Compile unit for this ObjectCreator, see CompileUnit */ - protected final CompileUnit compileUnit; - - /** List of keys to initiate in this ObjectCreator */ - protected final List<String> keys; - - /** List of symbols to initiate in this ObjectCreator */ - protected final List<Symbol> symbols; - - /** Code generator */ - protected final CodeGenerator codegen; - - private final boolean isScope; - private final boolean hasArguments; - private int fieldCount; - private int paramCount; - private String fieldObjectClassName; - private Class<?> fieldObjectClass; - private PropertyMap propertyMap; - - /** - * Constructor - * - * @param codegen the code generator - * @param keys the keys - * @param symbols the symbols corresponding to keys, same index - * @param isScope is this object scope - * @param hasArguments does the created object have an "arguments" property - */ - protected ObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final boolean isScope, final boolean hasArguments) { - this.codegen = codegen; - this.compileUnit = codegen.getCurrentCompileUnit(); - this.keys = keys; - this.symbols = symbols; - this.isScope = isScope; - this.hasArguments = hasArguments; - - countFields(); - findClass(); - } - - /** - * Tally the number of fields and parameters. - */ - private void countFields() { - for (final Symbol symbol : this.symbols) { - if (symbol != null) { - if (hasArguments() && symbol.isParam()) { - symbol.setFieldIndex(paramCount++); - } else { - symbol.setFieldIndex(fieldCount++); - } - } - } - } - - /** - * Locate (or indirectly create) the object container class. - */ - private void findClass() { - fieldObjectClassName = isScope() ? - ObjectClassGenerator.getClassName(fieldCount, paramCount) : - ObjectClassGenerator.getClassName(fieldCount); - - try { - this.fieldObjectClass = Context.forStructureClass(Compiler.binaryName(fieldObjectClassName)); - } catch (final ClassNotFoundException e) { - throw new AssertionError("Nashorn has encountered an internal error. Structure can not be created."); - } - } - - /** - * Generate code for making the object. - * @param method Script method. - */ - public abstract void makeObject(final MethodEmitter method); - - /** - * Create a new MapCreator - * @param clazz type of MapCreator - * @return map creator instantiated by type - */ - protected MapCreator newMapCreator(final Class<?> clazz) { - return new MapCreator(clazz, keys, symbols); - } - - /** - * Construct the property map appropriate for the object. - * @return the newly created property map - */ - protected PropertyMap makeMap() { - if (keys.isEmpty()) { //empty map - propertyMap = PropertyMap.newMap(fieldObjectClass); - } else { - propertyMap = newMapCreator(fieldObjectClass).makeMap(hasArguments()); - } - return propertyMap; - } - - /** - * Emit the correct map for the object. - * @param method method emitter - * @return the method emitter - */ - protected MethodEmitter loadMap(final MethodEmitter method) { - codegen.loadConstant(propertyMap); - return method; - } - - /** - * Get the class name for the object class, - * e.g. {@code com.nashorn.oracle.scripts.JO$2P0} - * - * @return script class name - */ - public String getClassName() { - return fieldObjectClassName; - } - - /** - * Is this a scope object - * @return true if scope - */ - protected boolean isScope() { - return isScope; - } - - /** - * Does the created object have an "arguments" property - * @return true if has an "arguments" property - */ - protected boolean hasArguments() { - return hasArguments; - } -}
--- a/src/jdk/nashorn/internal/codegen/objects/ObjectMapCreator.java Fri Feb 15 09:18:05 2013 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +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.objects; - -import java.util.List; -import jdk.nashorn.internal.ir.Symbol; -import jdk.nashorn.internal.runtime.Property; - -/** - * This map creator is used to guarantee that all properties start out as - * object types. Only semantically significant in the -Dnashorn.fields.dual=true world, - * where we want to avoid invalidation upon initialization e.g. for var x = {a:"str"}; - */ - -public class ObjectMapCreator extends MapCreator { - /** - * Constructor - * - * @param structure structure for object class - * @param keys keys in object - * @param symbols symbols in object corresponding to keys - */ - public ObjectMapCreator(final Class<?> structure, final List<String> keys, final List<Symbol> symbols) { - super(structure, keys, symbols); - } - - @Override - protected int getPropertyFlags(final Symbol symbol, final boolean isVarArg) { - return super.getPropertyFlags(symbol, isVarArg) | Property.IS_ALWAYS_OBJECT; - } -}
--- a/src/jdk/nashorn/internal/codegen/types/BooleanType.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/types/BooleanType.java Fri Feb 15 09:44:15 2013 +0100 @@ -59,7 +59,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.runtime.JSType; /**
--- a/src/jdk/nashorn/internal/codegen/types/IntType.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/types/IntType.java Fri Feb 15 09:44:15 2013 +0100 @@ -55,7 +55,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; /** * Type class: INT
--- a/src/jdk/nashorn/internal/codegen/types/LongType.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/types/LongType.java Fri Feb 15 09:44:15 2013 +0100 @@ -49,7 +49,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; /** * Type class: LONG
--- a/src/jdk/nashorn/internal/codegen/types/NumberType.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/types/NumberType.java Fri Feb 15 09:44:15 2013 +0100 @@ -42,7 +42,7 @@ import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.runtime.JSType; class NumberType extends NumericType {
--- a/src/jdk/nashorn/internal/ir/AccessNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/AccessNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,9 +25,9 @@ package jdk.nashorn.internal.ir; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.DEBUG_FIELDS; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source;
--- a/src/jdk/nashorn/internal/ir/BaseNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/BaseNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -60,7 +60,7 @@ */ protected BaseNode(final BaseNode baseNode, final CopyState cs) { super(baseNode); - base = cs.existingOrCopy(baseNode.getBase()); + this.base = cs.existingOrCopy(baseNode.getBase()); setStart(base.getStart()); }
--- a/src/jdk/nashorn/internal/ir/Block.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/Block.java Fri Feb 15 09:44:15 2013 +0100 @@ -40,7 +40,7 @@ import java.util.HashMap; import java.util.List; import jdk.nashorn.internal.codegen.Frame; -import jdk.nashorn.internal.codegen.MethodEmitter.Label; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.annotations.ParentNode; import jdk.nashorn.internal.ir.visitor.NodeVisitor; @@ -94,7 +94,6 @@ this.function = function; this.statements = new ArrayList<>(); this.symbols = new HashMap<>(); - this.frame = null; this.entryLabel = new Label("block_entry"); this.breakLabel = new Label("block_break"); } @@ -108,16 +107,16 @@ protected Block(final Block block, final CopyState cs) { super(block); - parent = block.parent; - function = block.function; - statements = new ArrayList<>(); + this.parent = block.parent; + this.function = block.function; + this.statements = new ArrayList<>(); for (final Node statement : block.getStatements()) { statements.add(cs.existingOrCopy(statement)); } - symbols = new HashMap<>(); - frame = block.frame == null ? null : block.frame.copy(); - entryLabel = new Label(block.entryLabel); - breakLabel = new Label(block.breakLabel); + this.symbols = new HashMap<>(); + this.frame = block.frame == null ? null : block.frame.copy(); + this.entryLabel = new Label(block.entryLabel); + this.breakLabel = new Label(block.breakLabel); assert block.symbols.isEmpty() : "must not clone with symbols"; }
--- a/src/jdk/nashorn/internal/ir/BreakNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/BreakNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,7 +25,7 @@ package jdk.nashorn.internal.ir; -import jdk.nashorn.internal.codegen.MethodEmitter; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source; @@ -75,7 +75,7 @@ * Return the target label of this break node. * @return the target label. */ - public MethodEmitter.Label getTargetLabel() { + public Label getTargetLabel() { if (targetNode instanceof BreakableNode) { return ((BreakableNode)targetNode).getBreakLabel(); } else if (targetNode instanceof Block) {
--- a/src/jdk/nashorn/internal/ir/BreakableNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/BreakableNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,7 +25,7 @@ package jdk.nashorn.internal.ir; -import jdk.nashorn.internal.codegen.MethodEmitter; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.runtime.Source; /** @@ -35,7 +35,7 @@ public abstract class BreakableNode extends Node { /** break label. */ - protected MethodEmitter.Label breakLabel; + protected Label breakLabel; /** * Constructor @@ -61,7 +61,7 @@ * Return the break label, i.e. the location to go to on break. * @return the break label */ - public MethodEmitter.Label getBreakLabel() { + public Label getBreakLabel() { return breakLabel; }
--- a/src/jdk/nashorn/internal/ir/CallNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/CallNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -164,10 +164,10 @@ newArgs.add(cs.existingOrCopy(arg)); } - function = cs.existingOrCopy(callNode.function); //TODO existing or same? - args = newArgs; - isNew = callNode.isNew; - inWithBlock = callNode.inWithBlock; + this.function = cs.existingOrCopy(callNode.function); //TODO existing or same? + this.args = newArgs; + this.isNew = callNode.isNew; + this.inWithBlock = callNode.inWithBlock; }
--- a/src/jdk/nashorn/internal/ir/CaseNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/CaseNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,7 +25,7 @@ package jdk.nashorn.internal.ir; -import jdk.nashorn.internal.codegen.MethodEmitter.Label; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source;
--- a/src/jdk/nashorn/internal/ir/CatchNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/CatchNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -67,10 +67,10 @@ private CatchNode(final CatchNode catchNode, final CopyState cs) { super(catchNode); - exception = (IdentNode)cs.existingOrCopy(catchNode.exception); - exceptionCondition = cs.existingOrCopy(catchNode.exceptionCondition); - body = (Block)cs.existingOrCopy(catchNode.body); - isSyntheticRethrow = catchNode.isSyntheticRethrow; + this.exception = (IdentNode)cs.existingOrCopy(catchNode.exception); + this.exceptionCondition = cs.existingOrCopy(catchNode.exceptionCondition); + this.body = (Block)cs.existingOrCopy(catchNode.body); + this.isSyntheticRethrow = catchNode.isSyntheticRethrow; } @Override
--- a/src/jdk/nashorn/internal/ir/ContinueNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/ContinueNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,7 +25,7 @@ package jdk.nashorn.internal.ir; -import jdk.nashorn.internal.codegen.MethodEmitter; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source; @@ -72,7 +72,7 @@ * Return the target label of this continue node. * @return the target label. */ - public MethodEmitter.Label getTargetLabel() { + public Label getTargetLabel() { assert targetNode instanceof WhileNode : "continue target must be a while node"; return ((WhileNode)targetNode).getContinueLabel(); }
--- a/src/jdk/nashorn/internal/ir/IdentNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/IdentNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -28,9 +28,9 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.__DIR__; import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__; import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.DEBUG_FIELDS; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source;
--- a/src/jdk/nashorn/internal/ir/IndexNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/IndexNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,9 +25,9 @@ package jdk.nashorn.internal.ir; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.DEBUG_FIELDS; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source;
--- a/src/jdk/nashorn/internal/ir/LabelNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/LabelNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -68,10 +68,10 @@ private LabelNode(final LabelNode labelNode, final CopyState cs) { super(labelNode); - label = (IdentNode)cs.existingOrCopy(labelNode.label); - body = (Block)cs.existingOrCopy(labelNode.body); - breakNode = cs.existingOrSame(labelNode.breakNode); - continueNode = cs.existingOrSame(labelNode.continueNode); + this.label = (IdentNode)cs.existingOrCopy(labelNode.label); + this.body = (Block)cs.existingOrCopy(labelNode.body); + this.breakNode = cs.existingOrSame(labelNode.breakNode); + this.continueNode = cs.existingOrSame(labelNode.continueNode); } @Override
--- a/src/jdk/nashorn/internal/ir/LineNumberNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/LineNumberNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -53,7 +53,7 @@ private LineNumberNode(final LineNumberNode lineNumberNode) { super(lineNumberNode); - lineNumber = lineNumberNode.getLineNumber(); + this.lineNumber = lineNumberNode.getLineNumber(); } @Override
--- a/src/jdk/nashorn/internal/ir/ObjectNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/ObjectNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -68,8 +68,8 @@ newElements.add(cs.existingOrCopy(element)); } - context = (Block)cs.existingOrCopy(objectNode.context); - elements = newElements; + this.context = (Block)cs.existingOrCopy(objectNode.context); + this.elements = newElements; } @Override
--- a/src/jdk/nashorn/internal/ir/ReturnNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/ReturnNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -65,8 +65,8 @@ private ReturnNode(final ReturnNode returnNode, final CopyState cs) { super(returnNode); - expression = cs.existingOrCopy(returnNode.expression); - tryChain = (TryNode)cs.existingOrSame(returnNode.tryChain); + this.expression = cs.existingOrCopy(returnNode.expression); + this.tryChain = (TryNode)cs.existingOrSame(returnNode.tryChain); } @Override
--- a/src/jdk/nashorn/internal/ir/SplitNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/SplitNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.List; import jdk.nashorn.internal.codegen.CompileUnit; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.codegen.MethodEmitter; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.annotations.Reference; @@ -57,7 +58,7 @@ /** A list of target labels in parent methods this split node may encounter. */ @Ignore - private final List<MethodEmitter.Label> externalTargets; + private final List<Label> externalTargets; /** True if this split node or any of its children contain a return statement. */ private boolean hasReturn; @@ -85,10 +86,10 @@ private SplitNode(final SplitNode splitNode, final CopyState cs) { super(splitNode); - name = splitNode.name; - functionNode = (FunctionNode)cs.existingOrSame(splitNode.functionNode); - body = cs.existingOrCopy(splitNode.body); - externalTargets = new ArrayList<>(); + this.name = splitNode.name; + this.functionNode = (FunctionNode)cs.existingOrSame(splitNode.functionNode); + this.body = cs.existingOrCopy(splitNode.body); + this.externalTargets = new ArrayList<>(); } @Override @@ -196,7 +197,7 @@ * Get the external targets for this SplitNode * @return list of external targets */ - public List<MethodEmitter.Label> getExternalTargets() { + public List<Label> getExternalTargets() { return Collections.unmodifiableList(externalTargets); } @@ -204,7 +205,7 @@ * Add an external target for this SplitNode * @param targetLabel target label */ - public void addExternalTarget(final MethodEmitter.Label targetLabel) { + public void addExternalTarget(final Label targetLabel) { externalTargets.add(targetLabel); }
--- a/src/jdk/nashorn/internal/ir/SwitchNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/SwitchNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -28,7 +28,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import jdk.nashorn.internal.codegen.MethodEmitter.Label; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source; @@ -59,12 +59,7 @@ */ public SwitchNode(final Source source, final long token, final int finish) { super(source, token, finish); - - expression = null; - tag = null; - cases = null; - defaultCase = null; - breakLabel = new Label("switch_break"); + this.breakLabel = new Label("switch_break"); } private SwitchNode(final SwitchNode switchNode, final CopyState cs) { @@ -76,11 +71,11 @@ newCases.add((CaseNode)cs.existingOrCopy(caseNode)); } - expression = cs.existingOrCopy(switchNode.getExpression()); - tag = switchNode.getTag(); - cases = newCases; - defaultCase = (CaseNode)cs.existingOrCopy(switchNode.getDefaultCase()); - breakLabel = new Label(switchNode.getBreakLabel()); + this.expression = cs.existingOrCopy(switchNode.getExpression()); + this.tag = switchNode.getTag(); + this.cases = newCases; + this.defaultCase = (CaseNode)cs.existingOrCopy(switchNode.getDefaultCase()); + this.breakLabel = new Label(switchNode.getBreakLabel()); } @Override
--- a/src/jdk/nashorn/internal/ir/ThrowNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/ThrowNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -60,8 +60,8 @@ private ThrowNode(final ThrowNode throwNode, final CopyState cs) { super(throwNode); - expression = cs.existingOrCopy(throwNode.expression); - tryChain = (TryNode)cs.existingOrSame(throwNode.tryChain); + this.expression = cs.existingOrCopy(throwNode.expression); + this.tryChain = (TryNode)cs.existingOrSame(throwNode.tryChain); } @Override
--- a/src/jdk/nashorn/internal/ir/TryNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/TryNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -28,7 +28,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import jdk.nashorn.internal.codegen.MethodEmitter.Label; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source;
--- a/src/jdk/nashorn/internal/ir/UnaryNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/UnaryNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -67,7 +67,7 @@ protected UnaryNode(final UnaryNode unaryNode, final CopyState cs) { super(unaryNode); - rhs = cs.existingOrCopy(unaryNode.rhs); + this.rhs = cs.existingOrCopy(unaryNode.rhs); } /**
--- a/src/jdk/nashorn/internal/ir/WhileNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/WhileNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,7 +25,7 @@ package jdk.nashorn.internal.ir; -import jdk.nashorn.internal.codegen.MethodEmitter.Label; +import jdk.nashorn.internal.codegen.Label; import jdk.nashorn.internal.ir.visitor.NodeVisitor; import jdk.nashorn.internal.runtime.Source; @@ -53,10 +53,8 @@ public WhileNode(final Source source, final long token, final int finish) { super(source, token, finish); - test = null; - body = null; - breakLabel = new Label("while_break"); - continueLabel = new Label("while_continue"); + this.breakLabel = new Label("while_break"); + this.continueLabel = new Label("while_continue"); } /** @@ -68,10 +66,10 @@ protected WhileNode(final WhileNode whileNode, final CopyState cs) { super(whileNode); - test = cs.existingOrCopy(whileNode.test); - body = (Block)cs.existingOrCopy(whileNode.body); - breakLabel = new Label(whileNode.breakLabel); - continueLabel = new Label(whileNode.continueLabel); + this.test = cs.existingOrCopy(whileNode.test); + this.body = (Block)cs.existingOrCopy(whileNode.body); + this.breakLabel = new Label(whileNode.breakLabel); + this.continueLabel = new Label(whileNode.continueLabel); } @Override
--- a/src/jdk/nashorn/internal/ir/WithNode.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/WithNode.java Fri Feb 15 09:44:15 2013 +0100 @@ -57,8 +57,8 @@ private WithNode(final WithNode withNode, final CopyState cs) { super(withNode); - expression = cs.existingOrCopy(withNode.expression); - body = (Block)cs.existingOrCopy(withNode.body); + this.expression = cs.existingOrCopy(withNode.expression); + this.body = (Block)cs.existingOrCopy(withNode.body); } @Override
--- a/src/jdk/nashorn/internal/objects/NativeRegExp.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeRegExp.java Fri Feb 15 09:44:15 2013 +0100 @@ -203,8 +203,7 @@ } /** - * External constructor used in generated code created by {@link jdk.nashorn.internal.codegen.CodeGenerator}, which - * explain the {@code public} access. + * External constructor used in generated code, which explains the public access * * @param regexp regexp * @param flags flags
--- a/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java Fri Feb 15 09:44:15 2013 +0100 @@ -94,7 +94,6 @@ /** * Constructor called by (compiler) generated code for {@link ScriptObject}s. - * Code is generated by {@link jdk.nashorn.internal.codegen.CodeGenerator#newFunctionObject} * * @param data static function data * @param methodHandle handle for invocation
--- a/src/jdk/nashorn/internal/runtime/AccessorProperty.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/AccessorProperty.java Fri Feb 15 09:44:15 2013 +0100 @@ -25,24 +25,24 @@ package jdk.nashorn.internal.runtime; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.ACCESSOR_TYPES; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.DEBUG_FIELDS; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.LOG; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.OBJECT_FIELDS_ONLY; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.PRIMITIVE_TYPE; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.createGetter; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.createGuardBoxedPrimitiveSetter; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.createSetter; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.getAccessorType; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.getAccessorTypeIndex; -import static jdk.nashorn.internal.codegen.objects.ObjectClassGenerator.getNumberOfAccessorTypes; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.ACCESSOR_TYPES; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.LOG; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_TYPE; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGetter; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGuardBoxedPrimitiveSetter; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createSetter; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorType; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorTypeIndex; +import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getNumberOfAccessorTypes; import static jdk.nashorn.internal.runtime.linker.Lookup.MH; import static jdk.nashorn.internal.runtime.linker.MethodHandleFactory.stripName; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.linker.Lookup; import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
--- a/src/jdk/nashorn/internal/runtime/Context.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/Context.java Fri Feb 15 09:44:15 2013 +0100 @@ -51,8 +51,9 @@ import jdk.nashorn.internal.codegen.ClassEmitter; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.Namespace; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.debug.ASTWriter; import jdk.nashorn.internal.ir.debug.PrintVisitor; import jdk.nashorn.internal.parser.Parser; import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory; @@ -917,7 +918,11 @@ return null; } - if (_print_lower_parse) { + if (_print_ast) { + getErr().println(new ASTWriter(functionNode)); + } + + if (_print_parse) { getErr().println(new PrintVisitor(functionNode)); }
--- a/src/jdk/nashorn/internal/runtime/ECMAException.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/ECMAException.java Fri Feb 15 09:44:15 2013 +0100 @@ -46,7 +46,6 @@ public final class ECMAException extends NashornException { /** * Method handle pointing to the constructor {@link ECMAException#ECMAException(Object, String, int, int)}, - * used from {@link jdk.nashorn.internal.codegen.CodeGenerator} */ public static final Call THROW_INIT = constructorNoLookup(ECMAException.class, Object.class, String.class, int.class, int.class);
--- a/src/jdk/nashorn/internal/runtime/FindProperty.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/FindProperty.java Fri Feb 15 09:44:15 2013 +0100 @@ -28,7 +28,7 @@ import static jdk.nashorn.internal.runtime.linker.Lookup.MH; import java.lang.invoke.MethodHandle; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; /** * This class represents the result from a find property search.
--- a/src/jdk/nashorn/internal/runtime/Property.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/Property.java Fri Feb 15 09:44:15 2013 +0100 @@ -31,7 +31,7 @@ import java.lang.invoke.MethodHandle; import java.util.Objects; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.codegen.types.Type; /**
--- a/src/jdk/nashorn/internal/runtime/Scope.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/Scope.java Fri Feb 15 09:44:15 2013 +0100 @@ -27,7 +27,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup; -import jdk.nashorn.internal.codegen.CodeGenerator; import jdk.nashorn.internal.codegen.CompilerConstants; /** @@ -35,10 +34,10 @@ */ public interface Scope { - /** Method handle that points to {@link Scope#getSplitState}. Used by {@link CodeGenerator} */ + /** Method handle that points to {@link Scope#getSplitState}. */ public static final CompilerConstants.Call GET_SPLIT_STATE = interfaceCallNoLookup(Scope.class, "getSplitState", int.class); - /** Method handle that points to {@link Scope#setSplitState(int)}. Used by {@link CodeGenerator} */ + /** Method handle that points to {@link Scope#setSplitState(int)}. */ public static final CompilerConstants.Call SET_SPLIT_STATE = interfaceCallNoLookup(Scope.class, "setSplitState", void.class, int.class); /**
--- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Fri Feb 15 09:44:15 2013 +0100 @@ -60,7 +60,7 @@ import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.codegen.CompilerConstants.Call; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.objects.AccessorPropertyDescriptor; import jdk.nashorn.internal.objects.DataPropertyDescriptor; import jdk.nashorn.internal.runtime.arrays.ArrayData; @@ -144,13 +144,13 @@ /** Method handle for setting a function argument at a given index. Used from MapCreator */ public static final Call SET_ARGUMENT = virtualCall(ScriptObject.class, "setArgument", void.class, int.class, Object.class); - /** Method handle for getting the proto of a ScriptObject - used by {@link jdk.nashorn.internal.codegen.CodeGenerator} */ + /** Method handle for getting the proto of a ScriptObject */ public static final Call GET_PROTO = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class); - /** Method handle for setting the proto of a ScriptObject - used by {@link jdk.nashorn.internal.codegen.CodeGenerator} */ + /** Method handle for setting the proto of a ScriptObject */ public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class); - /** Method handle for setting the user accessors of a ScriptObject - used by {@link jdk.nashorn.internal.codegen.CodeGenerator} */ + /** Method handle for setting the user accessors of a ScriptObject */ public static final Call SET_USER_ACCESSORS = virtualCall(ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class); /** Method handle for getter for {@link UserAccessorProperty}, given a slot */
--- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Fri Feb 15 09:44:15 2013 +0100 @@ -71,27 +71,25 @@ /** Method handle to generic === operator, operating on objects */ public static final Call EQ_STRICT = staticCallNoLookup(ScriptRuntime.class, "EQ_STRICT", boolean.class, Object.class, Object.class); - /** Method handle used to enter a {@code with} scope at runtime. Used from {@link jdk.nashorn.internal.codegen.CodeGenerator} */ + /** Method handle used to enter a {@code with} scope at runtime. */ public static final Call OPEN_WITH = staticCallNoLookup(ScriptRuntime.class, "openWith", ScriptObject.class, ScriptObject.class, Object.class); - /** Method handle used to exit a {@code with} scope at runtime. Used from {@link jdk.nashorn.internal.codegen.CodeGenerator} */ + /** Method handle used to exit a {@code with} scope at runtime. */ public static final Call CLOSE_WITH = staticCallNoLookup(ScriptRuntime.class, "closeWith", ScriptObject.class, ScriptObject.class); /** * Method used to place a scope's variable into the Global scope, which has to be done for the - * properties declared at outermost script level. Used from {@link jdk.nashorn.internal.codegen.CodeGenerator} + * properties declared at outermost script level. */ public static final Call MERGE_SCOPE = staticCallNoLookup(ScriptRuntime.class, "mergeScope", ScriptObject.class, ScriptObject.class); /** * Return an appropriate iterator for the elements in a for-in construct - * Used from {@link jdk.nashorn.internal.codegen.CodeGenerator} */ public static final Call TO_PROPERTY_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toPropertyIterator", Iterator.class, Object.class); /** * Return an appropriate iterator for the elements in a for-each construct - * Used from {@link jdk.nashorn.internal.codegen.CodeGenerator} */ public static final Call TO_VALUE_ITERATOR = staticCallNoLookup(ScriptRuntime.class, "toValueIterator", Iterator.class, Object.class);
--- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Fri Feb 15 09:44:15 2013 +0100 @@ -31,7 +31,7 @@ import java.lang.invoke.MethodHandle; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.runtime.linker.Lookup; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.NashornGuards;
--- a/src/jdk/nashorn/internal/runtime/StructureLoader.java Fri Feb 15 09:18:05 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/StructureLoader.java Fri Feb 15 09:44:15 2013 +0100 @@ -38,7 +38,7 @@ import java.security.CodeSource; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator; +import jdk.nashorn.internal.codegen.ObjectClassGenerator; /** * Responsible for on the fly construction of structure classes as well