Improve the way sparse/packed switch data blocks are found and processed

This commit is contained in:
Ben Gruver 2011-10-09 01:17:14 -04:00
parent 82cdb8a8af
commit cb3e0ea38a
3 changed files with 96 additions and 46 deletions

View File

@ -40,9 +40,8 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDataPseudoInstruction> public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDataPseudoInstruction> {
implements Iterable<LabelMethodItem> { private final List<PackedSwitchTarget> targets;
private final List<LabelMethodItem> labels;
public PackedSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, public PackedSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress,
PackedSwitchDataPseudoInstruction instruction) { PackedSwitchDataPseudoInstruction instruction) {
@ -50,13 +49,29 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
int baseCodeAddress = methodDefinition.getPackedSwitchBaseAddress(codeAddress); int baseCodeAddress = methodDefinition.getPackedSwitchBaseAddress(codeAddress);
labels = new ArrayList<LabelMethodItem>(); targets = new ArrayList<PackedSwitchTarget>();
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.iterateKeysAndTargets(); Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.iterateKeysAndTargets();
while (iterator.hasNext()) {
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); if (baseCodeAddress >= 0) {
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "pswitch_"); while (iterator.hasNext()) {
label = methodDefinition.getLabelCache().internLabel(label); PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
labels.add(label); PackedSwitchLabelTarget packedSwitchLabelTarget = new PackedSwitchLabelTarget();
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "pswitch_");
label = methodDefinition.getLabelCache().internLabel(label);
packedSwitchLabelTarget.Target = label;
targets.add(packedSwitchLabelTarget);
}
} else {
while (iterator.hasNext()) {
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
PackedSwitchOffsetTarget packedSwitchOffsetTarget = new PackedSwitchOffsetTarget();
packedSwitchOffsetTarget.Target = target.targetAddressOffset;
targets.add(packedSwitchOffsetTarget);
}
} }
} }
@ -66,8 +81,8 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
IntegerRenderer.writeTo(writer, instruction.getFirstKey()); IntegerRenderer.writeTo(writer, instruction.getFirstKey());
writer.indent(4); writer.indent(4);
writer.write('\n'); writer.write('\n');
for (LabelMethodItem label: labels) { for (PackedSwitchTarget target: targets) {
label.writeTo(writer); target.writeTargetTo(writer);
writer.write('\n'); writer.write('\n');
} }
writer.deindent(4); writer.deindent(4);
@ -75,7 +90,24 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
return true; return true;
} }
public Iterator<LabelMethodItem> iterator() { private static abstract class PackedSwitchTarget {
return labels.iterator(); public abstract void writeTargetTo(IndentingWriter writer) throws IOException;
}
private static class PackedSwitchLabelTarget extends PackedSwitchTarget {
public LabelMethodItem Target;
public void writeTargetTo(IndentingWriter writer) throws IOException {
Target.writeTo(writer);
}
}
private static class PackedSwitchOffsetTarget extends PackedSwitchTarget {
public int Target;
public void writeTargetTo(IndentingWriter writer) throws IOException {
if (Target >= 0) {
writer.write('+');
}
writer.printSignedIntAsDec(Target);
}
} }
} }

View File

