Skip to content

Commit

Permalink
Implement factor out of deterministic expressions, fix julianhyde#17
Browse files Browse the repository at this point in the history
  • Loading branch information
vlsi committed Apr 20, 2014
1 parent 6865c27 commit b969768
Show file tree
Hide file tree
Showing 28 changed files with 893 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ public static <T> Predicate<T> xor(Predicate<? super T>... predicates) {
return xor(Arrays.asList(predicates));
}

abstract static class AbstractPredicate<T> implements Predicate<T> {
public abstract static class AbstractPredicate<T> implements Predicate<T> {
public Predicate<T> and(Predicate<? super T> p) {
//noinspection unchecked
return Predicates.and((Predicate) this, p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class BinaryExpression extends Expression {

@Override
public Expression accept(Visitor visitor) {
visitor = visitor.preVisit(this);
Expression expression0 = this.expression0.accept(visitor);
Expression expression1 = this.expression1.accept(visitor);
return visitor.visit(this, expression0, expression1);
Expand Down
41 changes: 33 additions & 8 deletions src/main/java/net/hydromatic/linq4j/expressions/BlockBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public class BlockBuilder {
private final boolean optimizing;
private final BlockBuilder parent;

private static final Visitor OPTIMIZE_VISITOR = new OptimizeVisitor();

/**
* Creates a non-optimizing BlockBuilder.
*/
Expand Down Expand Up @@ -297,10 +299,11 @@ public BlockStatement toBlock() {
endless loop. Optimize should not loop forever, however it is hard to
prove if it always finishes in reasonable time. */
for (int i = 0; i < 10; i++) {
if (!optimize()) {
if (!optimize(createOptimizeVisitor(), true)) {
break;
}
}
optimize(createFinishingOptimizeVisitor(), false);
}
return Expressions.block(statements);
}
Expand All @@ -311,25 +314,26 @@ public BlockStatement toBlock() {
*
* @return if any optimizations were made or not
*/
private boolean optimize() {
private boolean optimize(Visitor optimizer, boolean performInline) {
boolean optimized = false;
final UseCounter useCounter = new UseCounter();
for (Statement statement : statements) {
if (statement instanceof DeclarationStatement) {
if (statement instanceof DeclarationStatement && performInline) {
DeclarationStatement decl = (DeclarationStatement) statement;
useCounter.map.put(decl.parameter, new Slot());
}
// We are added only counters up to current statement.
// It is fine to count usages as the latter declarations cannot be used
// in more recent statements.
statement.accept(useCounter);
if (!useCounter.map.isEmpty()) {
statement.accept(useCounter);
}
}
final Map<ParameterExpression, Expression> subMap =
new IdentityHashMap<ParameterExpression, Expression>(useCounter.map
.size());
new IdentityHashMap<ParameterExpression, Expression>(
useCounter.map.size());
final SubstituteVariableVisitor visitor = new SubstituteVariableVisitor(
subMap);
final OptimizeVisitor optimizer = new OptimizeVisitor();
final ArrayList<Statement> oldStatements = new ArrayList<Statement>(
statements);
statements.clear();
Expand All @@ -338,7 +342,7 @@ private boolean optimize() {
if (oldStatement instanceof DeclarationStatement) {
DeclarationStatement statement = (DeclarationStatement) oldStatement;
final Slot slot = useCounter.map.get(statement.parameter);
int count = slot.count;
int count = slot == null ? 100 : slot.count;
if (count > 1 && isSafeForReuse(statement)
&& isSimpleExpression(statement.initializer)) {
// Inline simple final constants
Expand Down Expand Up @@ -400,6 +404,27 @@ && isSimpleExpression(statement.initializer)) {
return optimized;
}

/**
* Creates a visitor that will be used during block optimization.
* Subclasses might provide more specific optimizations (e.g. partial
* evaluation).
*
* @return visitor used to optimize the statements when converting to block
*/
protected Visitor createOptimizeVisitor() {
return OPTIMIZE_VISITOR;
}

/**
* Creates a final optimization visitor.
* Typically, the visitor will factor out constant expressions.
*
* @return visitor that is used to finalize the optimization
*/
protected Visitor createFinishingOptimizeVisitor() {
return new DeterministicCodeOptimizer();
}

/**
* Creates a name for a new variable, unique within this block, controlling
* whether the variable can be inlined later.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ private boolean distinctVariables(boolean fail) {

@Override
public BlockStatement accept(Visitor visitor) {
visitor = visitor.preVisit(this);
List<Statement> newStatements = Expressions.acceptStatements(statements,
visitor);
return visitor.visit(this, newStatements);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ public class ClassDeclaration extends MemberDeclaration {
public final String classClass = "class";
public final String name;
public final List<MemberDeclaration> memberDeclarations;
private final Type extended;
private final List<Type> implemented;
public final Type extended;
public final List<Type> implemented;

public ClassDeclaration(int modifier, String name, Type extended,
List<Type> implemented, List<MemberDeclaration> memberDeclarations) {
Expand Down Expand Up @@ -60,6 +60,7 @@ public void accept(ExpressionWriter writer) {
}

public ClassDeclaration accept(Visitor visitor) {
visitor = visitor.preVisit(this);
final List<MemberDeclaration> members1 =
Expressions.acceptMemberDeclarations(memberDeclarations, visitor);
return visitor.visit(this, members1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public ConditionalStatement(List<Node> expressionList) {

@Override
public Statement accept(Visitor visitor) {
visitor = visitor.preVisit(this);
List<Node> list = Expressions.acceptNodes(expressionList, visitor);
return visitor.visit(this, list);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ public ConstructorDeclaration(int modifier, Type declaredAgainst,

@Override
public MemberDeclaration accept(Visitor visitor) {
visitor = visitor.preVisit(this);
// do not visit parameters
final BlockStatement body = this.body.accept(visitor);
return visitor.visit(this, parameters, body);
return visitor.visit(this, body);
}

public void accept(ExpressionWriter writer) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ public DeclarationStatement(int modifiers, ParameterExpression parameter,

@Override
public DeclarationStatement accept(Visitor visitor) {
visitor = visitor.preVisit(this);
// do not visit parameter - visit may not return a ParameterExpression
Expression initializer = this.initializer != null
? this.initializer.accept(visitor)
: null;
return visitor.visit(this, parameter, initializer);
return visitor.visit(this, initializer);
}

@Override
Expand Down
Loading

0 comments on commit b969768

Please sign in to comment.