1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.rop.type; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashMap; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Representation of a method decriptor. Instances of this class are 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * generally interned and may be usefully compared with each other 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * using {@code ==}. 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class Prototype implements Comparable<Prototype> { 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} intern table mapping string descriptors to instances */ 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static final HashMap<String, Prototype> internTable = 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new HashMap<String, Prototype>(500); 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} method descriptor */ 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final String descriptor; 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} return type */ 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final Type returnType; 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} list of parameter types */ 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final StdTypeList parameterTypes; 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code null-ok;} list of parameter frame types, if calculated */ 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private StdTypeList parameterFrameTypes; 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns the unique instance corresponding to the 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * given method descriptor. See vmspec-2 sec4.3.3 for details on the 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * field descriptor syntax. 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param descriptor {@code non-null;} the descriptor 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the corresponding instance 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @throws IllegalArgumentException thrown if the descriptor has 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * invalid syntax 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static Prototype intern(String descriptor) { 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (descriptor == null) { 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("descriptor == null"); 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Prototype result = internTable.get(descriptor); 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (result != null) { 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type[] params = makeParameterArray(descriptor); 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int paramCount = 0; 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int at = 1; 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (;;) { 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int startAt = at; 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul char c = descriptor.charAt(at); 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (c == ')') { 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul at++; 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Skip array markers. 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul while (c == '[') { 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul at++; 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul c = descriptor.charAt(at); 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (c == 'L') { 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // It looks like the start of a class name; find the end. 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int endAt = descriptor.indexOf(';', at); 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (endAt == -1) { 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bad descriptor"); 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul at = endAt + 1; 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul at++; 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul params[paramCount] = 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type.intern(descriptor.substring(startAt, at)); 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul paramCount++; 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type returnType = Type.internReturnType(descriptor.substring(at)); 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StdTypeList parameterTypes = new StdTypeList(paramCount); 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < paramCount; i++) { 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul parameterTypes.set(i, params[i]); 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result = new Prototype(descriptor, returnType, parameterTypes); 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return putIntern(result); 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Helper for {@link #intern} which returns an empty array to 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * populate with parsed parameter types, and which also ensures 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * that there is a '(' at the start of the descriptor and a 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * single ')' somewhere before the end. 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param descriptor {@code non-null;} the descriptor string 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} array large enough to hold all parsed parameter 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * types, but which is likely actually larger than needed 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static Type[] makeParameterArray(String descriptor) { 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int length = descriptor.length(); 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (descriptor.charAt(0) != '(') { 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bad descriptor"); 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * This is a cheesy way to establish an upper bound on the 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * number of parameters: Just count capital letters. 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int closeAt = 0; 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int maxParams = 0; 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 1; i < length; i++) { 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul char c = descriptor.charAt(i); 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (c == ')') { 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul closeAt = i; 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul break; 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((c >= 'A') && (c <= 'Z')) { 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul maxParams++; 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if ((closeAt == 0) || (closeAt == (length - 1))) { 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bad descriptor"); 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (descriptor.indexOf(')', closeAt + 1) != -1) { 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new IllegalArgumentException("bad descriptor"); 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return new Type[maxParams]; 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Interns an instance, adding to the descriptor as necessary based 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * on the given definer, name, and flags. For example, an init 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * method has an uninitialized object of type {@code definer} 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * as its first argument. 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param descriptor {@code non-null;} the descriptor string 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param definer {@code non-null;} class the method is defined on 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param isStatic whether this is a static method 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param isInit whether this is an init method 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the interned instance 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static Prototype intern(String descriptor, Type definer, 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean isStatic, boolean isInit) { 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Prototype base = intern(descriptor); 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (isStatic) { 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return base; 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (isInit) { 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul definer = definer.asUninitialized(Integer.MAX_VALUE); 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return base.withFirstParameter(definer); 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Interns an instance which consists of the given number of 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@code int}s along with the given return type 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param returnType {@code non-null;} the return type 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param count {@code > 0;} the number of elements in the prototype 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the interned instance 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public static Prototype internInts(Type returnType, int count) { 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // Make the descriptor... 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuffer sb = new StringBuffer(100); 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('('); 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < count; i++) { 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append('I'); 196917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 197917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 198917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(')'); 199917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(returnType.getDescriptor()); 200917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 201917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul // ...and intern it. 202917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return intern(sb.toString()); 203917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 204917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 205917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 206917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. This is a private constructor; use one 207917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * of the public static methods to get instances. 208917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 209917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param descriptor {@code non-null;} the descriptor string 210917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 211917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private Prototype(String descriptor, Type returnType, 212917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StdTypeList parameterTypes) { 213917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (descriptor == null) { 214917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("descriptor == null"); 215917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 216917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 217917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (returnType == null) { 218917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("returnType == null"); 219917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 220917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 221917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (parameterTypes == null) { 222917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul throw new NullPointerException("parameterTypes == null"); 223917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 224917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 225917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.descriptor = descriptor; 226917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.returnType = returnType; 227917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.parameterTypes = parameterTypes; 228917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.parameterFrameTypes = null; 229917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 230917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 231917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 232917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 233917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public boolean equals(Object other) { 234917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this == other) { 235917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 236917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Since externally-visible instances are interned, this 237917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * check helps weed out some easy cases. 238917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 239917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return true; 240917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 241917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 242917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (!(other instanceof Prototype)) { 243917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return false; 244917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 245917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 246917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return descriptor.equals(((Prototype) other).descriptor); 247917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 248917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 249917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 250917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 251917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int hashCode() { 252917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return descriptor.hashCode(); 253917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 254917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 255917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 256917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public int compareTo(Prototype other) { 257917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (this == other) { 258917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 0; 259917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 260917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 261917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /* 262917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * The return type is the major order, and then args in order, 263917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * and then the shorter list comes first (similar to string 264917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * sorting). 265917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 266917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 267917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int result = returnType.compareTo(other.returnType); 268917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 269917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (result != 0) { 270917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 271917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 272917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 273917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int thisSize = parameterTypes.size(); 274917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int otherSize = other.parameterTypes.size(); 275917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = Math.min(thisSize, otherSize); 276917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 277917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < size; i++) { 278917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type thisType = parameterTypes.get(i); 279917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type otherType = other.parameterTypes.get(i); 280917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 281917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul result = thisType.compareTo(otherType); 282917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 283917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (result != 0) { 284917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return result; 285917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 286917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 287917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 288917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (thisSize < otherSize) { 289917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return -1; 290917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else if (thisSize > otherSize) { 291917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 1; 292917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 293917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return 0; 294917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 295917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 296917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 297917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@inheritDoc} */ 298917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul @Override 299917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toString() { 300917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return descriptor; 301917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 302917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 303917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 304917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the descriptor string. 305917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 306917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the descriptor 307917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 308917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String getDescriptor() { 309917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return descriptor; 310917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 311917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 312917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 313917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the return type. 314917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 315917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the return type 316917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 317917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Type getReturnType() { 318917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return returnType; 319917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 320917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 321917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 322917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the list of parameter types. 323917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 324917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the list of parameter types 325917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 326917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public StdTypeList getParameterTypes() { 327917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return parameterTypes; 328917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 329917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 330917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 331917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Gets the list of frame types corresponding to the list of parameter 332917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * types. The difference between the two lists (if any) is that all 333917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * "intlike" types (see {@link Type#isIntlike}) are replaced by 334917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * {@link Type#INT}. 335917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 336917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the list of parameter frame types 337917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 338917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public StdTypeList getParameterFrameTypes() { 339917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (parameterFrameTypes == null) { 340917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int sz = parameterTypes.size(); 341917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StdTypeList list = new StdTypeList(sz); 342917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul boolean any = false; 343917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (int i = 0; i < sz; i++) { 344917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Type one = parameterTypes.get(i); 345917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (one.isIntlike()) { 346917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul any = true; 347917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul one = Type.INT; 348917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 349917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul list.set(i, one); 350917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 351917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul parameterFrameTypes = any ? list : parameterTypes; 352917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 353917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 354917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return parameterFrameTypes; 355917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 356917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 357917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 358917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Returns a new interned instance, which is the same as this instance, 359917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * except that it has an additional parameter prepended to the original's 360917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * argument list. 361917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 362917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param param {@code non-null;} the new first parameter 363917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} an appropriately-constructed instance 364917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 365917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Prototype withFirstParameter(Type param) { 366917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String newDesc = "(" + param.getDescriptor() + descriptor.substring(1); 367917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StdTypeList newParams = parameterTypes.withFirst(param); 368917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 369917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul newParams.setImmutable(); 370917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 371917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Prototype result = 372917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul new Prototype(newDesc, returnType, newParams); 373917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 374917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return putIntern(result); 375917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 376917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 377917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 378917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Puts the given instance in the intern table if it's not already 379917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * there. If a conflicting value is already in the table, then leave it. 380917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Return the interned value. 381917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 382917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param desc {@code non-null;} instance to make interned 383917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return {@code non-null;} the actual interned object 384917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 385917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static Prototype putIntern(Prototype desc) { 386917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul synchronized (internTable) { 387917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String descriptor = desc.getDescriptor(); 388917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Prototype already = internTable.get(descriptor); 389917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (already != null) { 390917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return already; 391917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 392917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul internTable.put(descriptor, desc); 393917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return desc; 394917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 395917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 396917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 397