# HG changeset patch # User sundar # Date 1373640149 -19800 # Node ID 7907640d3be5997ae5c23cdc4af1a713a2fbef71 # Parent 4abe332f1270fcb2dde4d9895c317534b639b633# Parent bfb736c5aa43ebd47b166bf4cc95d32ca75f2e78 Merge diff -r 4abe332f1270 -r 7907640d3be5 nashorn/make/build.xml --- a/nashorn/make/build.xml Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/make/build.xml Fri Jul 12 20:12:29 2013 +0530 @@ -219,8 +219,10 @@ target="${javac.target}" debug="${javac.debug}" encoding="${javac.encoding}" - includeantruntime="false"> - + includeantruntime="false" fork="true"> + + + diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Fri Jul 12 20:12:29 2013 +0530 @@ -33,6 +33,7 @@ import java.io.InputStreamReader; import java.io.Reader; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.net.URL; import java.nio.charset.Charset; import java.security.AccessController; @@ -184,6 +185,19 @@ } private T getInterfaceInner(final Object self, final Class clazz) { + if (clazz == null || !clazz.isInterface()) { + throw new IllegalArgumentException("interface Class expected"); + } + + // perform security access check as early as possible + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + if (! Modifier.isPublic(clazz.getModifiers())) { + throw new SecurityException("attempt to implement non-public interfce: " + clazz); + } + Context.checkPackageAccess(clazz.getName()); + } + final ScriptObject realSelf; final ScriptObject ctxtGlobal = getNashornGlobalFrom(context); if(self == null) { @@ -193,6 +207,7 @@ } else { realSelf = (ScriptObject)self; } + try { final ScriptObject oldGlobal = getNashornGlobal(); try { diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/Attr.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java Fri Jul 12 20:12:29 2013 +0530 @@ -61,6 +61,7 @@ import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CaseNode; import jdk.nashorn.internal.ir.CatchNode; +import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; @@ -72,7 +73,6 @@ import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.ir.ObjectNode; -import jdk.nashorn.internal.ir.PropertyNode; import jdk.nashorn.internal.ir.ReturnNode; import jdk.nashorn.internal.ir.RuntimeNode; import jdk.nashorn.internal.ir.RuntimeNode.Request; @@ -94,7 +94,6 @@ import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.PropertyMap; -import jdk.nashorn.internal.runtime.ScriptObject; /** * This is the attribution pass of the code generator. Attr takes Lowered IR, @@ -166,19 +165,19 @@ } private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) { - initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL, FunctionNode.FUNCTION_TYPE); + initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL); initCompileConstant(THIS, body, IS_PARAM | IS_THIS, Type.OBJECT); if (functionNode.isVarArg()) { - initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL, Type.OBJECT_ARRAY); + initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL); if (functionNode.needsArguments()) { - initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.typeFor(ScriptObject.class)); + initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED); addLocalDef(ARGUMENTS.symbolName()); } } initParameters(functionNode, body); - initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.typeFor(ScriptObject.class)); + initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED); initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.OBJECT); } @@ -513,7 +512,6 @@ assert nameSymbol != null; selfInit = selfInit.setName((IdentNode)name.setSymbol(lc, nameSymbol)); - selfInit = (VarNode)selfInit.setSymbol(lc, nameSymbol); newStatements.add(selfInit); newStatements.addAll(body.getStatements()); @@ -741,14 +739,8 @@ } @Override - public Node leavePropertyNode(final PropertyNode propertyNode) { - // assign a pseudo symbol to property name, see NASHORN-710 - return propertyNode.setSymbol(lc, new Symbol(propertyNode.getKeyName(), 0, Type.OBJECT)); - } - - @Override public Node leaveReturnNode(final ReturnNode returnNode) { - final Node expr = returnNode.getExpression(); + final Expression expr = returnNode.getExpression(); final Type returnType; if (expr != null) { @@ -785,7 +777,7 @@ final LiteralNode lit = (LiteralNode)test; if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) { if (JSType.isRepresentableAsInt(lit.getNumber())) { - newCaseNode = caseNode.setTest(LiteralNode.newInstance(lit, lit.getInt32()).accept(this)); + newCaseNode = caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this)); } } } else { @@ -848,19 +840,18 @@ @Override public Node leaveVarNode(final VarNode varNode) { - VarNode newVarNode = varNode; + final Expression init = varNode.getInit(); + final IdentNode ident = varNode.getName(); + final String name = ident.getName(); - final Node init = newVarNode.getInit(); - final IdentNode ident = newVarNode.getName(); - final String name = ident.getName(); - - final Symbol symbol = findSymbol(lc.getCurrentBlock(), ident.getName()); + final Symbol symbol = findSymbol(lc.getCurrentBlock(), name); + assert ident.getSymbol() == symbol; if (init == null) { // var x; with no init will be treated like a use of x by // leaveIdentNode unless we remove the name from the localdef list. removeLocalDef(name); - return end(newVarNode.setSymbol(lc, symbol)); + return end(varNode); } addLocalDef(name); @@ -869,8 +860,7 @@ final IdentNode newIdent = (IdentNode)ident.setSymbol(lc, symbol); - newVarNode = newVarNode.setName(newIdent); - newVarNode = (VarNode)newVarNode.setSymbol(lc, symbol); + final VarNode newVarNode = varNode.setName(newIdent); final boolean isScript = lc.getDefiningFunction(symbol).isProgram(); //see NASHORN-56 if ((init.getType().isNumeric() || init.getType().isBoolean()) && !isScript) { @@ -880,7 +870,7 @@ newType(symbol, Type.OBJECT); } - assert newVarNode.hasType() : newVarNode + " has no type"; + assert newVarNode.getName().hasType() : newVarNode + " has no type"; return end(newVarNode); } @@ -908,11 +898,11 @@ public Node leaveDELETE(final UnaryNode unaryNode) { final FunctionNode currentFunctionNode = lc.getCurrentFunction(); final boolean strictMode = currentFunctionNode.isStrict(); - final Node rhs = unaryNode.rhs(); - final Node strictFlagNode = LiteralNode.newInstance(unaryNode, strictMode).accept(this); + final Expression rhs = unaryNode.rhs(); + final Expression strictFlagNode = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this); Request request = Request.DELETE; - final List args = new ArrayList<>(); + final List args = new ArrayList<>(); if (rhs instanceof IdentNode) { // If this is a declared variable or a function parameter, delete always fails (except for globals). @@ -923,7 +913,7 @@ if (failDelete && rhs.getSymbol().isThis()) { return LiteralNode.newInstance(unaryNode, true).accept(this); } - final Node literalNode = LiteralNode.newInstance(unaryNode, name).accept(this); + final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); if (!failDelete) { args.add(compilerConstant(SCOPE)); @@ -935,16 +925,17 @@ request = Request.FAIL_DELETE; } } else if (rhs instanceof AccessNode) { - final Node base = ((AccessNode)rhs).getBase(); - final IdentNode property = ((AccessNode)rhs).getProperty(); + final Expression base = ((AccessNode)rhs).getBase(); + final IdentNode property = ((AccessNode)rhs).getProperty(); args.add(base); - args.add(LiteralNode.newInstance(unaryNode, property.getName()).accept(this)); + args.add((Expression)LiteralNode.newInstance(unaryNode, property.getName()).accept(this)); args.add(strictFlagNode); } else if (rhs instanceof IndexNode) { - final Node base = ((IndexNode)rhs).getBase(); - final Node index = ((IndexNode)rhs).getIndex(); + final IndexNode indexNode = (IndexNode)rhs; + final Expression base = indexNode.getBase(); + final Expression index = indexNode.getIndex(); args.add(base); args.add(index); @@ -999,15 +990,15 @@ @Override public Node leaveTYPEOF(final UnaryNode unaryNode) { - final Node rhs = unaryNode.rhs(); + final Expression rhs = unaryNode.rhs(); - List args = new ArrayList<>(); + List args = new ArrayList<>(); if (rhs instanceof IdentNode && !rhs.getSymbol().isParam() && !rhs.getSymbol().isVar()) { args.add(compilerConstant(SCOPE)); - args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null + args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null } else { args.add(rhs); - args.add(LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' + args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' } RuntimeNode runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args); @@ -1041,8 +1032,8 @@ */ @Override public Node leaveADD(final BinaryNode binaryNode) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); ensureTypeNotUnknown(lhs); ensureTypeNotUnknown(rhs); @@ -1097,8 +1088,8 @@ private Node leaveAssignmentNode(final BinaryNode binaryNode) { BinaryNode newBinaryNode = binaryNode; - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); final Type type; if (rhs.getType().isNumeric()) { @@ -1134,8 +1125,8 @@ @Override public Node leaveASSIGN_ADD(final BinaryNode binaryNode) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); final Type widest = Type.widest(lhs.getType(), rhs.getType()); //Type.NUMBER if we can't prove that the add doesn't overflow. todo @@ -1414,19 +1405,26 @@ @Override public Node leaveTernaryNode(final TernaryNode ternaryNode) { - final Node lhs = ternaryNode.rhs(); - final Node rhs = ternaryNode.third(); + final Expression trueExpr = ternaryNode.getTrueExpression(); + final Expression falseExpr = ternaryNode.getFalseExpression(); + + ensureTypeNotUnknown(trueExpr); + ensureTypeNotUnknown(falseExpr); - ensureTypeNotUnknown(lhs); - ensureTypeNotUnknown(rhs); + final Type type = Type.widest(trueExpr.getType(), falseExpr.getType()); + return end(ensureSymbol(type, ternaryNode)); + } - final Type type = Type.widest(lhs.getType(), rhs.getType()); - return end(ensureSymbol(type, ternaryNode)); + private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) { + final Class type = cc.type(); + // Must not call this method for constants with no explicit types; use the one with (..., Type) signature instead. + assert type != null; + initCompileConstant(cc, block, flags, Type.typeFor(type)); } private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags, final Type type) { final Symbol symbol = defineSymbol(block, cc.symbolName(), flags); - newType(symbol, type); + symbol.setTypeOverride(type); symbol.setNeedsSlot(true); } @@ -1531,7 +1529,7 @@ } } - private static void ensureTypeNotUnknown(final Node node) { + private static void ensureTypeNotUnknown(final Expression node) { final Symbol symbol = node.getSymbol(); @@ -1588,13 +1586,13 @@ * * @param assignmentDest the destination node of the assignment, e.g. lhs for binary nodes */ - private Node ensureAssignmentSlots(final Node assignmentDest) { + private Expression ensureAssignmentSlots(final Expression assignmentDest) { final LexicalContext attrLexicalContext = lc; - return assignmentDest.accept(new NodeVisitor(new LexicalContext()) { + return (Expression)assignmentDest.accept(new NodeVisitor(new LexicalContext()) { @Override public Node leaveIndexNode(final IndexNode indexNode) { assert indexNode.getSymbol().isTemp(); - final Node index = indexNode.getIndex(); + final Expression index = indexNode.getIndex(); //only temps can be set as needing slots. the others will self resolve //it is illegal to take a scope var and force it to be a slot, that breaks Symbol indexSymbol = index.getSymbol(); @@ -1636,7 +1634,7 @@ changed.clear(); final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor(new LexicalContext()) { - private Node widen(final Node node, final Type to) { + private Expression widen(final Expression node, final Type to) { if (node instanceof LiteralNode) { return node; } @@ -1648,7 +1646,7 @@ symbol = temporarySymbols.getTypedTemporarySymbol(to); } newType(symbol, to); - final Node newNode = node.setSymbol(lc, symbol); + final Expression newNode = node.setSymbol(lc, symbol); changed.add(newNode); return newNode; } @@ -1703,7 +1701,7 @@ private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode, final Type destType) { //e.g. for -=, Number, no wider, destType (binaryNode.getWidestOperationType()) is the coerce type - final Node lhs = binaryNode.lhs(); + final Expression lhs = binaryNode.lhs(); newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType // ensureSymbol(destType, binaryNode); //for OP= nodes, the node can carry a narrower types than its lhs rhs. This is perfectly fine @@ -1711,9 +1709,9 @@ return end(ensureSymbol(destType, ensureAssignmentSlots(binaryNode))); } - private Node ensureSymbol(final Type type, final Node node) { + private Expression ensureSymbol(final Type type, final Expression expr) { LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type); - return temporarySymbols.ensureSymbol(lc, type, node); + return temporarySymbols.ensureSymbol(lc, type, expr); } private Symbol newInternal(final String name, final Type type) { @@ -1835,11 +1833,11 @@ return true; } - private Node end(final Node node) { + private T end(final T node) { return end(node, true); } - private Node end(final Node node, final boolean printNode) { + private T end(final T node, final boolean printNode) { if(node instanceof Statement) { // If we're done with a statement, all temporaries can be reused. temporarySymbols.reuse(); @@ -1854,10 +1852,13 @@ append(" in '"). append(lc.getCurrentFunction().getName()); - if (node.getSymbol() == null) { - sb.append(" "); - } else { - sb.append(" '); + if(node instanceof Expression) { + final Symbol symbol = ((Expression)node).getSymbol(); + if (symbol == null) { + sb.append(" "); + } else { + sb.append(" '); + } } LOG.unindent(); diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java --- a/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java Fri Jul 12 20:12:29 2013 +0530 @@ -34,7 +34,7 @@ import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.BinaryNode; -import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.TernaryNode; import jdk.nashorn.internal.ir.UnaryNode; @@ -52,16 +52,16 @@ this.method = method; } - void execute(final Node node, final Label label, final boolean state) { + void execute(final Expression node, final Label label, final boolean state) { branchOptimizer(node, label, state); } - private void load(final Node node) { + private void load(final Expression node) { codegen.load(node); } private void branchOptimizer(final UnaryNode unaryNode, final Label label, final boolean state) { - final Node rhs = unaryNode.rhs(); + final Expression rhs = unaryNode.rhs(); switch (unaryNode.tokenType()) { case NOT: @@ -88,8 +88,8 @@ } private void branchOptimizer(final BinaryNode binaryNode, final Label label, final boolean state) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); switch (binaryNode.tokenType()) { case AND: @@ -173,7 +173,7 @@ } } - private void branchOptimizer(final Node node, final Label label, final boolean state) { + private void branchOptimizer(final Expression node, final Label label, final boolean state) { if (!(node instanceof TernaryNode)) { if (node instanceof BinaryNode) { diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Jul 12 20:12:29 2013 +0530 @@ -55,10 +55,12 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.TreeMap; import jdk.nashorn.internal.codegen.ClassEmitter.Flag; import jdk.nashorn.internal.codegen.CompilerConstants.Call; @@ -69,6 +71,7 @@ import jdk.nashorn.internal.ir.BaseNode; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; +import jdk.nashorn.internal.ir.BlockStatement; import jdk.nashorn.internal.ir.BreakNode; import jdk.nashorn.internal.ir.BreakableNode; import jdk.nashorn.internal.ir.CallNode; @@ -76,7 +79,8 @@ import jdk.nashorn.internal.ir.CatchNode; import jdk.nashorn.internal.ir.ContinueNode; import jdk.nashorn.internal.ir.EmptyNode; -import jdk.nashorn.internal.ir.ExecuteNode; +import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.ExpressionStatement; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; @@ -182,6 +186,8 @@ /** From what size should we use spill instead of fields for JavaScript objects? */ private static final int OBJECT_SPILL_THRESHOLD = 300; + private final Set emittedMethods = new HashSet<>(); + /** * Constructor. * @@ -350,11 +356,11 @@ * * @return the method emitter used */ - MethodEmitter load(final Node node) { + MethodEmitter load(final Expression node) { return load(node, false); } - private MethodEmitter load(final Node node, final boolean baseAlreadyOnStack) { + private MethodEmitter load(final Expression node, final boolean baseAlreadyOnStack) { final Symbol symbol = node.getSymbol(); // If we lack symbols, we just generate what we see. @@ -488,6 +494,9 @@ @Override public boolean enterBlock(final Block block) { + if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) { + return false; + } method.label(block.getEntryLabel()); initLocals(block); @@ -539,11 +548,11 @@ return false; } - private int loadArgs(final List args) { + private int loadArgs(final List args) { return loadArgs(args, null, false, args.size()); } - private int loadArgs(final List args, final String signature, final boolean isVarArg, final int argCount) { + private int loadArgs(final List args, final String signature, final boolean isVarArg, final int argCount) { // arg have already been converted to objects here. if (isVarArg || argCount > LinkerCallSite.ARGLIMIT) { loadArgsArray(args); @@ -553,7 +562,7 @@ // pad with undefined if size is too short. argCount is the real number of args int n = 0; final Type[] params = signature == null ? null : Type.getMethodArguments(signature); - for (final Node arg : args) { + for (final Expression arg : args) { assert arg != null; load(arg); if (n >= argCount) { @@ -574,13 +583,13 @@ @Override public boolean enterCallNode(final CallNode callNode) { - lineNumber(callNode); - - final List args = callNode.getArgs(); - final Node function = callNode.getFunction(); - final Block currentBlock = lc.getCurrentBlock(); + lineNumber(callNode.getLineNumber()); + + final List args = callNode.getArgs(); + final Expression function = callNode.getFunction(); + final Block currentBlock = lc.getCurrentBlock(); final CodeGeneratorLexicalContext codegenLexicalContext = lc; - final Type callNodeType = callNode.getType(); + final Type callNodeType = callNode.getType(); function.accept(new NodeVisitor(new LexicalContext()) { @@ -771,11 +780,19 @@ } @Override - public boolean enterExecuteNode(final ExecuteNode executeNode) { - lineNumber(executeNode); - - final Node expression = executeNode.getExpression(); - expression.accept(this); + public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) { + lineNumber(expressionStatement); + + expressionStatement.getExpression().accept(this); + + return false; + } + + @Override + public boolean enterBlockStatement(final BlockStatement blockStatement) { + lineNumber(blockStatement); + + blockStatement.getBlock().accept(this); return false; } @@ -794,10 +811,10 @@ } private void enterFor(final ForNode forNode) { - final Node init = forNode.getInit(); - final Node test = forNode.getTest(); - final Block body = forNode.getBody(); - final Node modify = forNode.getModify(); + final Expression init = forNode.getInit(); + final Expression test = forNode.getTest(); + final Block body = forNode.getBody(); + final Expression modify = forNode.getModify(); if (init != null) { init.accept(this); @@ -827,19 +844,13 @@ private void enterForIn(final ForNode forNode) { final Block body = forNode.getBody(); - final Node modify = forNode.getModify(); + final Expression modify = forNode.getModify(); final Symbol iter = forNode.getIterator(); final Label loopLabel = new Label("loop"); - Node init = forNode.getInit(); - - // We have to evaluate the optional initializer expression - // of the iterator variable of the for-in statement. - if (init instanceof VarNode) { - init.accept(this); - init = ((VarNode)init).getName(); - } + final Expression init = forNode.getInit(); + assert init instanceof IdentNode; load(modify); assert modify.getType().isObject(); @@ -848,7 +859,7 @@ method._goto(forNode.getContinueLabel()); method.label(loopLabel); - new Store(init) { + new Store(init) { @Override protected void storeNonDiscard() { return; @@ -1003,17 +1014,28 @@ return false; } - LOG.info("=== BEGIN ", functionNode.getName()); - - assert functionNode.getCompileUnit() != null : "no compile unit for " + functionNode.getName() + " " + Debug.id(functionNode); - unit = lc.pushCompileUnit(functionNode.getCompileUnit()); - assert lc.hasCompileUnits(); - - method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode)); - // new method - reset last line number - lastLineNumber = -1; - // Mark end for variable tables. - method.begin(); + final String fnName = functionNode.getName(); + // NOTE: we only emit the method for a function with the given name once. We can have multiple functions with + // the same name as a result of inlining finally blocks. However, in the future -- with type specialization, + // notably -- we might need to check for both name *and* signature. Of course, even that might not be + // sufficient; the function might have a code dependency on the type of the variables in its enclosing scopes, + // and the type of such a variable can be different in catch and finally blocks. So, in the future we will have + // to decide to either generate a unique method for each inlined copy of the function, maybe figure out its + // exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't + // worth it, and generate one method with most generic type closure. + if(!emittedMethods.contains(fnName)) { + LOG.info("=== BEGIN ", fnName); + + assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode); + unit = lc.pushCompileUnit(functionNode.getCompileUnit()); + assert lc.hasCompileUnits(); + + method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode)); + // new method - reset last line number + lastLineNumber = -1; + // Mark end for variable tables. + method.begin(); + } return true; } @@ -1021,13 +1043,14 @@ @Override public Node leaveFunctionNode(final FunctionNode functionNode) { try { - method.end(); // wrap up this method - unit = lc.popCompileUnit(functionNode.getCompileUnit()); - method = lc.popMethodEmitter(method); - LOG.info("=== END ", functionNode.getName()); + if(emittedMethods.add(functionNode.getName())) { + method.end(); // wrap up this method + unit = lc.popCompileUnit(functionNode.getCompileUnit()); + method = lc.popMethodEmitter(method); + LOG.info("=== END ", functionNode.getName()); + } final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED); - newFunctionObject(newFunctionNode, functionNode); return newFunctionNode; } catch (final Throwable t) { @@ -1047,7 +1070,7 @@ public boolean enterIfNode(final IfNode ifNode) { lineNumber(ifNode); - final Node test = ifNode.getTest(); + final Expression test = ifNode.getTest(); final Block pass = ifNode.getPass(); final Block fail = ifNode.getFail(); @@ -1087,7 +1110,10 @@ } private void lineNumber(final Statement statement) { - final int lineNumber = statement.getLineNumber(); + lineNumber(statement.getLineNumber()); + } + + private void lineNumber(int lineNumber) { if (lineNumber != lastLineNumber) { method.lineNumber(lineNumber); } @@ -1106,7 +1132,7 @@ private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) { assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY; - final Node[] nodes = arrayLiteralNode.getValue(); + final Expression[] nodes = arrayLiteralNode.getValue(); final Object presets = arrayLiteralNode.getPresets(); final int[] postsets = arrayLiteralNode.getPostsets(); final Class type = arrayType.getTypeClass(); @@ -1166,11 +1192,11 @@ return method; } - private void storeElement(final Node[] nodes, final Type elementType, final int index) { + private void storeElement(final Expression[] nodes, final Type elementType, final int index) { method.dup(); method.load(index); - final Node element = nodes[index]; + final Expression element = nodes[index]; if (element == null) { method.loadEmpty(elementType); @@ -1182,7 +1208,7 @@ method.arraystore(); } - private MethodEmitter loadArgsArray(final List args) { + private MethodEmitter loadArgsArray(final List args) { final Object[] array = new Object[args.size()]; loadConstant(array); @@ -1313,7 +1339,7 @@ } @Override - public boolean enterLiteralNode(final LiteralNode literalNode) { + public boolean enterLiteralNode(final LiteralNode literalNode) { assert literalNode.getSymbol() != null : literalNode + " has no symbol"; load(literalNode).store(literalNode.getSymbol()); return false; @@ -1323,16 +1349,16 @@ public boolean enterObjectNode(final ObjectNode objectNode) { final List elements = objectNode.getElements(); - final List keys = new ArrayList<>(); - final List symbols = new ArrayList<>(); - final List values = new ArrayList<>(); + final List keys = new ArrayList<>(); + final List symbols = new ArrayList<>(); + final List values = new ArrayList<>(); boolean hasGettersSetters = false; for (PropertyNode propertyNode: elements) { - final Node value = propertyNode.getValue(); + final Expression value = propertyNode.getValue(); final String key = propertyNode.getKeyName(); - final Symbol symbol = value == null ? null : propertyNode.getSymbol(); + final Symbol symbol = value == null ? null : propertyNode.getKey().getSymbol(); if (value == null) { hasGettersSetters = true; @@ -1346,9 +1372,9 @@ if (elements.size() > OBJECT_SPILL_THRESHOLD) { new SpillObjectCreator(this, keys, symbols, values).makeObject(method); } else { - new FieldObjectCreator(this, keys, symbols, values) { + new FieldObjectCreator(this, keys, symbols, values) { @Override - protected void loadValue(final Node node) { + protected void loadValue(final Expression node) { load(node); } @@ -1419,7 +1445,7 @@ final Type returnType = lc.getCurrentFunction().getReturnType(); - final Node expression = returnNode.getExpression(); + final Expression expression = returnNode.getExpression(); if (expression != null) { load(expression); } else { @@ -1435,7 +1461,7 @@ return node instanceof LiteralNode && ((LiteralNode) node).isNull(); } - private boolean nullCheck(final RuntimeNode runtimeNode, final List args, final String signature) { + private boolean nullCheck(final RuntimeNode runtimeNode, final List args, final String signature) { final Request request = runtimeNode.getRequest(); if (!Request.isEQ(request) && !Request.isNE(request)) { @@ -1444,11 +1470,11 @@ assert args.size() == 2 : "EQ or NE or TYPEOF need two args"; - Node lhs = args.get(0); - Node rhs = args.get(1); + Expression lhs = args.get(0); + Expression rhs = args.get(1); if (isNullLiteral(lhs)) { - final Node tmp = lhs; + final Expression tmp = lhs; lhs = rhs; rhs = tmp; } @@ -1502,7 +1528,7 @@ return false; } - private boolean specializationCheck(final RuntimeNode.Request request, final Node node, final List args) { + private boolean specializationCheck(final RuntimeNode.Request request, final Expression node, final List args) { if (!request.canSpecialize()) { return false; } @@ -1555,10 +1581,11 @@ * * TODO - remove this - Access Specializer will always know after Attr/Lower */ + final List args = runtimeNode.getArgs(); if (runtimeNode.isPrimitive() && !runtimeNode.isFinal() && isReducible(runtimeNode.getRequest())) { - final Node lhs = runtimeNode.getArgs().get(0); - assert runtimeNode.getArgs().size() > 1 : runtimeNode + " must have two args"; - final Node rhs = runtimeNode.getArgs().get(1); + final Expression lhs = args.get(0); + assert args.size() > 1 : runtimeNode + " must have two args"; + final Expression rhs = args.get(1); final Type type = runtimeNode.getType(); final Symbol symbol = runtimeNode.getSymbol(); @@ -1595,9 +1622,6 @@ } } - // Get the request arguments. - final List args = runtimeNode.getArgs(); - if (nullCheck(runtimeNode, args, new FunctionSignature(false, false, runtimeNode.getType(), args).toString())) { return false; } @@ -1606,7 +1630,7 @@ return false; } - for (final Node arg : runtimeNode.getArgs()) { + for (final Expression arg : args) { load(arg).convert(Type.OBJECT); //TODO this should not be necessary below Lower } @@ -1617,7 +1641,7 @@ false, false, runtimeNode.getType(), - runtimeNode.getArgs().size()).toString()); + args.size()).toString()); method.convert(runtimeNode.getType()); method.store(runtimeNode.getSymbol()); @@ -1626,8 +1650,6 @@ @Override public boolean enterSplitNode(final SplitNode splitNode) { - lineNumber(splitNode); - final CompileUnit splitCompileUnit = splitNode.getCompileUnit(); final FunctionNode fn = lc.getCurrentFunction(); @@ -1772,7 +1794,7 @@ public boolean enterSwitchNode(final SwitchNode switchNode) { lineNumber(switchNode); - final Node expression = switchNode.getExpression(); + final Expression expression = switchNode.getExpression(); final Symbol tag = switchNode.getTag(); final boolean allInteger = tag.getSymbolType().isInteger(); final List cases = switchNode.getCases(); @@ -1869,11 +1891,13 @@ method.store(tag); method.conditionalJump(Condition.NE, true, defaultLabel); } else { + assert tag.getSymbolType().isObject(); + method.convert(Type.OBJECT); //e.g. 1 literal pushed and tag is object method.store(tag); } for (final CaseNode caseNode : cases) { - final Node test = caseNode.getTest(); + final Expression test = caseNode.getTest(); if (test != null) { method.load(tag); @@ -1913,10 +1937,10 @@ final Source source = lc.getCurrentFunction().getSource(); - final Node expression = throwNode.getExpression(); - final int position = throwNode.position(); - final int line = source.getLine(position); - final int column = source.getColumn(position); + final Expression expression = throwNode.getExpression(); + final int position = throwNode.position(); + final int line = source.getLine(position); + final int column = source.getColumn(position); load(expression); assert expression.getType().isObject(); @@ -1965,10 +1989,10 @@ lc.push(catchBlock); enterBlock(catchBlock); - final CatchNode catchNode = (CatchNode)catchBlocks.get(i).getStatements().get(0); - final IdentNode exception = catchNode.getException(); - final Node exceptionCondition = catchNode.getExceptionCondition(); - final Block catchBody = catchNode.getBody(); + final CatchNode catchNode = (CatchNode)catchBlocks.get(i).getStatements().get(0); + final IdentNode exception = catchNode.getException(); + final Expression exceptionCondition = catchNode.getExceptionCondition(); + final Block catchBody = catchNode.getBody(); new Store(exception) { @Override @@ -2036,7 +2060,7 @@ @Override public boolean enterVarNode(final VarNode varNode) { - final Node init = varNode.getInit(); + final Expression init = varNode.getInit(); if (init == null) { return false; @@ -2044,8 +2068,8 @@ lineNumber(varNode); - final Symbol varSymbol = varNode.getSymbol(); - assert varSymbol != null : "variable node " + varNode + " requires a symbol"; + final Symbol varSymbol = varNode.getName().getSymbol(); + assert varSymbol != null : "variable node " + varNode + " requires a name with a symbol"; assert method != null; @@ -2065,9 +2089,7 @@ method.dynamicSet(type, identNode.getName(), flags); } } else { - assert varNode.getType() == varNode.getName().getType() : "varNode type=" + varNode.getType() + " nametype=" + varNode.getName().getType() + " inittype=" + init.getType(); - - method.convert(varNode.getType()); // aw: convert moved here + method.convert(varNode.getName().getType()); // aw: convert moved here method.store(varSymbol); } @@ -2078,11 +2100,11 @@ public boolean enterWhileNode(final WhileNode whileNode) { lineNumber(whileNode); - final Node test = whileNode.getTest(); - final Block body = whileNode.getBody(); - final Label breakLabel = whileNode.getBreakLabel(); - final Label continueLabel = whileNode.getContinueLabel(); - final Label loopLabel = new Label("loop"); + final Expression test = whileNode.getTest(); + final Block body = whileNode.getBody(); + final Label breakLabel = whileNode.getBreakLabel(); + final Label continueLabel = whileNode.getContinueLabel(); + final Label loopLabel = new Label("loop"); if (!whileNode.isDoWhile()) { method._goto(continueLabel); @@ -2109,8 +2131,8 @@ @Override public boolean enterWithNode(final WithNode withNode) { - final Node expression = withNode.getExpression(); - final Node body = withNode.getBody(); + final Expression expression = withNode.getExpression(); + final Node body = withNode.getBody(); // It is possible to have a "pathological" case where the with block does not reference *any* identifiers. It's // pointless, but legal. In that case, if nothing else in the method forced the assignment of a slot to the @@ -2185,7 +2207,7 @@ // do this better with convert calls to method. TODO @Override public boolean enterCONVERT(final UnaryNode unaryNode) { - final Node rhs = unaryNode.rhs(); + final Expression rhs = unaryNode.rhs(); final Type to = unaryNode.getType(); if (to.isObject() && rhs instanceof LiteralNode) { @@ -2222,11 +2244,11 @@ @Override public boolean enterDECINC(final UnaryNode unaryNode) { - final Node rhs = unaryNode.rhs(); - final Type type = unaryNode.getType(); - final TokenType tokenType = unaryNode.tokenType(); - final boolean isPostfix = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX; - final boolean isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX; + final Expression rhs = unaryNode.rhs(); + final Type type = unaryNode.getType(); + final TokenType tokenType = unaryNode.tokenType(); + final boolean isPostfix = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX; + final boolean isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX; assert !type.isObject(); @@ -2270,7 +2292,7 @@ @Override public boolean enterDISCARD(final UnaryNode unaryNode) { - final Node rhs = unaryNode.rhs(); + final Expression rhs = unaryNode.rhs(); lc.pushDiscard(rhs); load(rhs); @@ -2287,7 +2309,7 @@ @Override public boolean enterNEW(final UnaryNode unaryNode) { final CallNode callNode = (CallNode)unaryNode.rhs(); - final List args = callNode.getArgs(); + final List args = callNode.getArgs(); // Load function reference. load(callNode.getFunction()).convert(Type.OBJECT); // must detect type error @@ -2300,7 +2322,7 @@ @Override public boolean enterNOT(final UnaryNode unaryNode) { - final Node rhs = unaryNode.rhs(); + final Expression rhs = unaryNode.rhs(); load(rhs); @@ -2334,19 +2356,18 @@ return false; } - private Node enterNumericAdd(final Node lhs, final Node rhs, final Type type, final Symbol symbol) { + private void enterNumericAdd(final Expression lhs, final Expression rhs, final Type type, final Symbol symbol) { assert lhs.getType().equals(rhs.getType()) && lhs.getType().equals(type) : lhs.getType() + " != " + rhs.getType() + " != " + type + " " + new ASTWriter(lhs) + " " + new ASTWriter(rhs); load(lhs); load(rhs); method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack? method.store(symbol); - return null; } @Override public boolean enterADD(final BinaryNode binaryNode) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); final Type type = binaryNode.getType(); if (type.isNumeric()) { @@ -2362,8 +2383,8 @@ } private boolean enterAND_OR(final BinaryNode binaryNode) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); final Label skip = new Label("skip"); @@ -2390,8 +2411,8 @@ @Override public boolean enterASSIGN(final BinaryNode binaryNode) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); final Type lhsType = lhs.getType(); final Type rhsType = rhs.getType(); @@ -2659,8 +2680,8 @@ } private boolean enterComma(final BinaryNode binaryNode) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); load(lhs); load(rhs); @@ -2691,7 +2712,7 @@ return false; } - private boolean enterCmp(final Node lhs, final Node rhs, final Condition cond, final Type type, final Symbol symbol) { + private boolean enterCmp(final Expression lhs, final Expression rhs, final Condition cond, final Type type, final Symbol symbol) { final Type lhsType = lhs.getType(); final Type rhsType = rhs.getType(); @@ -2844,21 +2865,21 @@ @Override public boolean enterTernaryNode(final TernaryNode ternaryNode) { - final Node lhs = ternaryNode.lhs(); - final Node rhs = ternaryNode.rhs(); - final Node third = ternaryNode.third(); + final Expression test = ternaryNode.getTest(); + final Expression trueExpr = ternaryNode.getTrueExpression(); + final Expression falseExpr = ternaryNode.getFalseExpression(); final Symbol symbol = ternaryNode.getSymbol(); final Label falseLabel = new Label("ternary_false"); final Label exitLabel = new Label("ternary_exit"); - Type widest = Type.widest(rhs.getType(), third.getType()); - if (rhs.getType().isArray() || third.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type + Type widest = Type.widest(trueExpr.getType(), falseExpr.getType()); + if (trueExpr.getType().isArray() || falseExpr.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type widest = Type.OBJECT; } - load(lhs); - assert lhs.getType().isBoolean() : "lhs in ternary must be boolean"; + load(test); + assert test.getType().isBoolean() : "lhs in ternary must be boolean"; // we still keep the conversion here as the AccessSpecializer can have separated the types, e.g. var y = x ? x=55 : 17 // will left as (Object)x=55 : (Object)17 by Lower. Then the first term can be {I}x=55 of type int, which breaks the @@ -2866,11 +2887,11 @@ // to early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to // do this property. Then we never need any conversions in CodeGenerator method.ifeq(falseLabel); - load(rhs); + load(trueExpr); method.convert(widest); method._goto(exitLabel); method.label(falseLabel); - load(third); + load(falseExpr); method.convert(widest); method.label(exitLabel); method.store(symbol); @@ -2923,8 +2944,8 @@ * * @param */ - private abstract class SelfModifyingStore extends Store { - protected SelfModifyingStore(final T assignNode, final Node target) { + private abstract class SelfModifyingStore extends Store { + protected SelfModifyingStore(final T assignNode, final Expression target) { super(assignNode, target); } @@ -2937,13 +2958,13 @@ /** * Helper class to generate stores */ - private abstract class Store { + private abstract class Store { /** An assignment node, e.g. x += y */ protected final T assignNode; /** The target node to store to, e.g. x */ - private final Node target; + private final Expression target; /** How deep on the stack do the arguments go if this generates an indy call */ private int depth; @@ -2957,7 +2978,7 @@ * @param assignNode the node representing the whole assignment * @param target the target node of the assignment (destination) */ - protected Store(final T assignNode, final Node target) { + protected Store(final T assignNode, final Expression target) { this.assignNode = assignNode; this.target = target; } @@ -3000,8 +3021,8 @@ private void enterBaseNode() { assert target instanceof BaseNode : "error - base node " + target + " must be instanceof BaseNode"; - final BaseNode baseNode = (BaseNode)target; - final Node base = baseNode.getBase(); + final BaseNode baseNode = (BaseNode)target; + final Expression base = baseNode.getBase(); load(base); method.convert(Type.OBJECT); @@ -3022,7 +3043,7 @@ public boolean enterIndexNode(final IndexNode node) { enterBaseNode(); - final Node index = node.getIndex(); + final Expression index = node.getIndex(); // could be boolean here as well load(index); if (!index.getType().isNumeric()) { diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java --- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java Fri Jul 12 20:12:29 2013 +0530 @@ -21,6 +21,7 @@ import jdk.nashorn.internal.codegen.types.Range; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.CallNode; +import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.LexicalContext; @@ -256,17 +257,20 @@ @Override public Node leaveDefault(final Node node) { - final Symbol symbol = node.getSymbol(); - if (symbol != null) { - final Range range = symbol.getRange(); - final Type symbolType = symbol.getSymbolType(); - if (!symbolType.isNumeric()) { - return node; - } - final Type rangeType = range.getType(); - if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range - RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange()); - return node.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols())); + if(node instanceof Expression) { + final Expression expr = (Expression)node; + final Symbol symbol = expr.getSymbol(); + if (symbol != null) { + final Range range = symbol.getRange(); + final Type symbolType = symbol.getSymbolType(); + if (!symbolType.isNumeric()) { + return expr; + } + final Type rangeType = range.getType(); + if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range + RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange()); + return expr.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols())); + } } } return node; diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/Compiler.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java Fri Jul 12 20:12:29 2013 +0530 @@ -528,8 +528,8 @@ return this.env; } - private static String safeSourceName(final Source source) { - String baseName = new File(source.getName()).getName(); + private String safeSourceName(final Source src) { + String baseName = new File(src.getName()).getName(); final int index = baseName.lastIndexOf(".js"); if (index != -1) { @@ -537,6 +537,9 @@ } baseName = baseName.replace('.', '_').replace('-', '_'); + if (! env._loader_per_compile) { + baseName = baseName + installer.getUniqueScriptId(); + } final String mangled = NameCodec.encode(baseName); return mangled != null ? mangled : baseName; diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java --- a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java Fri Jul 12 20:12:29 2013 +0530 @@ -100,10 +100,10 @@ CALLEE(":callee", ScriptFunction.class), /** the varargs variable when necessary */ - VARARGS(":varargs"), + VARARGS(":varargs", Object[].class), /** the arguments vector when necessary and the slot */ - ARGUMENTS("arguments", Object.class, 2), + ARGUMENTS("arguments", ScriptObject.class, 2), /** prefix for iterators for for (x in ...) */ ITERATOR_PREFIX(":i", Iterator.class), diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java --- a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java Fri Jul 12 20:12:29 2013 +0530 @@ -39,7 +39,8 @@ import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CaseNode; import jdk.nashorn.internal.ir.CatchNode; -import jdk.nashorn.internal.ir.ExecuteNode; +import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.ExpressionStatement; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; @@ -146,9 +147,9 @@ * strings etc as well. */ @Override - public Node leaveADD(final BinaryNode binaryNode) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + public Expression leaveADD(final BinaryNode binaryNode) { + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); final Type type = binaryNode.getType(); @@ -240,7 +241,7 @@ return leaveASSIGN(binaryNode); } - private boolean symbolIsInteger(Node node) { + private boolean symbolIsInteger(final Expression node) { final Symbol symbol = node.getSymbol(); assert symbol != null && symbol.getSymbolType().isInteger() : "int coercion expected: " + Debug.id(symbol) + " " + symbol + " " + lc.getCurrentFunction().getSource(); return true; @@ -372,7 +373,7 @@ @Override public Node leaveCatchNode(final CatchNode catchNode) { - final Node exceptionCondition = catchNode.getExceptionCondition(); + final Expression exceptionCondition = catchNode.getExceptionCondition(); if (exceptionCondition != null) { return catchNode.setExceptionCondition(convert(exceptionCondition, Type.BOOLEAN)); } @@ -380,16 +381,16 @@ } @Override - public Node leaveExecuteNode(final ExecuteNode executeNode) { + public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) { temporarySymbols.reuse(); - return executeNode.setExpression(discard(executeNode.getExpression())); + return expressionStatement.setExpression(discard(expressionStatement.getExpression())); } @Override public Node leaveForNode(final ForNode forNode) { - final Node init = forNode.getInit(); - final Node test = forNode.getTest(); - final Node modify = forNode.getModify(); + final Expression init = forNode.getInit(); + final Expression test = forNode.getTest(); + final Expression modify = forNode.getModify(); if (forNode.isForIn()) { return forNode.setModify(lc, convert(forNode.getModify(), Type.OBJECT)); // NASHORN-400 @@ -439,13 +440,13 @@ public boolean enterLiteralNode(final LiteralNode literalNode) { if (literalNode instanceof ArrayLiteralNode) { final ArrayLiteralNode arrayLiteralNode = (ArrayLiteralNode)literalNode; - final Node[] array = arrayLiteralNode.getValue(); + final Expression[] array = arrayLiteralNode.getValue(); final Type elementType = arrayLiteralNode.getElementType(); for (int i = 0; i < array.length; i++) { final Node element = array[i]; if (element != null) { - array[i] = convert(element.accept(this), elementType); + array[i] = convert((Expression)element.accept(this), elementType); } } } @@ -455,7 +456,7 @@ @Override public Node leaveReturnNode(final ReturnNode returnNode) { - final Node expr = returnNode.getExpression(); + final Expression expr = returnNode.getExpression(); if (expr != null) { return returnNode.setExpression(convert(expr, lc.getCurrentFunction().getReturnType())); } @@ -464,8 +465,8 @@ @Override public Node leaveRuntimeNode(final RuntimeNode runtimeNode) { - final List args = runtimeNode.getArgs(); - for (final Node arg : args) { + final List args = runtimeNode.getArgs(); + for (final Expression arg : args) { assert !arg.getType().isUnknown(); } return runtimeNode; @@ -479,12 +480,12 @@ return switchNode; } - final Node expression = switchNode.getExpression(); + final Expression expression = switchNode.getExpression(); final List cases = switchNode.getCases(); final List newCases = new ArrayList<>(); for (final CaseNode caseNode : cases) { - final Node test = caseNode.getTest(); + final Expression test = caseNode.getTest(); newCases.add(test != null ? caseNode.setTest(convert(test, Type.OBJECT)) : caseNode); } @@ -495,7 +496,7 @@ @Override public Node leaveTernaryNode(final TernaryNode ternaryNode) { - return ternaryNode.setLHS(convert(ternaryNode.lhs(), Type.BOOLEAN)); + return ternaryNode.setTest(convert(ternaryNode.getTest(), Type.BOOLEAN)); } @Override @@ -505,16 +506,16 @@ @Override public Node leaveVarNode(final VarNode varNode) { - final Node init = varNode.getInit(); + final Expression init = varNode.getInit(); if (init != null) { final SpecializedNode specialized = specialize(varNode); final VarNode specVarNode = (VarNode)specialized.node; Type destType = specialized.type; if (destType == null) { - destType = specVarNode.getType(); + destType = specVarNode.getName().getType(); } - assert specVarNode.hasType() : specVarNode + " doesn't have a type"; - final Node convertedInit = convert(init, destType); + assert specVarNode.getName().hasType() : specVarNode + " doesn't have a type"; + final Expression convertedInit = convert(init, destType); temporarySymbols.reuse(); return specVarNode.setInit(convertedInit); } @@ -524,7 +525,7 @@ @Override public Node leaveWhileNode(final WhileNode whileNode) { - final Node test = whileNode.getTest(); + final Expression test = whileNode.getTest(); if (test != null) { return whileNode.setTest(lc, convert(test, Type.BOOLEAN)); } @@ -599,8 +600,8 @@ */ @SuppressWarnings("fallthrough") private Node leaveCmp(final BinaryNode binaryNode, final RuntimeNode.Request request) { - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); Type widest = Type.widest(lhs.getType(), rhs.getType()); @@ -696,10 +697,10 @@ } } - SpecializedNode specialize(final Assignment assignment) { + SpecializedNode specialize(final Assignment assignment) { final Node node = ((Node)assignment); final T lhs = assignment.getAssignmentDest(); - final Node rhs = assignment.getAssignmentSource(); + final Expression rhs = assignment.getAssignmentSource(); if (!canHaveCallSiteType(lhs)) { return new SpecializedNode(node, null); @@ -718,8 +719,16 @@ } final Node newNode = assignment.setAssignmentDest(setTypeOverride(lhs, to)); - final Node typePropagatedNode = propagateType(newNode, to); - + final Node typePropagatedNode; + if(newNode instanceof Expression) { + typePropagatedNode = propagateType((Expression)newNode, to); + } else if(newNode instanceof VarNode) { + // VarNode, being a statement, doesn't have its own symbol; it uses the symbol of its name instead. + final VarNode varNode = (VarNode)newNode; + typePropagatedNode = varNode.setName((IdentNode)propagateType(varNode.getName(), to)); + } else { + throw new AssertionError(); + } return new SpecializedNode(typePropagatedNode, to); } @@ -759,7 +768,7 @@ * @param to new type */ @SuppressWarnings("unchecked") - T setTypeOverride(final T node, final Type to) { + T setTypeOverride(final T node, final Type to) { final Type from = node.getType(); if (!node.getType().equals(to)) { LOG.info("Changing call override type for '", node, "' from ", node.getType(), " to ", to); @@ -788,7 +797,7 @@ * @param to destination type * @return conversion node */ - private Node convert(final Node node, final Type to) { + private Expression convert(final Expression node, final Type to) { assert !to.isUnknown() : "unknown type for " + node + " class=" + node.getClass(); assert node != null : "node is null"; assert node.getSymbol() != null : "node " + node + " " + node.getClass() + " has no symbol! " + lc.getCurrentFunction(); @@ -804,7 +813,7 @@ return node; } - Node resultNode = node; + Expression resultNode = node; if (node instanceof LiteralNode && !(node instanceof ArrayLiteralNode) && !to.isObject()) { final LiteralNode newNode = new LiteralNodeConstantEvaluator((LiteralNode)node, to).eval(); @@ -828,9 +837,9 @@ return temporarySymbols.ensureSymbol(lc, to, resultNode); } - private static Node discard(final Node node) { + private static Expression discard(final Expression node) { if (node.getSymbol() != null) { - final Node discard = new UnaryNode(Token.recast(node.getToken(), TokenType.DISCARD), node); + final UnaryNode discard = new UnaryNode(Token.recast(node.getToken(), TokenType.DISCARD), node); //discard never has a symbol in the discard node - then it would be a nop assert !node.isTerminal(); return discard; @@ -853,7 +862,7 @@ * @param node * @param to */ - private Node propagateType(final Node node, final Type to) { + private Expression propagateType(final Expression node, final Type to) { Symbol symbol = node.getSymbol(); if (symbol.isTemp() && symbol.getSymbolType() != to) { symbol = symbol.setTypeOverrideShared(to, temporarySymbols); diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java --- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java Fri Jul 12 20:12:29 2013 +0530 @@ -28,8 +28,8 @@ import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; +import jdk.nashorn.internal.ir.BlockStatement; import jdk.nashorn.internal.ir.EmptyNode; -import jdk.nashorn.internal.ir.ExecuteNode; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.IfNode; @@ -91,7 +91,7 @@ if (test instanceof LiteralNode) { final Block shortCut = ((LiteralNode)test).isTrue() ? ifNode.getPass() : ifNode.getFail(); if (shortCut != null) { - return new ExecuteNode(shortCut.getLineNumber(), shortCut.getToken(), shortCut.getFinish(), shortCut); + return new BlockStatement(ifNode.getLineNumber(), shortCut); } return new EmptyNode(ifNode); } @@ -100,9 +100,9 @@ @Override public Node leaveTernaryNode(final TernaryNode ternaryNode) { - final Node test = ternaryNode.lhs(); + final Node test = ternaryNode.getTest(); if (test instanceof LiteralNode) { - return ((LiteralNode)test).isTrue() ? ternaryNode.rhs() : ternaryNode.third(); + return ((LiteralNode)test).isTrue() ? ternaryNode.getTrueExpression() : ternaryNode.getFalseExpression(); } return ternaryNode; } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java --- a/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java Fri Jul 12 20:12:29 2013 +0530 @@ -31,8 +31,8 @@ import java.util.ArrayList; import java.util.List; import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.FunctionNode; -import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.linker.LinkerCallSite; @@ -63,7 +63,7 @@ * @param retType what is the return type * @param args argument list of AST Nodes */ - public FunctionSignature(final boolean hasSelf, final boolean hasCallee, final Type retType, final List args) { + public FunctionSignature(final boolean hasSelf, final boolean hasCallee, final Type retType, final List args) { this(hasSelf, hasCallee, retType, FunctionSignature.typeArray(args)); } @@ -167,7 +167,7 @@ * * @return the array of types */ - private static Type[] typeArray(final List args) { + private static Type[] typeArray(final List args) { if (args == null) { return null; } @@ -175,7 +175,7 @@ final Type[] typeArray = new Type[args.size()]; int pos = 0; - for (final Node arg : args) { + for (final Expression arg : args) { typeArray[pos++] = arg.getType(); } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/Lower.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java Fri Jul 12 20:12:29 2013 +0530 @@ -37,12 +37,14 @@ import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; import jdk.nashorn.internal.ir.BlockLexicalContext; +import jdk.nashorn.internal.ir.BlockStatement; import jdk.nashorn.internal.ir.BreakNode; import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CatchNode; import jdk.nashorn.internal.ir.ContinueNode; import jdk.nashorn.internal.ir.EmptyNode; -import jdk.nashorn.internal.ir.ExecuteNode; +import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.ExpressionStatement; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; @@ -138,7 +140,7 @@ public boolean enterBlock(final Block block) { final FunctionNode function = lc.getCurrentFunction(); if (lc.isFunctionBody() && function.isProgram() && !function.hasDeclaredFunctions()) { - new ExecuteNode(block.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this); + new ExpressionStatement(function.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this); } return true; } @@ -154,7 +156,7 @@ final boolean isProgram = currentFunction.isProgram(); final Statement last = lc.getLastStatement(); final ReturnNode returnNode = new ReturnNode( - last == null ? block.getLineNumber() : last.getLineNumber(), //TODO? + last == null ? currentFunction.getLineNumber() : last.getLineNumber(), //TODO? currentFunction.getToken(), currentFunction.getFinish(), isProgram ? @@ -195,23 +197,21 @@ } @Override - public Node leaveExecuteNode(final ExecuteNode executeNode) { - final Node expr = executeNode.getExpression(); - ExecuteNode node = executeNode; + public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) { + final Expression expr = expressionStatement.getExpression(); + ExpressionStatement node = expressionStatement; final FunctionNode currentFunction = lc.getCurrentFunction(); if (currentFunction.isProgram()) { - if (!(expr instanceof Block) || expr instanceof FunctionNode) { // it's not a block, but can be a function - if (!isInternalExpression(expr) && !isEvalResultAssignment(expr)) { - node = executeNode.setExpression( - new BinaryNode( - Token.recast( - executeNode.getToken(), - TokenType.ASSIGN), - compilerConstant(RETURN), - expr)); - } + if (!isInternalExpression(expr) && !isEvalResultAssignment(expr)) { + node = expressionStatement.setExpression( + new BinaryNode( + Token.recast( + expressionStatement.getToken(), + TokenType.ASSIGN), + compilerConstant(RETURN), + expr)); } } @@ -219,6 +219,11 @@ } @Override + public Node leaveBlockStatement(BlockStatement blockStatement) { + return addStatement(blockStatement); + } + + @Override public Node leaveForNode(final ForNode forNode) { ForNode newForNode = forNode; @@ -302,11 +307,11 @@ final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName("catch_all")); - final Block catchBody = new Block(lineNumber, token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW)). + final Block catchBody = new Block(token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW)). setIsTerminal(lc, true); //ends with throw, so terminal final CatchNode catchAllNode = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, CatchNode.IS_SYNTHETIC_RETHROW); - final Block catchAllBlock = new Block(lineNumber, token, finish, catchAllNode); + final Block catchAllBlock = new Block(token, finish, catchAllNode); //catchallblock -> catchallnode (catchnode) -> exception -> throw @@ -355,14 +360,14 @@ if (!isTerminal(newStatements)) { newStatements.add(throwNode); } - return new Block(throwNode.getLineNumber(), throwNode.getToken(), throwNode.getFinish(), newStatements); + return BlockStatement.createReplacement(throwNode, newStatements); } return throwNode; } @Override public Node leaveBreakNode(final BreakNode breakNode) { - return copy(breakNode, Lower.this.lc.getBreakable(breakNode.getLabel())); + return copy(breakNode, (Node)Lower.this.lc.getBreakable(breakNode.getLabel())); } @Override @@ -372,15 +377,15 @@ @Override public Node leaveReturnNode(final ReturnNode returnNode) { - final Node expr = returnNode.getExpression(); + final Expression expr = returnNode.getExpression(); final List newStatements = new ArrayList<>(); - final Node resultNode; + final Expression resultNode; if (expr != null) { //we need to evaluate the result of the return in case it is complex while //still in the try block, store it in a result value and return it afterwards resultNode = new IdentNode(Lower.this.compilerConstant(RETURN)); - newStatements.add(new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr))); + newStatements.add(new ExpressionStatement(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr))); } else { resultNode = null; } @@ -390,7 +395,7 @@ newStatements.add(expr == null ? returnNode : returnNode.setExpression(resultNode)); } - return new ExecuteNode(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new Block(returnNode.getLineNumber(), returnNode.getToken(), lc.getCurrentBlock().getFinish(), newStatements)); + return BlockStatement.createReplacement(returnNode, lc.getCurrentBlock().getFinish(), newStatements); } private Node copy(final Statement endpoint, final Node targetNode) { @@ -399,7 +404,7 @@ if (!isTerminal(newStatements)) { newStatements.add(endpoint); } - return new ExecuteNode(endpoint.getLineNumber(), endpoint.getToken(), endpoint.getFinish(), new Block(endpoint.getLineNumber(), endpoint.getToken(), finish, newStatements)); + return BlockStatement.createReplacement(endpoint, finish, newStatements); } return endpoint; } @@ -461,7 +466,7 @@ if (tryNode.getCatchBlocks().isEmpty()) { newTryNode = tryNode.setFinallyBody(null); } else { - Block outerBody = new Block(tryNode.getLineNumber(), tryNode.getToken(), tryNode.getFinish(), new ArrayList(Arrays.asList(tryNode.setFinallyBody(null)))); + Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), new ArrayList(Arrays.asList(tryNode.setFinallyBody(null)))); newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null); } @@ -478,7 +483,7 @@ public Node leaveVarNode(final VarNode varNode) { addStatement(varNode); if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && lc.getCurrentFunction().isProgram()) { - new ExecuteNode(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this); + new ExpressionStatement(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this); } return varNode; } @@ -511,7 +516,7 @@ * @param function function called by a CallNode * @return transformed node to marker function or identity if not ident/access/indexnode */ - private static Node markerFunction(final Node function) { + private static Expression markerFunction(final Expression function) { if (function instanceof IdentNode) { return ((IdentNode)function).setIsFunction(); } else if (function instanceof BaseNode) { @@ -553,15 +558,15 @@ private CallNode checkEval(final CallNode callNode) { if (callNode.getFunction() instanceof IdentNode) { - final List args = callNode.getArgs(); - final IdentNode callee = (IdentNode)callNode.getFunction(); + final List args = callNode.getArgs(); + final IdentNode callee = (IdentNode)callNode.getFunction(); // 'eval' call with at least one argument if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) { final FunctionNode currentFunction = lc.getCurrentFunction(); return callNode.setEvalArgs( new CallNode.EvalArgs( - ensureUniqueNamesIn(args.get(0)).accept(this), + (Expression)ensureUniqueNamesIn(args.get(0)).accept(this), compilerConstant(THIS), evalLocation(callee), currentFunction.isStrict())); @@ -630,7 +635,7 @@ * @param expression expression to check for internal symbol * @return true if internal, false otherwise */ - private static boolean isInternalExpression(final Node expression) { + private static boolean isInternalExpression(final Expression expression) { final Symbol symbol = expression.getSymbol(); return symbol != null && symbol.isInternal(); } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java --- a/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java Fri Jul 12 20:12:29 2013 +0530 @@ -435,13 +435,13 @@ * @return Open method emitter. */ private static MethodEmitter newInitScopeWithArgumentsMethod(final ClassEmitter classEmitter) { - final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class, Object.class); + final MethodEmitter init = classEmitter.init(PropertyMap.class, ScriptObject.class, ScriptObject.class); init.begin(); init.load(Type.OBJECT, JAVA_THIS.slot()); init.load(Type.OBJECT, INIT_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)); + init.invoke(constructorNoLookup(FunctionScope.class, PropertyMap.class, ScriptObject.class, ScriptObject.class)); return init; } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java --- a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java Fri Jul 12 20:12:29 2013 +0530 @@ -28,11 +28,11 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Map; - import jdk.nashorn.internal.codegen.types.Range; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.Assignment; import jdk.nashorn.internal.ir.BinaryNode; +import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.LexicalContext; @@ -87,7 +87,7 @@ } //destination visited - private Symbol setRange(final Node dest, final Range range) { + private Symbol setRange(final Expression dest, final Range range) { if (range.isUnknown()) { return null; } @@ -352,7 +352,6 @@ range = range.isUnknown() ? Range.createGenericRange() : range; setRange(node.getName(), range); - setRange(node, range); } return node; @@ -438,12 +437,12 @@ * @return */ private static Symbol findLoopCounter(final LoopNode node) { - final Node test = node.getTest(); + final Expression test = node.getTest(); if (test != null && test.isComparison()) { final BinaryNode binaryNode = (BinaryNode)test; - final Node lhs = binaryNode.lhs(); - final Node rhs = binaryNode.rhs(); + final Expression lhs = binaryNode.lhs(); + final Expression rhs = binaryNode.rhs(); //detect ident cmp int_literal if (lhs instanceof IdentNode && rhs instanceof LiteralNode && ((LiteralNode)rhs).getType().isInteger()) { diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java --- a/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java Fri Jul 12 20:12:29 2013 +0530 @@ -25,26 +25,25 @@ package jdk.nashorn.internal.codegen; +import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; +import static jdk.nashorn.internal.codegen.types.Type.OBJECT; + +import java.util.List; import jdk.nashorn.internal.codegen.types.Type; +import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.LiteralNode; -import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.ir.Symbol; import jdk.nashorn.internal.runtime.Property; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.scripts.JO; -import java.util.List; - -import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; -import static jdk.nashorn.internal.codegen.types.Type.OBJECT; - /** * An object creator that uses spill properties. */ public class SpillObjectCreator extends ObjectCreator { - private final List values; + private final List values; /** * Constructor @@ -54,7 +53,7 @@ * @param symbols symbols for fields in object * @param values list of values corresponding to keys */ - protected SpillObjectCreator(final CodeGenerator codegen, final List keys, final List symbols, final List values) { + protected SpillObjectCreator(final CodeGenerator codegen, final List keys, final List symbols, final List values) { super(codegen, keys, symbols, false, false); this.values = values; makeMap(); @@ -107,7 +106,7 @@ for (int i = 0; i < length; i++) { final String key = keys.get(i); final Property property = propertyMap.findProperty(key); - final Node value = values.get(i); + final Expression value = values.get(i); if (property == null && value != null) { method.dup(); diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/Splitter.java --- a/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java Fri Jul 12 20:12:29 2013 +0530 @@ -31,7 +31,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; - import jdk.nashorn.internal.ir.Block; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.FunctionNode.CompilationState; @@ -221,14 +220,13 @@ * @return New split node. */ private SplitNode createBlockSplitNode(final Block parent, final FunctionNode function, final List statements, final long weight) { - final int lineNumber = parent.getLineNumber(); final long token = parent.getToken(); final int finish = parent.getFinish(); final String name = function.uniqueName(SPLIT_PREFIX.symbolName()); - final Block newBlock = new Block(lineNumber, token, finish, statements); + final Block newBlock = new Block(token, finish, statements); - return new SplitNode(lineNumber, name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT)); + return new SplitNode(name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT)); } @Override diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java --- a/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java Fri Jul 12 20:12:29 2013 +0530 @@ -27,7 +27,6 @@ import java.util.List; import java.util.Map; - import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BinaryNode; @@ -36,7 +35,7 @@ import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CatchNode; import jdk.nashorn.internal.ir.ContinueNode; -import jdk.nashorn.internal.ir.ExecuteNode; +import jdk.nashorn.internal.ir.ExpressionStatement; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.IdentNode; @@ -158,8 +157,8 @@ } @Override - public Node leaveExecuteNode(final ExecuteNode executeNode) { - return executeNode; + public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) { + return expressionStatement; } @Override diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/codegen/types/Type.java --- a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java Fri Jul 12 20:12:29 2013 +0530 @@ -47,9 +47,8 @@ import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG; import java.lang.invoke.MethodHandle; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import jdk.internal.org.objectweb.asm.MethodVisitor; import jdk.nashorn.internal.codegen.CompilerConstants.Call; @@ -548,19 +547,19 @@ * @return the Type representing this class */ public static Type typeFor(final Class clazz) { - Type type = cache.get(clazz); - - if (type == null) { - assert !clazz.isPrimitive() || clazz == void.class; - if (clazz.isArray()) { - type = new ArrayType(clazz); - } else { - type = new ObjectType(clazz); - } - cache.put(clazz, type); + final Type type = cache.get(clazz); + if(type != null) { + return type; } - - return type; + assert !clazz.isPrimitive() || clazz == void.class; + final Type newType; + if (clazz.isArray()) { + newType = new ArrayType(clazz); + } else { + newType = new ObjectType(clazz); + } + final Type existingType = cache.putIfAbsent(clazz, newType); + return existingType == null ? newType : existingType; } @Override @@ -663,35 +662,38 @@ } } + /** Mappings between java classes and their Type singletons */ + private static final ConcurrentMap, Type> cache = new ConcurrentHashMap<>(); + /** * This is the boolean singleton, used for all boolean types */ - public static final Type BOOLEAN = new BooleanType(); + public static final Type BOOLEAN = putInCache(new BooleanType()); /** * This is an integer type, i.e INT, INT32. */ - public static final Type INT = new IntType(); + public static final Type INT = putInCache(new IntType()); /** * This is the number singleton, used for all number types */ - public static final Type NUMBER = new NumberType(); + public static final Type NUMBER = putInCache(new NumberType()); /** * This is the long singleton, used for all long types */ - public static final Type LONG = new LongType(); + public static final Type LONG = putInCache(new LongType()); /** * A string singleton */ - public static final Type STRING = new ObjectType(String.class); + public static final Type STRING = putInCache(new ObjectType(String.class)); /** * This is the object singleton, used for all object types */ - public static final Type OBJECT = new ObjectType(); + public static final Type OBJECT = putInCache(new ObjectType()); /** * This is the singleton for integer arrays @@ -775,13 +777,13 @@ }; /** Singleton for method handle arrays used for properties etc. */ - public static final ArrayType METHODHANDLE_ARRAY = new ArrayType(MethodHandle[].class); + public static final ArrayType METHODHANDLE_ARRAY = putInCache(new ArrayType(MethodHandle[].class)); /** This is the singleton for string arrays */ - public static final ArrayType STRING_ARRAY = new ArrayType(String[].class); + public static final ArrayType STRING_ARRAY = putInCache(new ArrayType(String[].class)); /** This is the singleton for object arrays */ - public static final ArrayType OBJECT_ARRAY = new ArrayType(Object[].class); + public static final ArrayType OBJECT_ARRAY = putInCache(new ArrayType(Object[].class)); /** This type, always an object type, just a toString override */ public static final Type THIS = new ObjectType() { @@ -855,18 +857,8 @@ } }; - /** Mappings between java classes and their Type singletons */ - private static final Map, Type> cache = Collections.synchronizedMap(new HashMap, Type>()); - - //TODO may need to be cleared, as all types are retained throughout code generation - static { - cache.put(BOOLEAN.getTypeClass(), BOOLEAN); - cache.put(INT.getTypeClass(), INT); - cache.put(LONG.getTypeClass(), LONG); - cache.put(NUMBER.getTypeClass(), NUMBER); - cache.put(STRING.getTypeClass(), STRING); - cache.put(OBJECT.getTypeClass(), OBJECT); - cache.put(OBJECT_ARRAY.getTypeClass(), OBJECT_ARRAY); + private static T putInCache(T type) { + cache.put(type.getTypeClass(), type); + return type; } - } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/ir/AccessNode.java --- a/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java Fri Jul 12 20:12:29 2013 +0530 @@ -45,12 +45,12 @@ * @param base base node * @param property property */ - public AccessNode(final long token, final int finish, final Node base, final IdentNode property) { + public AccessNode(final long token, final int finish, final Expression base, final IdentNode property) { super(token, finish, base, false, false); this.property = property.setIsPropertyName(); } - private AccessNode(final AccessNode accessNode, final Node base, final IdentNode property, final boolean isFunction, final boolean hasCallSiteType) { + private AccessNode(final AccessNode accessNode, final Expression base, final IdentNode property, final boolean isFunction, final boolean hasCallSiteType) { super(accessNode, base, isFunction, hasCallSiteType); this.property = property; } @@ -63,7 +63,7 @@ public Node accept(final NodeVisitor visitor) { if (visitor.enterAccessNode(this)) { return visitor.leaveAccessNode( - setBase(base.accept(visitor)). + setBase((Expression)base.accept(visitor)). setProperty((IdentNode)property.accept(visitor))); } return this; @@ -103,7 +103,7 @@ return property; } - private AccessNode setBase(final Node base) { + private AccessNode setBase(final Expression base) { if (this.base == base) { return this; } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/ir/Assignment.java --- a/nashorn/src/jdk/nashorn/internal/ir/Assignment.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/ir/Assignment.java Fri Jul 12 20:12:29 2013 +0530 @@ -31,7 +31,7 @@ * * @param the destination type */ -public interface Assignment { +public interface Assignment { /** * Get assignment destination @@ -45,7 +45,7 @@ * * @return get the assignment source node */ - public Node getAssignmentSource(); + public Expression getAssignmentSource(); /** * Set assignment destination node. diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/ir/BaseNode.java --- a/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java Fri Jul 12 20:12:29 2013 +0530 @@ -26,6 +26,7 @@ package jdk.nashorn.internal.ir; import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS; + import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Immutable; @@ -37,10 +38,10 @@ * @see IndexNode */ @Immutable -public abstract class BaseNode extends Node implements FunctionCall, TypeOverride { +public abstract class BaseNode extends Expression implements FunctionCall, TypeOverride { /** Base Node. */ - protected final Node base; + protected final Expression base; private final boolean isFunction; @@ -55,7 +56,7 @@ * @param isFunction is this a function * @param hasCallSiteType does this access have a callsite type */ - public BaseNode(final long token, final int finish, final Node base, final boolean isFunction, final boolean hasCallSiteType) { + public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction, final boolean hasCallSiteType) { super(token, base.getStart(), finish); this.base = base; this.isFunction = isFunction; @@ -69,7 +70,7 @@ * @param isFunction is this a function * @param hasCallSiteType does this access have a callsite type */ - protected BaseNode(final BaseNode baseNode, final Node base, final boolean isFunction, final boolean hasCallSiteType) { + protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final boolean hasCallSiteType) { super(baseNode); this.base = base; this.isFunction = isFunction; @@ -80,7 +81,7 @@ * Get the base node for this access * @return the base node */ - public Node getBase() { + public Expression getBase() { return base; } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java --- a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java Fri Jul 12 20:12:29 2013 +0530 @@ -34,11 +34,11 @@ * BinaryNode nodes represent two operand operations. */ @Immutable -public final class BinaryNode extends Node implements Assignment { +public final class BinaryNode extends Expression implements Assignment { /** Left hand side argument. */ - private final Node lhs; + private final Expression lhs; - private final Node rhs; + private final Expression rhs; /** * Constructor @@ -47,13 +47,13 @@ * @param lhs left hand side * @param rhs right hand side */ - public BinaryNode(final long token, final Node lhs, final Node rhs) { + public BinaryNode(final long token, final Expression lhs, final Expression rhs) { super(token, lhs.getStart(), rhs.getFinish()); this.lhs = lhs; this.rhs = rhs; } - private BinaryNode(final BinaryNode binaryNode, final Node lhs, final Node rhs) { + private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs) { super(binaryNode); this.lhs = lhs; this.rhs = rhs; @@ -141,17 +141,17 @@ } @Override - public Node getAssignmentDest() { + public Expression getAssignmentDest() { return isAssignment() ? lhs() : null; } @Override - public Node setAssignmentDest(Node n) { + public BinaryNode setAssignmentDest(Expression n) { return setLHS(n); } @Override - public Node getAssignmentSource() { + public Expression getAssignmentSource() { return rhs(); } @@ -162,7 +162,7 @@ @Override public Node accept(final NodeVisitor visitor) { if (visitor.enterBinaryNode(this)) { - return visitor.leaveBinaryNode(setLHS(lhs.accept(visitor)).setRHS(rhs.accept(visitor))); + return visitor.leaveBinaryNode(setLHS((Expression)lhs.accept(visitor)).setRHS((Expression)rhs.accept(visitor))); } return this; @@ -218,7 +218,7 @@ * Get the left hand side expression for this node * @return the left hand side expression */ - public Node lhs() { + public Expression lhs() { return lhs; } @@ -226,7 +226,7 @@ * Get the right hand side expression for this node * @return the left hand side expression */ - public Node rhs() { + public Expression rhs() { return rhs; } @@ -235,7 +235,7 @@ * @param lhs new left hand side expression * @return a node equivalent to this one except for the requested change. */ - public BinaryNode setLHS(final Node lhs) { + public BinaryNode setLHS(final Expression lhs) { if (this.lhs == lhs) { return this; } @@ -247,7 +247,7 @@ * @param rhs new left hand side expression * @return a node equivalent to this one except for the requested change. */ - public BinaryNode setRHS(final Node rhs) { + public BinaryNode setRHS(final Expression rhs) { if (this.rhs == rhs) { return this; } diff -r 4abe332f1270 -r 7907640d3be5 nashorn/src/jdk/nashorn/internal/ir/Block.java --- a/nashorn/src/jdk/nashorn/internal/ir/Block.java Mon Jul 08 18:43:41 2013 +0530 +++ b/nashorn/src/jdk/nashorn/internal/ir/Block.java Fri Jul 12 20:12:29 2013 +0530 @@ -38,11 +38,10 @@ import jdk.nashorn.internal.ir.visitor.NodeVisitor; /** - * IR representation for a list of statements and functions. All provides the - * basis for script body. + * IR representation for a list of statements. */ @Immutable -public class Block extends BreakableNode implements Flags { +public class Block extends Node implements BreakableNode, Flags { /** List of statements */ protected final List statements; @@ -52,6 +51,9 @@ /** Entry label. */ protected final Label entryLabel; + /** Break label. */ + private final Label breakLabel; + /** Does the block/function need a new scope? */ protected final int flags; @@ -76,17 +78,17 @@ /** * Constructor * - * @param lineNumber line number * @param token token * @param finish finish * @param statements statements */ - public Block(final int lineNumber, final long token, final int finish, final Statement... statements) { - super(lineNumber, token, finish, new Label("block_break")); + public Block(final long token, final int finish, final Statement... statements) { + super(token, finish); this.statements = Arrays.asList(statements); this.symbols = new LinkedHashMap<>(); this.entryLabel = new Label("block_entry"); + this.breakLabel = new Label("block_break"); this.flags = 0; } @@ -98,8 +100,8 @@ * @param finish finish * @param statements statements */ - public Block(final int lineNumber, final long token, final int finish, final List statements) { - this(lineNumber, token, finish, statements.toArray(new Statement[statements.size()])); + public Block(final long token, final int finish, final List statements) { + this(token, finish, statements.toArray(new Statement[statements.size()])); } private Block(final Block block, final int finish, final List statements, final int flags, final Map symbols) { @@ -108,6 +110,7 @@ this.flags = flags; this.symbols = new LinkedHashMap<>(symbols); //todo - symbols have no dependencies on any IR node and can as far as we understand it be shallow copied now this.entryLabel = new Label(block.entryLabel); + this.breakLabel = new Label(block.breakLabel); this.finish = finish; } @@ -223,6 +226,11 @@ return entryLabel; } + @Override + public Label getBreakLabel() { + return breakLabel; + } + /** * Get the list of statements in this block * @@ -322,7 +330,17 @@ } @Override - protected boolean isBreakableWithoutLabel() { + public boolean isBreakableWithoutLabel() { return false; } + + @Override + public List