Search in sources :

Example 16 with Jump

use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.

the class StatementGenerator method visit.

/**
     * 13.7.2 The do-while Statement
     * <p>
     * 13.1.8 Runtime Semantics: Evaluation<br>
     * 13.1.7 Runtime Semantics: LabelledEvaluation<br>
     * 13.7.2.6 Runtime Semantics: LabelledEvaluation
     */
@Override
public Completion visit(DoWhileStatement node, CodeVisitor mv) {
    assert mv.getStackSize() == 0;
    Jump lblNext = new Jump();
    ContinueLabel lblContinue = new ContinueLabel();
    BreakLabel lblBreak = new BreakLabel();
    Bool btest = Bool.evaluate(node.getTest());
    mv.enterVariableScope();
    Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(node, mv);
    /* step 1 */
    if (node.hasCompletionValue()) {
        mv.storeUndefinedAsCompletionValue();
    }
    /* step 2 (repeat loop) */
    mv.mark(lblNext);
    /* steps 2.a-c */
    Completion result;
    {
        mv.enterIteration(node, lblBreak, lblContinue);
        result = node.getStatement().accept(this, mv);
        mv.exitIteration(node);
    }
    /* step 2.b (abrupt completion - continue) */
    if (lblContinue.isTarget()) {
        mv.mark(lblContinue);
        restoreEnvironment(savedEnv, mv);
    }
    /* steps 2.d-g */
    if (!result.isAbrupt() || lblContinue.isTarget()) {
        if (btest == Bool.Any) {
            ValType type = expression(node.getTest(), mv);
            ToBoolean(type, mv);
            mv.ifne(lblNext);
        } else if (btest == Bool.True) {
            mv.goTo(lblNext);
        }
    }
    /* step 2.b (abrupt completion - break) */
    if (lblBreak.isTarget()) {
        mv.mark(lblBreak);
        restoreEnvironment(savedEnv, mv);
    }
    mv.exitVariableScope();
    /* steps 2.b, 2.g */
    if (btest == Bool.True) {
        if (!result.isAbrupt() && !lblBreak.isTarget()) {
            // infinite loop
            return Completion.Abrupt;
        }
        return result.normal(lblBreak.isTarget());
    }
    return result.normal(lblContinue.isTarget() || lblBreak.isTarget());
}
Also used : ContinueLabel(com.github.anba.es6draft.compiler.Labels.ContinueLabel) LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) BreakLabel(com.github.anba.es6draft.compiler.Labels.BreakLabel) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 17 with Jump

use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.

the class SwitchStatementGenerator method CaseBlockEvaluation.

/**
     * 13.12.9 Runtime Semantics: CaseBlockEvaluation
     * 
     * @param node
     *            the switch statement
     * @param type
     *            the switch statement type
     * @param lblExit
     *            the exit label
     * @param switchValue
     *            the variable which holds the switch value
     * @param mv
     *            the code visitor
     * @return the completion value
     */
