jdk.nashorn.internal.ir.VarNode Java Examples

The following examples show how to use jdk.nashorn.internal.ir.VarNode. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: SplitIntoFunctions.java    From openjdk-jdk8u with GNU General Public License v2.0 6 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    if (!inSplitNode()) {
        return super.enterVarNode(varNode);
    }
    assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't

    final Expression init = varNode.getInit();

    // Move a declaration-only var statement to the top of the outermost function.
    getCurrentFunctionState().varStatements.add(varNode.setInit(null));
    // If it had an initializer, replace it with an assignment expression statement. Note that "var" is a
    // statement, so it doesn't contribute to :return of the programs, therefore we are _not_ adding a
    // ":return = ..." assignment around the original assignment.
    if (init != null) {
        final long token = Token.recast(varNode.getToken(), TokenType.ASSIGN);
        new ExpressionStatement(varNode.getLineNumber(), token, varNode.getFinish(),
                new BinaryNode(token, varNode.getName(), varNode.getInit())).accept(this);
    }

    return false;
}
 
Example #2
Source File: FoldConstants.java    From TencentKona-8 with GNU General Public License v2.0 6 votes vote down vote up
/**
 * When we eliminate dead code, we must preserve var declarations as they are scoped to the whole
 * function. This method gathers var nodes from code passed to it, removing their initializers.
 *
 * @param deadCodeRoot the root node of eliminated dead code
 * @param statements a list that will be receiving the var nodes from the dead code, with their
 * initializers removed.
 */
static void extractVarNodesFromDeadCode(final Node deadCodeRoot, final List<Statement> statements) {
    deadCodeRoot.accept(new SimpleNodeVisitor() {
        @Override
        public boolean enterVarNode(final VarNode varNode) {
            statements.add(varNode.setInit(null));
            return false;
        }

        @Override
        public boolean enterFunctionNode(final FunctionNode functionNode) {
            // Don't descend into nested functions
            return false;
        }
    });
}
 
Example #3
Source File: FoldConstants.java    From hottub with GNU General Public License v2.0 6 votes vote down vote up
/**
 * When we eliminate dead code, we must preserve var declarations as they are scoped to the whole
 * function. This method gathers var nodes from code passed to it, removing their initializers.
 *
 * @param deadCodeRoot the root node of eliminated dead code
 * @param statements a list that will be receiving the var nodes from the dead code, with their
 * initializers removed.
 */
static void extractVarNodesFromDeadCode(final Node deadCodeRoot, final List<Statement> statements) {
    deadCodeRoot.accept(new SimpleNodeVisitor() {
        @Override
        public boolean enterVarNode(final VarNode varNode) {
            statements.add(varNode.setInit(null));
            return false;
        }

        @Override
        public boolean enterFunctionNode(final FunctionNode functionNode) {
            // Don't descend into nested functions
            return false;
        }
    });
}
 
Example #4
Source File: Attr.java    From nashorn with GNU General Public License v2.0 6 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    start(varNode);

    final IdentNode ident = varNode.getName();
    final String    name  = ident.getName();

    final Symbol symbol = defineSymbol(lc.getCurrentBlock(), name, IS_VAR);
    assert symbol != null;

    // NASHORN-467 - use before definition of vars - conservative
    if (isLocalUse(ident.getName())) {
        newType(symbol, Type.OBJECT);
        symbol.setCanBeUndefined();
    }

    return true;
}
 
Example #5
Source File: FoldConstants.java    From jdk8u_nashorn with GNU General Public License v2.0 6 votes vote down vote up
/**
 * When we eliminate dead code, we must preserve var declarations as they are scoped to the whole
 * function. This method gathers var nodes from code passed to it, removing their initializers.
 *
 * @param deadCodeRoot the root node of eliminated dead code
 * @param statements a list that will be receiving the var nodes from the dead code, with their
 * initializers removed.
 */
