• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.dx.rop.cst;
18 
19 import com.android.dx.rop.type.Type;
20 
21 /**
22  * Constants of type {@code MethodHandle}.
23  */
24 public final class CstMethodHandle extends TypedConstant {
25 
26     public static final int METHOD_HANDLE_TYPE_STATIC_PUT = 0;
27     public static final int METHOD_HANDLE_TYPE_STATIC_GET = 1;
28     public static final int METHOD_HANDLE_TYPE_INSTANCE_PUT = 2;
29     public static final int METHOD_HANDLE_TYPE_INSTANCE_GET = 3;
30 
31     public static final int METHOD_HANDLE_TYPE_INVOKE_STATIC = 4;
32     public static final int METHOD_HANDLE_TYPE_INVOKE_INSTANCE = 5;
33     public static final int METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR = 6;
34     public static final int METHOD_HANDLE_TYPE_INVOKE_DIRECT = 7;
35     public static final int METHOD_HANDLE_TYPE_INVOKE_INTERFACE = 8;
36 
37     private static final String [] TYPE_NAMES = {
38         "static-put", "static-get", "instance-put", "instance-get",
39         "invoke-static", "invoke-instance", "invoke-constructor", "invoke-direct",
40         "invoke-interface"
41     };
42 
43     /** The type of MethodHandle */
44     private final int type;
45 
46     /** {@code non-null;} the referenced constant */
47     private final Constant ref;
48 
49     /**
50      * Makes an instance for the given value. This may (but does not
51      * necessarily) return an already-allocated instance.
52      *
53      * @param type the type of this handle
54      * @param ref {@code non-null;} the referenced field or method constant
55      * @return {@code non-null;} the appropriate instance
56      */
make(int type, Constant ref)57     public static CstMethodHandle make(int type, Constant ref) {
58         if (isAccessor(type)) {
59             if (!(ref instanceof CstFieldRef)) {
60                 throw new IllegalArgumentException("ref has wrong type: " + ref.getClass());
61             }
62         } else if (isInvocation(type)) {
63             if (!(ref instanceof CstBaseMethodRef)) {
64                 throw new IllegalArgumentException("ref has wrong type: " + ref.getClass());
65             }
66         } else {
67             throw new IllegalArgumentException("type is out of range: " + type);
68         }
69         return new CstMethodHandle(type, ref);
70     }
71 
72     /**
73      * Constructs an instance. This constructor is private; use {@link #make}.
74      *
75      * @param type the type of this handle
76      * @param ref the actual referenced constant
77      */
CstMethodHandle(int type, Constant ref)78     private CstMethodHandle(int type, Constant ref) {
79         this.type = type;
80         this.ref = ref;
81     }
82 
83     /**
84      * Gets the actual constant.
85      *
86      * @return the value
87      */
getRef()88     public Constant getRef() {
89         return ref;
90     }
91 
92     /**
93      * Gets the type of this method handle.
94      *
95      * @return the type
96      */
getMethodHandleType()97     public int getMethodHandleType() {
98         return type;
99     }
100 
101     /**
102      * Reports whether the method handle type is a field accessor.
103      *
104      * @param type the method handle type
105      * @return true if the method handle type is a field accessor, false otherwise
106      */
isAccessor(int type)107     public static boolean isAccessor(int type) {
108         switch (type) {
109             case METHOD_HANDLE_TYPE_STATIC_PUT:
110             case METHOD_HANDLE_TYPE_STATIC_GET:
111             case METHOD_HANDLE_TYPE_INSTANCE_PUT:
112             case METHOD_HANDLE_TYPE_INSTANCE_GET:
113                 return true;
114             default:
115                 return false;
116         }
117     }
118 
119     /**
120      * Reports whether the method handle is a field accessor.
121      *
122      * @return true if the method handle is a field accessor, false otherwise
123      */
isAccessor()124     public boolean isAccessor() {
125         return isAccessor(type);
126     }
127 
128     /**
129      * Reports whether the method handle type is a method invocation.
130      *
131      * @param type the method handle type
132      * @return true if the method handle type is a method invocation, false otherwise
133      */
isInvocation(int type)134     public static boolean isInvocation(int type) {
135         switch (type) {
136             case METHOD_HANDLE_TYPE_INVOKE_STATIC:
137             case METHOD_HANDLE_TYPE_INVOKE_INSTANCE:
138             case METHOD_HANDLE_TYPE_INVOKE_CONSTRUCTOR:
139             case METHOD_HANDLE_TYPE_INVOKE_DIRECT:
140             case METHOD_HANDLE_TYPE_INVOKE_INTERFACE:
141                 return true;
142             default:
143                 return false;
144         }
145     }
146 
147     /**
148      * Reports whether the method handle is a method invocation.
149      *
150      * @return true if the method handle is a method invocation, false otherwise
151      */
isInvocation()152     public boolean isInvocation() {
153         return isInvocation(type);
154     }
155 
156     /**
157      * Gets a human readable name for a method handle type.
158      *
159      * @param type the method handle type
160      * @return the string representation of the type
161      */
getMethodHandleTypeName(final int type)162     public static String getMethodHandleTypeName(final int type) {
163         return TYPE_NAMES[type];
164     }
165 
166     /** {@inheritDoc} */
167     @Override
isCategory2()168     public boolean isCategory2() {
169         return false;
170     }
171 
172     /** {@inheritDoc} */
173     @Override
compareTo0(Constant other)174     protected int compareTo0(Constant other) {
175         CstMethodHandle otherHandle = (CstMethodHandle) other;
176         if (getMethodHandleType() == otherHandle.getMethodHandleType()) {
177             return getRef().compareTo(otherHandle.getRef());
178         } else {
179             return Integer.compare(getMethodHandleType(), otherHandle.getMethodHandleType());
180         }
181     }
182 
183     /** {@inheritDoc} */
184     @Override
toString()185     public String toString() {
186         return "method-handle{" + toHuman() + "}";
187     }
188 
189     /** {@inheritDoc} */
190     @Override
typeName()191     public String typeName() {
192         return "method handle";
193     }
194 
195     /** {@inheritDoc} */
196     @Override
toHuman()197     public String toHuman() {
198         return getMethodHandleTypeName(type)+ "," + ref.toString();
199     }
200 
201     @Override
getType()202     public Type getType() {
203         return Type.METHOD_HANDLE;
204     }
205 }
206