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