static void extractVarNodesFromDeadCode(final Node deadCodeRoot, final List<Statement> statements) {
    deadCodeRoot.accept(new SimpleNodeVisitor() {
        @Override
        public boolean enterVarNode(final VarNode varNode) {
            statements.add(varNode.setInit(null));
            return false;
        }

        @Override
        public boolean enterFunctionNode(final FunctionNode functionNode) {
            // Don't descend into nested functions
            return false;
        }
    });
}
 
Example #6
Source File: LocalVariableTypesCalculator.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    if (!reachable) {
        return false;
    }
    final Expression init = varNode.getInit();
    if(init != null) {
        onAssignment(varNode.getName(), visitExpression(init));
    }
    return false;
}
 
Example #7
Source File: PrintVisitor.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    sb.append(varNode.isConst() ? "const " : varNode.isLet() ? "let " : "var ");
    varNode.getName().toString(sb, printTypes);
    printLocalVariableConversion(varNode.getName());
    final Node init = varNode.getInit();
    if (init != null) {
        sb.append(" = ");
        init.accept(this);
    }

    return false;
}
 
Example #8
Source File: AssignSymbols.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
private void defineVarIdent(final VarNode varNode) {
    final IdentNode ident = varNode.getName();
    final int flags;
    if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) {
        flags = IS_SCOPE;
    } else {
        flags = 0;
    }
    defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | flags);
}
 
Example #9
Source File: AssignSymbols.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
@Override
public Node leaveVarNode(final VarNode varNode) {
    if (!varNode.isFunctionDeclaration()) {
        defineVarIdent(varNode);
    }
    return super.leaveVarNode(varNode);
}
 
Example #10
Source File: AssignSymbols.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
private void throwUnprotectedSwitchError(final VarNode varNode) {
    // Block scoped declarations in switch statements without explicit blocks should be declared
    // in a common block that contains all the case clauses. We cannot support this without a
    // fundamental rewrite of how switch statements are handled (case nodes contain blocks and are
    // directly contained by switch node). As a temporary solution we throw a reference error here.
    final String msg = ECMAErrors.getMessage("syntax.error.unprotected.switch.declaration", varNode.isLet() ? "let" : "const");
    throwParserException(msg, varNode);
}
 
Example #11
Source File: AssignSymbols.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Define symbols for all variable declarations at the top of the function scope. This way we can get around
 * problems like
 *
 * while (true) {
 *   break;
 *   if (true) {
 *     var s;
 *   }
 * }
 *
 * to an arbitrary nesting depth.
 *
 * see NASHORN-73
 *
 * @param functionNode the FunctionNode we are entering
 * @param body the body of the FunctionNode we are entering
 */
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
    // This visitor will assign symbol to all declared variables.
    body.accept(new SimpleNodeVisitor() {
        @Override
        protected boolean enterDefault(final Node node) {
            // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
            // This will also prevent visiting nested functions (as FunctionNode is an expression).
            return !(node instanceof Expression);
        }

        @Override
        public Node leaveVarNode(final VarNode varNode) {
            final IdentNode ident  = varNode.getName();
            final boolean blockScoped = varNode.isBlockScoped();
            if (blockScoped && lc.inUnprotectedSwitchContext()) {
                throwUnprotectedSwitchError(varNode);
            }
            final Block block = blockScoped ? lc.getCurrentBlock() : body;
            final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
            if (varNode.isFunctionDeclaration()) {
                symbol.setIsFunctionDeclaration();
            }
            return varNode.setName(ident.setSymbol(symbol));
        }
    });
}
 
Example #12
Source File: AssignSymbols.java    From openjdk-jdk9 with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
 * used to create assignment of {@code :callee} to the function name symbol in self-referential function
 * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
 *
 * @param name the ident node identifying the variable to initialize
 * @param initConstant the compiler constant it is initialized to
 * @param fn the function node the assignment is for
 * @return a var node with the appropriate assignment
 */
