Allow mulitple locks in BoostLockedRegionPriority

Each one of the property will now take a comma sepereated list of class
and method names.

BUG: 36631902
Change-Id: I559d320a5ea601289495eb1343652a46f6b00cf4
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/BoostLockedRegionPriorityTests.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/BoostLockedRegionPriorityTests.java
index 3d9aa64..ccbd88c 100644
--- a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/BoostLockedRegionPriorityTests.java
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/BoostLockedRegionPriorityTests.java
@@ -27,29 +27,29 @@
 
 public class BoostLockedRegionPriorityTests extends RuntimeTest {
 
-  private RuntimeTestInfo TEST001 =
-      new RuntimeTestInfo(
-          AbstractTestTools.getTestRootDir(
-              "com.android.jack.transformations.boostlockregionpriority.test001"),
-          "com.android.jack.transformations.boostlockregionpriority.test001.dx.Tests");
+  private RuntimeTestInfo TEST001 = new RuntimeTestInfo(
+      AbstractTestTools
+          .getTestRootDir("com.android.jack.transformations.boostlockregionpriority.test001"),
+      "com.android.jack.transformations.boostlockregionpriority.test001.dx.Tests");
 
   @Test
   @Runtime
   public void test001() throws Exception {
-    new RuntimeTestHelper(TEST001)
-        .addIgnoredCandidateToolchain(JillBasedToolchain.class)
+    new RuntimeTestHelper(TEST001).addIgnoredCandidateToolchain(JillBasedToolchain.class)
         .addProperty("jack.transformations.boost-locked-region-priority", "true")
-        .addProperty(
-            "jack.transformations.boost-locked-region-priority.classname",
-            "com.android.jack.transformations.boostlockregionpriority.test001.jack.LockedRegion")
-        .addProperty(
-            "jack.transformations.boost-locked-region-priority.request",
+        .addProperty("jack.transformations.boost-locked-region-priority.classname",
+            "com.android.jack.transformations.boostlockregionpriority.test001.jack.LockedRegion,"
+                + "com.android.jack.transformations.boostlockregionpriority.test001.jack.LockedRegion2,")
+        .addProperty("jack.transformations.boost-locked-region-priority.request",
             "com.android.jack.transformations.boostlockregionpriority.test001.jack."
-                + "Request#request")
-        .addProperty(
-            "jack.transformations.boost-locked-region-priority.reset",
+                + "Request#request,"
+                + "com.android.jack.transformations.boostlockregionpriority.test001.jack."
+                + "Request2#request")
+        .addProperty("jack.transformations.boost-locked-region-priority.reset",
             "com.android.jack.transformations.boostlockregionpriority.test001.jack."
-                + "Reset#reset")
+                + "Reset#reset,"
+                + "com.android.jack.transformations.boostlockregionpriority.test001.jack."
+                + "Reset2#reset,")
         .compileAndRunTest();
   }
 
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/dx/Tests.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/dx/Tests.java
index c204342..f76d9e0 100644
--- a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/dx/Tests.java
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/dx/Tests.java
@@ -17,10 +17,17 @@
 package com.android.jack.transformations.boostlockregionpriority.test001.dx;
 
 import com.android.jack.transformations.boostlockregionpriority.test001.jack.LockedRegion;
+import com.android.jack.transformations.boostlockregionpriority.test001.jack.LockedRegion2;
+import com.android.jack.transformations.boostlockregionpriority.test001.jack.LockedRegion3;
 import com.android.jack.transformations.boostlockregionpriority.test001.jack.Request;
+import com.android.jack.transformations.boostlockregionpriority.test001.jack.Request2;
+import com.android.jack.transformations.boostlockregionpriority.test001.jack.Request3;
 import com.android.jack.transformations.boostlockregionpriority.test001.jack.Reset;
+import com.android.jack.transformations.boostlockregionpriority.test001.jack.Reset2;
+import com.android.jack.transformations.boostlockregionpriority.test001.jack.Reset3;
 
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 
 public class Tests {
@@ -31,6 +38,14 @@
     Assert.assertEquals(1, Request.count);
     Assert.assertEquals(1, Reset.count);
     Assert.assertEquals(1, LockedRegion.count);
+
+    Assert.assertEquals(0, Request2.count);
+    Assert.assertEquals(0, Reset2.count);
+    Assert.assertEquals(0, LockedRegion2.count);
+
+    Assert.assertEquals(0, Request3.count);
+    Assert.assertEquals(0, Reset3.count);
+    Assert.assertEquals(0, LockedRegion3.count);
   }
 
   @Test
@@ -40,6 +55,14 @@
     Assert.assertEquals(4, Request.count);
     Assert.assertEquals(4, Reset.count);
     Assert.assertEquals(4, LockedRegion.count);
+
+    Assert.assertEquals(0, Request2.count);
+    Assert.assertEquals(0, Reset2.count);
+    Assert.assertEquals(0, LockedRegion2.count);
+
+    Assert.assertEquals(0, Request3.count);
+    Assert.assertEquals(0, Reset3.count);
+    Assert.assertEquals(0, LockedRegion3.count);
   }
 
   /**
@@ -58,6 +81,14 @@
     Assert.assertEquals(1, Request.count);
     Assert.assertEquals(1, Reset.count);
     Assert.assertEquals(1, LockedRegion.count);
+
+    Assert.assertEquals(0, Request2.count);
+    Assert.assertEquals(0, Reset2.count);
+    Assert.assertEquals(0, LockedRegion2.count);
+
+    Assert.assertEquals(0, Request3.count);
+    Assert.assertEquals(0, Reset3.count);
+    Assert.assertEquals(0, LockedRegion3.count);
   }
 
   @Test
@@ -67,5 +98,65 @@
     Assert.assertEquals(0, Request.count);
     Assert.assertEquals(0, Reset.count);
     Assert.assertEquals(1, LockedRegion.count);
+
+    Assert.assertEquals(0, Request2.count);
+    Assert.assertEquals(0, Reset2.count);
+    Assert.assertEquals(0, LockedRegion2.count);
+
+    Assert.assertEquals(0, Request3.count);
+    Assert.assertEquals(0, Reset3.count);
+    Assert.assertEquals(0, LockedRegion3.count);
+  }
+
+  @Test
+  public void testLock2ThisBoost() {
+    LockedRegion2 r = new LockedRegion2();
+    r.invokeLockThis();
+    Assert.assertEquals(0, Request.count);
+    Assert.assertEquals(0, Reset.count);
+    Assert.assertEquals(0, LockedRegion.count);
+
+    Assert.assertEquals(1, Request2.count);
+    Assert.assertEquals(1, Reset2.count);
+    Assert.assertEquals(1, LockedRegion2.count);
+
+    Assert.assertEquals(0, Request3.count);
+    Assert.assertEquals(0, Reset3.count);
+    Assert.assertEquals(0, LockedRegion3.count);
+  }
+
+  @Test
+  public void testDoubleLockThisBoost() {
+    LockedRegion r = new LockedRegion();
+    LockedRegion2 r2 = new LockedRegion2();
+    r.invokeLockThis();
+    r2.invokeLockThis();
+
+    Assert.assertEquals(1, Request.count);
+    Assert.assertEquals(1, Reset.count);
+    Assert.assertEquals(1, LockedRegion.count);
+
+    Assert.assertEquals(1, Request2.count);
+    Assert.assertEquals(1, Reset2.count);
+    Assert.assertEquals(1, LockedRegion2.count);
+
+    Assert.assertEquals(0, Request3.count);
+    Assert.assertEquals(0, Reset3.count);
+    Assert.assertEquals(0, LockedRegion3.count);
+  }
+
+  @Before
+  public void clearCounts() {
+    Reset.count = 0;
+    Request.count = 0;
+    LockedRegion.count = 0;
+
+    Reset2.count = 0;
+    Request2.count = 0;
+    LockedRegion2.count = 0;
+
+    Reset3.count = 0;
+    Request3.count = 0;
+    LockedRegion3.count = 0;
   }
 }
\ No newline at end of file
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion.java
index 996f67b..d18e170 100644
--- a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion.java
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion.java
@@ -22,12 +22,6 @@
 
   private Object objectLock = new Object();
 
-  public LockedRegion() {
-    count = 0;
-    Request.count = 0;
-    Reset.count = 0;
-  }
-
   private static void region() {
     count++;
   }
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion2.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion2.java
new file mode 100644
index 0000000..600116c
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion2.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.transformations.boostlockregionpriority.test001.jack;
+
+public class LockedRegion2 {
+
+  public static int count = 0;
+
+  private static void region() {
+    count++;
+  }
+
+  public void invokeLockThis() {
+    synchronized (this) {
+      region();
+    }
+  }
+
+  public void invokeLockThisException() {
+    synchronized (this) {
+      region();
+      throw new RuntimeException();
+    }
+  }
+
+}
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion3.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion3.java
new file mode 100644
index 0000000..45d90cc
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/LockedRegion3.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.transformations.boostlockregionpriority.test001.jack;
+
+/**
+ * This one does NOT get any boosting.
+ */
+public class LockedRegion3 {
+
+  public static int count = 0;
+
+  private static void region() {
+    count++;
+  }
+
+  public void invokeLockThis() {
+    synchronized (this) {
+      region();
+    }
+  }
+}
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Request2.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Request2.java
new file mode 100644
index 0000000..0b9edd8
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Request2.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.transformations.boostlockregionpriority.test001.jack;
+
+public class Request2 {
+  public static int count = 0;
+  public static void request() {
+    count++;
+  }
+}
+
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Request3.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Request3.java
new file mode 100644
index 0000000..3883e3f
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Request3.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.transformations.boostlockregionpriority.test001.jack;
+
+public class Request3 {
+  public static int count = 0;
+  public static void request() {
+    count++;
+  }
+}
+
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Reset2.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Reset2.java
new file mode 100644
index 0000000..a25bc86
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Reset2.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.transformations.boostlockregionpriority.test001.jack;
+
+public class Reset2 {
+  public static int count = 0;
+  public static void reset() {
+    count++;
+  }
+}
+
diff --git a/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Reset3.java b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Reset3.java
new file mode 100644
index 0000000..925b868
--- /dev/null
+++ b/jack-tests/tests/com/android/jack/transformations/boostlockregionpriority/test001/jack/Reset3.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.jack.transformations.boostlockregionpriority.test001.jack;
+
+public class Reset3 {
+  public static int count = 0;
+  public static void reset() {
+    count++;
+  }
+}
+
diff --git a/jack/src/com/android/jack/transformations/BoostLockedRegionPriorityFeature.java b/jack/src/com/android/jack/transformations/BoostLockedRegionPriorityFeature.java
index f7c4616..4fa12b8 100644
--- a/jack/src/com/android/jack/transformations/BoostLockedRegionPriorityFeature.java
+++ b/jack/src/com/android/jack/transformations/BoostLockedRegionPriorityFeature.java
@@ -24,11 +24,14 @@
 import com.android.sched.item.Description;
 import com.android.sched.item.Feature;
 import com.android.sched.item.Name;
