|  | // 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); | 
|  | } | 
|  | } | 
|  | } |