blob: 1e89e13a326019aa7322d99135fc49421aaeca1a [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;
public abstract class UseRegistry {
private DexItemFactory factory;
public enum MethodHandleUse {
ARGUMENT_TO_LAMBDA_METAFACTORY,
NOT_ARGUMENT_TO_LAMBDA_METAFACTORY
}
public UseRegistry(DexItemFactory factory) {
this.factory = factory;
}
public abstract boolean registerInitClass(DexType type);
public abstract boolean registerInvokeVirtual(DexMethod method);
public abstract boolean registerInvokeDirect(DexMethod method);
public abstract boolean registerInvokeStatic(DexMethod method);
public abstract boolean registerInvokeInterface(DexMethod method);
public abstract boolean registerInvokeSuper(DexMethod method);
public abstract boolean registerInstanceFieldRead(DexField field);
public boolean registerInstanceFieldReadFromMethodHandle(DexField field) {
return registerInstanceFieldRead(field);
}
public abstract boolean registerInstanceFieldWrite(DexField field);
public boolean registerInstanceFieldWriteFromMethodHandle(DexField field) {
return registerInstanceFieldWrite(field);
}
public abstract boolean registerNewInstance(DexType type);
public abstract boolean registerStaticFieldRead(DexField field);
public boolean registerStaticFieldReadFromMethodHandle(DexField field) {
return registerStaticFieldRead(field);
}
public abstract boolean registerStaticFieldWrite(DexField field);
public boolean registerStaticFieldWriteFromMethodHandle(DexField field) {
return registerStaticFieldWrite(field);
}
public abstract boolean registerTypeReference(DexType type);
public boolean registerConstClass(DexType type) {
return registerTypeReference(type);
}
public boolean registerCheckCast(DexType type) {
return registerTypeReference(type);
}
public void registerMethodHandle(DexMethodHandle methodHandle, MethodHandleUse use) {
switch (methodHandle.type) {
case INSTANCE_GET:
registerInstanceFieldReadFromMethodHandle(methodHandle.asField());
break;
case INSTANCE_PUT:
registerInstanceFieldWriteFromMethodHandle(methodHandle.asField());
break;
case STATIC_GET:
registerStaticFieldReadFromMethodHandle(methodHandle.asField());
break;
case STATIC_PUT:
registerStaticFieldWriteFromMethodHandle(methodHandle.asField());
break;
case INVOKE_INSTANCE:
registerInvokeVirtual(methodHandle.asMethod());
break;
case INVOKE_STATIC:
registerInvokeStatic(methodHandle.asMethod());
break;
case INVOKE_CONSTRUCTOR:
DexMethod method = methodHandle.asMethod();
registerNewInstance(method.holder);
registerInvokeDirect(method);
break;
case INVOKE_INTERFACE:
registerInvokeInterface(methodHandle.asMethod());
break;
case INVOKE_SUPER:
registerInvokeSuper(methodHandle.asMethod());
break;
case INVOKE_DIRECT:
registerInvokeDirect(methodHandle.asMethod());
break;
default:
throw new AssertionError();
}
}
public void registerCallSite(DexCallSite callSite) {
boolean isLambdaMetaFactory =
factory.isLambdaMetafactoryMethod(callSite.bootstrapMethod.asMethod());
if (!isLambdaMetaFactory) {
registerMethodHandle(
callSite.bootstrapMethod, MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY);
}
// Lambda metafactory will use this type as the main SAM
// interface for the dynamically created lambda class.
registerTypeReference(callSite.methodProto.returnType);
// Register bootstrap method arguments.
// Only Type, MethodHandle, and MethodType need to be registered.
for (DexValue arg : callSite.bootstrapArgs) {
switch (arg.getValueKind()) {
case METHOD_HANDLE:
DexMethodHandle handle = arg.asDexValueMethodHandle().value;
MethodHandleUse use =
isLambdaMetaFactory
? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY
: MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY;
registerMethodHandle(handle, use);
break;
case METHOD_TYPE:
registerProto(arg.asDexValueMethodType().value);
break;
case TYPE:
registerTypeReference(arg.asDexValueType().value);
break;
default:
assert arg.isDexValueInt()
|| arg.isDexValueLong()
|| arg.isDexValueFloat()
|| arg.isDexValueDouble()
|| arg.isDexValueString();
}
}
}
public void registerProto(DexProto proto) {
registerTypeReference(proto.returnType);
for (DexType type : proto.parameters.values) {
registerTypeReference(type);
}
}
}