Merge "Move inserted method after end of try block"

This commit is contained in:
Colin Cross
2017-08-04 15:54:24 +00:00
committed by Gerrit Code Review
4 changed files with 58 additions and 3 deletions

View File

@@ -9,7 +9,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
asm-5.2 \ asm-5.2 \
asm-commons-5.2 \ asm-commons-5.2 \
asm-tree-5.2 \ asm-tree-5.2 \
asm-analysis-5.2 asm-analysis-5.2 \
guava-20.0 \
include $(BUILD_HOST_JAVA_LIBRARY) include $(BUILD_HOST_JAVA_LIBRARY)

View File

@@ -18,6 +18,7 @@ import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes; import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.TryCatchBlockSorter; import org.objectweb.asm.commons.TryCatchBlockSorter;
@@ -32,6 +33,10 @@ import org.objectweb.asm.tree.analysis.AnalyzerException;
import org.objectweb.asm.tree.analysis.BasicValue; import org.objectweb.asm.tree.analysis.BasicValue;
import org.objectweb.asm.tree.analysis.Frame; import org.objectweb.asm.tree.analysis.Frame;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
/** /**
* This visitor does two things: * This visitor does two things:
* *
@@ -140,10 +145,26 @@ class LockFindingClassVisitor extends ClassVisitor {
if (operand instanceof LockTargetState) { if (operand instanceof LockTargetState) {
LockTargetState state = (LockTargetState) operand; LockTargetState state = (LockTargetState) operand;
for (int j = 0; j < state.getTargets().size(); j++) { for (int j = 0; j < state.getTargets().size(); j++) {
// The instruction after a monitor_exit should be a label for the end of the implicit
// catch block that surrounds the synchronized block to call monitor_exit when an exception
// occurs.
checkState(instructions.get(i + 1).getType() == AbstractInsnNode.LABEL,
"Expected to find label after monitor exit");
int labelIndex = i + 1;
checkElementIndex(labelIndex, instructions.size());
LabelNode label = (LabelNode)instructions.get(labelIndex);
checkNotNull(handlersMap.get(i));
checkElementIndex(0, handlersMap.get(i).size());
checkState(handlersMap.get(i).get(0).end == label,
"Expected label to be the end of monitor exit's try block");
LockTarget target = state.getTargets().get(j); LockTarget target = state.getTargets().get(j);
MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKESTATIC, MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKESTATIC,
target.getPostOwner(), target.getPostMethod(), "()V", false); target.getPostOwner(), target.getPostMethod(), "()V", false);
insertMethodCallAfter(mn, frameMap, handlersMap, s, i, call); insertMethodCallAfter(mn, frameMap, handlersMap, label, labelIndex, call);
} }
} }
} }

View File

@@ -228,4 +228,26 @@ public class TestMain {
Assert.assertEquals(TestTarget.unboostCount, 1); Assert.assertEquals(TestTarget.unboostCount, 1);
Assert.assertEquals(TestTarget.invokeCount, 1); Assert.assertEquals(TestTarget.invokeCount, 1);
} }
@Test
public void testUnboostThatThrows() {
TestTarget.resetCount();
TestTarget t = new TestTarget();
boolean asserted = false;
Assert.assertEquals(TestTarget.boostCount, 0);
Assert.assertEquals(TestTarget.unboostCount, 0);
try {
t.synchronizedThrowsOnUnboost();
} catch (RuntimeException e) {
asserted = true;
}
Assert.assertEquals(asserted, true);
Assert.assertEquals(TestTarget.boostCount, 1);
Assert.assertEquals(TestTarget.unboostCount, 0);
Assert.assertEquals(TestTarget.invokeCount, 1);
}
} }

View File

@@ -17,12 +17,17 @@ public class TestTarget {
public static int boostCount = 0; public static int boostCount = 0;
public static int unboostCount = 0; public static int unboostCount = 0;
public static int invokeCount = 0; public static int invokeCount = 0;
public static boolean nextUnboostThrows = false;
public static void boost() { public static void boost() {
boostCount++; boostCount++;
} }
public static void unboost() { public static void unboost() {
if (nextUnboostThrows) {
nextUnboostThrows = false;
throw new RuntimeException();
}
unboostCount++; unboostCount++;
} }
@@ -49,4 +54,11 @@ public class TestTarget {
invoke(); invoke();
return this; return this;
} }
public void synchronizedThrowsOnUnboost() {
nextUnboostThrows = true;
synchronized(this) {
invoke();
}
}
} }