private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) {
    final IdentNode init = compilerConstantIdentifier(initConstant);
    assert init.getSymbol() != null && init.getSymbol().isBytecodeLocal();

    final VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init);

    final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName());
    assert nameSymbol != null;

    return (VarNode)synthVar.setName(name.setSymbol(nameSymbol)).accept(this);
}
 
Example #13
Source File: Parser.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
private void addFunctionDeclarations(final FunctionNode functionNode) {
    VarNode lastDecl = null;
    for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
        Statement decl = functionDeclarations.get(i);
        if (lastDecl == null && decl instanceof VarNode) {
            decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
            lc.setFlag(functionNode, FunctionNode.HAS_FUNCTION_DECLARATIONS);
        }
        prependStatement(decl);
    }
}
 
Example #14
Source File: Lower.java    From openjdk-jdk8u-backup with GNU General Public License v2.0 5 votes vote down vote up
@Override
public Node leaveVarNode(final VarNode varNode) {
    addStatement(varNode);
    if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION) && lc.getCurrentFunction().isProgram()) {
        new ExpressionStatement(varNode.getLineNumber(), varNode.getToken(), varNode.getFinish(), new IdentNode(varNode.getName())).accept(this);
    }
    return varNode;
}
 
Example #15
Source File: FinalizeTypes.java    From nashorn with GNU General Public License v2.0 5 votes vote down vote up
<T extends Expression> SpecializedNode specialize(final Assignment<T> assignment) {
    final Node node = ((Node)assignment);
    final T lhs = assignment.getAssignmentDest();
    final Expression rhs = assignment.getAssignmentSource();

    if (!canHaveCallSiteType(lhs)) {
        return new SpecializedNode(node, null);
    }

    final Type to;
    if (node.isSelfModifying()) {
        to = node.getWidestOperationType();
    } else {
        to = rhs.getType();
    }

    if (!isSupportedCallSiteType(to)) {
        //meaningless to specialize to boolean or object
        return new SpecializedNode(node, null);
    }

    final Node newNode = assignment.setAssignmentDest(setTypeOverride(lhs, 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);
}
 
Example #16
Source File: FoldConstants.java    From openjdk-8 with GNU General Public License v2.0 5 votes vote down vote up
private static void extractVarNodes(final Block block, final List<Statement> statements) {
    final LexicalContext lc = new LexicalContext();
    block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
        @Override
        public boolean enterVarNode(VarNode varNode) {
            statements.add(varNode.setInit(null));
            return false;
        }
    });
}
 
Example #17
Source File: CodeGenerator.java    From openjdk-8-source with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {

    final Expression init = varNode.getInit();

    if (init == null) {
        return false;
    }

    lineNumber(varNode);

    final IdentNode identNode = varNode.getName();
    final Symbol identSymbol = identNode.getSymbol();
    assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol";

    assert method != null;

    final boolean needsScope = identSymbol.isScope();
    if (needsScope) {
        method.loadCompilerConstant(SCOPE);
    }

    if (needsScope) {
        load(init);
        int flags = CALLSITE_SCOPE | getCallSiteFlags();
        if (isFastScope(identSymbol)) {
            storeFastScopeVar(identSymbol, flags);
        } else {
            method.dynamicSet(identNode.getName(), flags);
        }
    } else {
        load(init, identNode.getType());
        method.store(identSymbol);
    }

    return false;
}
 
Example #18
Source File: AssignSymbols.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
@Override
public Node leaveVarNode(final VarNode varNode) {
    if (!varNode.isFunctionDeclaration()) {
        defineVarIdent(varNode);
    }
    return super.leaveVarNode(varNode);
}
 
