private Set<TreeNode> getAncestors(TreeNode node) { Set<TreeNode> ancestors = Sets.newHashSet(); while (node != currentTopNode) { ancestors.add(node); node = node.getParent(); } return ancestors; }
private Expression getConditionChild(TreeNode conditional) { if (conditional instanceof InfixExpression) { return ((InfixExpression) conditional).getOperands().get(0); } else if (conditional instanceof ConditionalExpression) { return ((ConditionalExpression) conditional).getExpression(); } else { throw new AssertionError( "Unexpected conditional node type: " + conditional.getClass().toString()); } }
private boolean isWithinConditionalBranch(TreeNode node, TreeNode limit) { while (node != limit) { TreeNode parent = node.getParent(); if (isConditional(parent) && getConditionChild(parent) != node) { return true; } node = parent; } return false; }
private TreeNode getTopConditional(TreeNode node, TreeNode limit) { TreeNode topConditional = null; while (node != limit) { node = node.getParent(); if (isConditional(node)) { topConditional = node; } } return topConditional; }
private void extractOrderedAccesses( List<Statement> stmtList, TreeNode subExpr, List<VariableAccess> toExtract) { for (int i = 0; i < toExtract.size(); i++) { VariableAccess access = toExtract.get(i); TreeNode topConditional = getTopConditional(access.expression, subExpr); if (topConditional != null) { // Conditional expressions require special handling when extracting the // access because execution of the access may not be guaranteed. // Here we collect all accesses that are decendant of the conditional // expression and pass them to an appropriate extraction method. int j = i + 1; for (; j < toExtract.size(); j++) { if (getTopConditional(toExtract.get(j).expression, subExpr) != topConditional) { break; } } if (topConditional instanceof InfixExpression) { extractInfixConditional( stmtList, (InfixExpression) topConditional, toExtract.subList(i, j)); } else if (topConditional instanceof ConditionalExpression) { extractConditionalExpression( stmtList, (ConditionalExpression) topConditional, toExtract.subList(i, j)); } else { throw new AssertionError( "Unexpected conditional node type: " + topConditional.getClass().toString()); } i = j - 1; } else { IVariableBinding newVar = new GeneratedVariableBinding( "unseq$" + count++, 0, access.expression.getTypeBinding(), false, false, null, currentMethod); stmtList.add(new VariableDeclarationStatement(newVar, access.expression.copy())); access.expression.replaceWith(new SimpleName(newVar)); } } }
private boolean isUnsequenced( VariableAccess modification, Set<TreeNode> modificationAncestors, VariableAccess access) { TreeNode commonAncestor = currentTopNode; TreeNode node = access.expression; while (node != currentTopNode) { if (modificationAncestors.contains(node)) { commonAncestor = node; break; } node = node.getParent(); } // If either access is executed in a conditional branch that does not // contain the other access, then they are not unsequenced. if (isWithinConditionalBranch(modification.expression, commonAncestor) || isWithinConditionalBranch(access.expression, commonAncestor)) { return false; } else if (commonAncestor instanceof Assignment && modification.expression == commonAncestor) { // "i = 1 + (i = 2);" is not unsequenced. // "i = 1 + i++;" is unsequenced (according to clang). return access.expression instanceof PrefixExpression || access.expression instanceof PostfixExpression; } return true; }
private void extractInfixConditional( List<Statement> stmtList, InfixExpression conditional, List<VariableAccess> toExtract) { InfixExpression.Operator op = conditional.getOperator(); List<Expression> branches = conditional.getOperands(); int lastIfExtractIdx = 0; IVariableBinding conditionalVar = null; int lastExtracted = 0; Expression lastBranch = null; for (int i = 0; i < toExtract.size(); i++) { VariableAccess access = toExtract.get(i); TreeNode node = access.expression; while (node.getParent() != conditional) { node = node.getParent(); } assert node instanceof Expression; Expression branch = (Expression) node; // Extract all accesses from the previous branch. if (lastBranch != null && branch != lastBranch) { extractOrderedAccesses(stmtList, lastBranch, toExtract.subList(lastExtracted, i)); lastExtracted = i; } lastBranch = branch; // If there's a new modification in a new branch, then we extract an if-statement. if (access.isModification && branch != branches.get(lastIfExtractIdx)) { ITypeBinding boolType = typeEnv.resolveJavaType("boolean"); if (conditionalVar == null) { conditionalVar = new GeneratedVariableBinding( "unseq$" + count++, 0, boolType, false, false, null, currentMethod); conditional.replaceWith(new SimpleName(conditionalVar)); stmtList.add(new VariableDeclarationStatement(conditionalVar, null)); } List<Expression> subBranches = branches.subList(lastIfExtractIdx, branches.indexOf(branch)); IfStatement newIf = new IfStatement(); Expression ifExpr = new Assignment( new SimpleName(conditionalVar), conditionalFromSubBranches(subBranches, op)); if (op == InfixExpression.Operator.CONDITIONAL_OR) { ifExpr = new PrefixExpression( boolType, PrefixExpression.Operator.NOT, ParenthesizedExpression.parenthesize(ifExpr)); } newIf.setExpression(ifExpr); stmtList.add(newIf); Block thenBlock = new Block(); stmtList = thenBlock.getStatements(); newIf.setThenStatement(thenBlock); lastIfExtractIdx = branches.indexOf(branch); } } extractOrderedAccesses( stmtList, lastBranch, toExtract.subList(lastExtracted, toExtract.size())); if (conditionalVar != null) { List<Expression> remainingBranches = Lists.newArrayList(); remainingBranches.add(new SimpleName(conditionalVar)); remainingBranches.addAll(branches.subList(lastIfExtractIdx, branches.size())); stmtList.add( new ExpressionStatement( new Assignment( new SimpleName(conditionalVar), conditionalFromSubBranches(remainingBranches, op)))); } }
private void extractConditionalExpression( List<Statement> stmtList, ConditionalExpression conditional, List<VariableAccess> toExtract) { Expression condition = conditional.getExpression(); Expression thenExpr = conditional.getThenExpression(); Expression elseExpr = conditional.getElseExpression(); List<VariableAccess> conditionAccesses = Lists.newArrayList(); List<VariableAccess> thenAccesses = Lists.newArrayList(); List<VariableAccess> elseAccesses = Lists.newArrayList(); boolean needsExtraction = false; for (VariableAccess access : toExtract) { TreeNode node = access.expression; while (node.getParent() != conditional) { node = node.getParent(); } if (node == condition) { conditionAccesses.add(access); } else if (node == thenExpr) { thenAccesses.add(access); } else if (node == elseExpr) { elseAccesses.add(access); } else { throw new AssertionError(); } if (node != condition && access.isModification) { // We only need to extract an if-statement if there is a modification // that executes conditionally. needsExtraction = true; } } extractOrderedAccesses(stmtList, condition, conditionAccesses); // The recursive call might replace the condition child. condition = conditional.getExpression(); if (needsExtraction) { IVariableBinding resultVar = new GeneratedVariableBinding( "unseq$" + count++, 0, conditional.getTypeBinding(), false, false, null, currentMethod); conditional.replaceWith(new SimpleName(resultVar)); stmtList.add(new VariableDeclarationStatement(resultVar, null)); IfStatement newIf = new IfStatement(); newIf.setExpression(condition.copy()); stmtList.add(newIf); Block thenBlock = new Block(); newIf.setThenStatement(thenBlock); List<Statement> thenStmts = thenBlock.getStatements(); extractOrderedAccesses(thenStmts, thenExpr, thenAccesses); // The recursive call might replace the then expression child. thenExpr = conditional.getThenExpression(); thenStmts.add( new ExpressionStatement(new Assignment(new SimpleName(resultVar), thenExpr.copy()))); Block elseBlock = new Block(); newIf.setElseStatement(elseBlock); List<Statement> elseStmts = elseBlock.getStatements(); extractOrderedAccesses(elseStmts, elseExpr, elseAccesses); // The recursive call might replace the else expression child. elseExpr = conditional.getElseExpression(); elseStmts.add( new ExpressionStatement(new Assignment(new SimpleName(resultVar), elseExpr.copy()))); } else { extractOrderedAccesses(stmtList, thenExpr, thenAccesses); extractOrderedAccesses(stmtList, elseExpr, elseAccesses); } }