blob: d2237352f80c8bc3fe6ffaf1dff8bde36458e631 [file] [log] [blame]
// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.graph;
import com.android.tools.r8.dex.IndexedItemCollection;
public class DexMethodHandle extends IndexedDexItem {
public enum MethodHandleType {
// Method handle dex type.
STATIC_PUT((short) 0x00),
STATIC_GET((short) 0x01),
INSTANCE_PUT((short) 0x02),
INSTANCE_GET((short) 0x03),
INVOKE_STATIC((short) 0x04),
INVOKE_INSTANCE((short) 0x05),
// Upcoming method handle dex type.
INVOKE_CONSTRUCTOR((short) 0x06),
// Internal method handle needed by lambda desugaring.
INVOKE_INTERFACE((short) 0x07),
INVOKE_SUPER((short) 0x08);
private final short value;
MethodHandleType(short value) {
this.value = value;
}
public short getValue() {
return value;
}
public static MethodHandleType getKind(int value) {
MethodHandleType kind;
switch (value) {
case 0x00:
kind = STATIC_PUT;
break;
case 0x01:
kind = STATIC_GET;
break;
case 0x02:
kind = INSTANCE_PUT;
break;
case 0x03:
kind = INSTANCE_GET;
break;
case 0x04:
kind = INVOKE_STATIC;
break;
case 0x05:
kind = INVOKE_INSTANCE;
break;
case 0x06:
kind = INVOKE_CONSTRUCTOR;
break;
case 0x07:
kind = INVOKE_INTERFACE;
break;
case 0x08:
kind = INVOKE_SUPER;
break;
default:
throw new AssertionError();
}
assert kind.getValue() == value;
return kind;
}
public boolean isFieldType() {
return isStaticPut() || isStaticGet() || isInstancePut() || isInstanceGet();
}
public boolean isMethodType() {
return isInvokeStatic() || isInvokeInstance() || isInvokeInterface() || isInvokeSuper()
|| isInvokeConstructor();
}
public boolean isStaticPut() {
return this == MethodHandleType.STATIC_PUT;
}
public boolean isStaticGet() {
return this == MethodHandleType.STATIC_GET;
}
public boolean isInstancePut() {
return this == MethodHandleType.INSTANCE_PUT;
}
public boolean isInstanceGet() {
return this == MethodHandleType.INSTANCE_GET;
}
public boolean isInvokeStatic() {
return this == MethodHandleType.INVOKE_STATIC;
}
public boolean isInvokeInstance() {
return this == MethodHandleType.INVOKE_INSTANCE;
}
public boolean isInvokeInterface() {
return this == MethodHandleType.INVOKE_INTERFACE;
}
public boolean isInvokeSuper() {
return this == MethodHandleType.INVOKE_SUPER;
}
public boolean isInvokeConstructor() {
return this == MethodHandleType.INVOKE_CONSTRUCTOR;
}
}
public MethodHandleType type;
public Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod;
public DexMethodHandle(
MethodHandleType type, Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod) {
this.type = type;
this.fieldOrMethod = fieldOrMethod;
}
public int computeHashCode() {
return type.hashCode() + fieldOrMethod.computeHashCode() * 7;
}
public boolean computeEquals(Object other) {
if (other instanceof DexMethodHandle) {
DexMethodHandle o = (DexMethodHandle) other;
return type.equals(o.type) && fieldOrMethod.equals(o.fieldOrMethod);
}
return false;
}
public String toString() {
StringBuilder builder = new StringBuilder("MethodHandle: {")
.append(type)
.append(", ")
.append(fieldOrMethod.toSourceString())
.append("}");
return builder.toString();
}
@Override
public void collectIndexedItems(IndexedItemCollection indexedItems) {
if (indexedItems.addMethodHandle(this)) {
fieldOrMethod.collectIndexedItems(indexedItems);
}
}
@Override
public int getOffset(ObjectToOffsetMapping mapping) {
return mapping.getOffsetFor(this);
}
// TODO(mikaelpeltier): Adapt syntax when invoke-custom will be available into smali.
public String toSmaliString() {
return toString();
}
public boolean isFieldHandle() {
return type.isFieldType();
}
public boolean isMethodHandle() {
return type.isMethodType();
}
public boolean isStaticHandle() {
return type.isStaticPut() || type.isStaticGet() || type.isInvokeStatic();
}
public DexMethod asMethod() {
assert isMethodHandle();
return (DexMethod) fieldOrMethod;
}
public DexField asField() {
assert isFieldHandle();
return (DexField) fieldOrMethod;
}
}