Example #19
Source File: AssignSymbols.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
private FunctionNode createSyntheticInitializers(final FunctionNode functionNode) {
    final List<VarNode> syntheticInitializers = new ArrayList<>(2);

    // Must visit the new var nodes in the context of the body. We could also just set the new statements into the
    // block and then revisit the entire block, but that seems to be too much double work.
    final Block body = functionNode.getBody();
    lc.push(body);
    try {
        if (functionNode.usesSelfSymbol()) {
            // "var fn = :callee"
            syntheticInitializers.add(createSyntheticInitializer(functionNode.getIdent(), CALLEE, functionNode));
        }

        if (functionNode.needsArguments()) {
            // "var arguments = :arguments"
            syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()),
                    ARGUMENTS, functionNode));
        }

        if (syntheticInitializers.isEmpty()) {
            return functionNode;
        }

        for(final ListIterator<VarNode> it = syntheticInitializers.listIterator(); it.hasNext();) {
            it.set((VarNode)it.next().accept(this));
        }
    } finally {
        lc.pop(body);
    }

    final List<Statement> stmts = body.getStatements();
    final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
    newStatements.addAll(syntheticInitializers);
    newStatements.addAll(stmts);
    return functionNode.setBody(lc, body.setStatements(lc, newStatements));
}
 
Example #20
Source File: AssignSymbols.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
 * used to create assignment of {@code :callee} to the function name symbol in self-referential function
 * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
 *
 * @param name the ident node identifying the variable to initialize
 * @param initConstant the compiler constant it is initialized to
 * @param fn the function node the assignment is for
 * @return a var node with the appropriate assignment
 */
private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) {
    final IdentNode init = compilerConstantIdentifier(initConstant);
    assert init.getSymbol() != null && init.getSymbol().isBytecodeLocal();

    final VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init);

    final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName());
    assert nameSymbol != null;

    return (VarNode)synthVar.setName(name.setSymbol(nameSymbol)).accept(this);
}
 
Example #21
Source File: AssignSymbols.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Define symbols for all variable declarations at the top of the function scope. This way we can get around
 * problems like
 *
 * while (true) {
 *   break;
 *   if (true) {
 *     var s;
 *   }
 * }
 *
 * to an arbitrary nesting depth.
 *
 * see NASHORN-73
 *
 * @param functionNode the FunctionNode we are entering
 * @param body the body of the FunctionNode we are entering
 */
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
    // This visitor will assign symbol to all declared variables.
    body.accept(new SimpleNodeVisitor() {
        @Override
        protected boolean enterDefault(final Node node) {
            // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
            // This will also prevent visiting nested functions (as FunctionNode is an expression).
            return !(node instanceof Expression);
        }

        @Override
        public Node leaveVarNode(final VarNode varNode) {
            final IdentNode ident  = varNode.getName();
            final boolean blockScoped = varNode.isBlockScoped();
            if (blockScoped && lc.inUnprotectedSwitchContext()) {
                throwUnprotectedSwitchError(varNode);
            }
            final Block block = blockScoped ? lc.getCurrentBlock() : body;
            final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
            if (varNode.isFunctionDeclaration()) {
                symbol.setIsFunctionDeclaration();
            }
            return varNode.setName(ident.setSymbol(symbol));
        }
    });
}
 
Example #22
Source File: Attr.java    From nashorn with GNU General Public License v2.0 5 votes vote down vote up
@Override
public Node leaveVarNode(final VarNode varNode) {
    final Expression init  = varNode.getInit();
    final IdentNode  ident = varNode.getName();
    final String     name  = 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(varNode);
    }

    addLocalDef(name);

    assert symbol != null;

    final IdentNode newIdent = (IdentNode)ident.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) {
        // Forbid integers as local vars for now as we have no way to treat them as undefined
        newType(symbol, init.getType());
    } else {
        newType(symbol, Type.OBJECT);
    }

    assert newVarNode.getName().hasType() : newVarNode + " has no type";

    return end(newVarNode);
}
 
Example #23
Source File: PrintVisitor.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    sb.append(varNode.isConst() ? "const " : varNode.isLet() ? "let " : "var ");
    varNode.getName().toString(sb, printTypes);
    printLocalVariableConversion(varNode.getName());
    final Node init = varNode.getInit();
    if (init != null) {
        sb.append(" = ");
        init.accept(this);
    }

    return false;
}
 
