1/* 2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24package jdk.test.lib.jittester; 25 26import java.util.ArrayList; 27import java.util.Collection; 28import java.util.HashMap; 29import java.util.Map; 30import java.util.Stack; 31import java.util.stream.Collectors; 32import jdk.test.lib.jittester.types.TypeKlass; 33 34 35public class SymbolTable { 36 37 private static final Stack<HashMap<Type, ArrayList<Symbol>>> SYMBOL_STACK 38 = new Stack<>(); 39 private static int VARIABLE_NUMBER = 0; 40 private static int FUNCTION_NUMBER = 0; 41 42 private static void initExternalSymbols() { 43 44 String classList = ProductionParams.addExternalSymbols.value(); 45 if (classList.equals("all")) { 46 TypeList.getReferenceTypes() 47 .forEach(Type::exportSymbols); 48 } else { 49 String[] splittedList = classList.split(","); 50 for (Type type : TypeList.getReferenceTypes()) { 51 for (String str : splittedList) { 52 if (type.getName().equals(str)) { 53 type.exportSymbols(); 54 break; 55 } 56 } 57 } 58 } 59 60 } 61 62 static { 63 SYMBOL_STACK.push(new HashMap<>()); 64 if (!ProductionParams.disableExternalSymbols.value()) { 65 initExternalSymbols(); 66 } 67 } 68 69 public static void add(Symbol symbol) { 70 HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek(); 71 if (!vars.containsKey(symbol.type)) { 72 vars.put(symbol.type, new ArrayList<>()); 73 } 74 vars.get(symbol.type).add(symbol); 75 } 76 77 public static void remove(Symbol symbol) { 78 HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek(); 79 if (vars.containsKey(symbol.type)) { 80 ArrayList<Symbol> symbolsOfType = vars.get(symbol.type); 81 symbolsOfType.remove(symbol); 82 if (symbolsOfType.isEmpty()) { 83 vars.remove(symbol.type); 84 } 85 } 86 } 87 88 protected static Collection<Symbol> get(Type type) { 89 HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek(); 90 if (vars.containsKey(type)) { 91 return vars.get(type); 92 } 93 return new ArrayList<>(); 94 } 95 96 public static Collection<Symbol> get(Type type, Class<?> classToCheck) { 97 HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek(); 98 if (vars.containsKey(type)) { 99 return vars.get(type).stream() 100 .filter(classToCheck::isInstance) 101 .collect(Collectors.toList()); 102 } 103 return new ArrayList<>(); 104 } 105 106 protected static Collection<Symbol> get(TypeKlass typeKlass, Type type, 107 Class<?> classToCheck) { 108 HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek(); 109 if (vars.containsKey(type)) { 110 ArrayList<Symbol> result = new ArrayList<>(); 111 for (Symbol symbol : vars.get(type)) { 112 if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.owner)) { 113 result.add(symbol); 114 } 115 } 116 return result; 117 } 118 return new ArrayList<>(); 119 } 120 121 protected static HashMap<Type, ArrayList<Symbol>> getAll() { 122 return SYMBOL_STACK.peek(); 123 } 124 125 protected static HashMap<Type, ArrayList<Symbol>> getAll(Class<?> classToCheck) { 126 HashMap<Type, ArrayList<Symbol>> result = new HashMap<>(); 127 128 for (Type type : SYMBOL_STACK.peek().keySet()) { 129 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type); 130 for (Symbol symbol : symbolsOfType) { 131 if (classToCheck.isInstance(symbol)) { 132 if (!result.containsKey(type)) { 133 result.put(type, new ArrayList<>()); 134 } 135 result.get(type).add(symbol); 136 } 137 } 138 } 139 140 return result; 141 } 142 143 protected static HashMap<Type, ArrayList<Symbol>> getAll(TypeKlass typeKlass, Class<?> classToCheck) { 144 HashMap<Type, ArrayList<Symbol>> result = new HashMap<>(); 145 146 for (Type type : SYMBOL_STACK.peek().keySet()) { 147 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type); 148 for (Symbol symbol : symbolsOfType) { 149 if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.owner)) { 150 if (!result.containsKey(type)) { 151 result.put(type, new ArrayList<>()); 152 } 153 result.get(type).add(symbol); 154 } 155 } 156 } 157 158 return result; 159 } 160 161 protected static ArrayList<Symbol> getAllCombined() { 162 ArrayList<Symbol> result = new ArrayList<>(); 163 for (Type type : SYMBOL_STACK.peek().keySet()) { 164 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type); 165 for (Symbol symbol : symbolsOfType) { 166 result.add(symbol); 167 } 168 } 169 170 return result; 171 } 172 173 public static ArrayList<Symbol> getAllCombined(Class<?> classToCheck) { 174 ArrayList<Symbol> result = new ArrayList<>(); 175 for (Type type : SYMBOL_STACK.peek().keySet()) { 176 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type); 177 for (Symbol symbol : symbolsOfType) { 178 if (classToCheck.isInstance(symbol)) { 179 result.add(symbol); 180 } 181 } 182 } 183 184 return result; 185 } 186 187 public static ArrayList<Symbol> getAllCombined(TypeKlass typeKlass, Class<?> classToCheck) { 188 ArrayList<Symbol> result = new ArrayList<>(); 189 for (Type type : SYMBOL_STACK.peek().keySet()) { 190 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type); 191 for (Symbol symbol : symbolsOfType) { 192 if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.owner)) { 193 result.add(symbol); 194 } 195 } 196 } 197 198 return result; 199 } 200 201 public static ArrayList<Symbol> getAllCombined(TypeKlass typeKlass) { 202 ArrayList<Symbol> result = new ArrayList<>(); 203 for (Type t : SYMBOL_STACK.peek().keySet()) { 204 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(t); 205 for (Symbol symbol : symbolsOfType) { 206 if (typeKlass.equals(symbol.owner)) { 207 result.add(symbol); 208 } 209 } 210 } 211 212 return result; 213 } 214 215 protected static ArrayList<Symbol> getAllCombined(String name, Class<?> classToCheck) { 216 ArrayList<Symbol> result = new ArrayList<>(); 217 for (Type type : SYMBOL_STACK.peek().keySet()) { 218 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type); 219 for (Symbol symbol : symbolsOfType) { 220 if (classToCheck.isInstance(symbol) && name.equals(symbol.name)) { 221 result.add(symbol); 222 } 223 } 224 } 225 226 return result; 227 } 228 229 public static Symbol get(String name, Class<?> classToCheck) { 230 for (Type type : SYMBOL_STACK.peek().keySet()) { 231 ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type); 232 for (Symbol symbol : symbolsOfType) { 233 if (classToCheck.isInstance(symbol) && name.equals(symbol.name)) { 234 return symbol; 235 } 236 } 237 } 238 return null; 239 } 240 241 public static void removeAll() { 242 SYMBOL_STACK.clear(); 243 SYMBOL_STACK.push(new HashMap<>()); 244 VARIABLE_NUMBER = 0; 245 FUNCTION_NUMBER = 0; 246 if (!ProductionParams.disableExternalSymbols.value()) { 247 initExternalSymbols(); 248 } 249 } 250 251 public static void push() { 252 // Do deep cloning.. 253 HashMap<Type, ArrayList<Symbol>> prev = SYMBOL_STACK.peek(); 254 HashMap<Type, ArrayList<Symbol>> top = new HashMap<>(prev.size()); 255 SYMBOL_STACK.push(top); 256 for (Map.Entry<Type, ArrayList<Symbol>> entry : prev.entrySet()) { 257 ArrayList<Symbol> prevArray = entry.getValue(); 258 ArrayList<Symbol> topArray = new ArrayList<>(prevArray.size()); 259 top.put(entry.getKey(), topArray); 260 for (Symbol symbol : prevArray) { 261 topArray.add(symbol.copy()); 262 } 263 } 264 } 265 266 public static void merge() { 267 // Merging means moving element at the top of stack one step down, while removing the 268 // previous element. 269 HashMap<Type, ArrayList<Symbol>> top = SYMBOL_STACK.pop(); 270 SYMBOL_STACK.pop(); 271 SYMBOL_STACK.push(top); 272 } 273 274 public static void pop() { 275 SYMBOL_STACK.pop(); 276 } 277 278 public static int getNextVariableNumber() { 279 return ++VARIABLE_NUMBER; 280 } 281 282 public static int getNextFunctionNumber() { 283 return ++FUNCTION_NUMBER; 284 } 285 286 @Override 287 public String toString() { 288 return SYMBOL_STACK.toString(); 289 } 290} 291