1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.rop.type; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.HashMap; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 22ed0fe6c2f310f8c2cc28c35c2b473d8de36db8a4Jesse Wilson * Representation of a method descriptor. Instances of this class are 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * generally interned and may be usefully compared with each other 2499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * using {@code ==}. 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class Prototype implements Comparable<Prototype> { 2799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} intern table mapping string descriptors to instances */ 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final HashMap<String, Prototype> internTable = 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new HashMap<String, Prototype>(500); 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} method descriptor */ 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final String descriptor; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} return type */ 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final Type returnType; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} list of parameter types */ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final StdTypeList parameterTypes; 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 4099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code null-ok;} list of parameter frame types, if calculated */ 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private StdTypeList parameterFrameTypes; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 44de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * Returns the unique instance corresponding to the 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * given method descriptor. See vmspec-2 sec4.3.3 for details on the 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * field descriptor syntax. 47de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param descriptor {@code non-null;} the descriptor 4999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the corresponding instance 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @throws IllegalArgumentException thrown if the descriptor has 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invalid syntax 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static Prototype intern(String descriptor) { 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (descriptor == null) { 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("descriptor == null"); 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 58590f78fc4b6e3268149c5eacb7c8b7dd33497f44jeffhao Prototype result; 59590f78fc4b6e3268149c5eacb7c8b7dd33497f44jeffhao synchronized (internTable) { 60590f78fc4b6e3268149c5eacb7c8b7dd33497f44jeffhao result = internTable.get(descriptor); 61590f78fc4b6e3268149c5eacb7c8b7dd33497f44jeffhao } 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result != null) { 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type[] params = makeParameterArray(descriptor); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int paramCount = 0; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int at = 1; 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (;;) { 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int startAt = at; 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char c = descriptor.charAt(at); 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (c == ')') { 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at++; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Skip array markers. 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project while (c == '[') { 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at++; 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project c = descriptor.charAt(at); 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (c == 'L') { 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // It looks like the start of a class name; find the end. 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int endAt = descriptor.indexOf(';', at); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (endAt == -1) { 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("bad descriptor"); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at = endAt + 1; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project at++; 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project params[paramCount] = 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type.intern(descriptor.substring(startAt, at)); 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project paramCount++; 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type returnType = Type.internReturnType(descriptor.substring(at)); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StdTypeList parameterTypes = new StdTypeList(paramCount); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < paramCount; i++) { 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parameterTypes.set(i, params[i]); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = new Prototype(descriptor, returnType, parameterTypes); 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return putIntern(result); 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Helper for {@link #intern} which returns an empty array to 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * populate with parsed parameter types, and which also ensures 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that there is a '(' at the start of the descriptor and a 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * single ')' somewhere before the end. 116de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 11799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param descriptor {@code non-null;} the descriptor string 11899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} array large enough to hold all parsed parameter 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * types, but which is likely actually larger than needed 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static Type[] makeParameterArray(String descriptor) { 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int length = descriptor.length(); 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (descriptor.charAt(0) != '(') { 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("bad descriptor"); 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This is a cheesy way to establish an upper bound on the 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * number of parameters: Just count capital letters. 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int closeAt = 0; 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int maxParams = 0; 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 1; i < length; i++) { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char c = descriptor.charAt(i); 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (c == ')') { 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project closeAt = i; 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((c >= 'A') && (c <= 'Z')) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project maxParams++; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((closeAt == 0) || (closeAt == (length - 1))) { 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("bad descriptor"); 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (descriptor.indexOf(')', closeAt + 1) != -1) { 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new IllegalArgumentException("bad descriptor"); 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return new Type[maxParams]; 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Interns an instance, adding to the descriptor as necessary based 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * on the given definer, name, and flags. For example, an init 15999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * method has an uninitialized object of type {@code definer} 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * as its first argument. 161de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 16299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param descriptor {@code non-null;} the descriptor string 16399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param definer {@code non-null;} class the method is defined on 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param isStatic whether this is a static method 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param isInit whether this is an init method 16699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the interned instance 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static Prototype intern(String descriptor, Type definer, 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean isStatic, boolean isInit) { 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Prototype base = intern(descriptor); 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isStatic) { 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return base; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (isInit) { 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project definer = definer.asUninitialized(Integer.MAX_VALUE); 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return base.withFirstParameter(definer); 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Interns an instance which consists of the given number of 18599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code int}s along with the given return type 186de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 18799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param returnType {@code non-null;} the return type 18899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param count {@code > 0;} the number of elements in the prototype 18999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the interned instance 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static Prototype internInts(Type returnType, int count) { 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Make the descriptor... 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuffer sb = new StringBuffer(100); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append('('); 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < count; i++) { 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append('I'); 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(')'); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(returnType.getDescriptor()); 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ...and intern it. 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return intern(sb.toString()); 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs an instance. This is a private constructor; use one 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of the public static methods to get instances. 212de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 21399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param descriptor {@code non-null;} the descriptor string 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private Prototype(String descriptor, Type returnType, 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StdTypeList parameterTypes) { 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (descriptor == null) { 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("descriptor == null"); 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (returnType == null) { 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("returnType == null"); 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (parameterTypes == null) { 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new NullPointerException("parameterTypes == null"); 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.descriptor = descriptor; 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.returnType = returnType; 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.parameterTypes = parameterTypes; 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.parameterFrameTypes = null; 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean equals(Object other) { 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this == other) { 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since externally-visible instances are interned, this 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * check helps weed out some easy cases. 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!(other instanceof Prototype)) { 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return descriptor.equals(((Prototype) other).descriptor); 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int hashCode() { 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return descriptor.hashCode(); 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int compareTo(Prototype other) { 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this == other) { 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 264de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The return type is the major order, and then args in order, 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and then the shorter list comes first (similar to string 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * sorting). 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = returnType.compareTo(other.returnType); 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result != 0) { 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int thisSize = parameterTypes.size(); 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int otherSize = other.parameterTypes.size(); 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int size = Math.min(thisSize, otherSize); 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < size; i++) { 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type thisType = parameterTypes.get(i); 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type otherType = other.parameterTypes.get(i); 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = thisType.compareTo(otherType); 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (result != 0) { 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thisSize < otherSize) { 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return -1; 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (thisSize > otherSize) { 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 0; 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** {@inheritDoc} */ 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project @Override 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String toString() { 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return descriptor; 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the descriptor string. 309de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 31099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the descriptor 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String getDescriptor() { 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return descriptor; 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the return type. 318de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 31999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the return type 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Type getReturnType() { 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return returnType; 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the list of parameter types. 327de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 32899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the list of parameter types 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public StdTypeList getParameterTypes() { 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return parameterTypes; 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Gets the list of frame types corresponding to the list of parameter 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * types. The difference between the two lists (if any) is that all 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "intlike" types (see {@link Type#isIntlike}) are replaced by 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@link Type#INT}. 339de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 34099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the list of parameter frame types 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public StdTypeList getParameterFrameTypes() { 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (parameterFrameTypes == null) { 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int sz = parameterTypes.size(); 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StdTypeList list = new StdTypeList(sz); 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean any = false; 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < sz; i++) { 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Type one = parameterTypes.get(i); 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (one.isIntlike()) { 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project any = true; 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project one = Type.INT; 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project list.set(i, one); 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parameterFrameTypes = any ? list : parameterTypes; 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return parameterFrameTypes; 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a new interned instance, which is the same as this instance, 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * except that it has an additional parameter prepended to the original's 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * argument list. 365de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 36699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param param {@code non-null;} the new first parameter 36799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} an appropriately-constructed instance 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public Prototype withFirstParameter(Type param) { 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String newDesc = "(" + param.getDescriptor() + descriptor.substring(1); 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StdTypeList newParams = parameterTypes.withFirst(param); 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project newParams.setImmutable(); 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Prototype result = 376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project new Prototype(newDesc, returnType, newParams); 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return putIntern(result); 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Puts the given instance in the intern table if it's not already 383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * there. If a conflicting value is already in the table, then leave it. 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Return the interned value. 385de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 38699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param desc {@code non-null;} instance to make interned 38799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} the actual interned object 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static Prototype putIntern(Prototype desc) { 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project synchronized (internTable) { 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String descriptor = desc.getDescriptor(); 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Prototype already = internTable.get(descriptor); 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (already != null) { 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return already; 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project internTable.put(descriptor, desc); 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return desc; 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 401