summaryrefslogtreecommitdiff
path: root/dx/src/com/android/dx/rop/code/InvokePolymorphicInsn.java
diff options
context:
space:
mode:
Diffstat (limited to 'dx/src/com/android/dx/rop/code/InvokePolymorphicInsn.java')
-rw-r--r--dx/src/com/android/dx/rop/code/InvokePolymorphicInsn.java91
1 files changed, 79 insertions, 12 deletions
diff --git a/dx/src/com/android/dx/rop/code/InvokePolymorphicInsn.java b/dx/src/com/android/dx/rop/code/InvokePolymorphicInsn.java
index e5def1da4..ca5a3b8f4 100644
--- a/dx/src/com/android/dx/rop/code/InvokePolymorphicInsn.java
+++ b/dx/src/com/android/dx/rop/code/InvokePolymorphicInsn.java
@@ -28,9 +28,18 @@ import com.android.dx.rop.type.TypeList;
* multiple constants.
*/
public class InvokePolymorphicInsn extends Insn {
- private static final CstString INVOKE_DESCRIPTOR =
+ /** Default descriptor for signature polymorphic methods. */
+ private static final CstString DEFAULT_DESCRIPTOR =
new CstString("([Ljava/lang/Object;)Ljava/lang/Object;");
+ /** Descriptor for VarHandle set methods. */
+ private static final CstString VARHANDLE_SET_DESCRIPTOR =
+ new CstString("([Ljava/lang/Object;)V");
+
+ /** Descriptor for VarHandle compare-and-set methods. */
+ private static final CstString VARHANDLE_COMPARE_AND_SET_DESCRIPTOR =
+ new CstString("([Ljava/lang/Object;)Z");
+
/** {@code non-null;} list of exceptions caught */
private final TypeList catches;
@@ -42,10 +51,9 @@ public class InvokePolymorphicInsn extends Insn {
private final CstMethodRef callSiteMethod;
/**
- * {@code non-null;} method to invoke, either {@code java.lang.invoke.MethodHandle.invoke} or
- * {@code java.lang.invoke.MethodHandle.invokeExact}.
+ * {@code non-null;} signature polymorphic method.
*/
- private final CstMethodRef invokeMethod;
+ private final CstMethodRef polymorphicMethod;
/**
* {@code non-null;} the call site prototype.
@@ -82,7 +90,7 @@ public class InvokePolymorphicInsn extends Insn {
}
this.callSiteMethod = callSiteMethod;
- this.invokeMethod = makeInvokeMethod(callSiteMethod);
+ this.polymorphicMethod = makePolymorphicMethod(callSiteMethod);
this.callSiteProto = makeCallSiteProto(callSiteMethod);
}
@@ -137,8 +145,8 @@ public class InvokePolymorphicInsn extends Insn {
*
* @return {@code non-null;} method reference to be invoked
*/
- public CstMethodRef getInvokeMethod() {
- return invokeMethod;
+ public CstMethodRef getPolymorphicMethod() {
+ return polymorphicMethod;
}
/**
@@ -155,15 +163,74 @@ public class InvokePolymorphicInsn extends Insn {
/** {@inheritDoc} */
@Override
public String getInlineString() {
- return getInvokeMethod().toString() + " " +
+ return getPolymorphicMethod().toString() + " " +
getCallSiteProto().toString() + " " +
ThrowingInsn.toCatchString(catches);
}
- private static CstMethodRef makeInvokeMethod(final CstMethodRef callSiteMethod) {
- // The name is either invoke or invokeExact. The INVOKE_DESCRIPTOR is fixed.
- CstNat cstNat = new CstNat(callSiteMethod.getNat().getName(), INVOKE_DESCRIPTOR);
- return new CstMethodRef(callSiteMethod.getDefiningClass(), cstNat);
+ private static CstMethodRef makePolymorphicMethod(final CstMethodRef callSiteMethod) {
+ CstType definingClass= callSiteMethod.getDefiningClass();
+ CstString cstMethodName = callSiteMethod.getNat().getName();
+ String methodName = callSiteMethod.getNat().getName().getString();
+
+ if (definingClass.equals(CstType.METHOD_HANDLE)) {
+ if (methodName.equals("invoke") || methodName.equals("invokeExact")) {
+ CstNat cstNat = new CstNat(cstMethodName, DEFAULT_DESCRIPTOR);
+ return new CstMethodRef(definingClass, cstNat);
+ }
+ }
+
+ if (definingClass.equals(CstType.VAR_HANDLE)) {
+ switch (methodName) {
+ case "compareAndExchange":
+ case "compareAndExchangeAcquire":
+ case "compareAndExchangeRelease":
+ case "get":
+ case "getAcquire":
+ case "getAndAdd":
+ case "getAndAddAcquire":
+ case "getAndAddRelease":
+ case "getAndBitwiseAnd":
+ case "getAndBitwiseAndAcquire":
+ case "getAndBitwiseAndRelease":
+ case "getAndBitwiseOr":
+ case "getAndBitwiseOrAcquire":
+ case "getAndBitwiseOrRelease":
+ case "getAndBitwiseXor":
+ case "getAndBitwiseXorAcquire":
+ case "getAndBitwiseXorRelease":
+ case "getAndSet":
+ case "getAndSetAcquire":
+ case "getAndSetRelease":
+ case "getOpaque":
+ case "getVolatile":
+ {
+ CstNat cstNat = new CstNat(cstMethodName, DEFAULT_DESCRIPTOR);
+ return new CstMethodRef(definingClass, cstNat);
+ }
+ case "set":
+ case "setOpaque":
+ case "setRelease":
+ case "setVolatile":
+ {
+ CstNat cstNat = new CstNat(cstMethodName, VARHANDLE_SET_DESCRIPTOR);
+ return new CstMethodRef(definingClass, cstNat);
+ }
+ case "compareAndSet":
+ case "weakCompareAndSet":
+ case "weakCompareAndSetAcquire":
+ case "weakCompareAndSetPlain":
+ case "weakCompareAndSetRelease":
+ {
+ CstNat cstNat = new CstNat(cstMethodName, VARHANDLE_COMPARE_AND_SET_DESCRIPTOR);
+ return new CstMethodRef(definingClass, cstNat);
+ }
+ default:
+ break;
+ }
+ }
+ throw new IllegalArgumentException("Unknown signature polymorphic method: " +
+ callSiteMethod.toHuman());
}
private static CstProtoRef makeCallSiteProto(final CstMethodRef callSiteMethod) {