Example #24
Source File: Parser.java    From openjdk-jdk8u with GNU General Public License v2.0 5 votes vote down vote up
private void addFunctionDeclarations(final FunctionNode functionNode) {
    VarNode lastDecl = null;
    for (int i = functionDeclarations.size() - 1; i >= 0; i--) {
        Statement decl = functionDeclarations.get(i);
        if (lastDecl == null && decl instanceof VarNode) {
            decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION);
            lc.setFlag(functionNode, FunctionNode.HAS_FUNCTION_DECLARATIONS);
        }
        prependStatement(decl);
    }
}
 
Example #25
Source File: AssignSymbols.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    start(varNode);
    // Normally, a symbol assigned in a var statement is not live for its RHS. Since we also represent function
    // declarations as VarNodes, they are exception to the rule, as they need to have the symbol visible to the
    // body of the declared function for self-reference.
    if (varNode.isFunctionDeclaration()) {
        defineVarIdent(varNode);
    }
    return true;
}
 
Example #26
Source File: LocalVariableTypesCalculator.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    if (!reachable) {
        return false;
    }
    final Expression init = varNode.getInit();
    if(init != null) {
        onAssignment(varNode.getName(), visitExpression(init));
    }
    return false;
}
 
Example #27
Source File: FoldConstants.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
private static void extractVarNodes(final Block block, final List<Statement> statements) {
    final LexicalContext lc = new LexicalContext();
    block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
        @Override
        public boolean enterVarNode(final VarNode varNode) {
            statements.add(varNode.setInit(null));
            return false;
        }
    });
}
 
Example #28
Source File: AssignSymbols.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public Node leaveVarNode(final VarNode varNode) {
    if (!varNode.isFunctionDeclaration()) {
        defineVarIdent(varNode);
    }
    return super.leaveVarNode(varNode);
}
 
Example #29
Source File: AssignSymbols.java    From jdk8u60 with GNU General Public License v2.0 5 votes vote down vote up
@Override
public boolean enterVarNode(final VarNode varNode) {
    start(varNode);
    // Normally, a symbol assigned in a var statement is not live for its RHS. Since we also represent function
    // declarations as VarNodes, they are exception to the rule, as they need to have the symbol visible to the
    // body of the declared function for self-reference.
    if (varNode.isFunctionDeclaration()) {
        defineVarIdent(varNode);
    }
    return true;
}
 
Example #30
Source File: AssignSymbols.java    From jdk8u_nashorn with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Define symbols for all variable declarations at the top of the function scope. This way we can get around
 * problems like
 *
 * while (true) {
 *   break;
 *   if (true) {
 *     var s;
 *   }
 * }
 *
 * to an arbitrary nesting depth.
 *
 * see NASHORN-73
 *
 * @param functionNode the FunctionNode we are entering
 * @param body the body of the FunctionNode we are entering
 */
private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
    // This visitor will assign symbol to all declared variables.
    body.accept(new SimpleNodeVisitor() {
        @Override
        protected boolean enterDefault(final Node node) {
            // Don't bother visiting expressions; var is a statement, it can't be inside an expression.
            // This will also prevent visiting nested functions (as FunctionNode is an expression).
            return !(node instanceof Expression);
        }

        @Override
        public Node leaveVarNode(final VarNode varNode) {
            final IdentNode ident  = varNode.getName();
            final boolean blockScoped = varNode.isBlockScoped();
            if (blockScoped && lc.inUnprotectedSwitchContext()) {
                throwUnprotectedSwitchError(varNode);
            }
            final Block block = blockScoped ? lc.getCurrentBlock() : body;
            final Symbol symbol = defineSymbol(block, ident.getName(), ident, varNode.getSymbolFlags());
            if (varNode.isFunctionDeclaration()) {
                symbol.setIsFunctionDeclaration();
            }
            return varNode.setName(ident.setSymbol(symbol));
        }
    });
}