Fix support for the kind values of MethodHandle

The current implementation only supported 6 of the possible kind values for a MethodHandle object.
However, as the link below shows there are in fact 9. All 9 can be seen in the MethodHandleType
class which is used by dexdump to translate the kind value of a MethodHandle object to a string
representation.

https://android.googlesource.com/platform/art/+/android-8.1.0_r41/runtime/dex_file.h

Moreover, this in fact lines up with the 9 different kinds for a MethodHandle object in standard
java bytecode (though the values are swapped around for some reason).

https://docs.oracle.com/javase/8/docs/api/java/lang/invoke/MethodHandleInfo.html

These changes add in the additional 3 kind values and make sure all nesscary hooks using the
kind values of MethodHandle reference them.

For testing purposes, I found the easiest way to get correctly formatted invoke-custom and
invoke-polymorphic instructions was to use the already generated dex files used to test
dexdump. They can be found at the link below (invoke-custom.dex and invoke-polymorphic.dex).

https://android.googlesource.com/platform/art/+/android-8.1.0_r41/test/dexdump/
This commit is contained in:
Albert Gorski 2018-08-03 17:03:45 -04:00 committed by Ben Gruver
parent 49ecdb334b
commit c6b0408092
13 changed files with 110 additions and 82 deletions

View File

@ -60,8 +60,8 @@ public class ReferenceFormatter {
} }
writer.write(")@"); writer.write(")@");
MethodHandleReference methodHandle = callSite.getMethodHandle(); MethodHandleReference methodHandle = callSite.getMethodHandle();
if (methodHandle.getMethodHandleType() != MethodHandleType.STATIC_INVOKE) { if (methodHandle.getMethodHandleType() != MethodHandleType.INVOKE_STATIC) {
throw new IllegalArgumentException("The linker method handle for a call site must be of type static-invoke"); throw new IllegalArgumentException("The linker method handle for a call site must be of type invoke-static");
} }
writeReference(writer, ReferenceType.METHOD, callSite.getMethodHandle().getMemberReference()); writeReference(writer, ReferenceType.METHOD, callSite.getMethodHandle().getMemberReference());
} }

View File

