use of org.mozilla.javascript.ast.Jump in project hackpad by dropbox.
the class CodeGenerator method visitStatement.
private void visitStatement(Node node, int initialStackDepth) {
int type = node.getType();
Node child = node.getFirstChild();
switch(type) {
case Token.FUNCTION:
{
int fnIndex = node.getExistingIntProp(Node.FUNCTION_PROP);
int fnType = scriptOrFn.getFunctionNode(fnIndex).getFunctionType();
// at statement level, they must only be present as expressions.
if (fnType == FunctionNode.FUNCTION_EXPRESSION_STATEMENT) {
addIndexOp(Icode_CLOSURE_STMT, fnIndex);
} else {
if (fnType != FunctionNode.FUNCTION_STATEMENT) {
throw Kit.codeBug();
}
}
// function, not undefined.
if (!itsInFunctionFlag) {
addIndexOp(Icode_CLOSURE_EXPR, fnIndex);
stackChange(1);
addIcode(Icode_POP_RESULT);
stackChange(-1);
}
}
break;
case Token.LABEL:
case Token.LOOP:
case Token.BLOCK:
case Token.EMPTY:
case Token.WITH:
updateLineNumber(node);
case Token.SCRIPT:
// fall through
while (child != null) {
visitStatement(child, initialStackDepth);
child = child.getNext();
}
break;
case Token.ENTERWITH:
visitExpression(child, 0);
addToken(Token.ENTERWITH);
stackChange(-1);
break;
case Token.LEAVEWITH:
addToken(Token.LEAVEWITH);
break;
case Token.LOCAL_BLOCK:
{
int local = allocLocal();
node.putIntProp(Node.LOCAL_PROP, local);
updateLineNumber(node);
while (child != null) {
visitStatement(child, initialStackDepth);
child = child.getNext();
}
addIndexOp(Icode_LOCAL_CLEAR, local);
releaseLocal(local);
}
break;
case Token.DEBUGGER:
addIcode(Icode_DEBUGGER);
break;
case Token.SWITCH:
updateLineNumber(node);
// See comments in IRFactory.createSwitch() for description
// of SWITCH node
{
visitExpression(child, 0);
for (Jump caseNode = (Jump) child.getNext(); caseNode != null; caseNode = (Jump) caseNode.getNext()) {
if (caseNode.getType() != Token.CASE)
throw badTree(caseNode);
Node test = caseNode.getFirstChild();
addIcode(Icode_DUP);
stackChange(1);
visitExpression(test, 0);
addToken(Token.SHEQ);
stackChange(-1);
// If true, Icode_IFEQ_POP will jump and remove case
// value from stack
addGoto(caseNode.target, Icode_IFEQ_POP);
stackChange(-1);
}
addIcode(Icode_POP);
stackChange(-1);
}
break;
case Token.TARGET:
markTargetLabel(node);
break;
case Token.IFEQ:
case Token.IFNE:
{
Node target = ((Jump) node).target;
visitExpression(child, 0);
addGoto(target, type);
stackChange(-1);
}
break;
case Token.GOTO:
{
Node target = ((Jump) node).target;
addGoto(target, type);
}
break;
case Token.JSR:
{
Node target = ((Jump) node).target;
addGoto(target, Icode_GOSUB);
}
break;
case Token.FINALLY:
{
// Account for incomming GOTOSUB address
stackChange(1);
int finallyRegister = getLocalBlockRef(node);
addIndexOp(Icode_STARTSUB, finallyRegister);
stackChange(-1);
while (child != null) {
visitStatement(child, initialStackDepth);
child = child.getNext();
}
addIndexOp(Icode_RETSUB, finallyRegister);
}
break;
case Token.EXPR_VOID:
case Token.EXPR_RESULT:
updateLineNumber(node);
visitExpression(child, 0);
addIcode((type == Token.EXPR_VOID) ? Icode_POP : Icode_POP_RESULT);
stackChange(-1);
break;
case Token.TRY:
{
Jump tryNode = (Jump) node;
int exceptionObjectLocal = getLocalBlockRef(tryNode);
int scopeLocal = allocLocal();
addIndexOp(Icode_SCOPE_SAVE, scopeLocal);
int tryStart = iCodeTop;
boolean savedFlag = itsInTryFlag;
itsInTryFlag = true;
while (child != null) {
visitStatement(child, initialStackDepth);
child = child.getNext();
}
itsInTryFlag = savedFlag;
Node catchTarget = tryNode.target;
if (catchTarget != null) {
int catchStartPC = labelTable[getTargetLabel(catchTarget)];
addExceptionHandler(tryStart, catchStartPC, catchStartPC, false, exceptionObjectLocal, scopeLocal);
}
Node finallyTarget = tryNode.getFinally();
if (finallyTarget != null) {
int finallyStartPC = labelTable[getTargetLabel(finallyTarget)];
addExceptionHandler(tryStart, finallyStartPC, finallyStartPC, true, exceptionObjectLocal, scopeLocal);
}
addIndexOp(Icode_LOCAL_CLEAR, scopeLocal);
releaseLocal(scopeLocal);
}
break;
case Token.CATCH_SCOPE:
{
int localIndex = getLocalBlockRef(node);
int scopeIndex = node.getExistingIntProp(Node.CATCH_SCOPE_PROP);
String name = child.getString();
child = child.getNext();
// load expression object
visitExpression(child, 0);
addStringPrefix(name);
addIndexPrefix(localIndex);
addToken(Token.CATCH_SCOPE);
addUint8(scopeIndex != 0 ? 1 : 0);
stackChange(-1);
}
break;
case Token.THROW:
updateLineNumber(node);
visitExpression(child, 0);
addToken(Token.THROW);
addUint16(lineNumber & 0xFFFF);
stackChange(-1);
break;
case Token.RETHROW:
updateLineNumber(node);
addIndexOp(Token.RETHROW, getLocalBlockRef(node));
break;
case Token.RETURN:
updateLineNumber(node);
if (node.getIntProp(Node.GENERATOR_END_PROP, 0) != 0) {
// We're in a generator, so change RETURN to GENERATOR_END
addIcode(Icode_GENERATOR_END);
addUint16(lineNumber & 0xFFFF);
} else if (child != null) {
visitExpression(child, ECF_TAIL);
addToken(Token.RETURN);
stackChange(-1);
} else {
addIcode(Icode_RETUNDEF);
}
break;
case Token.RETURN_RESULT:
updateLineNumber(node);
addToken(Token.RETURN_RESULT);
break;
case Token.ENUM_INIT_KEYS:
case Token.ENUM_INIT_VALUES:
case Token.ENUM_INIT_ARRAY:
visitExpression(child, 0);
addIndexOp(type, getLocalBlockRef(node));
stackChange(-1);
break;
case Icode_GENERATOR:
break;
default:
throw badTree(node);
}
if (stackDepth != initialStackDepth) {
throw Kit.codeBug();
}
}
use of org.mozilla.javascript.ast.Jump in project hackpad by dropbox.
the class BodyCodegen method visitSwitch.
private void visitSwitch(Jump switchNode, Node child) {
// See comments in IRFactory.createSwitch() for description
// of SWITCH node
generateExpression(child, switchNode);
// save selector value
short selector = getNewWordLocal();
cfw.addAStore(selector);
for (Jump caseNode = (Jump) child.getNext(); caseNode != null; caseNode = (Jump) caseNode.getNext()) {
if (caseNode.getType() != Token.CASE)
throw Codegen.badTree();
Node test = caseNode.getFirstChild();
generateExpression(test, caseNode);
cfw.addALoad(selector);
addScriptRuntimeInvoke("shallowEq", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + ")Z");
addGoto(caseNode.target, ByteCode.IFNE);
}
releaseWordLocal(selector);
}
use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class BodyCodegen method visitSwitch.
private void visitSwitch(Jump switchNode, Node child) {
// See comments in IRFactory.createSwitch() for description
// of SWITCH node
generateExpression(child, switchNode);
// save selector value
short selector = getNewWordLocal();
cfw.addAStore(selector);
for (Jump caseNode = (Jump) child.getNext(); caseNode != null; caseNode = (Jump) caseNode.getNext()) {
if (caseNode.getType() != Token.CASE)
throw Codegen.badTree();
Node test = caseNode.getFirstChild();
generateExpression(test, caseNode);
cfw.addALoad(selector);
addScriptRuntimeInvoke("shallowEq", "(Ljava/lang/Object;" + "Ljava/lang/Object;" + ")Z");
addGoto(caseNode.target, ByteCode.IFNE);
}
releaseWordLocal(selector);
}
use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class IRFactory method createLoop.
private Node createLoop(Jump loop, int loopType, Node body, Node cond, Node init, Node incr) {
Node bodyTarget = Node.newTarget();
Node condTarget = Node.newTarget();
if (loopType == LOOP_FOR && cond.getType() == Token.EMPTY) {
cond = new Node(Token.TRUE);
}
Jump IFEQ = new Jump(Token.IFEQ, cond);
IFEQ.target = bodyTarget;
Node breakTarget = Node.newTarget();
loop.addChildToBack(bodyTarget);
loop.addChildrenToBack(body);
if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
// propagate lineno to condition
loop.addChildrenToBack(new Node(Token.EMPTY, loop.getLineno()));
}
loop.addChildToBack(condTarget);
loop.addChildToBack(IFEQ);
loop.addChildToBack(breakTarget);
loop.target = breakTarget;
Node continueTarget = condTarget;
if (loopType == LOOP_WHILE || loopType == LOOP_FOR) {
// Just add a GOTO to the condition in the do..while
loop.addChildToFront(makeJump(Token.GOTO, condTarget));
if (loopType == LOOP_FOR) {
int initType = init.getType();
if (initType != Token.EMPTY) {
if (initType != Token.VAR && initType != Token.LET) {
init = new Node(Token.EXPR_VOID, init);
}
loop.addChildToFront(init);
}
Node incrTarget = Node.newTarget();
loop.addChildAfter(incrTarget, body);
if (incr.getType() != Token.EMPTY) {
incr = new Node(Token.EXPR_VOID, incr);
loop.addChildAfter(incr, incrTarget);
}
continueTarget = incrTarget;
}
}
loop.setContinue(continueTarget);
return loop;
}
use of org.mozilla.javascript.ast.Jump in project HL4A by HL4A.
the class IRFactory method closeSwitch.
private void closeSwitch(Node switchBlock) {
if (switchBlock.getType() != Token.BLOCK)
throw Kit.codeBug();
Jump switchNode = (Jump) switchBlock.getFirstChild();
if (switchNode.getType() != Token.SWITCH)
throw Kit.codeBug();
Node switchBreakTarget = Node.newTarget();
// switchNode.target is only used by NodeTransformer
// to detect switch end
switchNode.target = switchBreakTarget;
Node defaultTarget = switchNode.getDefault();
if (defaultTarget == null) {
defaultTarget = switchBreakTarget;
}
switchBlock.addChildAfter(makeJump(Token.GOTO, defaultTarget), switchNode);
switchBlock.addChildToBack(switchBreakTarget);
}
Aggregations