/** * ...IterationStatement : * ... * while ( Expression ) Statement * ... * * See 12.6 * * Parse while statement. */ private void whileStatement() { // Capture WHILE token. final long whileToken = token; // WHILE tested in caller. next(); // Construct WHILE node. WhileNode whileNode = new WhileNode(line, whileToken, Token.descPosition(whileToken), false); lc.push(whileNode); try { expect(LPAREN); final int whileLine = line; final JoinPredecessorExpression test = joinPredecessorExpression(); expect(RPAREN); final Block body = getStatement(); appendStatement(whileNode = new WhileNode(whileLine, whileToken, finish, false). setTest(lc, test). setBody(lc, body)); } finally { lc.pop(whileNode); } }
@Override public boolean enterForNode(final ForNode forNode) { if(!reachable) { return false; } final Expression init = forNode.getInit(); if(forNode.isForIn()) { final JoinPredecessorExpression iterable = forNode.getModify(); iterable.accept(this); enterTestFirstLoop(forNode, null, init, // If we're iterating over property names, and we can discern from the runtime environment // of the compilation that the object being iterated over must use strings for property // names (e.g., it is a native JS object or array), then we'll not bother trying to treat // the property names optimistically. !compiler.useOptimisticTypes() || (!forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression()))); } else { if(init != null) { init.accept(this); } enterTestFirstLoop(forNode, forNode.getModify(), null, false); } return false; }
@Override public boolean enterForNode(final ForNode forNode) { if(!reachable) { return false; } final Expression init = forNode.getInit(); if(forNode.isForInOrOf()) { final JoinPredecessorExpression iterable = forNode.getModify(); visitExpression(iterable); enterTestFirstLoop(forNode, null, init, // If we're iterating over property names, and we can discern from the runtime environment // of the compilation that the object being iterated over must use strings for property // names (e.g., it is a native JS object or array), then we'll not bother trying to treat // the property names optimistically. !compiler.useOptimisticTypes() || (!forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression()))); } else { if(init != null) { visitExpressionOnEmptyStack(init); } enterTestFirstLoop(forNode, forNode.getModify(), null, false); } assertTypeStackIsEmpty(); return false; }
@Override public boolean enterForNode(final ForNode forNode) { if(!reachable) { return false; } final Expression init = forNode.getInit(); if(forNode.isForIn()) { final JoinPredecessorExpression iterable = forNode.getModify(); visitExpression(iterable); enterTestFirstLoop(forNode, null, init, // If we're iterating over property names, and we can discern from the runtime environment // of the compilation that the object being iterated over must use strings for property // names (e.g., it is a native JS object or array), then we'll not bother trying to treat // the property names optimistically. !compiler.useOptimisticTypes() || (!forNode.isForEach() && compiler.hasStringPropertyIterator(iterable.getExpression()))); } else { if(init != null) { visitExpressionOnEmptyStack(init); } enterTestFirstLoop(forNode, forNode.getModify(), null, false); } assertTypeStackIsEmpty(); return false; }
/** * ...IterationStatement : * ... * do Statement while( Expression ) ; * ... * * See 12.6 * * Parse DO WHILE statement. */ private void doStatement() { // Capture DO token. final long doToken = token; // DO tested in the caller. next(); WhileNode doWhileNode = new WhileNode(-1, doToken, Token.descPosition(doToken), true); lc.push(doWhileNode); try { // Get DO body. final Block body = getStatement(); expect(WHILE); expect(LPAREN); final int doLine = line; final JoinPredecessorExpression test = joinPredecessorExpression(); expect(RPAREN); if (type == SEMICOLON) { endOfLine(); } doWhileNode.setFinish(finish); //line number is last appendStatement(doWhileNode = new WhileNode(doLine, doToken, finish, true). setBody(lc, body). setTest(lc, test)); } finally { lc.pop(doWhileNode); } }
@Override public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinPredecessorExpression) { final Expression expr = joinPredecessorExpression.getExpression(); if(expr != null) { expr.accept(this); } else { nullValue(); } return false; }
private void optimizeLogicalOperand(final Expression expr, final Label label, final boolean state, final boolean isRhs) { final JoinPredecessorExpression jpexpr = (JoinPredecessorExpression)expr; if(LocalVariableConversion.hasLiveConversion(jpexpr)) { final Label after = new Label("after"); branchOptimizer(jpexpr.getExpression(), after, !state); method.beforeJoinPoint(jpexpr); method._goto(label); method.label(after); if(isRhs) { method.beforeJoinPoint(jpexpr); } } else { branchOptimizer(jpexpr.getExpression(), label, state); } }
private void enterDoWhileLoop(final WhileNode loopNode) { final JoinPredecessorExpression test = loopNode.getTest(); final Block body = loopNode.getBody(); final Label continueLabel = loopNode.getContinueLabel(); final Label breakLabel = loopNode.getBreakLabel(); final Map<Symbol, LvarType> beforeLoopTypes = localVariableTypes; final Label repeatLabel = new Label(""); for(;;) { jumpToLabel(loopNode, repeatLabel, beforeLoopTypes); final Map<Symbol, LvarType> beforeRepeatTypes = localVariableTypes; body.accept(this); if(reachable) { jumpToLabel(body, continueLabel); } joinOnLabel(continueLabel); if(!reachable) { break; } test.accept(this); jumpToLabel(test, breakLabel); if(isAlwaysFalse(test)) { break; } jumpToLabel(test, repeatLabel); joinOnLabel(repeatLabel); if(localVariableTypes.equals(beforeRepeatTypes)) { break; } resetJoinPoint(continueLabel); resetJoinPoint(breakLabel); resetJoinPoint(repeatLabel); } if(isAlwaysTrue(test)) { doesNotContinueSequentially(); } leaveBreakable(loopNode); }
private void enterDoWhile(final WhileNode whileNode) { final int liveLocalsOnContinueOrBreak = method.getUsedSlotsWithLiveTemporaries(); method.beforeJoinPoint(whileNode); final Block body = whileNode.getBody(); body.accept(this); emitContinueLabel(whileNode.getContinueLabel(), liveLocalsOnContinueOrBreak); if(method.isReachable()) { lineNumber(whileNode); final JoinPredecessorExpression test = whileNode.getTest(); final Label bodyEntryLabel = body.getEntryLabel(); final boolean testHasLiveConversion = LocalVariableConversion.hasLiveConversion(test); if(Expression.isAlwaysFalse(test)) { loadAndDiscard(test); if(testHasLiveConversion) { method.beforeJoinPoint(test); } } else if(testHasLiveConversion) { // If we have conversions after the test in do-while, they need to be effected on both branches. final Label beforeExit = new Label("do_while_preexit"); emitBranch(test.getExpression(), beforeExit, false); method.beforeJoinPoint(test); method._goto(bodyEntryLabel); method.label(beforeExit); method.beforeJoinPoint(test); } else { emitBranch(test.getExpression(), bodyEntryLabel, true); } } method.breakLabel(whileNode.getBreakLabel(), liveLocalsOnContinueOrBreak); }
/** * ...IterationStatement : * ... * while ( Expression ) Statement * ... * * See 12.6 * * Parse while statement. */ private void whileStatement() { // Capture WHILE token. final long whileToken = token; final int whileLine = line; // WHILE tested in caller. next(); final ParserContextLoopNode whileNode = new ParserContextLoopNode(); lc.push(whileNode); JoinPredecessorExpression test = null; Block body = null; try { expect(LPAREN); test = joinPredecessorExpression(); expect(RPAREN); body = getStatement(); } finally { lc.pop(whileNode); } if (body != null) { appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body)); } }
/** * ...IterationStatement : * ... * do Statement while( Expression ) ; * ... * * See 12.6 * * Parse DO WHILE statement. */ private void doStatement() { // Capture DO token. final long doToken = token; int doLine = 0; // DO tested in the caller. next(); final ParserContextLoopNode doWhileNode = new ParserContextLoopNode(); lc.push(doWhileNode); Block body = null; JoinPredecessorExpression test = null; try { // Get DO body. body = getStatement(); expect(WHILE); expect(LPAREN); doLine = line; test = joinPredecessorExpression(); expect(RPAREN); if (type == SEMICOLON) { endOfLine(); } } finally { lc.pop(doWhileNode); } appendStatement(new WhileNode(doLine, doToken, finish, true, test, body)); }
private void enterDoWhileLoop(final WhileNode loopNode) { assertTypeStackIsEmpty(); final JoinPredecessorExpression test = loopNode.getTest(); final Block body = loopNode.getBody(); final Label continueLabel = loopNode.getContinueLabel(); final Label breakLabel = loopNode.getBreakLabel(); final Map<Symbol, LvarType> beforeLoopTypes = localVariableTypes; final Label repeatLabel = new Label(""); for(;;) { jumpToLabel(loopNode, repeatLabel, beforeLoopTypes); final Map<Symbol, LvarType> beforeRepeatTypes = localVariableTypes; body.accept(this); if(reachable) { jumpToLabel(body, continueLabel); } joinOnLabel(continueLabel); if(!reachable) { break; } visitExpressionOnEmptyStack(test); jumpToLabel(test, breakLabel); if(isAlwaysFalse(test)) { break; } jumpToLabel(test, repeatLabel); joinOnLabel(repeatLabel); if(localVariableTypes.equals(beforeRepeatTypes)) { break; } resetJoinPoint(continueLabel); resetJoinPoint(breakLabel); resetJoinPoint(repeatLabel); } if(isAlwaysTrue(test)) { doesNotContinueSequentially(); } leaveBreakable(loopNode); }
@Override public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) { final Expression expr = joinExpr.getExpression(); if (expr != null) { expr.accept(this); } else { typeStack.push(LvarType.UNDEFINED); } return false; }
private static Expression newBinaryExpression(final long op, final Expression lhs, final Expression rhs) { final TokenType opType = Token.descType(op); // Build up node. if (BinaryNode.isLogical(opType)) { return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs)); } return new BinaryNode(op, lhs, rhs); }