Repair information about variable names in debug tables

This commit is contained in:
Alexey Andreev 2016-06-25 18:58:45 +03:00
parent feafa032df
commit 6e2eb8386b
3 changed files with 138 additions and 13 deletions

View File

@ -23,6 +23,7 @@ import java.util.Map;
import org.teavm.common.DominatorTree;
import org.teavm.common.Graph;
import org.teavm.common.GraphUtils;
import org.teavm.common.IntegerArray;
import org.teavm.model.BasicBlock;
import org.teavm.model.Incoming;
import org.teavm.model.Instruction;
@ -82,6 +83,11 @@ public class PhiUpdater {
private List<List<Phi>> synthesizedPhis = new ArrayList<>();
private List<List<TryCatchJoint>> synthesizedJoints = new ArrayList<>();
private boolean[] usedDefinitions;
private IntegerArray variableToSourceMap = new IntegerArray(10);
public int getSourceVariable(int var) {
return variableToSourceMap.get(var);
}
public void updatePhis(Program program, Variable[] arguments) {
if (program.basicBlockCount() == 0) {
@ -93,8 +99,11 @@ public class PhiUpdater {
domFrontiers = new int[cfg.size()][];
variableMap = new Variable[program.variableCount()];
usedDefinitions = new boolean[program.variableCount()];
for (int i = 0; i < program.variableCount(); ++i) {
variableToSourceMap.add(-1);
}
for (int i = 0; i < arguments.length; ++i) {
variableMap[i] = arguments[i];
mapVariable(i, arguments[i]);
usedDefinitions[i] = true;
}
phiMap = new Phi[program.basicBlockCount()][];
@ -175,13 +184,13 @@ public class PhiUpdater {
for (Phi phi : synthesizedPhis.get(index)) {
Variable var = program.createVariable();
var.getDebugNames().addAll(phi.getReceiver().getDebugNames());
variableMap[phi.getReceiver().getIndex()] = var;
mapVariable(phi.getReceiver().getIndex(), var);
phi.setReceiver(var);
}
for (TryCatchJoint joint : synthesizedJoints.get(index)) {
Variable var = program.createVariable();
var.getDebugNames().addAll(joint.getReceiver().getDebugNames());
variableMap[joint.getReceiver().getIndex()] = var;
mapVariable(joint.getReceiver().getIndex(), var);
joint.setReceiver(var);
}
for (Phi phi : currentBlock.getPhis()) {
@ -320,10 +329,18 @@ public class PhiUpdater {
private Variable define(Variable var) {
Variable original = var;
var = introduce(var, false);
variableMap[original.getIndex()] = var;
mapVariable(original.getIndex(), var);
return var;
}
private void mapVariable(int index, Variable var) {
variableMap[index] = var;
while (variableToSourceMap.size() <= var.getIndex()) {
variableToSourceMap.add(-1);
}
variableToSourceMap.set(var.getIndex(), index);
}
private Variable introduce(Variable var, boolean clear) {
Variable original = var;
Variable old = variableMap[var.getIndex()];

View File

@ -15,22 +15,26 @@
*/
package org.teavm.parsing;
import com.carrotsearch.hppc.IntIntMap;
import com.carrotsearch.hppc.IntIntOpenHashMap;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.JSRInlinerAdapter;
import org.objectweb.asm.tree.*;
import org.teavm.common.Graph;
import org.teavm.common.GraphUtils;
import org.teavm.model.*;
import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.PhiUpdater;
import org.teavm.model.util.ProgramUtils;
import org.teavm.optimization.UnreachableBasicBlockEliminator;
/**
*
* @author Alexey Andreev
*/
public final class Parser {
private Parser() {
}
@ -45,13 +49,17 @@ public final class Parser {
ValueType[] signature = MethodDescriptor.parseSignature(node.desc);
MethodHolder method = new MethodHolder(node.name, signature);
parseModifiers(node.access, method);
ProgramParser programParser = new ProgramParser();
programParser.setFileName(fileName);
Program program = programParser.parse(node, className);
new UnreachableBasicBlockEliminator().optimize(program);
PhiUpdater phiUpdater = new PhiUpdater();
phiUpdater.updatePhis(program, applySignature(program, method.getParameterTypes()));
Variable[] argumentMapping = applySignature(program, method.getParameterTypes());
phiUpdater.updatePhis(program, argumentMapping);
method.setProgram(program);
applyDebugNames(program, phiUpdater, programParser, argumentMapping);
parseAnnotations(method.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations);
while (program.variableCount() <= method.parameterCount()) {
program.createVariable();
@ -67,6 +75,110 @@ public final class Parser {
return method;
}
private static void applyDebugNames(Program program, PhiUpdater phiUpdater, ProgramParser parser,
Variable[] argumentMapping) {
if (program.basicBlockCount() == 0) {
return;
}
IntIntMap[] blockEntryVariableMappings = getBlockEntryVariableMappings(program, phiUpdater, argumentMapping);
DefinitionExtractor defExtractor = new DefinitionExtractor();
Map<Integer, String> debugNames = new HashMap<>();
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
IntIntMap varMap = blockEntryVariableMappings[i];
for (Instruction insn : block.getInstructions()) {
insn.acceptVisitor(defExtractor);
Map<Integer, String> newDebugNames = parser.getDebugNames(insn);
if (newDebugNames != null) {
debugNames = newDebugNames;
}
for (Variable definedVar : defExtractor.getDefinedVariables()) {
int sourceVar = phiUpdater.getSourceVariable(definedVar.getIndex());
if (sourceVar >= 0) {
varMap.put(sourceVar, definedVar.getIndex());
}
}
for (Map.Entry<Integer, String> debugName : debugNames.entrySet()) {
int receiver = varMap.getOrDefault(debugName.getKey(), -1);
if (receiver >= 0) {
program.variableAt(receiver).getDebugNames().add(debugName.getValue());
}
}
}
}
}
private static IntIntMap[] getBlockEntryVariableMappings(Program program, PhiUpdater phiUpdater,
Variable[] argumentMapping) {
class Step {
int node;
IntIntMap varMap;
Step(int node, IntIntMap varMap) {
this.node = node;
this.varMap = varMap;
}
}
IntIntMap[] result = new IntIntMap[program.basicBlockCount()];
DefinitionExtractor defExtractor = new DefinitionExtractor();
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
Graph dom = GraphUtils.buildDominatorGraph(GraphUtils.buildDominatorTree(cfg), cfg.size());
Step[] stack = new Step[program.basicBlockCount()];
int top = 0;
IntIntOpenHashMap entryVarMap = new IntIntOpenHashMap();
for (int i = 0; i < argumentMapping.length; ++i) {
Variable arg = argumentMapping[i];
if (arg != null) {
entryVarMap.put(i, arg.getIndex());
}
}
stack[top++] = new Step(0, entryVarMap);
while (top > 0) {
Step step = stack[--top];
int node = step.node;
IntIntMap varMap = new IntIntOpenHashMap(step.varMap);
BasicBlock block = program.basicBlockAt(node);
for (TryCatchJoint joint : block.getTryCatchJoints()) {
int receiver = joint.getReceiver().getIndex();
int sourceVar = phiUpdater.getSourceVariable(receiver);
if (sourceVar >= 0) {
varMap.put(sourceVar, receiver);
}
}
for (Phi phi : block.getPhis()) {
int receiver = phi.getReceiver().getIndex();
int sourceVar = phiUpdater.getSourceVariable(receiver);
if (sourceVar >= 0) {
varMap.put(sourceVar, receiver);
}
}
result[node] = new IntIntOpenHashMap(varMap);
for (Instruction insn : block.getInstructions()) {
insn.acceptVisitor(defExtractor);
for (Variable definedVar : defExtractor.getDefinedVariables()) {
int sourceVar = phiUpdater.getSourceVariable(definedVar.getIndex());
if (sourceVar >= 0) {
varMap.put(sourceVar, definedVar.getIndex());
}
}
}
for (int successor : dom.outgoingEdges(node)) {
stack[top++] = new Step(successor, new IntIntOpenHashMap(varMap));
}
}
return result;
}
private static Variable[] applySignature(Program program, ValueType[] arguments) {
if (program.variableCount() == 0) {
return new Variable[0];

View File

@ -23,10 +23,6 @@ import org.teavm.model.instructions.*;
import org.teavm.model.util.InstructionTransitionExtractor;
import org.teavm.model.util.ProgramUtils;
/**
*
* @author Alexey Andreev
*/
public class ProgramParser {
private static final byte ROOT = 0;
private static final byte SINGLE = 1;