Search in sources :

Example 11 with Jump

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

the class AbstractIterationGenerator method generate.

/**
     * Emit code for the wrapped iteration.
     * 
     * @param node
     *            the ast node
     * @param iterator
     *            the iterator variable
     * @param target
     *            the target label
     * @param mv
     *            the code visitor
     * @return the completion value
     */
public final Completion generate(NODE node, Variable<ITERATOR> iterator, Jump target, CodeVisitor mv) {
    TryCatchLabel startIteration = new TryCatchLabel(), endIteration = new TryCatchLabel();
    TryCatchLabel handlerCatch = new TryCatchLabel();
    TryCatchLabel handlerCatchStackOverflow = null;
    if (codegen.isEnabled(Compiler.Option.IterationCatchStackOverflow)) {
        handlerCatchStackOverflow = new TryCatchLabel();
    }
    boolean hasTarget = target != null;
    if (!hasTarget) {
        target = new Jump();
    }
    mv.enterVariableScope();
    MutableValue<Object> completion = enterIteration(node, mv);
    // Emit loop body
    mv.mark(startIteration);
    Completion loopBodyResult = iterationBody(node, iterator, mv);
    if (!loopBodyResult.isAbrupt()) {
        mv.goTo(target);
    }
    mv.mark(endIteration);
    // Restore temporary abrupt targets
    List<TempLabel> tempLabels = exitIteration(node, mv);
    // Emit throw handler
    Completion throwResult = emitThrowHandler(node, iterator, handlerCatch, handlerCatchStackOverflow, mv);
    // Emit return handler
    Completion returnResult = emitReturnHandler(node, iterator, completion, tempLabels, mv);
    mv.exitVariableScope();
    mv.tryCatch(startIteration, endIteration, handlerCatch, Types.ScriptException);
    if (handlerCatchStackOverflow != null) {
        mv.tryCatch(startIteration, endIteration, handlerCatchStackOverflow, Types.Error);
    }
    if (!hasTarget) {
        mv.mark(target);
        epilogue(node, iterator, mv);
    }
    if (tempLabels.isEmpty()) {
        // No Return handler installed
        return throwResult.select(loopBodyResult);
    }
    return returnResult.select(throwResult.select(loopBodyResult));
}
Also used : Completion(com.github.anba.es6draft.compiler.StatementGenerator.Completion) TryCatchLabel(com.github.anba.es6draft.compiler.assembler.TryCatchLabel) Jump(com.github.anba.es6draft.compiler.assembler.Jump) TempLabel(com.github.anba.es6draft.compiler.Labels.TempLabel)

Example 12 with Jump

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

the class ExpressionGenerator method PerformEval.

/**
     * [18.2.1.1] Direct Call to Eval
     * 
     * @param call
     *            the function call expression
     * @param arguments
     *            the list of function call arguments
     * @param hasThisValue
     *            {@code true} if the thisValue is on the stack
     * @param afterCall
     *            the label after the call instruction
     * @param mv
     *            the code visitor
     */
