1 // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file 2 // for details. All rights reserved. Use of this source code is governed by a 3 // BSD-style license that can be found in the LICENSE file. 4 package com.android.tools.r8.graph; 5 6 import com.android.tools.r8.dex.IndexedItemCollection; 7 import com.android.tools.r8.errors.CompilationError; 8 import com.android.tools.r8.naming.NamingLens; 9 10 public class DexMethod extends Descriptor<DexEncodedMethod, DexMethod> 11 implements PresortedComparable<DexMethod> { 12 13 public final DexType holder; 14 public final DexProto proto; 15 public final DexString name; 16 17 // Caches used during processing. 18 private DexEncodedMethod singleTargetCache; 19 DexMethod(DexType holder, DexProto proto, DexString name)20 DexMethod(DexType holder, DexProto proto, DexString name) { 21 this.holder = holder; 22 this.proto = proto; 23 this.name = name; 24 if (!name.isValidMethodName()) { 25 throw new CompilationError( 26 "Method name '" + name.toString() + "' cannot be represented in dex format."); 27 } 28 } 29 30 @Override toString()31 public String toString() { 32 return "Method " + holder + "." + name + " " + proto.toString(); 33 } 34 35 @Override collectIndexedItems(IndexedItemCollection indexedItems)36 public void collectIndexedItems(IndexedItemCollection indexedItems) { 37 if (indexedItems.addMethod(this)) { 38 holder.collectIndexedItems(indexedItems); 39 proto.collectIndexedItems(indexedItems); 40 indexedItems.getRenamedName(this).collectIndexedItems(indexedItems); 41 } 42 } 43 44 @Override getOffset(ObjectToOffsetMapping mapping)45 public int getOffset(ObjectToOffsetMapping mapping) { 46 return mapping.getOffsetFor(this); 47 } 48 computeHashCode()49 public int computeHashCode() { 50 return holder.hashCode() 51 + proto.hashCode() * 7 52 + name.hashCode() * 31; 53 } 54 computeEquals(Object other)55 public boolean computeEquals(Object other) { 56 if (other instanceof DexMethod) { 57 DexMethod o = (DexMethod) other; 58 return holder.equals(o.holder) 59 && name.equals(o.name) 60 && proto.equals(o.proto); 61 } 62 return false; 63 } 64 65 @Override compareTo(DexMethod other)66 public int compareTo(DexMethod other) { 67 return sortedCompareTo(other.getSortedIndex()); 68 } 69 70 @Override slowCompareTo(DexMethod other)71 public int slowCompareTo(DexMethod other) { 72 int result = holder.slowCompareTo(other.holder); 73 if (result != 0) { 74 return result; 75 } 76 result = name.slowCompareTo(other.name); 77 if (result != 0) { 78 return result; 79 } 80 return proto.slowCompareTo(other.proto); 81 } 82 83 @Override slowCompareTo(DexMethod other, NamingLens namingLens)84 public int slowCompareTo(DexMethod other, NamingLens namingLens) { 85 int result = holder.slowCompareTo(other.holder, namingLens); 86 if (result != 0) { 87 return result; 88 } 89 result = namingLens.lookupName(this).slowCompareTo(namingLens.lookupName(other)); 90 if (result != 0) { 91 return result; 92 } 93 return proto.slowCompareTo(other.proto, namingLens); 94 } 95 96 @Override layeredCompareTo(DexMethod other, NamingLens namingLens)97 public int layeredCompareTo(DexMethod other, NamingLens namingLens) { 98 int result = holder.compareTo(other.holder); 99 if (result != 0) { 100 return result; 101 } 102 result = namingLens.lookupName(this).compareTo(namingLens.lookupName(other)); 103 if (result != 0) { 104 return result; 105 } 106 return proto.compareTo(other.proto); 107 } 108 109 @Override match(DexEncodedMethod entry)110 public boolean match(DexEncodedMethod entry) { 111 return entry.method.name == name && entry.method.proto == proto; 112 } 113 114 @Override getHolder()115 public DexType getHolder() { 116 return holder; 117 } 118 qualifiedName()119 public String qualifiedName() { 120 return holder + "." + name; 121 } 122 toSmaliString()123 public String toSmaliString() { 124 return holder.toSmaliString() + "->" + name + proto.toSmaliString(); 125 } 126 toSourceString()127 public String toSourceString() { 128 StringBuilder builder = new StringBuilder(); 129 builder.append(proto.returnType.toSourceString()); 130 builder.append(" "); 131 builder.append(holder.toSourceString()); 132 builder.append("."); 133 builder.append(name); 134 builder.append("("); 135 for (int i = 0; i < proto.parameters.values.length; i++) { 136 if (i != 0) { 137 builder.append(", "); 138 } 139 builder.append(proto.parameters.values[i].toSourceString()); 140 } 141 builder.append(")"); 142 return builder.toString(); 143 } 144 setSingleVirtualMethodCache(DexEncodedMethod method)145 synchronized public void setSingleVirtualMethodCache(DexEncodedMethod method) { 146 singleTargetCache = method == null ? DexEncodedMethod.SENTINEL : method; 147 } 148 isSingleVirtualMethodCached()149 synchronized public boolean isSingleVirtualMethodCached() { 150 return singleTargetCache != null; 151 } 152 getSingleVirtualMethodCache()153 synchronized public DexEncodedMethod getSingleVirtualMethodCache() { 154 assert isSingleVirtualMethodCached(); 155 return singleTargetCache == DexEncodedMethod.SENTINEL ? null : singleTargetCache; 156 } 157 } 158