+import com.android.sched.util.codec.ListCodec;
 import com.android.sched.util.config.HasKeyId;
 import com.android.sched.util.config.category.Private;
 import com.android.sched.util.config.id.BooleanPropertyId;
 import com.android.sched.util.config.id.PropertyId;
 
+import java.util.List;
+
 import javax.annotation.Nonnull;
 
 /**
@@ -48,31 +51,31 @@
           .addCategory(DumpInLibrary.class);
 
   @Nonnull
-  public static final PropertyId<String> BOOST_LOCK_CLASSNAME =
+  public static final PropertyId<List<String>> BOOST_LOCK_CLASSNAME =
       PropertyId.create(
               "jack.transformations.boost-locked-region-priority.classname",
-              "The class signature where acquiring it as a lock should boost a thread's prioirty",
-              new ClassNameCodec())
+              "The class signatures where acquiring it as a lock should boost a thread's prioirty",
+              new ListCodec<String>(new ClassNameCodec()))
           .requiredIf(BoostLockedRegionPriorityFeature.ENABLE.getValue().isTrue())
           .addCategory(Private.class)
           .addCategory(DumpInLibrary.class);
 
   @Nonnull
-  public static final PropertyId<MethodNameValue> BOOST_LOCK_REQUEST_METHOD =
+  public static final PropertyId<List<MethodNameValue>> BOOST_LOCK_REQUEST_METHOD =
       PropertyId.create(
               "jack.transformations.boost-locked-region-priority.request",
-              "Static method in the specified class that can boost a thread's prioirty",
-              new MethodNameCodec())
+              "Static methods in the specified classes that can boost a thread's prioirty",
+              new ListCodec<MethodNameValue>(new MethodNameCodec()))
           .requiredIf(BoostLockedRegionPriorityFeature.ENABLE.getValue().isTrue())
           .addCategory(Private.class)
           .addCategory(DumpInLibrary.class);
 
   @Nonnull
-  public static final PropertyId<MethodNameValue> BOOST_LOCK_RESET_METHOD =
+  public static final PropertyId<List<MethodNameValue>> BOOST_LOCK_RESET_METHOD =
       PropertyId.create(
               "jack.transformations.boost-locked-region-priority.reset",
-              "Static method in the specified class that can reset a thread's prioirty",
-              new MethodNameCodec())
+              "Static methods in the specified classes that can reset a thread's prioirty",
+              new ListCodec<MethodNameValue>(new MethodNameCodec()))
           .requiredIf(BoostLockedRegionPriorityFeature.ENABLE.getValue().isTrue())
           .addCategory(Private.class)
           .addCategory(DumpInLibrary.class);
diff --git a/jack/src/com/android/jack/transformations/ast/BoostLockedRegionPriority.java b/jack/src/com/android/jack/transformations/ast/BoostLockedRegionPriority.java
index a42d235..08f9dfb 100644
--- a/jack/src/com/android/jack/transformations/ast/BoostLockedRegionPriority.java
+++ b/jack/src/com/android/jack/transformations/ast/BoostLockedRegionPriority.java
@@ -53,8 +53,9 @@
 import com.android.sched.util.config.ThreadConfig;
 
 import java.util.Collections;
+import java.util.List;
 
-import javax.annotation.CheckForNull;
+import javax.annotation.Nonnegative;
 import javax.annotation.Nonnull;
 
 /**
@@ -96,81 +97,91 @@
  * exceptions. This is important for threads that might be reused like worker threads.
  */
 @Description("Raise locked region priority for certain types of locks.")
