| // Copyright (c) 2016, 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; | |
| import com.android.tools.r8.lightir.LirConstant; | |
| import com.android.tools.r8.naming.NamingLens; | |
| import com.android.tools.r8.utils.internal.ArrayUtils; | |
| import com.android.tools.r8.utils.internal.IntObjPredicate; | |
| import com.android.tools.r8.utils.structural.CompareToVisitor; | |
| import com.android.tools.r8.utils.structural.HashingVisitor; | |
| import com.android.tools.r8.utils.structural.StructuralMapping; | |
| import com.android.tools.r8.utils.structural.StructuralSpecification; | |
| import com.google.common.collect.Iterables; | |
| import java.util.Collections; | |
| import java.util.function.Consumer; | |
| public class DexProto extends IndexedDexItem | |
| implements NamingLensComparable<DexProto>, LirConstant { | |
| @SuppressWarnings("ReferenceEquality") | |
| public static boolean identical(DexProto t1, DexProto t2) { | |
| return t1 == t2; | |
| } | |
| public final boolean isIdenticalTo(DexProto other) { | |
| return identical(this, other); | |
| } | |
| public final boolean isNotIdenticalTo(DexProto other) { | |
| return !isIdenticalTo(other); | |
| } | |
| public static final DexProto SENTINEL = new DexProto(null, null); | |
| public final DexType returnType; | |
| public final DexTypeList parameters; | |
| DexProto(DexType returnType, DexTypeList parameters) { | |
| this.returnType = returnType; | |
| this.parameters = parameters; | |
| } | |
| private static void specify(StructuralSpecification<DexProto, ?> spec) { | |
| spec.withItem(DexProto::getReturnType).withItem(p -> p.parameters); | |
| } | |
| @Override | |
| public StructuralMapping<DexProto> getStructuralMapping() { | |
| return DexProto::specify; | |
| } | |
| @Override | |
| public DexProto self() { | |
| return this; | |
| } | |
| @Override | |
| public boolean computeEquals(Object other) { | |
| if (other instanceof DexProto) { | |
| DexProto o = (DexProto) other; | |
| return returnType.equals(o.returnType) && parameters.equals(o.parameters); | |
| } | |
| return false; | |
| } | |
| @Override | |
| public int computeHashCode() { | |
| return returnType.hashCode() * 7 + parameters.hashCode() * 13; | |
| } | |
| public DexType getReturnType() { | |
| return returnType; | |
| } | |
| public Iterable<DexType> getParameterBaseTypes(DexItemFactory dexItemFactory) { | |
| return Iterables.transform(parameters, type -> type.getBaseType()); | |
| } | |
| public Iterable<DexType> getBaseTypes(DexItemFactory dexItemFactory) { | |
| return Iterables.transform(getTypes(), type -> type.getBaseType()); | |
| } | |
| public Iterable<DexType> getTypes() { | |
| return Iterables.concat(Collections.singleton(returnType), parameters); | |
| } | |
| public void forEachType(Consumer<DexType> consumer) { | |
| consumer.accept(returnType); | |
| parameters.forEach(consumer); | |
| } | |
| public DexType getParameter(int index) { | |
| return parameters.values[index]; | |
| } | |
| public DexTypeList getParameters() { | |
| return parameters; | |
| } | |
| public int getArity() { | |
| return parameters.size(); | |
| } | |
| public DexProto prependParameter(DexType parameter, DexItemFactory dexItemFactory) { | |
| DexType[] parameterTypes = new DexType[getParameters().size() + 1]; | |
| parameterTypes[0] = parameter; | |
| System.arraycopy(getParameters().getBacking(), 0, parameterTypes, 1, getParameters().size()); | |
| return dexItemFactory.createProto(getReturnType(), parameterTypes); | |
| } | |
| @Override | |
| public String toString() { | |
| return "Proto " + returnType + " " + parameters; | |
| } | |
| public void collectIndexedItems(AppView<?> appView, IndexedItemCollection indexedItems) { | |
| if (indexedItems.addProto(this)) { | |
| returnType.collectIndexedItems(appView, indexedItems); | |
| parameters.collectIndexedItems(appView, indexedItems); | |
| } | |
| } | |
| @Override | |
| public int getOffset(ObjectToOffsetMapping mapping) { | |
| return mapping.getOffsetFor(this); | |
| } | |
| @Override | |
| public String toSmaliString() { | |
| return toDescriptorString(); | |
| } | |
| public String toDescriptorString() { | |
| return toDescriptorString(NamingLens.getIdentityLens()); | |
| } | |
| public String toDescriptorString(NamingLens lens) { | |
| StringBuilder builder = new StringBuilder(); | |
| builder.append("("); | |
| for (int i = 0; i < parameters.values.length; i++) { | |
| builder.append(lens.lookupDescriptor(parameters.values[i])); | |
| } | |
| builder.append(")"); | |
| builder.append(lens.lookupDescriptor(returnType)); | |
| return builder.toString(); | |
| } | |
| public String createShortyString() { | |
| StringBuilder shortyBuilder = new StringBuilder(); | |
| shortyBuilder.append(returnType.toShorty()); | |
| for (DexType argumentType : parameters) { | |
| shortyBuilder.append(argumentType.toShorty()); | |
| } | |
| return shortyBuilder.toString(); | |
| } | |
| @Override | |
| public LirConstantOrder getLirConstantOrder() { | |
| return LirConstantOrder.PROTO; | |
| } | |
| @Override | |
| public int internalLirConstantAcceptCompareTo(LirConstant other, CompareToVisitor visitor) { | |
| return acceptCompareTo((DexProto) other, visitor); | |
| } | |
| @Override | |
| public void internalLirConstantAcceptHashing(HashingVisitor visitor) { | |
| acceptHashing(visitor); | |
| } | |
| public DexProto withParameters(DexTypeList parameters, DexItemFactory factory) { | |
| return factory.createProto(returnType, parameters); | |
| } | |
| public DexProto withoutParameters(IntObjPredicate<DexType> predicate, DexItemFactory factory) { | |
| if (parameters.isEmpty()) { | |
| return this; | |
| } | |
| DexType[] newParameters = | |
| ArrayUtils.map( | |
| parameters.getBacking(), | |
| (index, parameter) -> predicate.test(index, parameter) ? null : parameter, | |
| DexType.EMPTY_ARRAY); | |
| if (newParameters == parameters.getBacking()) { | |
| return this; | |
| } | |
| return factory.createProto(returnType, newParameters); | |
| } | |
| public DexProto withReturnType(DexType returnType, DexItemFactory factory) { | |
| return factory.createProto(returnType, parameters); | |
| } | |
| } |