private Completion CaseBlockEvaluation(SwitchStatement node, SwitchType type, Jump lblExit, Variable<?> switchValue, CodeVisitor mv) {
    List<SwitchClause> clauses = node.getClauses();
    Jump lblDefault = null;
    Jump[] labels = new Jump[clauses.size()];
    for (int i = 0, size = clauses.size(); i < size; ++i) {
        labels[i] = new Jump();
        if (clauses.get(i).isDefaultClause()) {
            assert lblDefault == null;
            lblDefault = labels[i];
        }
    }
    if (type == SwitchType.Int) {
        emitIntSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
    } else if (type == SwitchType.Char) {
        emitCharSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
    } else if (type == SwitchType.String) {
        emitStringSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
    } else if (type == SwitchType.Generic) {
        emitGenericSwitch(clauses, labels, lblDefault, lblExit, switchValue, mv);
    } else {
        assert type == SwitchType.Default;
        assert switchValue == null;
    // Directly jump to default clause; since switch clauses before default clause are not
    // emitted, jump instruction can be elided as well, so we directly fall into the default
    // clause.
    }
    Completion result = Completion.Normal, lastResult = Completion.Normal;
    if (type == SwitchType.Default) {
        Iterator<SwitchClause> iter = clauses.iterator();
        // skip leading clauses until default clause found
        while (iter.hasNext()) {
            SwitchClause switchClause = iter.next();
            if (switchClause.isDefaultClause()) {
                lastResult = switchClause.accept(this, mv);
                break;
            }
        }
        // handle clauses following default clause until abrupt completion
        while (iter.hasNext() && !lastResult.isAbrupt()) {
            lastResult = iter.next().accept(this, mv);
        }
        result = lastResult;
    } else {
        int index = 0;
        for (SwitchClause switchClause : clauses) {
            Jump caseLabel = labels[index++];
            if (caseLabel != null) {
                mv.mark(caseLabel);
            } else if (lastResult.isAbrupt()) {
                // Ignore unreachable targets
                continue;
            }
            Completion innerResult = switchClause.accept(this, mv);
            if (innerResult.isAbrupt()) {
                // not fall-thru
                result = result.isAbrupt() ? result.select(innerResult) : innerResult;
            }
            lastResult = innerResult;
        }
    }
    return result.normal(lblDefault == null || !lastResult.isAbrupt());
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) SwitchClause(com.github.anba.es6draft.ast.SwitchClause) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 18 with Jump

use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.

the class SwitchStatementGenerator method visit.

/**
     * 13.12.11 Runtime Semantics: Evaluation
     */
@Override
public Completion visit(SwitchStatement node, CodeVisitor mv) {
    // stack -> switchValue
    ValType switchValueType = expression(node.getExpression(), mv);
    SwitchType type = SwitchType.of(node);
    boolean defaultOrReturn = false;
    if (type == SwitchType.Int) {
        if (!switchValueType.isNumeric() && switchValueType != ValType.Any) {
            defaultOrReturn = true;
        }
    } else if (type == SwitchType.Char) {
        if (switchValueType != ValType.String && switchValueType != ValType.Any) {
            defaultOrReturn = true;
        }
    } else if (type == SwitchType.String) {
        if (switchValueType != ValType.String && switchValueType != ValType.Any) {
            defaultOrReturn = true;
        }
    } else if (type == SwitchType.Generic) {
        mv.toBoxed(switchValueType);
        switchValueType = ValType.Any;
    } else {
        assert type == SwitchType.Default;
        defaultOrReturn = true;
    }
    final boolean defaultClausePresent = hasDefaultClause(node);
    if (defaultOrReturn) {
        // never true -> emit default switch or return
        mv.pop(switchValueType);
        if (defaultClausePresent) {
            type = SwitchType.Default;
        } else {
            return Completion.Normal;
        }
    }
    mv.enterVariableScope();
    Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(node, mv);
    Variable<?> switchValue = null;
    if (type != SwitchType.Default) {
        switchValue = mv.newVariable("switchValue", switchValueType.toClass());
        mv.store(switchValue);
    }
    BlockScope scope = node.getScope();
    if (scope.isPresent()) {
        newDeclarativeEnvironment(scope, mv);
        codegen.blockInit(node, mv);
        pushLexicalEnvironment(mv);
    }
    Jump lblExit = new Jump();
    BreakLabel lblBreak = new BreakLabel();
    mv.enterScope(node);
    mv.enterBreakable(node, lblBreak);
    Completion result = CaseBlockEvaluation(node, type, lblExit, switchValue, mv);
    mv.exitBreakable(node);
    mv.exitScope();
    if (!defaultClausePresent) {
        mv.mark(lblExit);
    }
    if (scope.isPresent() && !result.isAbrupt()) {
        popLexicalEnvironment(mv);
    }
    if (lblBreak.isTarget()) {
        mv.mark(lblBreak);
        restoreEnvironment(savedEnv, mv);
    }
    mv.exitVariableScope();
    return result.normal(lblBreak.isTarget());
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) BlockScope(com.github.anba.es6draft.ast.scope.BlockScope) BreakLabel(com.github.anba.es6draft.compiler.Labels.BreakLabel) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 19 with Jump