-@Constraint(
-  need = {JLock.class, JUnlock.class},
-  no = {JSynchronizedBlock.class}
-)
-@Transform(
-  add = {
-    JExpressionStatement.class,
-    JMethodCall.class,
-  }
-)
+@Constraint(need = {JLock.class, JUnlock.class},
+    no = {JSynchronizedBlock.class})
+@Transform(add = {JExpressionStatement.class, JMethodCall.class})
 public class BoostLockedRegionPriority implements RunnableSchedulable<JMethod> {
 
-  @CheckForNull private final JClass lockClass;
-  @CheckForNull private final JClass requestClass;
-  @CheckForNull private final JClass resetClass;
-  @CheckForNull private final JMethodId requestMethodId;
-  @CheckForNull private final JMethodId resetMethodId;
-  @Nonnull private final Filter<JMethod> filter = ThreadConfig.get(Options.METHOD_FILTER);
+  @Nonnull
+  private final JClass[] lockClass;
+  @Nonnull
+  private final JClass[] requestClass;
+  @Nonnull
+  private final JClass[] resetClass;
+  @Nonnull
+  private final JMethodId[] requestMethodId;
+  @Nonnull
+  private final JMethodId[] resetMethodId;
+  @Nonnull
+  private final Filter<JMethod> filter = ThreadConfig.get(Options.METHOD_FILTER);
 
   public BoostLockedRegionPriority() {
-    String className = ThreadConfig.get(BoostLockedRegionPriorityFeature.BOOST_LOCK_CLASSNAME);
-    MethodNameValue requestMethodNameValue =
+    List<String> classNames =
+        ThreadConfig.get(BoostLockedRegionPriorityFeature.BOOST_LOCK_CLASSNAME);
+    List<MethodNameValue> requestMethodNameValues =
         ThreadConfig.get(BoostLockedRegionPriorityFeature.BOOST_LOCK_REQUEST_METHOD);
-    MethodNameValue resetMethodNameValue =
+    List<MethodNameValue> resetMethodNameValues =
         ThreadConfig.get(BoostLockedRegionPriorityFeature.BOOST_LOCK_RESET_METHOD);
 
+    // Check the make sure the number of boost / reset methods is same as number of locks.
+    int totalLocks = classNames.size();
+    if (totalLocks != requestMethodNameValues.size()) {
+      Jack.getSession().getReporter().report(Severity.FATAL,
+          new BadBoostLockedRegionPriorityMethods(
+              BoostLockedRegionPriorityFeature.BOOST_LOCK_REQUEST_METHOD.getName(), totalLocks,
+              requestMethodNameValues.size()));
+    }
+    if (totalLocks != resetMethodNameValues.size()) {
+      Jack.getSession().getReporter().report(Severity.FATAL,
+          new BadBoostLockedRegionPriorityMethods(
+              BoostLockedRegionPriorityFeature.BOOST_LOCK_RESET_METHOD.getName(), totalLocks,
+              resetMethodNameValues.size()));
+    }
+
+    lockClass = new JClass[totalLocks];
+    resetClass = new JClass[totalLocks];
+    requestClass = new JClass[totalLocks];
+    requestMethodId = new JMethodId[totalLocks];
+    resetMethodId = new JMethodId[totalLocks];
+
     final JNodeLookup lookup = Jack.getSession().getLookup();
-    lockClass =
-        getClassOrReportFailure(
-            lookup,
-            NamingTools.getTypeSignatureName(className),
-            BoostLockedRegionPriorityFeature.BOOST_LOCK_CLASSNAME.getName());
-    requestClass =
-        getClassOrReportFailure(
-            lookup,
-            NamingTools.getTypeSignatureName(requestMethodNameValue.getClassName()),
-            BoostLockedRegionPriorityFeature.BOOST_LOCK_REQUEST_METHOD.getName());
-    resetClass =
-        getClassOrReportFailure(
-            lookup,
-            NamingTools.getTypeSignatureName(resetMethodNameValue.getClassName()),
-            BoostLockedRegionPriorityFeature.BOOST_LOCK_RESET_METHOD.getName());
-    requestMethodId =
-        getStaticMethodOrReportFailure(
-            requestClass,
-            requestMethodNameValue.getMethodName(),
-            BoostLockedRegionPriorityFeature.BOOST_LOCK_REQUEST_METHOD.getName());
-    resetMethodId =
-        getStaticMethodOrReportFailure(
-            resetClass,
-            resetMethodNameValue.getMethodName(),
-            BoostLockedRegionPriorityFeature.BOOST_LOCK_RESET_METHOD.getName());
+    for (int i = 0; i < totalLocks; i++) {
+      lockClass[i] =
+          getClassOrReportFailure(lookup, NamingTools.getTypeSignatureName(classNames.get(i)),
+              BoostLockedRegionPriorityFeature.BOOST_LOCK_CLASSNAME.getName());
+      requestClass[i] = getClassOrReportFailure(lookup,
+          NamingTools.getTypeSignatureName(requestMethodNameValues.get(i).getClassName()),
+          BoostLockedRegionPriorityFeature.BOOST_LOCK_REQUEST_METHOD.getName());
+      resetClass[i] = getClassOrReportFailure(lookup,
+          NamingTools.getTypeSignatureName(resetMethodNameValues.get(i).getClassName()),
+          BoostLockedRegionPriorityFeature.BOOST_LOCK_RESET_METHOD.getName());
+      requestMethodId[i] = getStaticMethodOrReportFailure(requestClass[i],
+          requestMethodNameValues.get(i).getMethodName(),
+          BoostLockedRegionPriorityFeature.BOOST_LOCK_REQUEST_METHOD.getName());
+      resetMethodId[i] = getStaticMethodOrReportFailure(resetClass[i],
+          resetMethodNameValues.get(i).getMethodName(),
+          BoostLockedRegionPriorityFeature.BOOST_LOCK_RESET_METHOD.getName());
+    }
   }
 
   private static JClass getClassOrReportFailure(JNodeLookup lookup, String name, String prop) {
     try {
       return lookup.getClass(name);
     } catch (Throwable e) {
-      Jack.getSession()
-          .getReporter()
-          .report(Severity.FATAL, new BadBoostLockedRegionPriorityConfigurationException(prop, e));
+      Jack.getSession().getReporter().report(Severity.FATAL,
+          new BadBoostLockedRegionPriorityConfigurationException(prop, e));
       Jack.getSession().abortEventually();
       return null;
     }
   }
 
-  private static JMethodId getStaticMethodOrReportFailure(
-      JClass cls, String name, String prop) {
+  private static JMethodId getStaticMethodOrReportFailure(JClass cls, String name, String prop) {
     try {
       return cls.getMethodId(name, Collections.<JType>emptyList(), MethodKind.STATIC,
           JPrimitiveTypeEnum.VOID.getType());
     } catch (Throwable e) {
-      Jack.getSession()
-          .getReporter()
-          .report(Severity.FATAL, new BadBoostLockedRegionPriorityConfigurationException(prop, e));
+      Jack.getSession().getReporter().report(Severity.FATAL,
+          new BadBoostLockedRegionPriorityConfigurationException(prop, e));
       Jack.getSession().abortEventually();
       return null;
     }
@@ -182,11 +193,7 @@
       return;
     }
 
-    if (lockClass == null
-        || requestClass == null
-        || resetClass == null
-        || requestMethodId == null
-        || resetMethodId == null) {
+    if (lockClass.length == 0) {
       return;
     }
 
@@ -197,8 +204,10 @@
   }
 
   private class Visitor extends JVisitor {
-    @Nonnull private final JMethod method;
-    @Nonnull private final TransformationRequest tr;
+    @Nonnull
+    private final JMethod method;
+    @Nonnull
+    private final TransformationRequest tr;
 
     public Visitor(@Nonnull JMethod method, @Nonnull TransformationRequest tr) {
       this.method = method;
@@ -208,7 +217,15 @@
     @Override
     public void endVisit(@Nonnull JLock jLock) {
       assert lockClass != null;
-      if (!jLock.getLockExpr().getType().isSameType(lockClass)) {
+      int lockIndex = -1;
+      for (int i = 0; i < lockClass.length; i++) {
+        if (jLock.getLockExpr().getType().isSameType(lockClass[i])) {
+          lockIndex = i;
+          break;
+        }
+      }
+
+      if (lockIndex == -1) {
         return;
       }
 
@@ -232,24 +249,25 @@
         return;
       }
 
-      tr.append(new PrependStatement(jTry.getTryBlock(), makeRequestCall(jLock.getSourceInfo())));
-      tr.append(new AppendStatement(finallyBlock, makeResetCall(jLock.getSourceInfo())));
+      tr.append(new PrependStatement(jTry.getTryBlock(),
+          makeRequestCall(lockIndex, jLock.getSourceInfo())));
+      tr.append(new AppendStatement(finallyBlock, makeResetCall(lockIndex, jLock.getSourceInfo())));
     }
 
     @Nonnull
-    private JExpressionStatement makeRequestCall(SourceInfo info) {
-      assert lockClass != null && requestClass != null && requestMethodId != null;
-      return new JExpressionStatement(
-          info,
-          new JMethodCall(
-              info, null, requestClass, requestMethodId, false));
-    }
-
-    @Nonnull
-    private JExpressionStatement makeResetCall(SourceInfo info) {
-      assert lockClass != null && resetClass != null && resetMethodId != null;
+    private JExpressionStatement makeRequestCall(int lockIndex, SourceInfo info) {
+      assert lockClass[lockIndex] != null && requestClass[lockIndex] != null
+          && requestMethodId[lockIndex] != null;
       return new JExpressionStatement(info,
-          new JMethodCall(info, null, resetClass, resetMethodId, false));
+          new JMethodCall(info, null, requestClass[lockIndex], requestMethodId[lockIndex], false));
+    }
+
+    @Nonnull
+    private JExpressionStatement makeResetCall(int lockIndex, SourceInfo info) {
+      assert lockClass[lockIndex] != null && requestClass[lockIndex] != null
+          && requestMethodId[lockIndex] != null;
+      return new JExpressionStatement(info,
+          new JMethodCall(info, null, resetClass[lockIndex], resetMethodId[lockIndex], false));
     }
   }
 
@@ -260,10 +278,11 @@
   private static class BadBoostLockedRegionPriorityConfigurationException
       extends ReportableException {
     private static final long serialVersionUID = 1L;
-    @Nonnull private final String prop;
+    @Nonnull
+    private final String prop;
 
-    public BadBoostLockedRegionPriorityConfigurationException(
-        @Nonnull String prop, @Nonnull Throwable cause) {
+    public BadBoostLockedRegionPriorityConfigurationException(@Nonnull String prop,
+        @Nonnull Throwable cause) {
       super(cause);
       this.prop = prop;
     }
@@ -298,6 +317,39 @@
     }
   }
 
+  /**
+   * Report to user the number of reset / boost method does not match the number of classes.
+   */
+  private static class BadBoostLockedRegionPriorityMethods implements Reportable {
+
+    @Nonnull
+    private final String methodName;
+
+    @Nonnegative
+    private final int numLocks;
+
+    @Nonnegative
+    private final int numMethods;
+
+    public BadBoostLockedRegionPriorityMethods(String methodName, int numLocks, int numMethods) {
+      this.methodName = methodName;
+      this.numLocks = numLocks;
+      this.numMethods = numMethods;
+    }
+
+    @Override
+    public String getMessage() {
+      return "Number of methods in " + methodName + " is " + numMethods + " but number of locks is "
+          + numLocks;
+    }
+
+    @Override
+    @Nonnull
+    public ProblemLevel getDefaultProblemLevel() {
+      return ProblemLevel.ERROR;
+    }
+  }
+
   private static void abortPass() {
     Jack.getSession().getReporter().report(Severity.FATAL, new BadBoostLockedRegionPriorityState());
     Jack.getSession().abortEventually();