@ -31,52 +31,45 @@
package org.jf.dexlib2; package org.jf.dexlib2;
import com.google.common.collect.Maps; import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import org.jf.util.ExceptionWithContext; import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.Map;
public class MethodHandleType { public class MethodHandleType {
public static final int STATIC_PUT = 0; public static final int STATIC_PUT = 0;
public static final int STATIC_GET = 1; public static final int STATIC_GET = 1;
public static final int INSTANCE_PUT = 2; public static final int INSTANCE_PUT = 2;
public static final int INSTANCE_GET = 3; public static final int INSTANCE_GET = 3;
public static final int STATIC_INVOKE = 4; public static final int INVOKE_STATIC = 4;
public static final int INSTANCE_INVOKE = 5; public static final int INVOKE_INSTANCE = 5;
public static final int INVOKE_CONSTRUCTOR = 6;
public static final int INVOKE_DIRECT = 7;
public static final int INVOKE_INTERFACE = 8;
private static final Map<String, Integer> methodHandleTypeNames = Maps.newHashMap(); private static final BiMap<Integer, String> methodHandleTypeNames = new ImmutableBiMap.Builder<Integer, String>()
.put(STATIC_PUT, "static-put")
static { .put(STATIC_GET, "static-get")
methodHandleTypeNames.put("static-put", STATIC_PUT); .put(INSTANCE_PUT, "instance-put")
methodHandleTypeNames.put("static-get", STATIC_GET); .put(INSTANCE_GET, "instance-get")
methodHandleTypeNames.put("instance-put", INSTANCE_PUT); .put(INVOKE_STATIC, "invoke-static")
methodHandleTypeNames.put("instance-get", INSTANCE_GET); .put(INVOKE_INSTANCE, "invoke-instance")
methodHandleTypeNames.put("static-invoke", STATIC_INVOKE); .put(INVOKE_CONSTRUCTOR, "invoke-constructor")
methodHandleTypeNames.put("instance-invoke", INSTANCE_INVOKE); .put(INVOKE_DIRECT, "invoke-direct")
} .put(INVOKE_INTERFACE, "invoke-interface")
.build();
@Nonnull public static String toString(int methodHandleType) { @Nonnull public static String toString(int methodHandleType) {
switch (methodHandleType) { String val = methodHandleTypeNames.get(methodHandleType);
case STATIC_PUT: if (val == null) {
return "static-put";
case STATIC_GET:
return "static-get";
case INSTANCE_PUT:
return "instance-put";
case INSTANCE_GET:
return "instance-get";
case STATIC_INVOKE:
return "static-invoke";
case INSTANCE_INVOKE:
return "instance-invoke";
default:
throw new InvalidMethodHandleTypeException(methodHandleType); throw new InvalidMethodHandleTypeException(methodHandleType);
} }
return val;
} }
public static int getMethodHandleType(String methodHandleType) { public static int getMethodHandleType(String methodHandleType) {
Integer ret = methodHandleTypeNames.get(methodHandleType); Integer ret = methodHandleTypeNames.inverse().get(methodHandleType);
if (ret == null) { if (ret == null) {
throw new ExceptionWithContext("Invalid method handle type: %s", methodHandleType); throw new ExceptionWithContext("Invalid method handle type: %s", methodHandleType);
} }

View File

@ -34,6 +34,7 @@ package org.jf.dexlib2.dexbacked.raw;
import org.jf.dexlib2.MethodHandleType; import org.jf.dexlib2.MethodHandleType;
import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator; import org.jf.dexlib2.dexbacked.raw.util.DexAnnotator;
import org.jf.dexlib2.util.AnnotatedBytes; import org.jf.dexlib2.util.AnnotatedBytes;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -59,11 +60,22 @@ public class MethodHandleItem {
int fieldOrMethodId = dexFile.readUshort(out.getCursor()); int fieldOrMethodId = dexFile.readUshort(out.getCursor());
String fieldOrMethodDescriptor; String fieldOrMethodDescriptor;
if (methodHandleType == MethodHandleType.STATIC_INVOKE || switch (methodHandleType) {
methodHandleType == MethodHandleType.INSTANCE_INVOKE) { case MethodHandleType.STATIC_PUT:
fieldOrMethodDescriptor = MethodIdItem.getReferenceAnnotation(dexFile, fieldOrMethodId); case MethodHandleType.STATIC_GET:
} else { case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.INSTANCE_GET:
fieldOrMethodDescriptor = FieldIdItem.getReferenceAnnotation(dexFile, fieldOrMethodId); fieldOrMethodDescriptor = FieldIdItem.getReferenceAnnotation(dexFile, fieldOrMethodId);
break;
case MethodHandleType.INVOKE_STATIC:
case MethodHandleType.INVOKE_INSTANCE:
case MethodHandleType.INVOKE_CONSTRUCTOR:
case MethodHandleType.INVOKE_DIRECT:
case MethodHandleType.INVOKE_INTERFACE:
fieldOrMethodDescriptor = MethodIdItem.getReferenceAnnotation(dexFile, fieldOrMethodId);
break;
default:
throw new ExceptionWithContext("Invalid method handle type: %d", methodHandleType);
} }
out.annotate(2, "field_or_method_id = %s", fieldOrMethodDescriptor); out.annotate(2, "field_or_method_id = %s", fieldOrMethodDescriptor);

View File

@ -61,13 +61,16 @@ public class DexBackedMethodHandleReference extends BaseMethodHandleReference {
public Reference getMemberReference() { public Reference getMemberReference() {
int memberIndex = dexFile.readUshort(methodHandleOffset + MethodHandleItem.MEMBER_ID_OFFSET); int memberIndex = dexFile.readUshort(methodHandleOffset + MethodHandleItem.MEMBER_ID_OFFSET);
switch (getMethodHandleType()) { switch (getMethodHandleType()) {
case MethodHandleType.INSTANCE_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.STATIC_PUT: case MethodHandleType.STATIC_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.INSTANCE_GET:
return new DexBackedFieldReference(dexFile, memberIndex); return new DexBackedFieldReference(dexFile, memberIndex);
case MethodHandleType.INSTANCE_INVOKE: case MethodHandleType.INVOKE_STATIC:
case MethodHandleType.STATIC_INVOKE: case MethodHandleType.INVOKE_INSTANCE:
case MethodHandleType.INVOKE_CONSTRUCTOR:
case MethodHandleType.INVOKE_DIRECT:
case MethodHandleType.INVOKE_INTERFACE:
return new DexBackedMethodReference(dexFile, memberIndex); return new DexBackedMethodReference(dexFile, memberIndex);
default: default:
throw new ExceptionWithContext("Invalid method handle type: %d", getMethodHandleType()); throw new ExceptionWithContext("Invalid method handle type: %d", getMethodHandleType());

View File

@ -48,9 +48,6 @@ public interface MethodHandleReference extends Reference, Comparable<MethodHandl
/** /**
* Gets the member that is being referenced by this method handle. * Gets the member that is being referenced by this method handle.
* *
* For STATIC_INVOKE and INSTANCE_INVOKE method handle types, this should be a MethodReference.
* For the other method handle types, this should be a FieldReference.
*
* @return A MethodReference or FieldReference, depending on the method handle type * @return A MethodReference or FieldReference, depending on the method handle type
*/ */
@Nonnull Reference getMemberReference(); @Nonnull Reference getMemberReference();

View File

@ -64,15 +64,18 @@ public class ImmutableMethodHandleReference extends BaseMethodHandleReference im
ImmutableReference memberReference; ImmutableReference memberReference;
switch (methodHandleType) { switch (methodHandleType) {
case MethodHandleType.INSTANCE_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.STATIC_PUT: case MethodHandleType.STATIC_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.INSTANCE_GET:
memberReference = ImmutableFieldReference.of( memberReference = ImmutableFieldReference.of(
(FieldReference) methodHandleReference.getMemberReference()); (FieldReference) methodHandleReference.getMemberReference());
break; break;
case MethodHandleType.INSTANCE_INVOKE: case MethodHandleType.INVOKE_STATIC:
case MethodHandleType.STATIC_INVOKE: case MethodHandleType.INVOKE_INSTANCE:
case MethodHandleType.INVOKE_CONSTRUCTOR:
case MethodHandleType.INVOKE_DIRECT:
case MethodHandleType.INVOKE_INTERFACE:
memberReference = ImmutableMethodReference.of( memberReference = ImmutableMethodReference.of(
(MethodReference) methodHandleReference.getMemberReference()); (MethodReference) methodHandleReference.getMemberReference());
break; break;

View File

@ -192,8 +192,8 @@ public final class ReferenceUtil {
} }
writer.write(")@"); writer.write(")@");
MethodHandleReference methodHandle = callSiteReference.getMethodHandle(); MethodHandleReference methodHandle = callSiteReference.getMethodHandle();
if (methodHandle.getMethodHandleType() != MethodHandleType.STATIC_INVOKE) { if (methodHandle.getMethodHandleType() != MethodHandleType.INVOKE_STATIC) {
throw new IllegalArgumentException("The linker method handle for a call site must be of type static-invoke"); throw new IllegalArgumentException("The linker method handle for a call site must be of type invoke-static");
} }
writeMethodDescriptor(writer, (MethodReference)callSiteReference.getMethodHandle().getMemberReference()); writeMethodDescriptor(writer, (MethodReference)callSiteReference.getMethodHandle().getMemberReference());
} }

View File

@ -609,15 +609,18 @@ public abstract class DexWriter<
writer.writeUshort(0); writer.writeUshort(0);
int memberIndex; int memberIndex;
switch (methodHandleReference.getMethodHandleType()) { switch (methodHandleReference.getMethodHandleType()) {
case MethodHandleType.INSTANCE_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.STATIC_PUT: case MethodHandleType.STATIC_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.INSTANCE_GET:
memberIndex = fieldSection.getItemIndex( memberIndex = fieldSection.getItemIndex(
methodHandleSection.getFieldReference(methodHandleReference)); methodHandleSection.getFieldReference(methodHandleReference));
break; break;
case MethodHandleType.INSTANCE_INVOKE: case MethodHandleType.INVOKE_STATIC:
case MethodHandleType.STATIC_INVOKE: case MethodHandleType.INVOKE_INSTANCE:
case MethodHandleType.INVOKE_CONSTRUCTOR:
case MethodHandleType.INVOKE_DIRECT:
case MethodHandleType.INVOKE_INTERFACE:
memberIndex = methodSection.getItemIndex( memberIndex = methodSection.getItemIndex(
methodHandleSection.getMethodReference(methodHandleReference)); methodHandleSection.getMethodReference(methodHandleReference));
break; break;

View File

@ -61,15 +61,18 @@ public class BuilderMethodHandlePool extends BaseBuilderPool
BuilderReference memberReference; BuilderReference memberReference;
switch (methodHandleReference.getMethodHandleType()) { switch (methodHandleReference.getMethodHandleType()) {
case MethodHandleType.INSTANCE_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.STATIC_PUT: case MethodHandleType.STATIC_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.INSTANCE_GET:
memberReference = dexBuilder.internFieldReference( memberReference = dexBuilder.internFieldReference(
(FieldReference) methodHandleReference.getMemberReference()); (FieldReference) methodHandleReference.getMemberReference());
break; break;
case MethodHandleType.INSTANCE_INVOKE: case MethodHandleType.INVOKE_STATIC:
case MethodHandleType.STATIC_INVOKE: case MethodHandleType.INVOKE_INSTANCE:
case MethodHandleType.INVOKE_CONSTRUCTOR:
case MethodHandleType.INVOKE_DIRECT:
case MethodHandleType.INVOKE_INTERFACE:
memberReference = dexBuilder.internMethodReference( memberReference = dexBuilder.internMethodReference(
(MethodReference) methodHandleReference.getMemberReference()); (MethodReference) methodHandleReference.getMemberReference());
break; break;

View File

@ -50,14 +50,17 @@ public class MethodHandlePool extends BaseIndexPool<MethodHandleReference>
Integer prev = internedItems.put(methodHandleReference, 0); Integer prev = internedItems.put(methodHandleReference, 0);
if (prev == null) { if (prev == null) {
switch (methodHandleReference.getMethodHandleType()) { switch (methodHandleReference.getMethodHandleType()) {
case MethodHandleType.INSTANCE_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.STATIC_PUT: case MethodHandleType.STATIC_PUT:
case MethodHandleType.STATIC_GET:
case MethodHandleType.INSTANCE_PUT:
case MethodHandleType.INSTANCE_GET:
dexPool.fieldSection.intern((FieldReference) methodHandleReference.getMemberReference()); dexPool.fieldSection.intern((FieldReference) methodHandleReference.getMemberReference());
break; break;
case MethodHandleType.INSTANCE_INVOKE: case MethodHandleType.INVOKE_STATIC:
case MethodHandleType.STATIC_INVOKE: case MethodHandleType.INVOKE_INSTANCE:
case MethodHandleType.INVOKE_CONSTRUCTOR:
case MethodHandleType.INVOKE_DIRECT:
case MethodHandleType.INVOKE_INTERFACE:
dexPool.methodSection.intern((MethodReference) methodHandleReference.getMemberReference()); dexPool.methodSection.intern((MethodReference) methodHandleReference.getMemberReference());
break; break;
default: default:

View File

@ -110,6 +110,7 @@ tokens {
INSTRUCTION_FORMAT35c_CALL_SITE; INSTRUCTION_FORMAT35c_CALL_SITE;
INSTRUCTION_FORMAT35c_METHOD; INSTRUCTION_FORMAT35c_METHOD;
INSTRUCTION_FORMAT35c_METHOD_ODEX; INSTRUCTION_FORMAT35c_METHOD_ODEX;
INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE;
INSTRUCTION_FORMAT35c_TYPE; INSTRUCTION_FORMAT35c_TYPE;
INSTRUCTION_FORMAT35mi_METHOD; INSTRUCTION_FORMAT35mi_METHOD;
INSTRUCTION_FORMAT35ms_METHOD; INSTRUCTION_FORMAT35ms_METHOD;
@ -586,6 +587,7 @@ simple_name
| INSTRUCTION_FORMAT35c_CALL_SITE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_CALL_SITE] | INSTRUCTION_FORMAT35c_CALL_SITE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_CALL_SITE]
| INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD] | INSTRUCTION_FORMAT35c_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD]
| INSTRUCTION_FORMAT35c_METHOD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_ODEX] | INSTRUCTION_FORMAT35c_METHOD_ODEX -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_ODEX]
| INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE]
| INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE] | INSTRUCTION_FORMAT35c_TYPE -> SIMPLE_NAME[$INSTRUCTION_FORMAT35c_TYPE]
| INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD] | INSTRUCTION_FORMAT35mi_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35mi_METHOD]
| INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD] | INSTRUCTION_FORMAT35ms_METHOD -> SIMPLE_NAME[$INSTRUCTION_FORMAT35ms_METHOD]
@ -724,7 +726,8 @@ call_site_reference
method_handle_reference method_handle_reference
: METHOD_HANDLE_TYPE_FIELD AT field_reference -> METHOD_HANDLE_TYPE_FIELD field_reference : METHOD_HANDLE_TYPE_FIELD AT field_reference -> METHOD_HANDLE_TYPE_FIELD field_reference
| METHOD_HANDLE_TYPE_METHOD AT method_reference -> METHOD_HANDLE_TYPE_METHOD method_reference; | METHOD_HANDLE_TYPE_METHOD AT method_reference -> METHOD_HANDLE_TYPE_METHOD method_reference
| INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE AT method_reference -> INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE method_reference;
method_handle_literal method_handle_literal
: method_handle_reference : method_handle_reference
@ -827,6 +830,10 @@ instruction_format31i
: INSTRUCTION_FORMAT31i : INSTRUCTION_FORMAT31i
| INSTRUCTION_FORMAT31i_OR_ID -> INSTRUCTION_FORMAT31i[$INSTRUCTION_FORMAT31i_OR_ID]; | INSTRUCTION_FORMAT31i_OR_ID -> INSTRUCTION_FORMAT31i[$INSTRUCTION_FORMAT31i_OR_ID];
instruction_format35c_method
: INSTRUCTION_FORMAT35c_METHOD
| INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE -> INSTRUCTION_FORMAT35c_METHOD[$INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE];
instruction instruction
: insn_format10t : insn_format10t
| insn_format10x | insn_format10x
@ -943,7 +950,7 @@ insn_format21c_field_odex
-> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER field_reference); -> ^(I_STATEMENT_FORMAT21c_FIELD[$start, "I_STATEMENT_FORMAT21c_FIELD"] INSTRUCTION_FORMAT21c_FIELD_ODEX REGISTER field_reference);
insn_format21c_method_handle insn_format21c_method_handle
: //e.g. const-method-handle v0, static-invoke@Ljava/lang/Integer;->toString(I)Ljava/lang/String; : //e.g. const-method-handle v0, invoke-static@Ljava/lang/Integer;->toString(I)Ljava/lang/String;
INSTRUCTION_FORMAT21c_METHOD_HANDLE REGISTER COMMA method_handle_reference INSTRUCTION_FORMAT21c_METHOD_HANDLE REGISTER COMMA method_handle_reference
-> ^(I_STATEMENT_FORMAT21c_METHOD_HANDLE[$start, "I_STATEMENT_FORMAT21c_METHOD_HANDLE"] -> ^(I_STATEMENT_FORMAT21c_METHOD_HANDLE[$start, "I_STATEMENT_FORMAT21c_METHOD_HANDLE"]
INSTRUCTION_FORMAT21c_METHOD_HANDLE REGISTER method_handle_reference); INSTRUCTION_FORMAT21c_METHOD_HANDLE REGISTER method_handle_reference);
@ -1069,8 +1076,8 @@ insn_format35c_call_site
insn_format35c_method insn_format35c_method
: //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V : //e.g. invoke-virtual {v0,v1} java/io/PrintStream/print(Ljava/lang/Stream;)V
INSTRUCTION_FORMAT35c_METHOD OPEN_BRACE register_list CLOSE_BRACE COMMA method_reference instruction_format35c_method OPEN_BRACE register_list CLOSE_BRACE COMMA method_reference
-> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] INSTRUCTION_FORMAT35c_METHOD register_list method_reference); -> ^(I_STATEMENT_FORMAT35c_METHOD[$start, "I_STATEMENT_FORMAT35c_METHOD"] instruction_format35c_method register_list method_reference);
insn_format35c_type insn_format35c_type
: //e.g. filled-new-array {v0,v1}, I : //e.g. filled-new-array {v0,v1}, I

View File

@ -514,7 +514,7 @@ call_site_reference returns[ImmutableCallSiteReference callSiteReference]
{ {
String callSiteName = $call_site_name.text; String callSiteName = $call_site_name.text;
ImmutableMethodHandleReference methodHandleReference = ImmutableMethodHandleReference methodHandleReference =
new ImmutableMethodHandleReference(MethodHandleType.STATIC_INVOKE, new ImmutableMethodHandleReference(MethodHandleType.INVOKE_STATIC,
$method_reference.methodReference); $method_reference.methodReference);
$callSiteReference = new ImmutableCallSiteReference( $callSiteReference = new ImmutableCallSiteReference(
callSiteName, methodHandleReference, $method_name.value, $method_prototype.proto, callSiteName, methodHandleReference, $method_name.value, $method_prototype.proto,
@ -522,7 +522,7 @@ call_site_reference returns[ImmutableCallSiteReference callSiteReference]
}; };
method_handle_type returns[int methodHandleType] method_handle_type returns[int methodHandleType]
: METHOD_HANDLE_TYPE_FIELD | METHOD_HANDLE_TYPE_METHOD { : (METHOD_HANDLE_TYPE_FIELD | METHOD_HANDLE_TYPE_METHOD | INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE) {
$methodHandleType = MethodHandleType.getMethodHandleType($text); $methodHandleType = MethodHandleType.getMethodHandleType($text);
}; };
@ -891,7 +891,7 @@ insn_format21c_field
}; };
insn_format21c_method_handle insn_format21c_method_handle
: //e.g. const-method-handle v0, static-invoke@Ljava/lang/Integer;->toString(I)Ljava/lang/String; : //e.g. const-method-handle v0, invoke-static@Ljava/lang/Integer;->toString(I)Ljava/lang/String;
^(I_STATEMENT_FORMAT21c_METHOD_HANDLE inst=(INSTRUCTION_FORMAT21c_METHOD_HANDLE) REGISTER method_handle_reference) ^(I_STATEMENT_FORMAT21c_METHOD_HANDLE inst=(INSTRUCTION_FORMAT21c_METHOD_HANDLE) REGISTER method_handle_reference)
{ {
Opcode opcode = opcodes.getOpcodeByName($inst.text); Opcode opcode = opcodes.getOpcodeByName($inst.text);

View File

@ -409,11 +409,11 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
"vtable@0x" {HexDigit}+ { return newToken(VTABLE_INDEX); } "vtable@0x" {HexDigit}+ { return newToken(VTABLE_INDEX); }
"field@0x" {HexDigit}+ { return newToken(FIELD_OFFSET); } "field@0x" {HexDigit}+ { return newToken(FIELD_OFFSET); }
"instance-get" | "instance-put" | "static-get" | "static-put" { "static-put" | "static-get" | "instance-put" | "instance-get" {
return newToken(METHOD_HANDLE_TYPE_FIELD); return newToken(METHOD_HANDLE_TYPE_FIELD);
} }
"instance-invoke" | "static-invoke" { "invoke-instance" | "invoke-constructor" {
return newToken(METHOD_HANDLE_TYPE_METHOD); return newToken(METHOD_HANDLE_TYPE_METHOD);
} }
@ -588,10 +588,14 @@ Type = {PrimitiveType} | {ClassDescriptor} | {ArrayPrefix} ({ClassDescriptor} |
return newToken(INSTRUCTION_FORMAT35c_CALL_SITE); return newToken(INSTRUCTION_FORMAT35c_CALL_SITE);
} }
"invoke-virtual" | "invoke-super" | "invoke-direct" | "invoke-static" | "invoke-interface" { "invoke-virtual" | "invoke-super" {
return newToken(INSTRUCTION_FORMAT35c_METHOD); return newToken(INSTRUCTION_FORMAT35c_METHOD);
} }
"invoke-direct" | "invoke-static" | "invoke-interface" {
return newToken(INSTRUCTION_FORMAT35c_METHOD_OR_METHOD_HANDLE_TYPE);
}
"invoke-direct-empty" { "invoke-direct-empty" {
return newToken(INSTRUCTION_FORMAT35c_METHOD_ODEX); return newToken(INSTRUCTION_FORMAT35c_METHOD_ODEX);
} }