Homework B (benchmarks)
This commit is contained in:
parent
72cc3206c4
commit
76fbabdf53
141 changed files with 7540 additions and 2032 deletions
60
src/cd/util/DepthFirstSearchPreOrder.java
Normal file
60
src/cd/util/DepthFirstSearchPreOrder.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
package cd.util;
|
||||
|
||||
import cd.ir.BasicBlock;
|
||||
import cd.ir.ControlFlowGraph;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A potentially handy iterator which yields the blocks in a control-flow
|
||||
* graph. The order is pre-order, depth-first. Pre-order means that a
|
||||
* node is visited before its successors.
|
||||
*/
|
||||
public class DepthFirstSearchPreOrder implements Iterable<BasicBlock> {
|
||||
|
||||
public final ControlFlowGraph cfg;
|
||||
|
||||
public DepthFirstSearchPreOrder(ControlFlowGraph cfg) {
|
||||
this.cfg = cfg;
|
||||
}
|
||||
|
||||
public Iterator<BasicBlock> iterator() {
|
||||
return new Iterator<BasicBlock>() {
|
||||
|
||||
/** Blocks we still need to visit */
|
||||
private final Stack<BasicBlock> stack = new Stack<BasicBlock>();
|
||||
|
||||
/** Blocks we pushed thus far */
|
||||
private final Set<BasicBlock> pushed = new HashSet<BasicBlock>();
|
||||
|
||||
{
|
||||
stack.add(cfg.start);
|
||||
pushed.add(cfg.start);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return !stack.isEmpty();
|
||||
}
|
||||
|
||||
public BasicBlock next() {
|
||||
if (stack.isEmpty())
|
||||
throw new NoSuchElementException();
|
||||
|
||||
BasicBlock res = stack.pop();
|
||||
for (BasicBlock s : res.successors)
|
||||
if (!pushed.contains(s)) {
|
||||
pushed.add(s);
|
||||
stack.add(s);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -9,12 +9,12 @@ public class FileUtil {
|
|||
public static String readAll(Reader ubReader) throws IOException {
|
||||
try (BufferedReader bReader = new BufferedReader(ubReader)) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
|
||||
while (true) {
|
||||
int ch = bReader.read();
|
||||
if (ch == -1)
|
||||
break;
|
||||
|
||||
|
||||
sb.append((char) ch);
|
||||
}
|
||||
return sb.toString();
|
||||
|
@ -32,7 +32,7 @@ public class FileUtil {
|
|||
}
|
||||
|
||||
public static String runCommand(File dir, String[] command,
|
||||
String[] substs, String input, boolean detectError)
|
||||
String[] substs, String input, boolean detectError)
|
||||
throws IOException {
|
||||
// Substitute the substitution strings $0, $1, etc
|
||||
String newCommand[] = new String[command.length];
|
||||
|
@ -53,12 +53,12 @@ public class FileUtil {
|
|||
osw.write(input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
final StringBuffer result = new StringBuffer();
|
||||
// thread to read stdout from child so that p.waitFor() is interruptible
|
||||
// by JUnit's timeout mechanism. Otherwise it would block in readAll()
|
||||
Thread t = new Thread () {
|
||||
Thread t = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
result.append(readAll(new InputStreamReader(p.getInputStream())));
|
||||
|
@ -67,7 +67,7 @@ public class FileUtil {
|
|||
}
|
||||
};
|
||||
t.start();
|
||||
|
||||
|
||||
if (detectError) {
|
||||
int err = p.waitFor();
|
||||
|
||||
|
@ -76,7 +76,7 @@ public class FileUtil {
|
|||
if (err != 0)
|
||||
return "Error: " + err + "\n";
|
||||
}
|
||||
|
||||
|
||||
t.join();
|
||||
return result.toString();
|
||||
} catch (InterruptedException e) {
|
||||
|
@ -94,13 +94,15 @@ public class FileUtil {
|
|||
public static void findJavaliFiles(File testDir, List<Object[]> result) {
|
||||
for (File testFile : testDir.listFiles()) {
|
||||
if (testFile.getName().endsWith(".javali"))
|
||||
result.add(new Object[] { testFile });
|
||||
result.add(new Object[]{testFile});
|
||||
else if (testFile.isDirectory())
|
||||
findJavaliFiles(testFile, result);
|
||||
}
|
||||
}
|
||||
|
||||
/** Finds all .javali under directory {@code testDir} and returns them. */
|
||||
/**
|
||||
* Finds all .javali under directory {@code testDir} and returns them.
|
||||
*/
|
||||
public static List<File> findJavaliFiles(File testDir) {
|
||||
List<File> result = new ArrayList<File>();
|
||||
for (File testFile : testDir.listFiles()) {
|
||||
|
|
|
@ -3,16 +3,18 @@ package cd.util;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Simple class for joining two objects of the same type */
|
||||
/**
|
||||
* Simple class for joining two objects of the same type
|
||||
*/
|
||||
public class Pair<T> {
|
||||
public T a;
|
||||
public T b;
|
||||
|
||||
|
||||
public Pair(T a, T b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
|
||||
public static <T> List<Pair<T>> zip(List<T> listA, List<T> listB) {
|
||||
List<Pair<T>> res = new ArrayList<Pair<T>>();
|
||||
for (int i = 0; i < Math.min(listA.size(), listB.size()); i++) {
|
||||
|
@ -20,24 +22,24 @@ public class Pair<T> {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public static <T> List<T> unzipA(List<Pair<T>> list) {
|
||||
List<T> res = new ArrayList<T>();
|
||||
for (Pair<T> p : list)
|
||||
res.add(p.a);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public static <T> List<T> unzipB(List<Pair<T>> list) {
|
||||
List<T> res = new ArrayList<T>();
|
||||
for (Pair<T> p : list)
|
||||
res.add(p.b);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
public static String join(
|
||||
List<Pair<?>> pairs,
|
||||
String itemSep,
|
||||
List<Pair<?>> pairs,
|
||||
String itemSep,
|
||||
String pairSep) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
boolean first = true;
|
||||
|
|
|
@ -1,15 +1,17 @@
|
|||
package cd.util;
|
||||
|
||||
/** Simple class for joining two objects of different type */
|
||||
public class Tuple<A,B> {
|
||||
/**
|
||||
* Simple class for joining two objects of different type
|
||||
*/
|
||||
public class Tuple<A, B> {
|
||||
public A a;
|
||||
public B b;
|
||||
|
||||
|
||||
public Tuple(A a, B b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return "(" + a.toString() + ", " + b.toString() + ")";
|
||||
}
|
||||
|
|
|
@ -8,11 +8,11 @@ import java.lang.reflect.Field;
|
|||
import java.util.*;
|
||||
|
||||
public class AstDump {
|
||||
|
||||
|
||||
public static String toString(Ast ast) {
|
||||
return toString(ast, "");
|
||||
}
|
||||
|
||||
|
||||
public static String toString(List<? extends Ast> astRoots) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Ast a : astRoots) {
|
||||
|
@ -26,22 +26,22 @@ public class AstDump {
|
|||
ad.dump(ast, indent);
|
||||
return ad.sb.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String toStringFlat(Ast ast) {
|
||||
AstDump ad = new AstDump();
|
||||
ad.dumpFlat(ast);
|
||||
return ad.sb.toString();
|
||||
}
|
||||
|
||||
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
private Visitor vis = new Visitor();
|
||||
|
||||
|
||||
protected void dump(Ast ast, String indent) {
|
||||
// print out the overall class structure
|
||||
sb.append(indent);
|
||||
String nodeName = ast.getClass().getSimpleName();
|
||||
List<Pair<?>> flds = vis.visit(ast, null);
|
||||
sb.append(String.format("%s (%s)\n",
|
||||
sb.append(String.format("%s (%s)\n",
|
||||
nodeName,
|
||||
Pair.join(flds, ": ", ", ")));
|
||||
|
||||
|
@ -51,11 +51,11 @@ public class AstDump {
|
|||
dump(child, newIndent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void dumpFlat(Ast ast) {
|
||||
String nodeName = ast.getClass().getSimpleName();
|
||||
List<Pair<?>> flds = vis.visit(ast, null);
|
||||
sb.append(String.format("%s(%s)[",
|
||||
sb.append(String.format("%s(%s)[",
|
||||
nodeName,
|
||||
Pair.join(flds, ":", ",")));
|
||||
|
||||
|
@ -68,39 +68,39 @@ public class AstDump {
|
|||
|
||||
sb.append("]");
|
||||
}
|
||||
|
||||
|
||||
protected class Visitor extends AstVisitor<List<Pair<?>>, Void> {
|
||||
|
||||
|
||||
@Override
|
||||
protected List<Pair<?>> dflt(Ast ast, Void arg) {
|
||||
ArrayList<Pair<?>> res = new ArrayList<Pair<?>>();
|
||||
|
||||
|
||||
// Get the list of fields and sort them by name:
|
||||
java.lang.Class<? extends Ast> rclass = ast.getClass();
|
||||
List<java.lang.reflect.Field> rflds =
|
||||
Arrays.asList(rclass.getFields());
|
||||
Collections.sort(rflds, new Comparator<java.lang.reflect.Field> () {
|
||||
List<java.lang.reflect.Field> rflds =
|
||||
Arrays.asList(rclass.getFields());
|
||||
Collections.sort(rflds, new Comparator<java.lang.reflect.Field>() {
|
||||
public int compare(Field o1, Field o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Create pairs for each one that is not of type Ast:
|
||||
for (java.lang.reflect.Field rfld : rflds) {
|
||||
rfld.setAccessible(true);
|
||||
|
||||
|
||||
// ignore various weird fields that show up from
|
||||
// time to time:
|
||||
if (rfld.getName().startsWith("$"))
|
||||
continue;
|
||||
|
||||
|
||||
// ignore fields of AST type, and rwChildren (they should be
|
||||
// uncovered using the normal tree walk)
|
||||
if (rfld.getType().isAssignableFrom(Ast.class))
|
||||
continue;
|
||||
if (rfld.getName().equals("rwChildren"))
|
||||
continue;
|
||||
|
||||
|
||||
// ignore NULL fields, but add others to our list of pairs
|
||||
try {
|
||||
Object value = rfld.get(ast);
|
||||
|
@ -110,12 +110,12 @@ public class AstDump {
|
|||
throw new RuntimeException(e);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ import cd.ir.Ast.*;
|
|||
import cd.ir.AstVisitor;
|
||||
|
||||
public class AstOneLine {
|
||||
|
||||
|
||||
public static String toString(Ast ast) {
|
||||
return new Visitor().visit(ast, null);
|
||||
}
|
||||
|
||||
protected static class Visitor extends AstVisitor<String, Void> {
|
||||
|
||||
|
||||
public String str(Ast ast) {
|
||||
return ast.accept(this, null);
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class AstOneLine {
|
|||
|
||||
@Override
|
||||
public String binaryOp(BinaryOp ast, Void arg) {
|
||||
return String.format("(%s %s %s)",
|
||||
return String.format("(%s %s %s)",
|
||||
str(ast.left()), ast.operator.repr, str(ast.right()));
|
||||
}
|
||||
|
||||
|
@ -36,12 +36,12 @@ public class AstOneLine {
|
|||
public String builtInRead(BuiltInRead ast, Void arg) {
|
||||
return String.format("read()");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String builtInWrite(BuiltInWrite ast, Void arg) {
|
||||
return String.format("write(%s)", str(ast.arg()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String builtInWriteln(BuiltInWriteln ast, Void arg) {
|
||||
return String.format("writeln()");
|
||||
|
@ -81,12 +81,12 @@ public class AstOneLine {
|
|||
public String methodCall(MethodCall ast, Void arg) {
|
||||
return str(ast.getMethodCallExpr());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String methodCall(MethodCallExpr ast, Void arg) {
|
||||
return String.format("%s.%s(...)", str(ast.receiver()), ast.methodName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String methodDecl(MethodDecl ast, Void arg) {
|
||||
return String.format("%s %s(...) {...}", ast.returnType, ast.name);
|
||||
|
@ -121,7 +121,7 @@ public class AstOneLine {
|
|||
public String thisRef(ThisRef ast, Void arg) {
|
||||
return "this";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String returnStmt(ReturnStmt ast, Void arg) {
|
||||
return ast.arg() != null ? String.format("return %s", str(ast.arg())) : "return";
|
||||
|
@ -136,10 +136,10 @@ public class AstOneLine {
|
|||
public String var(Var ast, Void arg) {
|
||||
{
|
||||
if (ast.sym != null) {
|
||||
String symName = ast.sym.toString();
|
||||
String symName = ast.sym.toString();
|
||||
if (ast.name == null || ast.name.equals(symName))
|
||||
return symName;
|
||||
|
||||
|
||||
// Return something strange to warn about the mismatch here:
|
||||
return String.format("(%s!=%s)", symName, ast.name);
|
||||
} else
|
||||
|
@ -156,6 +156,6 @@ public class AstOneLine {
|
|||
public String whileLoop(WhileLoop ast, Void arg) {
|
||||
return String.format("while (%s) {...}", str(ast.condition()));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
156
src/cd/util/debug/CfgDump.java
Normal file
156
src/cd/util/debug/CfgDump.java
Normal file
|
@ -0,0 +1,156 @@
|
|||
package cd.util.debug;
|
||||
|
||||
import cd.ir.Ast.ClassDecl;
|
||||
import cd.ir.Ast.MethodDecl;
|
||||
import cd.ir.Ast.Stmt;
|
||||
import cd.ir.BasicBlock;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class CfgDump {
|
||||
|
||||
public static void toString(
|
||||
MethodDecl mdecl,
|
||||
String phase,
|
||||
File filename,
|
||||
boolean dumpDominators) {
|
||||
if (filename == null) return;
|
||||
FileWriter fw;
|
||||
try {
|
||||
fw = new FileWriter(new File(filename.getAbsolutePath() + phase + ".dot"));
|
||||
fw.write(toString(mdecl, dumpDominators));
|
||||
fw.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void toString(
|
||||
List<? extends ClassDecl> astRoots,
|
||||
String phase,
|
||||
File filename,
|
||||
boolean dumpDominators) {
|
||||
if (filename == null) return;
|
||||
FileWriter fw;
|
||||
try {
|
||||
fw = new FileWriter(new File(filename.getAbsolutePath() + phase + ".dot"));
|
||||
fw.write(toString(astRoots, dumpDominators));
|
||||
fw.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static String toString(
|
||||
List<? extends ClassDecl> astRoots,
|
||||
boolean dumpDominators) {
|
||||
return new CfgDump().dump(astRoots, dumpDominators);
|
||||
}
|
||||
|
||||
public static String toString(
|
||||
MethodDecl mdecl,
|
||||
boolean dumpDominators) {
|
||||
return new CfgDump().dump(mdecl, dumpDominators);
|
||||
}
|
||||
|
||||
private int indent = 0;
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
|
||||
private void append(String format, Object... args) {
|
||||
String out = String.format(format, args);
|
||||
if (out.startsWith("}") || out.startsWith("]")) indent -= 2;
|
||||
for (int i = 0; i < indent; i++) sb.append(" ");
|
||||
if (out.endsWith("{") || out.endsWith("[")) indent += 2;
|
||||
sb.append(String.format(format, args));
|
||||
sb.append("\n");
|
||||
}
|
||||
|
||||
private String dump(
|
||||
MethodDecl mdecl,
|
||||
boolean dumpDominators) {
|
||||
sb.setLength(0);
|
||||
append("digraph G {");
|
||||
append("graph [ rankdir = \"LR\" ];");
|
||||
|
||||
dumpBlocks(dumpDominators, mdecl, "");
|
||||
|
||||
append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String dump(
|
||||
List<? extends ClassDecl> astRoots,
|
||||
boolean dumpDominators) {
|
||||
sb.setLength(0);
|
||||
append("digraph G {");
|
||||
append("graph [ rankdir = \"LR\" ];");
|
||||
|
||||
int sgcntr = 0, mcntr = 0;
|
||||
for (ClassDecl cdecl : astRoots) {
|
||||
//append("subgraph cluster_%d {", sgcntr++);
|
||||
//append("label = \"%s\";", cdecl.name);
|
||||
|
||||
for (MethodDecl mdecl : cdecl.methods()) {
|
||||
append("subgraph cluster_%d {", sgcntr++);
|
||||
append("label = \"%s.%s\"", cdecl.name, mdecl.name);
|
||||
String m = String.format("M%d_", mcntr++);
|
||||
|
||||
dumpBlocks(dumpDominators, mdecl, m);
|
||||
|
||||
append("}");
|
||||
}
|
||||
|
||||
//append("}");
|
||||
}
|
||||
|
||||
append("}");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void dumpBlocks(boolean dumpDominators, MethodDecl mdecl, String m) {
|
||||
for (BasicBlock blk : mdecl.cfg.allBlocks) {
|
||||
append("%sBB%d [", m, blk.index);
|
||||
append("shape=\"record\"");
|
||||
|
||||
// If we are not just dumping dominators, then build up
|
||||
// a label with all the instructions in the block.
|
||||
StringBuilder blklbl = new StringBuilder();
|
||||
blklbl.append(String.format("BB%d", blk.index));
|
||||
if (!dumpDominators || true) {
|
||||
for (Stmt stmt : blk.stmts)
|
||||
blklbl.append("|").append(AstOneLine.toString(stmt));
|
||||
if (blk.condition != null)
|
||||
blklbl.append("|If: " + AstOneLine.toString(blk.condition));
|
||||
}
|
||||
String[] replacements = new String[]{
|
||||
"<", "\\<",
|
||||
">", "\\>",
|
||||
"@", "\\@",
|
||||
"||", "\\|\\|",
|
||||
};
|
||||
String blklbls = blklbl.toString();
|
||||
for (int i = 0; i < replacements.length; i += 2)
|
||||
blklbls = blklbls.replace(replacements[i], replacements[i + 1]);
|
||||
append("label=\"%s\"", blklbls);
|
||||
append("];");
|
||||
|
||||
for (int idx = 0; idx < blk.successors.size(); idx++) {
|
||||
BasicBlock sblk = blk.successors.get(idx);
|
||||
String edgelbl = (idx == 0 ? "" : " [label=\"False\"]");
|
||||
append("%sBB%d -> %sBB%d%s;",
|
||||
m, blk.index, m, sblk.index, edgelbl);
|
||||
}
|
||||
|
||||
{
|
||||
if (dumpDominators && blk.dominatorTreeParent != null) {
|
||||
append("%sBB%d -> %sBB%d [color=\"red\" label=\"dom\"];",
|
||||
m, blk.index, m, blk.dominatorTreeParent.index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -11,13 +11,13 @@ import java.util.Set;
|
|||
import static java.util.Collections.sort;
|
||||
|
||||
class DumpUtils {
|
||||
|
||||
|
||||
static final Comparator<ClassDecl> classComparator = new Comparator<ClassDecl>() {
|
||||
public int compare(ClassDecl left, ClassDecl right) {
|
||||
return left.name.compareTo(right.name);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static final Comparator<MethodDecl> methodComparator = new Comparator<MethodDecl>() {
|
||||
public int compare(MethodDecl left, MethodDecl right) {
|
||||
return left.name.compareTo(right.name);
|
||||
|
@ -26,7 +26,7 @@ class DumpUtils {
|
|||
|
||||
static List<String> sortedStrings(Set<?> set) {
|
||||
List<String> strings = new ArrayList<String>();
|
||||
for(Object element : set)
|
||||
for (Object element : set)
|
||||
strings.add(element.toString());
|
||||
sort(strings);
|
||||
return strings;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue