mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
Repair information about variable names in debug tables
This commit is contained in:
parent
feafa032df
commit
6e2eb8386b
|
@ -23,6 +23,7 @@ import java.util.Map;
|
||||||
import org.teavm.common.DominatorTree;
|
import org.teavm.common.DominatorTree;
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphUtils;
|
import org.teavm.common.GraphUtils;
|
||||||
|
import org.teavm.common.IntegerArray;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.Incoming;
|
import org.teavm.model.Incoming;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
|
@ -82,6 +83,11 @@ public class PhiUpdater {
|
||||||
private List<List<Phi>> synthesizedPhis = new ArrayList<>();
|
private List<List<Phi>> synthesizedPhis = new ArrayList<>();
|
||||||
private List<List<TryCatchJoint>> synthesizedJoints = new ArrayList<>();
|
private List<List<TryCatchJoint>> synthesizedJoints = new ArrayList<>();
|
||||||
private boolean[] usedDefinitions;
|
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) {
|
public void updatePhis(Program program, Variable[] arguments) {
|
||||||
if (program.basicBlockCount() == 0) {
|
if (program.basicBlockCount() == 0) {
|
||||||
|
@ -93,8 +99,11 @@ public class PhiUpdater {
|
||||||
domFrontiers = new int[cfg.size()][];
|
domFrontiers = new int[cfg.size()][];
|
||||||
variableMap = new Variable[program.variableCount()];
|
variableMap = new Variable[program.variableCount()];
|
||||||
usedDefinitions = new boolean[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) {
|
for (int i = 0; i < arguments.length; ++i) {
|
||||||
variableMap[i] = arguments[i];
|
mapVariable(i, arguments[i]);
|
||||||
usedDefinitions[i] = true;
|
usedDefinitions[i] = true;
|
||||||
}
|
}
|
||||||
phiMap = new Phi[program.basicBlockCount()][];
|
phiMap = new Phi[program.basicBlockCount()][];
|
||||||
|
@ -175,13 +184,13 @@ public class PhiUpdater {
|
||||||
for (Phi phi : synthesizedPhis.get(index)) {
|
for (Phi phi : synthesizedPhis.get(index)) {
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable();
|
||||||
var.getDebugNames().addAll(phi.getReceiver().getDebugNames());
|
var.getDebugNames().addAll(phi.getReceiver().getDebugNames());
|
||||||
variableMap[phi.getReceiver().getIndex()] = var;
|
mapVariable(phi.getReceiver().getIndex(), var);
|
||||||
phi.setReceiver(var);
|
phi.setReceiver(var);
|
||||||
}
|
}
|
||||||
for (TryCatchJoint joint : synthesizedJoints.get(index)) {
|
for (TryCatchJoint joint : synthesizedJoints.get(index)) {
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable();
|
||||||
var.getDebugNames().addAll(joint.getReceiver().getDebugNames());
|
var.getDebugNames().addAll(joint.getReceiver().getDebugNames());
|
||||||
variableMap[joint.getReceiver().getIndex()] = var;
|
mapVariable(joint.getReceiver().getIndex(), var);
|
||||||
joint.setReceiver(var);
|
joint.setReceiver(var);
|
||||||
}
|
}
|
||||||
for (Phi phi : currentBlock.getPhis()) {
|
for (Phi phi : currentBlock.getPhis()) {
|
||||||
|
@ -320,10 +329,18 @@ public class PhiUpdater {
|
||||||
private Variable define(Variable var) {
|
private Variable define(Variable var) {
|
||||||
Variable original = var;
|
Variable original = var;
|
||||||
var = introduce(var, false);
|
var = introduce(var, false);
|
||||||
variableMap[original.getIndex()] = var;
|
mapVariable(original.getIndex(), var);
|
||||||
return 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) {
|
private Variable introduce(Variable var, boolean clear) {
|
||||||
Variable original = var;
|
Variable original = var;
|
||||||
Variable old = variableMap[var.getIndex()];
|
Variable old = variableMap[var.getIndex()];
|
||||||
|
|
|
@ -15,22 +15,26 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.parsing;
|
package org.teavm.parsing;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.IntIntMap;
|
||||||
|
import com.carrotsearch.hppc.IntIntOpenHashMap;
|
||||||
import java.lang.reflect.Array;
|
import java.lang.reflect.Array;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import org.objectweb.asm.Opcodes;
|
import org.objectweb.asm.Opcodes;
|
||||||
import org.objectweb.asm.Type;
|
import org.objectweb.asm.Type;
|
||||||
import org.objectweb.asm.commons.JSRInlinerAdapter;
|
import org.objectweb.asm.commons.JSRInlinerAdapter;
|
||||||
import org.objectweb.asm.tree.*;
|
import org.objectweb.asm.tree.*;
|
||||||
|
import org.teavm.common.Graph;
|
||||||
|
import org.teavm.common.GraphUtils;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
import org.teavm.model.util.DefinitionExtractor;
|
||||||
import org.teavm.model.util.PhiUpdater;
|
import org.teavm.model.util.PhiUpdater;
|
||||||
|
import org.teavm.model.util.ProgramUtils;
|
||||||
import org.teavm.optimization.UnreachableBasicBlockEliminator;
|
import org.teavm.optimization.UnreachableBasicBlockEliminator;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public final class Parser {
|
public final class Parser {
|
||||||
private Parser() {
|
private Parser() {
|
||||||
}
|
}
|
||||||
|
@ -45,13 +49,17 @@ public final class Parser {
|
||||||
ValueType[] signature = MethodDescriptor.parseSignature(node.desc);
|
ValueType[] signature = MethodDescriptor.parseSignature(node.desc);
|
||||||
MethodHolder method = new MethodHolder(node.name, signature);
|
MethodHolder method = new MethodHolder(node.name, signature);
|
||||||
parseModifiers(node.access, method);
|
parseModifiers(node.access, method);
|
||||||
|
|
||||||
ProgramParser programParser = new ProgramParser();
|
ProgramParser programParser = new ProgramParser();
|
||||||
programParser.setFileName(fileName);
|
programParser.setFileName(fileName);
|
||||||
Program program = programParser.parse(node, className);
|
Program program = programParser.parse(node, className);
|
||||||
new UnreachableBasicBlockEliminator().optimize(program);
|
new UnreachableBasicBlockEliminator().optimize(program);
|
||||||
PhiUpdater phiUpdater = new PhiUpdater();
|
PhiUpdater phiUpdater = new PhiUpdater();
|
||||||
phiUpdater.updatePhis(program, applySignature(program, method.getParameterTypes()));
|
Variable[] argumentMapping = applySignature(program, method.getParameterTypes());
|
||||||
|
phiUpdater.updatePhis(program, argumentMapping);
|
||||||
method.setProgram(program);
|
method.setProgram(program);
|
||||||
|
applyDebugNames(program, phiUpdater, programParser, argumentMapping);
|
||||||
|
|
||||||
parseAnnotations(method.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations);
|
parseAnnotations(method.getAnnotations(), node.visibleAnnotations, node.invisibleAnnotations);
|
||||||
while (program.variableCount() <= method.parameterCount()) {
|
while (program.variableCount() <= method.parameterCount()) {
|
||||||
program.createVariable();
|
program.createVariable();
|
||||||
|
@ -67,6 +75,110 @@ public final class Parser {
|
||||||
return method;
|
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) {
|
private static Variable[] applySignature(Program program, ValueType[] arguments) {
|
||||||
if (program.variableCount() == 0) {
|
if (program.variableCount() == 0) {
|
||||||
return new Variable[0];
|
return new Variable[0];
|
||||||
|
|
|
@ -23,10 +23,6 @@ import org.teavm.model.instructions.*;
|
||||||
import org.teavm.model.util.InstructionTransitionExtractor;
|
import org.teavm.model.util.InstructionTransitionExtractor;
|
||||||
import org.teavm.model.util.ProgramUtils;
|
import org.teavm.model.util.ProgramUtils;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Alexey Andreev
|
|
||||||
*/
|
|
||||||
public class ProgramParser {
|
public class ProgramParser {
|
||||||
private static final byte ROOT = 0;
|
private static final byte ROOT = 0;
|
||||||
private static final byte SINGLE = 1;
|
private static final byte SINGLE = 1;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user