@ -40,8 +40,7 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDataPseudoInstruction> public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDataPseudoInstruction> {
implements Iterable<LabelMethodItem> {
private final List<SparseSwitchTarget> targets; private final List<SparseSwitchTarget> targets;
public SparseSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress, public SparseSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress,
@ -52,16 +51,28 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
targets = new ArrayList<SparseSwitchTarget>(); targets = new ArrayList<SparseSwitchTarget>();
Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.iterateKeysAndTargets(); Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.iterateKeysAndTargets();
while (iterator.hasNext()) { if (baseCodeAddress != 0) {
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); while (iterator.hasNext()) {
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget(); SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next();
sparseSwitchTarget.Key = target.key; SparseSwitchLabelTarget sparseSwitchLabelTarget = new SparseSwitchLabelTarget();
sparseSwitchLabelTarget.Key = target.key;
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_"); LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_");
label = methodDefinition.getLabelCache().internLabel(label); label = methodDefinition.getLabelCache().internLabel(label);
sparseSwitchTarget.Target = label; sparseSwitchLabelTarget.Target = label;
targets.add(sparseSwitchTarget); targets.add(sparseSwitchLabelTarget);
}
} else {
//if we couldn't determine a base address, just use relative offsets rather than labels
while (iterator.hasNext()) {
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next();
SparseSwitchOffsetTarget sparseSwitchOffsetTarget = new SparseSwitchOffsetTarget();
sparseSwitchOffsetTarget.Key = target.key;
sparseSwitchOffsetTarget.Target = target.targetAddressOffset;
targets.add(sparseSwitchOffsetTarget);
}
} }
} }
@ -72,7 +83,7 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
for (SparseSwitchTarget target: targets) { for (SparseSwitchTarget target: targets) {
IntegerRenderer.writeTo(writer, target.Key); IntegerRenderer.writeTo(writer, target.Key);
writer.write(" -> "); writer.write(" -> ");
target.Target.writeTo(writer); target.writeTargetTo(writer);
writer.write('\n'); writer.write('\n');
} }
writer.deindent(4); writer.deindent(4);
@ -80,26 +91,25 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
return true; return true;
} }
public Iterator<LabelMethodItem> iterator() { private static abstract class SparseSwitchTarget {
return new Iterator<LabelMethodItem>() { public int Key;
private Iterator<SparseSwitchTarget> iterator = targets.iterator(); public abstract void writeTargetTo(IndentingWriter writer) throws IOException;
public boolean hasNext() {
return iterator.hasNext();
}
public LabelMethodItem next() {
return iterator.next().Target;
}
public void remove() {
iterator.remove();
}
};
} }
private static class SparseSwitchTarget { private static class SparseSwitchLabelTarget extends SparseSwitchTarget {
public int Key;
public LabelMethodItem Target; public LabelMethodItem Target;
public void writeTargetTo(IndentingWriter writer) throws IOException {
Target.writeTo(writer);
}
}
private static class SparseSwitchOffsetTarget extends SparseSwitchTarget {
public int Target;
public void writeTargetTo(IndentingWriter writer) throws IOException {
if (Target >= 0) {
writer.write('+');
}
writer.printSignedIntAsDec(Target);
}
} }
} }

View File

@ -239,8 +239,12 @@ public class MethodDefinition {
int packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress, -1); int packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress, -1);
if (packedSwitchBaseAddress == -1) { if (packedSwitchBaseAddress == -1) {
throw new RuntimeException("Could not find the packed switch statement corresponding to the packed " + Instruction[] instructions = encodedMethod.codeItem.getInstructions();
"switch data at address " + packedSwitchDataAddress); int index = instructionMap.get(packedSwitchDataAddress);
if (instructions[index].opcode == Opcode.NOP) {
packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress+2, -1);
}
} }
return packedSwitchBaseAddress; return packedSwitchBaseAddress;
@ -250,8 +254,12 @@ public class MethodDefinition {
int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1); int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1);
if (sparseSwitchBaseAddress == -1) { if (sparseSwitchBaseAddress == -1) {
throw new RuntimeException("Could not find the sparse switch statement corresponding to the sparse " + Instruction[] instructions = encodedMethod.codeItem.getInstructions();
"switch data at address " + sparseSwitchDataAddress); int index = instructionMap.get(sparseSwitchDataAddress);
if (instructions[index].opcode == Opcode.NOP) {
sparseSwitchBaseAddress = this.packedSwitchMap.get(sparseSwitchDataAddress+2, -1);
}
} }
return sparseSwitchBaseAddress; return sparseSwitchBaseAddress;