Add logic to TryListBuilder to merge contiguous try blocks with identical handlers

This commit is contained in:
Ben Gruver 2013-04-14 18:14:06 -07:00
parent 5916df9999
commit 8c3d16b7ee
2 changed files with 81 additions and 18 deletions

View File

@ -39,6 +39,7 @@ import org.jf.dexlib2.immutable.ImmutableExceptionHandler;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
@ -125,6 +126,17 @@ public class TryListBuilder
return newTryBlock;
}
public void delete() {
next.prev = prev;
prev.next = next;
}
public void mergeNext() {
//assert next.startCodeAddress == this.endCodeAddress;
this.endCodeAddress = next.endCodeAddress;
next.delete();
}
public void append(@Nonnull MutableTryBlock tryBlock) {
next.prev = tryBlock;
tryBlock.next = next;
@ -296,18 +308,48 @@ public class TryListBuilder
public List<TryBlock> getTryBlocks() {
return Lists.newArrayList(new Iterator<TryBlock>() {
private MutableTryBlock tryBlock = listStart;
// The next TryBlock to return. This has already been merged, if needed.
@Nullable private MutableTryBlock next;
{
next = listStart;
next = readNextItem();
}
/**
* Read the item that comes after the current value of the next field.
* @return The next item, or null if there is no next item
*/
@Nullable protected MutableTryBlock readNextItem() {
// We can assume that next is not null
MutableTryBlock ret = next.next;
if (ret == listEnd) {
return null;
}
while (ret.next != listEnd) {
if (ret.endCodeAddress == ret.next.startCodeAddress &&
ret.getExceptionHandlers().equals(ret.next.getExceptionHandlers())) {
ret.mergeNext();
} else {
break;
}
}
return ret;
}
@Override public boolean hasNext() {
return tryBlock.next != listEnd;
return next != null;
}
@Override public TryBlock next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
tryBlock = tryBlock.next;
return tryBlock;
TryBlock ret = next;
next = readNextItem();
return ret;
}
@Override public void remove() {

View File

@ -409,13 +409,7 @@ public class TryListBuilderTest {
List<TryBlock> tryBlocks = tlb.getTryBlocks();
List<? extends TryBlock> expected = ImmutableList.of(
new ImmutableTryBlock(0, 5,
ImmutableList.of(
new ImmutableExceptionHandler("LException1;", 5))),
new ImmutableTryBlock(5, 5,
ImmutableList.of(
new ImmutableExceptionHandler("LException1;", 5))),
new ImmutableTryBlock(10, 5,
new ImmutableTryBlock(0, 15,
ImmutableList.of(
new ImmutableExceptionHandler("LException1;", 5))));
@ -517,13 +511,7 @@ public class TryListBuilderTest {
List<TryBlock> tryBlocks = tlb.getTryBlocks();
List<? extends TryBlock> expected = ImmutableList.of(
new ImmutableTryBlock(0, 5,
ImmutableList.of(
new ImmutableExceptionHandler(null, 5))),
new ImmutableTryBlock(5, 5,
ImmutableList.of(
new ImmutableExceptionHandler(null, 5))),
new ImmutableTryBlock(10, 5,
new ImmutableTryBlock(0, 15,
ImmutableList.of(
new ImmutableExceptionHandler(null, 5))));
@ -542,4 +530,37 @@ public class TryListBuilderTest {
}
Assert.fail();
}
@Test
public void testHandlerMerge_MergeSame() {
TryListBuilder tlb = new TryListBuilder();
tlb.addHandler(null, 0, 15, 6);
tlb.addHandler("LException1;", 10, 20, 5);
tlb.addHandler("LException1;", 20, 30, 5);
tlb.addHandler(null, 25, 40, 6);
List<TryBlock> tryBlocks = tlb.getTryBlocks();
List<? extends TryBlock> expected = ImmutableList.of(
new ImmutableTryBlock(0, 10,
ImmutableList.of(
new ImmutableExceptionHandler(null, 6))),
new ImmutableTryBlock(10, 5,
ImmutableList.of(
new ImmutableExceptionHandler(null, 6),
new ImmutableExceptionHandler("LException1;", 5))),
new ImmutableTryBlock(15, 10,
ImmutableList.of(
new ImmutableExceptionHandler("LException1;", 5))),
new ImmutableTryBlock(25, 5,
ImmutableList.of(
new ImmutableExceptionHandler("LException1;", 5),
new ImmutableExceptionHandler(null, 6))),
new ImmutableTryBlock(30, 10,
ImmutableList.of(
new ImmutableExceptionHandler(null, 6))));
Assert.assertEquals(expected, tryBlocks);
}
}