private void PerformEval(Expression call, List<Expression> arguments, boolean hasThisValue, Jump afterCall, CodeVisitor mv) {
    int evalFlags = EvalFlags.Direct.getValue();
    if (mv.isStrict()) {
        evalFlags |= EvalFlags.Strict.getValue();
    }
    if (mv.isGlobalCode()) {
        evalFlags |= EvalFlags.GlobalCode.getValue();
    }
    if (isGlobalScope(mv.getScope())) {
        evalFlags |= EvalFlags.GlobalScope.getValue();
    }
    if (isGlobalThis(mv.getScope())) {
        evalFlags |= EvalFlags.GlobalThis.getValue();
    }
    if (isEnclosedByWithStatement(mv.getScope())) {
        evalFlags |= EvalFlags.EnclosedByWithStatement.getValue();
    }
    if (!mv.isStrict() && isEnclosedByLexicalDeclaration(mv.getScope())) {
        evalFlags |= EvalFlags.EnclosedByLexicalDeclaration.getValue();
    }
    // stack: [thisValue?, args?, func(Callable)] -> [thisValue?, args?]
    mv.pop();
    // stack: [thisValue?, args?] -> [args?]
    boolean constantArguments = hasConstantArguments(arguments);
    if (hasThisValue) {
        if (constantArguments) {
            // stack: [thisValue] -> []
            mv.pop();
        } else {
            // stack: [thisValue, args] -> [args]
            mv.swap();
            mv.pop();
        }
    }
    if (codegen.isEnabled(CompatibilityOption.Realm)) {
        if (constantArguments) {
            // stack: [] -> [args]
            ArgumentListEvaluation(call, arguments, mv);
        }
        // stack: [args] -> [result]
        mv.loadExecutionContext();
        mv.iconst(evalFlags);
        mv.invoke(Methods.Eval_directEvalWithTranslate);
        mv.goTo(afterCall);
    } else {
        if (arguments.isEmpty()) {
            assert constantArguments : "empty arguments list is constant";
            // stack: [] -> [result]
            mv.loadUndefined();
            mv.goTo(afterCall);
        } else if (hasArguments(arguments)) {
            if (constantArguments) {
                // stack: [] -> [arg_0]
                ValType type = arguments.get(0).accept(this, mv);
                mv.toBoxed(type);
            } else {
                // stack: [args] -> [arg_0]
                mv.iconst(0);
                mv.aaload();
            }
            mv.loadExecutionContext();
            mv.iconst(evalFlags);
            mv.invoke(Methods.Eval_directEval);
            mv.goTo(afterCall);
        } else {
            assert !constantArguments : "spread arguments list is not constant";
            Jump emptyArguments = new Jump();
            mv.dup();
            mv.arraylength();
            mv.ifeq(emptyArguments);
            {
                mv.iconst(0);
                mv.aaload();
                mv.loadExecutionContext();
                mv.iconst(evalFlags);
                mv.invoke(Methods.Eval_directEval);
                mv.goTo(afterCall);
            }
            mv.mark(emptyArguments);
            mv.pop();
            mv.loadUndefined();
            mv.goTo(afterCall);
        }
    }
}
Also used : ValType(com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 13 with Jump

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

the class ExpressionGenerator method visit.

/**
     * 12.13 Conditional Operator ( ? : )
     * <p>
     * 12.13.3 Runtime Semantics: Evaluation
     */
@Override
public ValType visit(ConditionalExpression node, CodeVisitor mv) {
    Jump l0 = new Jump(), l1 = new Jump();
    /* steps 1-2 */
    ValType typeTest = node.getTest().accept(this, mv);
    /* step 2 */
    ToBoolean(typeTest, mv);
    /* step 3 */
    mv.ifeq(l0);
    ValType typeThen = node.getThen().accept(this, mv);
    if (typeThen.isJavaPrimitive()) {
        // Try to avoid boxing if then-and-otherwise are both compatible primitive types.
        ValType expected = expressionType(node.getOtherwise());
        boolean sameType = typeThen == expected;
        if (sameType || (typeThen.isNumeric() && expected.isNumeric())) {
            if (!sameType) {
                ToNumber(typeThen, mv);
            }
            mv.goTo(l1);
            mv.mark(l0);
            ValType typeOtherwise = node.getOtherwise().accept(this, mv);
            assert expected == typeOtherwise : String.format("expected=%s, got=%s", expected, typeOtherwise);
            if (!sameType) {
                ToNumber(typeOtherwise, mv);
            }
            mv.mark(l1);
            return sameType ? typeThen : ValType.Number;
        }
    }
    mv.toBoxed(typeThen);
    mv.goTo(l1);
    /* step 4 */
    mv.mark(l0);
    ValType typeOtherwise = node.getOtherwise().accept(this, mv);
    mv.toBoxed(typeOtherwise);
    mv.mark(l1);
    return typeThen == typeOtherwise ? typeThen : ValType.Any;
}
Also used : ValType(com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType) Jump(com.github.anba.es6draft.compiler.assembler.Jump)

Example 14 with Jump

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

the class StatementGenerator method visit.

/**
     * 14.1.20 Runtime Semantics: Evaluation
     */
@Override
public Completion visit(FunctionDeclaration node, CodeVisitor mv) {
    /* B.3.3 Block-Level Function Declarations Web Legacy Compatibility Semantics */
    if (node.isLegacyBlockScoped()) {
        Name name = node.getIdentifier().getName();
        TopLevelScope top = mv.getScope().getTop();
        if (mv.isFunction()) {
            assert top instanceof FunctionScope;
            Name varName = ((FunctionScope) top).variableScope().resolveName(name, false);
            assert varName != null && name != varName;
            /* step 1.a.ii.3.1 */
            Value<DeclarativeEnvironmentRecord> fenv = getVariableEnvironmentRecord(Types.DeclarativeEnvironmentRecord, mv);
            /* steps 1.a.ii.3.5-6 */
            BindingOp.of(fenv, varName).setMutableBinding(fenv, varName, asm -> {
                Value<DeclarativeEnvironmentRecord> benv = getLexicalEnvironmentRecord(Types.DeclarativeEnvironmentRecord, mv);
                BindingOp.of(benv, name).getBindingValue(benv, name, false, mv);
            }, false, mv);
        } else {
            assert top instanceof ScriptScope;
            Name varName = name;
            int functionId = node.getLegacyBlockScopeId();
            Jump isLegacyScoped = null;
            if (functionId > 0) {
                isLegacyScoped = new Jump();
                mv.loadExecutionContext();
                mv.iconst(functionId);
                mv.invoke(Methods.ScriptRuntime_isLegacyBlockFunction);
                mv.ifeq(isLegacyScoped);
            }
            // The variable environment record is either:
            // 1. The global environment record for global (eval) scripts.
            // 2. Or a (function) declarative environment record for eval in functions.
            // 3. Or a script-context environment record for eval in JSR-223 scripting.
            Value<EnvironmentRecord> genv = getVariableEnvironmentRecord(Types.EnvironmentRecord, mv);
            BindingOp.of(genv, varName).setMutableBinding(genv, varName, asm -> {
                Value<DeclarativeEnvironmentRecord> benv = getLexicalEnvironmentRecord(Types.DeclarativeEnvironmentRecord, mv);
                BindingOp.of(benv, name).getBindingValue(benv, name, false, mv);
            }, false, mv);
            if (isLegacyScoped != null) {
                mv.mark(isLegacyScoped);
            }
        }
    }
    /* step 1 */
    return Completion.Empty;
}
Also used : ScriptScope(com.github.anba.es6draft.ast.scope.ScriptScope) TopLevelScope(com.github.anba.es6draft.ast.scope.TopLevelScope) FunctionScope(com.github.anba.es6draft.ast.scope.FunctionScope) DeclarativeEnvironmentRecord(com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord) Jump(com.github.anba.es6draft.compiler.assembler.Jump) EnvironmentRecord(com.github.anba.es6draft.runtime.EnvironmentRecord) DeclarativeEnvironmentRecord(com.github.anba.es6draft.runtime.DeclarativeEnvironmentRecord) InitializeBoundName(com.github.anba.es6draft.compiler.BindingInitializationGenerator.InitializeBoundName) MethodName(com.github.anba.es6draft.compiler.assembler.MethodName) Name(com.github.anba.es6draft.ast.scope.Name)

Example 15 with Jump

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

the class StatementGenerator method AsyncForInOfBodyEvaluation.

/**
     * 13.7.5.13 Runtime Semantics: ForIn/OfBodyEvaluation (lhs, stmt, iterator, lhsKind, labelSet)
     * <p>
     * stack: [Iterator] {@literal ->} []
     * 
     * @param <FORSTATEMENT>
     *            the for-statement node type
     * @param node
     *            the for-statement node
     * @param mv
     *            the code visitor
     * @return the completion value
     */
private <FORSTATEMENT extends IterationStatement & ForIterationNode> Completion AsyncForInOfBodyEvaluation(FORSTATEMENT node, CodeVisitor mv) {
    assert mv.getStackSize() == 1;
    ContinueLabel lblContinue = new ContinueLabel();
    BreakLabel lblBreak = new BreakLabel();
    Jump enter = new Jump(), test = new Jump();
    mv.enterVariableScope();
    Variable<ScriptObject> iterator = mv.newVariable("iter", ScriptObject.class);
    // stack: [Iterator] -> []
    mv.store(iterator);
    Variable<ScriptObject> nextResult = mv.newVariable("nextResult", ScriptObject.class);
    mv.anull();
    mv.store(nextResult);
    Variable<Object> nextValue = mv.newVariable("nextValue", Object.class);
    mv.anull();
    mv.store(nextValue);
    Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(node, mv);
    /* step 2 */
    if (node.hasCompletionValue()) {
        mv.storeUndefinedAsCompletionValue();
    }
    /* steps 3-4 (not applicable) */
    /* step 5 (repeat loop) */
    mv.nonDestructiveGoTo(test);
    /* steps 5.d-e */
    mv.mark(enter);
    IteratorValue(node, nextResult, mv);
    await(node, mv);
    mv.store(nextValue);
    /* steps 5.f-l */
    {
        mv.enterIteration(node, lblBreak, lblContinue);
        mv.enterWrapped();
        new AbstractIterationGenerator<FORSTATEMENT, ScriptObject>(codegen) {

            @Override
            protected Completion iterationBody(FORSTATEMENT node, Variable<ScriptObject> iterator, CodeVisitor mv) {
                return ForInOfBodyEvaluationInner(node, nextValue, mv);
            }

            @Override
            protected MutableValue<Object> enterIteration(FORSTATEMENT node, CodeVisitor mv) {
                return mv.enterIterationBody(node);
            }

            @Override
            protected List<TempLabel> exitIteration(FORSTATEMENT node, CodeVisitor mv) {
                return mv.exitIterationBody(node);
            }

            @Override
            protected void IteratorClose(FORSTATEMENT node, Variable<ScriptObject> iterator, Variable<? extends Throwable> throwable, CodeVisitor mv) {
                asyncIteratorClose(node, iterator, throwable, mv);
            }

            @Override
            protected void IteratorClose(FORSTATEMENT node, Variable<ScriptObject> iterator, CodeVisitor mv) {
                asyncIteratorClose(node, iterator, mv);
            }
        }.generate(node, iterator, test, mv);
        mv.exitWrapped();
        mv.exitIteration(node);
    }
    /* steps 5.m-n */
    if (lblContinue.isTarget()) {
        mv.mark(lblContinue);
        restoreEnvironment(savedEnv, mv);
    }
    /* steps 5.a-c */
    mv.mark(test);
    IteratorNext(node, iterator, mv);
    await(node, mv);
    // FIXME: spec bug - missing type check after await
    requireObjectResult(node, "next", mv);
    mv.store(nextResult);
    IteratorComplete(node, nextResult, mv);
    mv.ifeq(enter);
    /* steps 5.m-n */
    if (lblBreak.isTarget()) {
        mv.mark(lblBreak);
        restoreEnvironment(savedEnv, mv);
    }
    mv.exitVariableScope();
    return Completion.Normal;
}
Also used : ScriptObject(com.github.anba.es6draft.runtime.types.ScriptObject) Variable(com.github.anba.es6draft.compiler.assembler.Variable) Jump(com.github.anba.es6draft.compiler.assembler.Jump) TempLabel(com.github.anba.es6draft.compiler.Labels.TempLabel) ContinueLabel(com.github.anba.es6draft.compiler.Labels.ContinueLabel) LexicalEnvironment(com.github.anba.es6draft.runtime.LexicalEnvironment) ScriptObject(com.github.anba.es6draft.runtime.types.ScriptObject) FunctionObject(com.github.anba.es6draft.runtime.types.builtins.FunctionObject) BreakLabel(com.github.anba.es6draft.compiler.Labels.BreakLabel)

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