diff --git a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java index 2b7ba0135..68e25b7ec 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/JavascriptBuilder.java @@ -21,11 +21,15 @@ import java.util.List; import java.util.Map; import java.util.Set; import org.teavm.codegen.*; +import org.teavm.common.Graph; import org.teavm.dependency.DependencyChecker; import org.teavm.javascript.ast.ClassNode; import org.teavm.model.*; import org.teavm.model.resource.ClasspathClassHolderSource; +import org.teavm.model.util.GraphColorer; +import org.teavm.model.util.InterferenceGraphBuilder; import org.teavm.model.util.ListingBuilder; +import org.teavm.model.util.LivenessAnalyzer; import org.teavm.optimization.ClassSetOptimizer; /** @@ -161,9 +165,23 @@ public class JavascriptBuilder { printType(writer, parameterTypes[i]); } writer.println(")"); - if (method.getProgram() != null) { + if (method.getProgram() != null && method.getProgram().basicBlockCount() > 0) { ListingBuilder builder = new ListingBuilder(); - writer.println(builder.buildListing(method.getProgram(), " ")); + writer.print(builder.buildListing(method.getProgram(), " ")); + writer.print(" Register allocation:"); + LivenessAnalyzer analyzer = new LivenessAnalyzer(); + analyzer.analyze(method.getProgram()); + InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder(); + Graph interferenceGraph = interferenceBuilder.build(method.getProgram(), analyzer); + GraphColorer colorer = new GraphColorer(); + int[] colors = colorer.colorize(interferenceGraph, + Math.min(method.parameterCount() + 1, interferenceGraph.size())); + for (int i = 0; i < colors.length; ++i) { + writer.print(i + ":" + colors[i] + " "); + } + writer.println(); + writer.println(); + writer.flush(); } else { writer.println(); } diff --git a/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java b/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java index 43fbf9a35..1fc8fff1c 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java +++ b/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java @@ -15,6 +15,7 @@ */ package org.teavm.model.util; +import java.util.BitSet; import org.teavm.common.Graph; /** @@ -22,30 +23,64 @@ import org.teavm.common.Graph; * @author Alexey Andreev */ public class GraphColorer { - public void colorize(Graph graph) { - + public int[] colorize(Graph graph, int preservedColors) { + int[] colors = new int[graph.size()]; + boolean[] visited = new boolean[graph.size()]; + for (int i = 0; i < preservedColors; ++i) { + colors[i] = i; + visited[i] = true; + } + BitSet usedColors = new BitSet(); + for (int v : getOrdering(graph)) { + if (v < preservedColors) { + continue; + } + usedColors.clear(); + usedColors.set(0); + for (int succ : graph.outgoingEdges(v)) { + if (visited[succ]) { + usedColors.set(colors[succ]); + } + } + colors[v] = usedColors.nextClearBit(0); + visited[v] = true; + } + return colors; } private int[] getOrdering(Graph graph) { boolean[] visited = new boolean[graph.size()]; - int[] sets = new int[graph.size()]; - int[] next = new int[graph.size()]; - for (int i = 0; i < next.length; ++i) { - next[i] = i + 1; - } - int node = 0; - while (node < next.length) { - if (visited[node]) { + int[] ordering = new int[graph.size()]; + int index = 0; + int[] queue = new int[graph.size() * 2]; + for (int root = 0; root < graph.size(); ++root) { + if (visited[root]) { continue; } - visited[node] = true; - for (int succ : graph.outgoingEdges(node)) { - if (visited[succ]) { - + int head = 0; + int tail = 0; + queue[head++] = root; + while (head != tail) { + int v = queue[tail++]; + if (tail == queue.length) { + tail = 0; + } + if (visited[v]) { + continue; + } + visited[v] = true; + ordering[index++] = v; + for (int succ : graph.outgoingEdges(v)) { + if (visited[succ]) { + continue; + } + if (++head == queue.length) { + head = 0; + } + queue[head] = succ; } } - graph.outgoingEdges(node); } - return next; + return ordering; } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java b/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java index 1767315ab..2f60d2b0e 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java +++ b/teavm-core/src/main/java/org/teavm/model/util/InstructionStringifier.java @@ -253,7 +253,7 @@ public class InstructionStringifier implements InstructionVisitor { } else { sb.append(insn.getField().getClassName()); } - sb.append(".").append(insn.getField()); + sb.append(".").append(insn.getField().getFieldName()); } @Override @@ -263,7 +263,7 @@ public class InstructionStringifier implements InstructionVisitor { } else { sb.append(insn.getField().getClassName()); } - sb.append(".").append(insn.getField()).append(" := @").append(insn.getValue().getIndex()); + sb.append(".").append(insn.getField().getFieldName()).append(" := @").append(insn.getValue().getIndex()); } @Override @@ -332,7 +332,7 @@ public class InstructionStringifier implements InstructionVisitor { @Override public void visit(UnwrapArrayInstruction insn) { sb.append("@").append(insn.getReceiver().getIndex()).append(" := @") - .append(insn.getArray()).append(".data"); + .append(insn.getArray().getIndex()).append(".data"); } @Override diff --git a/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java b/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java index 9079b922b..563ccca9b 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/model/util/InterferenceGraphBuilder.java @@ -33,6 +33,7 @@ public class InterferenceGraphBuilder { UsageExtractor useExtractor = new UsageExtractor(); DefinitionExtractor defExtractor = new DefinitionExtractor(); InstructionTransitionExtractor succExtractor = new InstructionTransitionExtractor(); + List> outgoings = getOutgoings(program); for (int i = 0; i < program.basicBlockCount(); ++i) { BasicBlock block = program.basicBlockAt(i); block.getLastInstruction().acceptVisitor(succExtractor); @@ -46,6 +47,9 @@ public class InterferenceGraphBuilder { live.add(j); } } + for (Incoming outgoing : outgoings.get(i)) { + live.add(outgoing.getValue().getIndex()); + } for (int j = block.getInstructions().size() - 1; j >= 0; --j) { Instruction insn = block.getInstructions().get(j); insn.acceptVisitor(useExtractor); @@ -83,4 +87,20 @@ public class InterferenceGraphBuilder { } return builder.build(); } + + private List> getOutgoings(Program program) { + List> outgoings = new ArrayList<>(); + for (int i = 0; i < program.basicBlockCount(); ++i) { + outgoings.add(new ArrayList()); + } + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock block = program.basicBlockAt(i); + for (Phi phi : block.getPhis()) { + for(Incoming incoming : phi.getIncomings()) { + outgoings.get(incoming.getSource().getIndex()).add(incoming); + } + } + } + return outgoings; + } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java b/teavm-core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java index 8af0c581f..97ad76396 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java +++ b/teavm-core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java @@ -77,7 +77,7 @@ public class LivenessAnalyzer { } } - while (stack.isEmpty()) { + while (!stack.isEmpty()) { Task task = stack.pop(); if (liveVars[task.block].get(task.var) || !dominates(definitions[task.var], task.block)) { continue; @@ -98,23 +98,21 @@ public class LivenessAnalyzer { int index = 1; int[] stack = new int[domGraph.size() * 2]; int top = 0; - for (int i = domGraph.size(); i >= 0; --i) { + for (int i = domGraph.size() - 1; i >= 0; --i) { if (domGraph.incomingEdgesCount(i) == 0) { stack[top++] = i; } } while (top > 0) { - int v = stack[top--]; + int v = stack[--top]; if (domLeft[v] == 0) { domLeft[v] = index++; + stack[top++] = v; for (int succ : domGraph.outgoingEdges(v)) { stack[top++] = succ; } } else if (domRight[v] == 0) { domRight[v] = index++; - if (domGraph.incomingEdgesCount(0) > 0) { - stack[top++] = domGraph.incomingEdges(v)[0]; - } } } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/UsageExtractor.java b/teavm-core/src/main/java/org/teavm/model/util/UsageExtractor.java index 710b79e4b..e2f842371 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/UsageExtractor.java +++ b/teavm-core/src/main/java/org/teavm/model/util/UsageExtractor.java @@ -184,11 +184,12 @@ public class UsageExtractor implements InstructionVisitor { public void visit(InvokeInstruction insn) { if (insn.getInstance() != null) { usedVariables = new Variable[insn.getArguments().size() + 1]; + insn.getArguments().toArray(usedVariables); usedVariables[insn.getArguments().size()] = insn.getInstance(); } else { usedVariables = new Variable[insn.getArguments().size()]; + insn.getArguments().toArray(usedVariables); } - insn.getArguments().toArray(usedVariables); } @Override