use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class FunctionCodeGenerator method returnResultOrThis.
/**
* Generate bytecode for:
*
* <pre>
* if (tailCall && result instanceof TailCallInvocation) {
* return ((TailCallInvocation) result).toConstructTailCall(thisArgument);
* }
* if (Type.isObject(result)) {
* return Type.objectValue(result);
* }
* return thisArgument;
* </pre>
*
* @param thisArgument
* the variable which holds the thisArgument
* @param tailCall
* {@code true} if the constructor function contains a tail-call
* @param mv
* the instruction visitor
*/
private void returnResultOrThis(Variable<ScriptObject> thisArgument, boolean tailCall, InstructionVisitor mv) {
if (tailCall) {
Jump noTailCall = new Jump();
mv.dup();
mv.instanceOf(Types.TailCallInvocation);
mv.ifeq(noTailCall);
{
mv.checkcast(Types.TailCallInvocation);
mv.load(thisArgument);
mv.invoke(Methods.TailCallInvocation_toConstructTailCall);
mv._return();
}
mv.mark(noTailCall);
}
Jump noResult = new Jump();
mv.dup();
mv.instanceOf(Types.ScriptObject);
mv.ifeq(noResult);
{
mv.checkcast(Types.ScriptObject);
mv._return();
}
mv.mark(noResult);
mv.pop();
mv.load(thisArgument);
mv._return();
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class StatementGenerator method visitTryFinally.
/**
* 13.15.8 Runtime Semantics: Evaluation<br>
*
* <code>try-finally</code>
*
* @param node
* the try-statement
* @param mv
* the code visitor
* @return the completion value
*/
private Completion visitTryFinally(TryStatement node, CodeVisitor mv) {
TryCatchLabel startFinally = new TryCatchLabel(), endFinally = new TryCatchLabel();
TryCatchLabel handlerFinally = 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(startFinally);
Completion tryResult = emitTryBlock(node, noException, mv);
mv.mark(endFinally);
// Restore temporary abrupt targets
List<TempLabel> tempLabels = mv.exitFinallyScoped();
/* step 2 */
// Emit finally-block
Completion finallyResult = emitFinallyBlock(node, savedEnv, completion, tryResult, Completion.Abrupt, handlerFinally, handlerFinallyStackOverflow, noException, tempLabels, mv);
mv.exitVariableScope();
mv.tryCatch(startFinally, endFinally, handlerFinally, Types.ScriptException);
mv.tryCatch(startFinally, endFinally, handlerFinallyStackOverflow, Types.Error);
/* steps 3-6 */
return finallyResult.then(tryResult);
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class StatementGenerator method visitTryCatch.
/**
* 13.15.8 Runtime Semantics: Evaluation<br>
*
* <code>try-catch</code>
*
* @param node
* the try-statement
* @param mv
* the code visitor
* @return the completion value
*/
private Completion visitTryCatch(TryStatement node, CodeVisitor mv) {
TryCatchLabel startCatch = new TryCatchLabel(), endCatch = new TryCatchLabel();
TryCatchLabel handlerCatch = new TryCatchLabel();
TryCatchLabel handlerCatchStackOverflow = new TryCatchLabel();
Jump exceptionHandled = new Jump();
mv.enterVariableScope();
Variable<LexicalEnvironment<?>> savedEnv = saveEnvironment(mv);
/* step 1 */
// Emit try-block
mv.mark(startCatch);
Completion tryResult = emitTryBlock(node, exceptionHandled, mv);
mv.mark(endCatch);
/* step 2 */
// Emit catch-block
Completion catchResult = emitCatchBlock(node, savedEnv, handlerCatch, handlerCatchStackOverflow, mv);
/* step 3 */
if (!tryResult.isAbrupt()) {
mv.mark(exceptionHandled);
}
mv.exitVariableScope();
mv.tryCatch(startCatch, endCatch, handlerCatch, Types.ScriptException);
mv.tryCatch(startCatch, endCatch, handlerCatchStackOverflow, Types.Error);
/* steps 4-6 */
return tryResult.select(catchResult);
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class SwitchStatementGenerator method emitCharSwitch.
/**
* <h3>char-switch</h3>
*
* <pre>
* switch (v) {
* case "a": ...
* case "b": ...
* }
*
* var $v = v;
* if (typeof $v == 'string' {@literal &&} length($v) == 1) {
* tableswitch|lookupswitch(charCodeAt($v, 0)) {
* charCodeAt("a", 0): goto L1
* charCodeAt("b", 0): 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 emitCharSwitch(List<SwitchClause> clauses, Jump[] labels, Jump defaultClause, Jump lblExit, Variable<?> switchValue, CodeVisitor mv) {
Jump switchDefault = defaultClause != null ? defaultClause : lblExit;
if (switchValue.getType().equals(Types.CharSequence)) {
// test for char: value is character (string with only one character)
mv.load(switchValue);
mv.invoke(Methods.CharSequence_length);
mv.iconst(1);
mv.ificmpne(switchDefault);
mv.load(switchValue);
mv.iconst(0);
mv.invoke(Methods.CharSequence_charAt);
// mv.cast(Type.CHAR_TYPE, Type.INT_TYPE);
} else {
assert switchValue.getType().equals(Types.Object);
// test for char: type is java.lang.CharSequence
mv.load(switchValue);
mv.instanceOf(Types.CharSequence);
mv.ifeq(switchDefault);
// test for char: value is character (string with only one character)
mv.enterVariableScope();
Variable<CharSequence> switchValueChar = mv.newVariable("switchValueChar", CharSequence.class);
mv.load(switchValue);
mv.checkcast(Types.CharSequence);
mv.dup();
mv.store(switchValueChar);
mv.invoke(Methods.CharSequence_length);
mv.iconst(1);
mv.ificmpne(switchDefault);
mv.load(switchValueChar);
mv.iconst(0);
mv.invoke(Methods.CharSequence_charAt);
// mv.cast(Type.CHAR_TYPE, Type.INT_TYPE);
mv.exitVariableScope();
}
// emit tableswitch or lookupswitch
long[] entries = charSwitchEntries(clauses, defaultClause != null);
switchInstruction(switchDefault, labels, entries, mv);
}
use of com.github.anba.es6draft.compiler.assembler.Jump in project es6draft by anba.
the class SwitchStatementGenerator method emitStringSwitch.
/**
* <h3>String-switch</h3>
*
* <pre>
* switch (v) {
* case "key1": ...
* case "key2": ...
* }
*
* var $v = v;
* if (typeof $v == 'string') {
* lookupswitch(hashCode($v)) {
* hashCode("key1"): goto L1
* hashCode("key2"): goto L2
* }
* L1: if (equals($v, "key1")) ...
* L2: if (equals($v, "key2")) ...
* }
* </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 emitStringSwitch(List<SwitchClause> clauses, Jump[] labels, Jump defaultClause, Jump lblExit, Variable<?> switchValue, CodeVisitor mv) {
Jump switchDefault = defaultClause != null ? defaultClause : lblExit;
mv.enterVariableScope();
Variable<String> switchValueString = mv.newVariable("switchValueString", String.class);
if (switchValue.getType().equals(Types.CharSequence)) {
mv.load(switchValue);
mv.invoke(Methods.CharSequence_toString);
mv.dup();
mv.store(switchValueString);
mv.invoke(Methods.String_hashCode);
} else {
assert switchValue.getType().equals(Types.Object);
// test for string: type is java.lang.CharSequence
mv.load(switchValue);
mv.instanceOf(Types.CharSequence);
mv.ifeq(switchDefault);
mv.load(switchValue);
mv.checkcast(Types.CharSequence);
mv.invoke(Methods.CharSequence_toString);
mv.dup();
mv.store(switchValueString);
mv.invoke(Methods.String_hashCode);
}
long[] entries = stringSwitchEntries(clauses, defaultClause != null);
int distinctValues = distinctValues(entries);
Jump[] switchLabels = new Jump[distinctValues];
int[] switchKeys = new int[distinctValues];
for (int i = 0, j = 0, lastValue = 0, length = entries.length; i < length; ++i) {
int value = Value(entries[i]);
if (i == 0 || value != lastValue) {
switchLabels[j] = new Jump();
switchKeys[j] = value;
j += 1;
}
lastValue = value;
}
// emit lookupswitch
mv.lookupswitch(switchDefault, switchKeys, switchLabels);
// add String.equals() calls
for (int i = 0, j = 0, lastValue = 0, length = entries.length; i < length; ++i) {
int value = Value(entries[i]);
int index = Index(entries[i]);
if (i == 0 || value != lastValue) {
if (i != 0) {
mv.goTo(switchDefault);
}
mv.mark(switchLabels[j++]);
}
String string = ((StringLiteral) clauses.get(index).getExpression()).getValue();
mv.load(switchValueString);
mv.aconst(string);
mv.invoke(Methods.String_equals);
mv.ifne(labels[index]);
lastValue = value;
}
mv.goTo(switchDefault);
mv.exitVariableScope();
}
Aggregations