diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java index d2fed14df2961510b009179a9f536d69edd8deb8..e24ee97f2f958c8a02086b183c1d69c0322f41d5 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java @@ -52,10 +52,13 @@ import static jdk.nashorn.internal.ir.Symbol.KINDMASK; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Deque; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; + import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BinaryNode; @@ -139,6 +142,7 @@ final class Attr extends NodeOperatorVisitor { private final Set optimistic = new HashSet<>(); private final Set neverOptimistic = new HashSet<>(); + private final Map globalSymbols = new HashMap<>(); //reuse the same global symbol private int catchNestingLevel; @@ -454,7 +458,7 @@ final class Attr extends NodeOperatorVisitor { } // Create and add to appropriate block. - symbol = new Symbol(name, flags); + symbol = createSymbol(name, flags); symbolBlock.putSymbol(lc, symbol); if ((flags & Symbol.KINDMASK) != IS_GLOBAL) { @@ -467,6 +471,19 @@ final class Attr extends NodeOperatorVisitor { return symbol; } + private Symbol createSymbol(final String name, final int flags) { + if ((flags & Symbol.KINDMASK) == IS_GLOBAL) { + //reuse global symbols so they can be hashed + Symbol global = globalSymbols.get(name); + if (global == null) { + global = new Symbol(name, flags); + globalSymbols.put(name, global); + } + return global; + } + return new Symbol(name, flags); + } + @Override public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) { final Expression expr = expressionStatement.getExpression(); @@ -555,10 +572,16 @@ final class Attr extends NodeOperatorVisitor { } final int optimisticFlag = lc.hasOptimisticAssumptions() ? FunctionNode.IS_OPTIMISTIC : 0; + newFunctionNode = newFunctionNode.setState(lc, CompilationState.ATTR).setFlag(lc, optimisticFlag); popLocals(); + if (!env.isOnDemandCompilation() && newFunctionNode.isProgram()) { + newFunctionNode = newFunctionNode.setBody(lc, newFunctionNode.getBody().setFlag(lc, Block.IS_GLOBAL_SCOPE)); + assert newFunctionNode.getId() == 1; + } + return end(newFunctionNode, false); } @@ -576,7 +599,7 @@ final class Attr extends NodeOperatorVisitor { final IdentNode init = compilerConstant(initConstant); assert init.getSymbol() != null && init.getSymbol().hasSlot(); - VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init); + final VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init); final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName()); assert nameSymbol != null; @@ -631,7 +654,7 @@ final class Attr extends NodeOperatorVisitor { maybeForceScope(symbol); } else { LOG.info("No symbol exists. Declare undefined: ", symbol); - symbol = defineSymbol(block, name, IS_GLOBAL); + symbol = defineGlobalSymbol(block, name); // we have never seen this before, it can be undefined newType(symbol, Type.OBJECT); // TODO unknown -we have explicit casts anyway? symbol.setCanBeUndefined(); @@ -652,6 +675,10 @@ final class Attr extends NodeOperatorVisitor { return end(node); } + private Symbol defineGlobalSymbol(final Block block, final String name) { + return defineSymbol(block, name, IS_GLOBAL); + } + private boolean inCatch() { return catchNestingLevel > 0; } @@ -908,7 +935,7 @@ final class Attr extends NodeOperatorVisitor { } @Override - public boolean enterNOT(UnaryNode unaryNode) { + public boolean enterNOT(final UnaryNode unaryNode) { tagNeverOptimistic(unaryNode.getExpression()); return true; } @@ -1021,7 +1048,7 @@ final class Attr extends NodeOperatorVisitor { return end(coerce(unaryNode, Type.BOOLEAN)); } - private IdentNode compilerConstant(CompilerConstants cc) { + private IdentNode compilerConstant(final CompilerConstants cc) { return (IdentNode)createImplicitIdentifier(cc.symbolName()).setSymbol(lc, lc.getCurrentFunction().compilerConstant(cc)); } @@ -1040,7 +1067,7 @@ final class Attr extends NodeOperatorVisitor { public Node leaveTYPEOF(final UnaryNode unaryNode) { final Expression rhs = unaryNode.getExpression(); - List args = new ArrayList<>(); + final List args = new ArrayList<>(); if (rhs instanceof IdentNode && !rhs.getSymbol().isParam() && !rhs.getSymbol().isVar()) { args.add(compilerConstant(SCOPE)); args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null @@ -1099,7 +1126,7 @@ final class Attr extends NodeOperatorVisitor { //which will be corrected in the post pass if unknown at this stage Type argumentsType = Type.widest(lhs.getType(), rhs.getType()); - if(argumentsType.getTypeClass() == String.class) { + if (argumentsType.getTypeClass() == String.class) { assert binaryNode.isTokenType(TokenType.ADD); argumentsType = Type.OBJECT; } @@ -1151,7 +1178,7 @@ final class Attr extends NodeOperatorVisitor { final Symbol symbol = findSymbol(block, name); if (symbol == null) { - defineSymbol(block, name, IS_GLOBAL); + defineGlobalSymbol(block, name); } else { maybeForceScope(symbol); } @@ -1169,7 +1196,7 @@ final class Attr extends NodeOperatorVisitor { return end(ensureSymbol(binaryNode, type)); } - private boolean isLocal(FunctionNode function, Symbol symbol) { + private boolean isLocal(final FunctionNode function, final Symbol symbol) { final FunctionNode definingFn = lc.getDefiningFunction(symbol); // Temp symbols are not assigned to a block, so their defining fn is null; those can be assumed local return definingFn == null || definingFn == function; @@ -1372,7 +1399,7 @@ final class Attr extends NodeOperatorVisitor { final Type type = Type.narrowest(lhs.getType(), rhs.getType(), Type.INT); inferParameter(lhs, type); inferParameter(rhs, type); - Type widest = Type.widest(lhs.getType(), rhs.getType()); + final Type widest = Type.widest(lhs.getType(), rhs.getType()); ensureSymbol(lhs, widest); ensureSymbol(rhs, widest); return end(ensureSymbol(binaryNode, Type.BOOLEAN)); @@ -1390,7 +1417,7 @@ final class Attr extends NodeOperatorVisitor { } @Override - public boolean enterEQ(BinaryNode binaryNode) { + public boolean enterEQ(final BinaryNode binaryNode) { return enterBinaryArithmetic(binaryNode); } @@ -1549,7 +1576,7 @@ final class Attr extends NodeOperatorVisitor { } @Override - public boolean enterForNode(ForNode forNode) { + public boolean enterForNode(final ForNode forNode) { tagNeverOptimistic(forNode.getTest()); return true; } @@ -1570,7 +1597,7 @@ final class Attr extends NodeOperatorVisitor { } @Override - public boolean enterTernaryNode(TernaryNode ternaryNode) { + public boolean enterTernaryNode(final TernaryNode ternaryNode) { tagNeverOptimistic(ternaryNode.getTest()); return true; } @@ -1675,7 +1702,7 @@ final class Attr extends NodeOperatorVisitor { newParams.add((IdentNode)param.setSymbol(lc, paramSymbol)); assert paramSymbol != null; - Type type = paramSymbol.getSymbolType(); + final Type type = paramSymbol.getSymbolType(); // all param types are initialized to unknown // first we check if we do have a type (inferred during generation) @@ -1705,7 +1732,7 @@ final class Attr extends NodeOperatorVisitor { } } - FunctionNode newFunctionNode = functionNode; + final FunctionNode newFunctionNode = functionNode; return newFunctionNode.setParameters(lc, newParams); } @@ -1721,7 +1748,7 @@ final class Attr extends NodeOperatorVisitor { for (final Property property : map.getProperties()) { final String key = property.getKey(); - final Symbol symbol = defineSymbol(block, key, IS_GLOBAL); + final Symbol symbol = defineGlobalSymbol(block, key); newType(symbol, Type.OBJECT); LOG.info("Added global symbol from property map ", symbol); } @@ -1761,9 +1788,11 @@ final class Attr extends NodeOperatorVisitor { if (node instanceof LiteralNode) { return node; } - Type from = node.getType(); + final Type from = node.getType(); if (!Type.areEquivalent(from, to) && Type.widest(from, to) == to) { - LOG.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to); + if (LOG.isEnabled()) { + LOG.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to); + } Symbol symbol = node.getSymbol(); if (symbol.isShared() && symbol.wouldChangeType(to)) { symbol = temporarySymbols.getTypedTemporarySymbol(to); @@ -1875,7 +1904,7 @@ final class Attr extends NodeOperatorVisitor { } @Override - public Node leaveTernaryNode(TernaryNode ternaryNode) { + public Node leaveTernaryNode(final TernaryNode ternaryNode) { return widen(ternaryNode, Type.widest(ternaryNode.getTrueExpression().getType(), ternaryNode.getFalseExpression().getType())); } @@ -1938,19 +1967,19 @@ final class Attr extends NodeOperatorVisitor { } @Override - public boolean enterReturnNode(ReturnNode returnNode) { + public boolean enterReturnNode(final ReturnNode returnNode) { tagOptimistic(returnNode.getExpression()); return true; } @Override - public boolean enterIfNode(IfNode ifNode) { + public boolean enterIfNode(final IfNode ifNode) { tagNeverOptimistic(ifNode.getTest()); return true; } @Override - public boolean enterWhileNode(WhileNode whileNode) { + public boolean enterWhileNode(final WhileNode whileNode) { tagNeverOptimistic(whileNode.getTest()); return true; } @@ -1966,7 +1995,7 @@ final class Attr extends NodeOperatorVisitor { * @param expr an expression that is to be tagged as optimistic. */ private long tag(final Optimistic expr) { - return ((long)lc.getCurrentFunction().getId() << 32) | expr.getProgramPoint(); + return (long)lc.getCurrentFunction().getId() << 32 | expr.getProgramPoint(); } /** @@ -2000,7 +2029,7 @@ final class Attr extends NodeOperatorVisitor { return optimistic.contains(tag(expr)); } - private Type getOptimisticType(Optimistic expr) { + private Type getOptimisticType(final Optimistic expr) { return useOptimisticTypes() ? env.getOptimisticType(expr) : expr.getMostPessimisticType(); } @@ -2138,7 +2167,7 @@ final class Attr extends NodeOperatorVisitor { } private BinaryNode coerce(final BinaryNode binaryNode, final Type pessimisticType, final Type argumentsType) { - BinaryNode newNode = ensureSymbolTypeOverride(binaryNode, pessimisticType, argumentsType); + final BinaryNode newNode = ensureSymbolTypeOverride(binaryNode, pessimisticType, argumentsType); inferParameter(binaryNode.lhs(), newNode.getType()); inferParameter(binaryNode.rhs(), newNode.getType()); return newNode; @@ -2161,7 +2190,7 @@ final class Attr extends NodeOperatorVisitor { private static String name(final Node node) { final String cn = node.getClass().getName(); - int lastDot = cn.lastIndexOf('.'); + final int lastDot = cn.lastIndexOf('.'); if (lastDot == -1) { return cn; } diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java b/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java index 0b7dc1b292084fee8beb4ba24280b5ee2a087285..7e0c4536ebf5aa6ba22b51552a15f52da5baa4bb 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java @@ -277,51 +277,52 @@ public class ClassEmitter implements Emitter { } // $getXXXX$array - get the ith entry from the constants table and cast to XXXX[]. - for (final Class cls : constantMethodNeeded) { - if (cls.isArray()) { - defineGetArrayMethod(cls); + for (final Class clazz : constantMethodNeeded) { + if (clazz.isArray()) { + defineGetArrayMethod(clazz); } } } /** * Constructs a primitive specific method for getting the ith entry from the constants table and cast. - * @param cls Array class. + * @param clazz Array class. */ - private void defineGetArrayMethod(final Class cls) { + private void defineGetArrayMethod(final Class clazz) { assert unitClassName != null; - final String methodName = getArrayMethodName(cls); - final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, cls, int.class); + final String methodName = getArrayMethodName(clazz); + final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, clazz, int.class); getArrayMethod.begin(); getArrayMethod.getStatic(unitClassName, CONSTANTS.symbolName(), CONSTANTS.descriptor()) .load(Type.INT, 0) .arrayload() - .checkcast(cls) + .checkcast(clazz) .dup() .arraylength() - .invoke(staticCallNoLookup(Arrays.class, "copyOf", cls, cls, int.class)) + .invoke(staticCallNoLookup(Arrays.class, "copyOf", clazz, clazz, int.class)) ._return(); getArrayMethod.end(); } + /** * Generate the name of a get array from constant pool method. - * @param cls Name of array class. + * @param clazz Name of array class. * @return Method name. */ - static String getArrayMethodName(final Class cls) { - assert cls.isArray(); - return GET_ARRAY_PREFIX.symbolName() + cls.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName(); + static String getArrayMethodName(final Class clazz) { + assert clazz.isArray(); + return GET_ARRAY_PREFIX.symbolName() + clazz.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName(); } /** * Ensure a get constant method is issued for the class. - * @param cls Class of constant. + * @param clazz Class of constant. */ - void needGetConstantMethod(final Class cls) { - constantMethodNeeded.add(cls); + void needGetConstantMethod(final Class clazz) { + constantMethodNeeded.add(clazz); } /** @@ -672,7 +673,7 @@ public class ClassEmitter implements Emitter { } } - private MethodVisitor methodVisitor(EnumSet flags, final String methodName, final Class rtype, final Class... ptypes) { + private MethodVisitor methodVisitor(final EnumSet flags, final String methodName, final Class rtype, final Class... ptypes) { return cw.visitMethod(Flag.getValue(flags), methodName, methodDescriptor(rtype, ptypes), null, null); } diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java index 1e4493eeeb95c3b650dc0af2bb4776195b193804..0355d647be66e184048104f018aa481200ff3829 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -47,8 +47,6 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY; -import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getClassName; -import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount; import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL; import static jdk.nashorn.internal.ir.Symbol.IS_TEMP; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; @@ -76,6 +74,7 @@ import java.util.Map; import java.util.RandomAccess; import java.util.Set; import java.util.TreeMap; + import jdk.nashorn.internal.codegen.ClassEmitter.Flag; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.codegen.RuntimeCallSite.SpecializedRuntimeNode; @@ -224,11 +223,10 @@ final class CodeGenerator extends NodeOperatorVisitor ContinuationInfo. Used by compilation of rest-of function only. private final Map fnIdToContinuationInfo = new HashMap<>(); - // Function Id -> (Function Id -> Function Data)). Used by compilation of most-optimistic function only. - private final Map> fnIdToNestedFunctions = new HashMap<>(); - private final Deque