Search in sources :

Example 1 with ResumptionPoint

use of com.github.anba.es6draft.runtime.internal.ResumptionPoint in project es6draft by anba.

the class CodeVisitor method resume.

/**
     * Resume: Restores the locals and stack and jumps to the resumption point.
     * 
     * @param resume
     *            the variable which holds the resumption point
     * @param state
     *            the execution state
     */
private void resume(MutableValue<ResumptionPoint> resume, ExecutionState state) {
    assert hasStack();
    assert getStackSize() == 0;
    VariablesSnapshot variables = state.locals;
    boolean hasLocals = variables.getSize() > 0;
    // Emit line info for debugging.
    lineInfo(state.line);
    // (1) Restore locals
    if (hasLocals) {
        // stack: [] -> [<locals>]
        load(resume);
        invoke(Methods.ResumptionPoint_getLocals);
        // manually restore locals type information
        restoreVariables(variables);
        int index = 0;
        for (Variable<?> v : variables) {
            // stack: [<locals>] -> [<locals>, value]
            dup();
            loadFromArray(index++, v.getType());
            // stack: [<locals>, value] -> [<locals>]
            store(v);
        }
        // stack: [<locals>] -> []
        pop();
    }
    // stack: [] -> [<stack>]
    assert getStackSize() == 0;
    restoreStack(resume, state);
    assert Arrays.equals(state.stack, getStack()) : String.format("%s != %s", Arrays.toString(state.stack), Arrays.toString(getStack()));
    // stack: [...] -> [..., offset]
    boolean hasShared = state.shared != null;
    if (hasShared) {
        load(resume);
        invoke(Methods.ResumptionPoint_getOffset);
    }
    // Clear resume parameter to avoid leaking saved state.
    store(resume, anullValue());
    if (hasShared) {
        // stack: [..., offset] -> [...]
        InlineArrayList<ExecutionState> sharedStates = state.shared;
        int sharedSize = sharedStates.size();
        assert sharedSize > 0;
        if (sharedSize == 1) {
            iconst(state.offset);
            ificmpeq(state.instruction);
            goTo(sharedStates.get(0).instruction);
        } else {
            Jump[] restore = new Jump[sharedSize];
            for (int i = 0; i < sharedSize; ++i) {
                restore[i] = sharedStates.get(i).instruction;
            }
            int firstOffset = sharedStates.get(0).offset;
            int lastOffset = sharedStates.get(sharedSize - 1).offset;
            boolean consecutiveOffsets = (lastOffset - firstOffset) == (sharedSize - 1);
            if (consecutiveOffsets) {
                tableswitch(firstOffset, lastOffset, state.instruction, restore);
            } else {
                int[] keys = new int[sharedSize];
                for (int i = 0; i < sharedSize; ++i) {
                    keys[i] = sharedStates.get(i).offset;
                }
                lookupswitch(state.instruction, keys, restore);
            }
        }
    } else {
        goTo(state.instruction);
    }
}
Also used : ResumptionPoint(com.github.anba.es6draft.runtime.internal.ResumptionPoint)

Example 2 with ResumptionPoint

use of com.github.anba.es6draft.runtime.internal.ResumptionPoint in project es6draft by anba.

the class CodeVisitor method generatorEpilogue.

/**
     * Generates epilogue code for generator functions.
     * 
     * @param state
     *            the generator state
     */
final void generatorEpilogue(GeneratorState state) {
    mark(state.resumeSwitch);
    ArrayList<ExecutionState> states = this.states;
    if (states == null) {
        goTo(state.startBody);
    } else {
        MutableValue<ResumptionPoint> resume = resumptionPoint();
        int count = stateOffsetCounter;
        int uniqueCount = states.size();
        assert count > 0 && uniqueCount > 0;
        if (uniqueCount == 1) {
            resume(resume, states.get(0));
        } else {
            Jump[] restore = new Jump[count];
            for (ExecutionState execState : states) {
                Jump target = new Jump();
                restore[execState.offset] = target;
                if (execState.shared != null) {
                    for (ExecutionState shared : execState.shared) {
                        restore[shared.offset] = target;
                    }
                }
            }
            load(resume);
            invoke(Methods.ResumptionPoint_getOffset);
            tableswitch(0, count - 1, state.startBody, restore);
            for (ExecutionState execState : states) {
                mark(restore[execState.offset]);
                resume(resume, execState);
            }
        }
    }
}
Also used : ResumptionPoint(com.github.anba.es6draft.runtime.internal.ResumptionPoint) ResumptionPoint(com.github.anba.es6draft.runtime.internal.ResumptionPoint)

Example 3 with ResumptionPoint

use of com.github.anba.es6draft.runtime.internal.ResumptionPoint in project es6draft by anba.

the class CodeVisitor method newExecutionState.

/**
     * Creates a new object to save the current execution state.
     * 
     * @param instruction
     *            the resume instruction
     * @return the current execution state
     */
private ExecutionState newExecutionState(Jump instruction) {
    if (states == null) {
        states = new ArrayList<>();
    }
    assert hasParameter(CONTEXT_SLOT, ExecutionContext.class);
    assert hasParameter(RESUME_SLOT, ResumptionPoint.class) || hasParameter(RESUME_SLOT, ResumptionPoint[].class);
    VariablesSnapshot locals = getVariablesSnapshot(MIN_RECOVER_SLOT);
    Type[] stack = getStack();
    int offset = stateOffsetCounter++;
    int line = getLastLineNumber();
    for (ExecutionState state : states) {
        if (state.isCompatible(locals, stack)) {
            return state.addShared(instruction, offset, line);
        }
    }
    ExecutionState state = new ExecutionState(locals, stack, instruction, offset, line);
    states.add(state);
    return state;
}
Also used : ValType(com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType) MethodType(java.lang.invoke.MethodType) ResumptionPoint(com.github.anba.es6draft.runtime.internal.ResumptionPoint) ResumptionPoint(com.github.anba.es6draft.runtime.internal.ResumptionPoint)

Aggregations

ResumptionPoint (com.github.anba.es6draft.runtime.internal.ResumptionPoint)3 ValType (com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType)1 MethodType (java.lang.invoke.MethodType)1