Merge "Move inserted method after end of try block"
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user