summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/locked_region_code_injection/Android.mk4
-rw-r--r--tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java23
-rw-r--r--tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java22
-rw-r--r--tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java12
4 files changed, 58 insertions, 3 deletions
diff --git a/tools/locked_region_code_injection/Android.mk b/tools/locked_region_code_injection/Android.mk
index 0aed0cec27ab..d9217834f871 100644
--- a/tools/locked_region_code_injection/Android.mk
+++ b/tools/locked_region_code_injection/Android.mk
@@ -9,7 +9,7 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
asm-5.2 \
asm-commons-5.2 \
asm-tree-5.2 \
- asm-analysis-5.2
-
+ asm-analysis-5.2 \
+ guava-20.0 \
include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java
index 9374f23c945e..99ef8a7b707a 100644
--- a/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java
+++ b/tools/locked_region_code_injection/src/lockedregioncodeinjection/LockFindingClassVisitor.java
@@ -18,6 +18,7 @@ import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
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.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:
*
@@ -140,10 +145,26 @@ class LockFindingClassVisitor extends ClassVisitor {
if (operand instanceof LockTargetState) {
LockTargetState state = (LockTargetState) operand;
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);
MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKESTATIC,
target.getPostOwner(), target.getPostMethod(), "()V", false);
- insertMethodCallAfter(mn, frameMap, handlersMap, s, i, call);
+ insertMethodCallAfter(mn, frameMap, handlersMap, label, labelIndex, call);
}
}
}
diff --git a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java
index 1d4f2d455270..b86954d5e377 100644
--- a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java
+++ b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestMain.java
@@ -228,4 +228,26 @@ public class TestMain {
Assert.assertEquals(TestTarget.unboostCount, 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);
+ }
+
}
diff --git a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java
index 8e7d478a0e29..d1c8f340a598 100644
--- a/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java
+++ b/tools/locked_region_code_injection/test/lockedregioncodeinjection/TestTarget.java
@@ -17,12 +17,17 @@ public class TestTarget {
public static int boostCount = 0;
public static int unboostCount = 0;
public static int invokeCount = 0;
+ public static boolean nextUnboostThrows = false;
public static void boost() {
boostCount++;
}
public static void unboost() {
+ if (nextUnboostThrows) {
+ nextUnboostThrows = false;
+ throw new RuntimeException();
+ }
unboostCount++;
}
@@ -49,4 +54,11 @@ public class TestTarget {
invoke();
return this;
}
+
+ public void synchronizedThrowsOnUnboost() {
+ nextUnboostThrows = true;
+ synchronized(this) {
+ invoke();
+ }
+ }
}