| // 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.graph.DexValue.DexValueDouble; |
| import com.android.tools.r8.graph.DexValue.DexValueFloat; |
| import com.android.tools.r8.graph.DexValue.DexValueInt; |
| import com.android.tools.r8.graph.DexValue.DexValueLong; |
| import com.android.tools.r8.graph.DexValue.DexValueMethodHandle; |
| import com.android.tools.r8.graph.DexValue.DexValueMethodType; |
| import com.android.tools.r8.graph.DexValue.DexValueString; |
| import com.android.tools.r8.graph.DexValue.DexValueType; |
| |
| 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 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 registerInstanceFieldWrite(DexField field); |
| |
| public abstract boolean registerInstanceFieldRead(DexField field); |
| |
| public abstract boolean registerNewInstance(DexType type); |
| |
| public abstract boolean registerStaticFieldRead(DexField field); |
| |
| public abstract boolean registerStaticFieldWrite(DexField 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: |
| registerInstanceFieldRead(methodHandle.asField()); |
| break; |
| case INSTANCE_PUT: |
| registerInstanceFieldWrite(methodHandle.asField()); |
| break; |
| case STATIC_GET: |
| registerStaticFieldRead(methodHandle.asField()); |
| break; |
| case STATIC_PUT: |
| registerStaticFieldWrite(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.getHolder()); |
| 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()); |
| |
| 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) { |
| if (arg instanceof DexValueType) { |
| registerTypeReference(((DexValueType) arg).value); |
| } else if (arg instanceof DexValueMethodHandle) { |
| DexMethodHandle handle = ((DexValueMethodHandle) arg).value; |
| MethodHandleUse use = isLambdaMetaFactory |
| ? MethodHandleUse.ARGUMENT_TO_LAMBDA_METAFACTORY |
| : MethodHandleUse.NOT_ARGUMENT_TO_LAMBDA_METAFACTORY; |
| registerMethodHandle(handle, use); |
| } else if (arg instanceof DexValueMethodType) { |
| registerProto(((DexValueMethodType) arg).value); |
| } else { |
| assert (arg instanceof DexValueInt) |
| || (arg instanceof DexValueLong) |
| || (arg instanceof DexValueFloat) |
| || (arg instanceof DexValueDouble) |
| || (arg instanceof DexValueString); |
| } |
| } |
| } |
| |
| public void registerProto(DexProto proto) { |
| registerTypeReference(proto.returnType); |
| for (DexType type : proto.parameters.values) { |
| registerTypeReference(type); |
| } |
| } |
| } |