use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.

the class SwitchStatementGenerator method emitIntSwitch.

/**
     * <h3>int-switch</h3>
     * 
     * <pre>
     * switch (v) {
     * case 0: ...
     * case 1: ...
     * }
     * 
     * var $v = v;
     * if (typeof $v == 'number' {@literal &&} isInt($v)) {
     *   tableswitch|lookupswitch(int($v)) {
     *     int(0): goto L1
     *     int(1): goto L2
     *   }
     *   L1: ...
     *   L2: ...
     * }
     * </pre>
     * 
     * @param clauses
     *            the switch clauses
     * @param labels
     *            the labels for each switch clause
     * @param defaultClause
     *            the label for the default clause
     * @param lblExit
     *            the exit label
     * @param switchValue
     *            the variable which holds the switch value
     * @param mv
     *            the code visitor
     */
private void emitIntSwitch(List<SwitchClause> clauses, Jump[] labels, Jump defaultClause, Jump lblExit, Variable<?> switchValue, CodeVisitor mv) {
    Jump switchDefault = defaultClause != null ? defaultClause : lblExit;
    if (switchValue.getType().equals(Type.INT_TYPE)) {
        mv.load(switchValue);
    } else if (switchValue.getType().equals(Type.LONG_TYPE)) {
        // test for int: value is integer
        mv.load(switchValue);
        mv.dup2();
        mv.l2i();
        mv.i2l();
        mv.lcmp();
        mv.ifne(switchDefault);
        mv.load(switchValue);
        mv.l2i();
    } else if (switchValue.getType().equals(Type.DOUBLE_TYPE)) {
        // test for int: value is integer
        mv.load(switchValue);
        mv.dup2();
        mv.d2i();
        mv.i2d();
        mv.dcmpl();
        mv.ifne(switchDefault);
        mv.load(switchValue);
        mv.d2i();
    } else {
        assert switchValue.getType().equals(Types.Object);
        // test for int: type is java.lang.Number
        mv.load(switchValue);
        mv.instanceOf(Types.Number);
        mv.ifeq(switchDefault);
        // test for int: value is integer
        mv.enterVariableScope();
        Variable<Double> switchValueNum = mv.newVariable("switchValueNum", double.class);
        mv.load(switchValue);
        mv.checkcast(Types.Number);
        mv.invoke(Methods.Number_doubleValue);
        mv.dup2();
        mv.dup2();
        mv.store(switchValueNum);
        mv.d2i();
        mv.i2d();
        mv.dcmpl();
        mv.ifne(switchDefault);
        mv.load(switchValueNum);
        mv.d2i();
        mv.exitVariableScope();
    }
    // emit tableswitch or lookupswitch
    long[] entries = intSwitchEntries(clauses, defaultClause != null);
    switchInstruction(switchDefault, labels, entries, mv);
}
Also used : Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 20 with Jump

use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.

the class StatementGenerator method visitTryCatchFinally.

/**
     * 13.15.8 Runtime Semantics: Evaluation<br>
     * 
     * <code>try-catch-finally</code>
     * 
     * @param node
     *            the try-statement
     * @param mv
     *            the code visitor
     * @return the completion value
     */
