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);
}
}
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);
}
}
}
}
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;
}
Aggregations