Search in sources :

Example 1 with Jump

use of org.mozilla.javascript.ast.Jump in project hackpad by dropbox.

the class CodeGenerator method visitStatement.

private void visitStatement(Node node, int initialStackDepth) {
    int type = node.getType();
    Node child = node.getFirstChild();
    switch(type) {
        case Token.FUNCTION:
            {
                int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
                int fnType = scriptOrFn.getFunctionNode(fnIndex).getFunctionType();
                // at statement level, they must only be present as expressions.
                if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
                    addIndexOp(Icode_CLOSURE_STMT, fnIndex);
                } else {
                    if (fnType != FunctionNode.FUNCTION_STATEMENT) {
                        throw Kit.codeBug();
                    }
                }
                // function, not undefined.
                if (!itsInFunctionFlag) {
                    addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
                    stackChange(1);
                    addIcode(Icode_POP_RESULT);
                    stackChange(-1);
                }
            }
            break;
        case Token.LABEL:
        case Token.LOOP:
        case Token.BLOCK:
        case Token.EMPTY:
        case Token.WITH:
            updateLineNumber(node);
        case Token.SCRIPT:
            // fall through
            while (child != null) {
                visitStatement(child, initialStackDepth);
                child = child.getNext();
            }
            break;
        case Token.ENTERWITH:
            visitExpression(child, 0);
            addToken(Token.ENTERWITH);
            stackChange(-1);
            break;
        case Token.LEAVEWITH:
            addToken(Token.LEAVEWITH);
            break;
        case Token.LOCAL_BLOCK:
            {
                int local = allocLocal();
                node.putIntProp(Node.LOCAL_PROP, local);
                updateLineNumber(node);
                while (child != null) {
                    visitStatement(child, initialStackDepth);
                    child = child.getNext();
                }
                addIndexOp(Icode_LOCAL_CLEAR, local);
                releaseLocal(local);
            }
            break;
        case Token.DEBUGGER:
            addIcode(Icode_DEBUGGER);
            break;
        case Token.SWITCH:
            updateLineNumber(node);
            // See comments in IRFactory.createSwitch() for description
            // of SWITCH node
            {
                visitExpression(child, 0);
                for (Jump caseNode = (Jump) child.getNext(); caseNode != null; caseNode = (Jump) caseNode.getNext()) {
                    if (caseNode.getType() != Token.CASE)
                        throw badTree(caseNode);
                    Node test = caseNode.getFirstChild();
                    addIcode(Icode_DUP);
                    stackChange(1);
                    visitExpression(test, 0);
                    addToken(Token.SHEQ);
                    stackChange(-1);
                    // If true, Icode_IFEQ_POP will jump and remove case
                    // value from stack
                    addGoto(caseNode.target, Icode_IFEQ_POP);
                    stackChange(-1);
                }
                addIcode(Icode_POP);
                stackChange(-1);
            }
            break;
        case Token.TARGET:
            markTargetLabel(node);
            break;
        case Token.IFEQ:
        case Token.IFNE:
            {
                Node target = ((Jump) node).target;
                visitExpression(child, 0);
                addGoto(target, type);
                stackChange(-1);
            }
            break;
        case Token.GOTO:
            {
                Node target = ((Jump) node).target;
                addGoto(target, type);
            }
            break;
        case Token.JSR:
            {
                Node target = ((Jump) node).target;
                addGoto(target, Icode_GOSUB);
            }
            break;
        case Token.FINALLY:
            {
                // Account for incomming GOTOSUB address
                stackChange(1);
                int finallyRegister = getLocalBlockRef(node);
                addIndexOp(Icode_STARTSUB, finallyRegister);
                stackChange(-1);
                while (child != null) {
                    visitStatement(child, initialStackDepth);
                    child = child.getNext();
                }
                addIndexOp(Icode_RETSUB, finallyRegister);
            }
            break;
        case Token.EXPR_VOID:
        case Token.EXPR_RESULT:
            updateLineNumber(node);
            visitExpression(child, 0);
            addIcode((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT);
            stackChange(-1);
            break;
        case Token.TRY:
            {
                Jump tryNode = (Jump) node;
                int exceptionObjectLocal = getLocalBlockRef(tryNode);
                int scopeLocal = allocLocal();
                addIndexOp(Icode_SCOPE_SAVE, scopeLocal);
                int tryStart = iCodeTop;
                boolean savedFlag = itsInTryFlag;
                itsInTryFlag = true;
                while (child != null) {
                    visitStatement(child, initialStackDepth);
                    child = child.getNext();
                }
                itsInTryFlag = savedFlag;
                Node catchTarget = tryNode.target;
                if (catchTarget != null) {
                    int catchStartPC = labelTable[getTargetLabel(catchTarget)];
                    addExceptionHandler(tryStart, catchStartPC, catchStartPC, false, exceptionObjectLocal, scopeLocal);
                }
                Node finallyTarget = tryNode.getFinally();
                if (finallyTarget != null) {
                    int finallyStartPC = labelTable[getTargetLabel(finallyTarget)];
                    addExceptionHandler(tryStart, finallyStartPC, finallyStartPC, true, exceptionObjectLocal, scopeLocal);
                }
                addIndexOp(Icode_LOCAL_CLEAR, scopeLocal);
                releaseLocal(scopeLocal);
            }
            break;
        case Token.CATCH_SCOPE:
            {
                int localIndex = getLocalBlockRef(node);
                int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP);
                String name = child.getString();
                child = child.getNext();
                // load expression object
                visitExpression(child, 0);
                addStringPrefix(name);
                addIndexPrefix(localIndex);
                addToken(Token.CATCH_SCOPE);
                addUint8(scopeIndex != 0 ? 1 : 0);
                stackChange(-1);
            }
            break;
        case Token.THROW:
            updateLineNumber(node);
            visitExpression(child, 0);
            addToken(Token.THROW);
            addUint16(lineNumber & 0xFFFF);
            stackChange(-1);
            break;
        case Token.RETHROW:
            updateLineNumber(node);
            addIndexOp(Token.RETHROW, getLocalBlockRef(node));
            break;
        case Token.RETURN:
            updateLineNumber(node);
            if (node.getIntProp(Node.GENERATOR_END_PROP, 0) != 0) {
                // We're in a generator, so change RETURN to GENERATOR_END
                addIcode(Icode_GENERATOR_END);
                addUint16(lineNumber & 0xFFFF);
            } else if (child != null) {
                visitExpression(child, ECF_TAIL);
                addToken(Token.RETURN);
                stackChange(-1);
            } else {
                addIcode(Icode_RETUNDEF);
            }
            break;
        case Token.RETURN_RESULT:
            updateLineNumber(node);
            addToken(Token.RETURN_RESULT);
            break;
        case Token.ENUM_INIT_KEYS:
        case Token.ENUM_INIT_VALUES:
        case Token.ENUM_INIT_ARRAY:
            visitExpression(child, 0);
            addIndexOp(type, getLocalBlockRef(node));
            stackChange(-1);
            break;
        case Icode_GENERATOR:
            break;
        default:
            throw badTree(node);
    }
    if (stackDepth != initialStackDepth) {
        throw Kit.codeBug();
    }
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Example 2 with Jump