private Completion visitTryCatchFinally(TryStatement node, CodeVisitor mv) {
    TryCatchLabel startCatchFinally = new TryCatchLabel();
    TryCatchLabel endCatch = new TryCatchLabel(), handlerCatch = new TryCatchLabel();
    TryCatchLabel endFinally = new TryCatchLabel(), handlerFinally = new TryCatchLabel();
    TryCatchLabel handlerCatchStackOverflow = new TryCatchLabel();
    TryCatchLabel handlerFinallyStackOverflow = new TryCatchLabel();
    Jump noException = new Jump();
    mv.enterVariableScope();
    Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(mv);
    MutableValue<Object> completion = mv.enterFinallyScoped(node);
    /* step 1 */
    // Emit try-block
    mv.mark(startCatchFinally);
    Completion tryResult = emitTryBlock(node, noException, mv);
    mv.mark(endCatch);
    /* steps 2-3 */
    // Emit catch-block
    Completion catchResult = emitCatchBlock(node, savedEnv, handlerCatch, handlerCatchStackOverflow, mv);
    if (!catchResult.isAbrupt()) {
        mv.goTo(noException);
    }
    mv.mark(endFinally);
    // Restore temporary abrupt targets
    List<TempLabel> tempLabels = mv.exitFinallyScoped();
    /* step 4 */
    // Emit finally-block
    Completion finallyResult = emitFinallyBlock(node, savedEnv, completion, tryResult, catchResult, handlerFinally, handlerFinallyStackOverflow, noException, tempLabels, mv);
    mv.exitVariableScope();
    mv.tryCatch(startCatchFinally, endCatch, handlerCatch, Types.ScriptException);
    mv.tryCatch(startCatchFinally, endCatch, handlerCatchStackOverflow, Types.Error);
    mv.tryCatch(startCatchFinally, endFinally, handlerFinally, Types.ScriptException);
    mv.tryCatch(startCatchFinally, endFinally, handlerFinallyStackOverflow, Types.Error);
    /* steps 5-8 */
    return finallyResult.then(tryResult.select(catchResult));
}
Also used : LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) TryCatchLabel(com.github.anba.es6draft.compiler.assembler.TryCatchLabel) ScriptObject(com.github.anba.es6draft.runtime.types.ScriptObject) FunctionObject(com.github.anba.es6draft.runtime.types.builtins.FunctionObject) Jump(com.github.anba.es6draft.compiler.assembler.Jump) TempLabel(com.github.anba.es6draft.compiler.Labels.TempLabel)

Aggregations

Jump (com.github.anba.es6draft.compiler.assembler.Jump)46 LexicalEnvironment (com.github.anba.es6draft.runtime.LexicalEnvironment)14 Name (com.github.anba.es6draft.ast.scope.Name)10 MethodName (com.github.anba.es6draft.compiler.assembler.MethodName)9 DeclarativeEnvironmentRecord (com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord)9 ScriptObject (com.github.anba.es6draft.runtime.types.ScriptObject)8 TryCatchLabel (com.github.anba.es6draft.compiler.assembler.TryCatchLabel)7 GlobalEnvironmentRecord (com.github.anba.es6draft.runtime.GlobalEnvironmentRecord)7 FunctionObject (com.github.anba.es6draft.runtime.types.builtins.FunctionObject)7 ScriptName (com.github.anba.es6draft.compiler.CodeGenerator.ScriptName)6 BreakLabel (com.github.anba.es6draft.compiler.Labels.BreakLabel)6 TempLabel (com.github.anba.es6draft.compiler.Labels.TempLabel)6 Variable (com.github.anba.es6draft.compiler.assembler.Variable)6 EnvironmentRecord (com.github.anba.es6draft.runtime.EnvironmentRecord)6 ContinueLabel (com.github.anba.es6draft.compiler.Labels.ContinueLabel)5 Completion (com.github.anba.es6draft.compiler.StatementGenerator.Completion)5 BlockScope (com.github.anba.es6draft.ast.scope.BlockScope)4 FunctionDeclaration (com.github.anba.es6draft.ast.FunctionDeclaration)3 HoistableDeclaration (com.github.anba.es6draft.ast.HoistableDeclaration)3 ExecutionContext (com.github.anba.es6draft.runtime.ExecutionContext)3