• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017, 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 
8 public class DexMethodHandle extends IndexedDexItem {
9 
10   public enum MethodHandleType {
11     // Method handle dex type.
12     STATIC_PUT((short) 0x00),
13     STATIC_GET((short) 0x01),
14     INSTANCE_PUT((short) 0x02),
15     INSTANCE_GET((short) 0x03),
16     INVOKE_STATIC((short) 0x04),
17     INVOKE_INSTANCE((short) 0x05),
18     // Upcoming method handle dex type.
19     INVOKE_CONSTRUCTOR((short) 0x06),
20     // Internal method handle needed by lambda desugaring.
21     INVOKE_INTERFACE((short) 0x07),
22     INVOKE_SUPER((short) 0x08);
23 
24     private final short value;
25 
MethodHandleType(short value)26     MethodHandleType(short value) {
27       this.value = value;
28     }
29 
getValue()30     public short getValue() {
31       return value;
32     }
33 
getKind(int value)34     public static MethodHandleType getKind(int value) {
35       MethodHandleType kind;
36 
37       switch (value) {
38         case 0x00:
39           kind = STATIC_PUT;
40           break;
41         case 0x01:
42           kind = STATIC_GET;
43           break;
44         case 0x02:
45           kind = INSTANCE_PUT;
46           break;
47         case 0x03:
48           kind = INSTANCE_GET;
49           break;
50         case 0x04:
51           kind = INVOKE_STATIC;
52           break;
53         case 0x05:
54           kind = INVOKE_INSTANCE;
55           break;
56         case 0x06:
57           kind = INVOKE_CONSTRUCTOR;
58           break;
59         case 0x07:
60           kind = INVOKE_INTERFACE;
61           break;
62         case 0x08:
63           kind = INVOKE_SUPER;
64           break;
65         default:
66           throw new AssertionError();
67       }
68 
69       assert kind.getValue() == value;
70       return kind;
71     }
72 
isFieldType()73     public boolean isFieldType() {
74       return isStaticPut() || isStaticGet() || isInstancePut() || isInstanceGet();
75     }
76 
isMethodType()77     public boolean isMethodType() {
78       return isInvokeStatic() || isInvokeInstance() || isInvokeInterface() || isInvokeSuper()
79           || isInvokeConstructor();
80     }
81 
isStaticPut()82     public boolean isStaticPut() {
83       return this == MethodHandleType.STATIC_PUT;
84     }
85 
isStaticGet()86     public boolean isStaticGet() {
87       return this == MethodHandleType.STATIC_GET;
88     }
89 
isInstancePut()90     public boolean isInstancePut() {
91       return this == MethodHandleType.INSTANCE_PUT;
92     }
93 
isInstanceGet()94     public boolean isInstanceGet() {
95       return this == MethodHandleType.INSTANCE_GET;
96     }
97 
isInvokeStatic()98     public boolean isInvokeStatic() {
99       return this == MethodHandleType.INVOKE_STATIC;
100     }
101 
isInvokeInstance()102     public boolean isInvokeInstance() {
103       return this == MethodHandleType.INVOKE_INSTANCE;
104     }
105 
isInvokeInterface()106     public boolean isInvokeInterface() {
107       return this == MethodHandleType.INVOKE_INTERFACE;
108     }
109 
isInvokeSuper()110     public boolean isInvokeSuper() {
111       return this == MethodHandleType.INVOKE_SUPER;
112     }
113 
isInvokeConstructor()114     public boolean isInvokeConstructor() {
115       return this == MethodHandleType.INVOKE_CONSTRUCTOR;
116     }
117   }
118 
119   public MethodHandleType type;
120   public Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod;
121 
DexMethodHandle( MethodHandleType type, Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod)122   public DexMethodHandle(
123       MethodHandleType type, Descriptor<? extends DexItem, ? extends Descriptor> fieldOrMethod) {
124     this.type = type;
125     this.fieldOrMethod = fieldOrMethod;
126   }
127 
computeHashCode()128   public int computeHashCode() {
129     return type.hashCode() + fieldOrMethod.computeHashCode() * 7;
130   }
131 
computeEquals(Object other)132   public boolean computeEquals(Object other) {
133     if (other instanceof DexMethodHandle) {
134       DexMethodHandle o = (DexMethodHandle) other;
135       return type.equals(o.type) && fieldOrMethod.equals(o.fieldOrMethod);
136     }
137     return false;
138   }
139 
toString()140   public String toString() {
141     StringBuilder builder = new StringBuilder("MethodHandle: {")
142             .append(type)
143             .append(", ")
144             .append(fieldOrMethod.toSourceString())
145             .append("}");
146     return builder.toString();
147   }
148 
149   @Override
collectIndexedItems(IndexedItemCollection indexedItems)150   public void collectIndexedItems(IndexedItemCollection indexedItems) {
151     if (indexedItems.addMethodHandle(this)) {
152       fieldOrMethod.collectIndexedItems(indexedItems);
153     }
154   }
155 
156   @Override
getOffset(ObjectToOffsetMapping mapping)157   public int getOffset(ObjectToOffsetMapping mapping) {
158     return mapping.getOffsetFor(this);
159   }
160 
161   // TODO(mikaelpeltier): Adapt syntax when invoke-custom will be available into smali.
toSmaliString()162   public String toSmaliString() {
163     return toString();
164   }
165 
isFieldHandle()166   public boolean isFieldHandle() {
167     return type.isFieldType();
168   }
169 
isMethodHandle()170   public boolean isMethodHandle() {
171     return type.isMethodType();
172   }
173 
isStaticHandle()174   public boolean isStaticHandle() {
175     return type.isStaticPut() || type.isStaticGet() || type.isInvokeStatic();
176   }
177 
asMethod()178   public DexMethod asMethod() {
179     assert isMethodHandle();
180     return (DexMethod) fieldOrMethod;
181   }
182 
asField()183   public DexField asField() {
184     assert isFieldHandle();
185     return (DexField) fieldOrMethod;
186   }
187 }
188