use of org.mozilla.javascript.ast.Jump in project hackpad by dropbox.

the class BodyCodegen method visitSwitch.

private void visitSwitch(Jump switchNode, Node child) {
    // See comments in IRFactory.createSwitch() for description
    // of SWITCH node
    generateExpression(child, switchNode);
    // save selector value
    short selector = getNewWordLocal();
    cfw.addAStore(selector);
    for (Jump caseNode = (Jump) child.getNext(); caseNode != null; caseNode = (Jump) caseNode.getNext()) {
        if (caseNode.getType() != Token.CASE)
            throw Codegen.badTree();
        Node test = caseNode.getFirstChild();
        generateExpression(test, caseNode);
        cfw.addALoad(selector);
        addScriptRuntimeInvoke("shallowEq", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + ")Z");
        addGoto(caseNode.target, ByteCode.IFNE);
    }
    releaseWordLocal(selector);
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Example 3 with Jump

use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.

the class BodyCodegen method visitSwitch.

private void visitSwitch(Jump switchNode, Node child) {
    // See comments in IRFactory.createSwitch() for description
    // of SWITCH node
    generateExpression(child, switchNode);
    // save selector value
    short selector = getNewWordLocal();
    cfw.addAStore(selector);
    for (Jump caseNode = (Jump) child.getNext(); caseNode != null; caseNode = (Jump) caseNode.getNext()) {
        if (caseNode.getType() != Token.CASE)
            throw Codegen.badTree();
        Node test = caseNode.getFirstChild();
        generateExpression(test, caseNode);
        cfw.addALoad(selector);
        addScriptRuntimeInvoke("shallowEq", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + ")Z");
        addGoto(caseNode.target, ByteCode.IFNE);
    }
    releaseWordLocal(selector);
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Example 4 with Jump

use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.

the class IRFactory method createLoop.

private Node createLoop(Jump loop, int loopType, Node body, Node cond, Node init, Node incr) {
    Node bodyTarget = Node.newTarget();
    Node condTarget = Node.newTarget();
    if (loopType == LOOP_FOR && cond.getType() == Token.EMPTY) {
        cond = new Node(Token.TRUE);
    }
    Jump IFEQ = new Jump(Token.IFEQ, cond);
    IFEQ.target = bodyTarget;
    Node breakTarget = Node.newTarget();
    loop.addChildToBack(bodyTarget);
    loop.addChildrenToBack(body);
    if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
        // propagate lineno to condition
        loop.addChildrenToBack(new Node(Token.EMPTY, loop.getLineno()));
    }
    loop.addChildToBack(condTarget);
    loop.addChildToBack(IFEQ);
    loop.addChildToBack(breakTarget);
    loop.target = breakTarget;
    Node continueTarget = condTarget;
    if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
        // Just add a GOTO to the condition in the do..while
        loop.addChildToFront(makeJump(Token.GOTO, condTarget));
        if (loopType == LOOP_FOR) {
            int initType = init.getType();
            if (initType != Token.EMPTY) {
                if (initType != Token.VAR && initType != Token.LET) {
                    init = new Node(Token.EXPR_VOID, init);
                }
                loop.addChildToFront(init);
            }
            Node incrTarget = Node.newTarget();
            loop.addChildAfter(incrTarget, body);
            if (incr.getType() != Token.EMPTY) {
                incr = new Node(Token.EXPR_VOID, incr);
                loop.addChildAfter(incr, incrTarget);
            }
            continueTarget = incrTarget;
        }
    }
    loop.setContinue(continueTarget);
    return loop;
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Example 5 with Jump

use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.

the class IRFactory method closeSwitch.

private void closeSwitch(Node switchBlock) {
    if (switchBlock.getType() != Token.BLOCK)
        throw Kit.codeBug();
    Jump switchNode = (Jump) switchBlock.getFirstChild();
    if (switchNode.getType() != Token.SWITCH)
        throw Kit.codeBug();
    Node switchBreakTarget = Node.newTarget();
    // switchNode.target is only used by NodeTransformer
    // to detect switch end
    switchNode.target = switchBreakTarget;
    Node defaultTarget = switchNode.getDefault();
    if (defaultTarget == null) {
        defaultTarget = switchBreakTarget;
    }
    switchBlock.addChildAfter(makeJump(Token.GOTO, defaultTarget), switchNode);
    switchBlock.addChildToBack(switchBreakTarget);
}
Also used : ScriptNode(org.mozilla.javascript.ast.ScriptNode) AstNode(org.mozilla.javascript.ast.AstNode) LetNode(org.mozilla.javascript.ast.LetNode) FunctionNode(org.mozilla.javascript.ast.FunctionNode) Jump(org.mozilla.javascript.ast.Jump)

Aggregations

Jump (org.mozilla.javascript.ast.Jump)18 FunctionNode (org.mozilla.javascript.ast.FunctionNode)16 ScriptNode (org.mozilla.javascript.ast.ScriptNode)16 AstNode (org.mozilla.javascript.ast.AstNode)6 LetNode (org.mozilla.javascript.ast.LetNode)6 Scope (org.mozilla.javascript.ast.Scope)4 Name (org.mozilla.javascript.ast.Name)3 Iterator (java.util.Iterator)2 ArrayLiteral (org.mozilla.javascript.ast.ArrayLiteral)1 BreakStatement (org.mozilla.javascript.ast.BreakStatement)1 LabeledStatement (org.mozilla.javascript.ast.LabeledStatement)1