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.List;
public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDataPseudoInstruction>
implements Iterable<LabelMethodItem> {
private final List<LabelMethodItem> labels;
public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDataPseudoInstruction> {
private final List<PackedSwitchTarget> targets;
public PackedSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress,
PackedSwitchDataPseudoInstruction instruction) {
@ -50,13 +49,29 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
int baseCodeAddress = methodDefinition.getPackedSwitchBaseAddress(codeAddress);
labels = new ArrayList<LabelMethodItem>();
targets = new ArrayList<PackedSwitchTarget>();
Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = instruction.iterateKeysAndTargets();
while (iterator.hasNext()) {
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "pswitch_");
label = methodDefinition.getLabelCache().internLabel(label);
labels.add(label);
if (baseCodeAddress >= 0) {
while (iterator.hasNext()) {
PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next();
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());
writer.indent(4);
writer.write('\n');
for (LabelMethodItem label: labels) {
label.writeTo(writer);
for (PackedSwitchTarget target: targets) {
target.writeTargetTo(writer);
writer.write('\n');
}
writer.deindent(4);
@ -75,7 +90,24 @@ public class PackedSwitchMethodItem extends InstructionMethodItem<PackedSwitchDa
return true;
}
public Iterator<LabelMethodItem> iterator() {
return labels.iterator();
private static abstract class PackedSwitchTarget {
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.List;
public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDataPseudoInstruction>
implements Iterable<LabelMethodItem> {
public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDataPseudoInstruction> {
private final List<SparseSwitchTarget> targets;
public SparseSwitchMethodItem(MethodDefinition methodDefinition, CodeItem codeItem, int codeAddress,
@ -52,16 +51,28 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
targets = new ArrayList<SparseSwitchTarget>();
Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = instruction.iterateKeysAndTargets();
while (iterator.hasNext()) {
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next();
SparseSwitchTarget sparseSwitchTarget = new SparseSwitchTarget();
sparseSwitchTarget.Key = target.key;
if (baseCodeAddress != 0) {
while (iterator.hasNext()) {
SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next();
SparseSwitchLabelTarget sparseSwitchLabelTarget = new SparseSwitchLabelTarget();
sparseSwitchLabelTarget.Key = target.key;
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_");
label = methodDefinition.getLabelCache().internLabel(label);
sparseSwitchTarget.Target = label;
LabelMethodItem label = new LabelMethodItem(baseCodeAddress + target.targetAddressOffset, "sswitch_");
label = methodDefinition.getLabelCache().internLabel(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) {
IntegerRenderer.writeTo(writer, target.Key);
writer.write(" -> ");
target.Target.writeTo(writer);
target.writeTargetTo(writer);
writer.write('\n');
}
writer.deindent(4);
@ -80,26 +91,25 @@ public class SparseSwitchMethodItem extends InstructionMethodItem<SparseSwitchDa
return true;
}
public Iterator<LabelMethodItem> iterator() {
return new Iterator<LabelMethodItem>() {
private Iterator<SparseSwitchTarget> iterator = targets.iterator();
public boolean hasNext() {
return iterator.hasNext();
}
public LabelMethodItem next() {
return iterator.next().Target;
}
public void remove() {
iterator.remove();
}
};
private static abstract class SparseSwitchTarget {
public int Key;
public abstract void writeTargetTo(IndentingWriter writer) throws IOException;
}
private static class SparseSwitchTarget {
public int Key;
private static class SparseSwitchLabelTarget extends SparseSwitchTarget {
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);
if (packedSwitchBaseAddress == -1) {
throw new RuntimeException("Could not find the packed switch statement corresponding to the packed " +
"switch data at address " + packedSwitchDataAddress);
Instruction[] instructions = encodedMethod.codeItem.getInstructions();
int index = instructionMap.get(packedSwitchDataAddress);
if (instructions[index].opcode == Opcode.NOP) {
packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress+2, -1);
}
}
return packedSwitchBaseAddress;
@ -250,8 +254,12 @@ public class MethodDefinition {
int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1);
if (sparseSwitchBaseAddress == -1) {
throw new RuntimeException("Could not find the sparse switch statement corresponding to the sparse " +
"switch data at address " + sparseSwitchDataAddress);
Instruction[] instructions = encodedMethod.codeItem.getInstructions();
int index = instructionMap.get(sparseSwitchDataAddress);
if (instructions[index].opcode == Opcode.NOP) {
sparseSwitchBaseAddress = this.packedSwitchMap.get(sparseSwitchDataAddress+2, -1);
}
}
return sparseSwitchBaseAddress;