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 
  24 package jdk.test.lib.jittester;
  25 
  26 import java.util.ArrayList;
  27 import java.util.Collection;
  28 import java.util.HashMap;
  29 import java.util.Stack;
  30 import jdk.test.lib.jittester.types.TypeKlass;
  31 
  32 
  33 public class SymbolTable {
  34 
  35     private static final Stack<HashMap<Type, ArrayList<Symbol>>> SYMBOL_STACK
  36             = new Stack<>();
  37     private static int VARIABLE_NUMBER = 0;
  38     private static int FUNCTION_NUMBER = 0;
  39 
  40     static private void initExternalSymbols() {
  41 
  42         String classList = ProductionParams.addExternalSymbols.value();
  43         if (classList.equals("all")) {
  44             for (Type type : TypeList.getReferenceTypes()) {
  45                 type.exportSymbols();
  46             }
  47         } else {
  48             String[] splittedList = classList.split(",");
  49             for (Type type : TypeList.getReferenceTypes()) {
  50                 for (String str : splittedList) {
  51                     if (type.getName().equals(str)) {
  52                         type.exportSymbols();
  53                         break;
  54                     }
  55                 }
  56             }
  57         }
  58 
  59     }
  60 
  61     static {
  62         SYMBOL_STACK.push(new HashMap<>());
  63         if (!ProductionParams.disableExternalSymbols.value()) {
  64             initExternalSymbols();
  65         }
  66     }
  67 
  68     public static void add(Symbol symbol) {
  69         HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek();
  70         if (!vars.containsKey(symbol.type)) {
  71             vars.put(symbol.type, new ArrayList<>());
  72         }
  73         vars.get(symbol.type).add(symbol);
  74     }
  75 
  76     public static void remove(Symbol symbol) {
  77         HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek();
  78         if (vars.containsKey(symbol.type)) {
  79             ArrayList<Symbol> symbolsOfType = vars.get(symbol.type);
  80             symbolsOfType.remove(symbol);
  81             if (symbolsOfType.isEmpty()) {
  82                 vars.remove(symbol.type);
  83             }
  84         }
  85     }
  86 
  87     protected static Collection<Symbol> get(Type type) {
  88         HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek();
  89         if (vars.containsKey(type)) {
  90             return vars.get(type);
  91         }
  92         return new ArrayList<>();
  93     }
  94 
  95     public static Collection<Symbol> get(Type type, Class<?> classToCheck) {
  96         HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek();
  97         if (vars.containsKey(type)) {
  98             ArrayList<Symbol> result = new ArrayList<>();
  99             for (Symbol symbol : vars.get(type)) {
 100                 if (classToCheck.isInstance(symbol)) {
 101                     result.add(symbol);
 102                 }
 103             }
 104             return result;
 105         }
 106         return new ArrayList<>();
 107     }
 108 
 109     protected static Collection<Symbol> get(TypeKlass typeKlass, Type type,
 110             Class<?> classToCheck) {
 111         HashMap<Type, ArrayList<Symbol>> vars = SYMBOL_STACK.peek();
 112         if (vars.containsKey(type)) {
 113             ArrayList<Symbol> result = new ArrayList<>();
 114             for (Symbol symbol : vars.get(type)) {
 115                 if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.klass)) {
 116                     result.add(symbol);
 117                 }
 118             }
 119             return result;
 120         }
 121         return new ArrayList<>();
 122     }
 123 
 124     protected static HashMap<Type, ArrayList<Symbol>> getAll() {
 125         return SYMBOL_STACK.peek();
 126     }
 127 
 128     protected static HashMap<Type, ArrayList<Symbol>> getAll(Class<?> classToCheck) {
 129         HashMap<Type, ArrayList<Symbol>> result = new HashMap<>();
 130 
 131         for (Type type : SYMBOL_STACK.peek().keySet()) {
 132             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type);
 133             for (Symbol symbol : symbolsOfType) {
 134                 if (classToCheck.isInstance(symbol)) {
 135                     if (!result.containsKey(type)) {
 136                         result.put(type, new ArrayList<>());
 137                     }
 138                     result.get(type).add(symbol);
 139                 }
 140             }
 141         }
 142 
 143         return result;
 144     }
 145 
 146     protected static HashMap<Type, ArrayList<Symbol>> getAll(TypeKlass typeKlass, Class<?> classToCheck) {
 147         HashMap<Type, ArrayList<Symbol>> result = new HashMap<>();
 148 
 149         for (Type type : SYMBOL_STACK.peek().keySet()) {
 150             ArrayList<Symbol> symbolsOfType =  SYMBOL_STACK.peek().get(type);
 151             for (Symbol symbol : symbolsOfType) {
 152                 if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.klass)) {
 153                     if (!result.containsKey(type)) {
 154                         result.put(type, new ArrayList<>());
 155                     }
 156                     result.get(type).add(symbol);
 157                 }
 158             }
 159         }
 160 
 161         return result;
 162     }
 163 
 164     protected static ArrayList<Symbol> getAllCombined() {
 165         ArrayList<Symbol> result = new ArrayList<>();
 166         for (Type type : SYMBOL_STACK.peek().keySet()) {
 167             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type);
 168             for (Symbol symbol : symbolsOfType) {
 169                 result.add(symbol);
 170             }
 171         }
 172 
 173         return result;
 174     }
 175 
 176     public static ArrayList<Symbol> getAllCombined(Class<?> classToCheck) {
 177         ArrayList<Symbol> result = new ArrayList<>();
 178         for (Type type : SYMBOL_STACK.peek().keySet()) {
 179             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type);
 180             for (Symbol symbol : symbolsOfType) {
 181                 if (classToCheck.isInstance(symbol)) {
 182                     result.add(symbol);
 183                 }
 184             }
 185         }
 186 
 187         return result;
 188     }
 189 
 190     public static ArrayList<Symbol> getAllCombined(TypeKlass typeKlass, Class<?> classToCheck) {
 191         ArrayList<Symbol> result = new ArrayList<>();
 192         for (Type type : SYMBOL_STACK.peek().keySet()) {
 193             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type);
 194             for (Symbol symbol : symbolsOfType) {
 195                 if (classToCheck.isInstance(symbol) && typeKlass.equals(symbol.klass)) {
 196                     result.add(symbol);
 197                 }
 198             }
 199         }
 200 
 201         return result;
 202     }
 203 
 204     public static ArrayList<Symbol> getAllCombined(TypeKlass typeKlass) {
 205         ArrayList<Symbol> result = new ArrayList<>();
 206         for (Type t : SYMBOL_STACK.peek().keySet()) {
 207             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(t);
 208             for (Symbol symbol : symbolsOfType) {
 209                 if (typeKlass.equals(symbol.klass)) {
 210                     result.add(symbol);
 211                 }
 212             }
 213         }
 214 
 215         return result;
 216     }
 217 
 218     protected static ArrayList<Symbol> getAllCombined(String name, Class<?> classToCheck) {
 219         ArrayList<Symbol> result = new ArrayList<>();
 220         for (Type type : SYMBOL_STACK.peek().keySet()) {
 221             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type);
 222             for (Symbol symbol : symbolsOfType) {
 223                 if (classToCheck.isInstance(symbol) && name.equals(symbol.name)) {
 224                     result.add(symbol);
 225                 }
 226             }
 227         }
 228 
 229         return result;
 230     }
 231 
 232     public static Symbol get(String name, Class<?> classToCheck) {
 233         for (Type type : SYMBOL_STACK.peek().keySet()) {
 234             ArrayList<Symbol> symbolsOfType = SYMBOL_STACK.peek().get(type);
 235             for (Symbol symbol : symbolsOfType) {
 236                 if (classToCheck.isInstance(symbol) && name.equals(symbol.name)) {
 237                     return symbol;
 238                 }
 239             }
 240         }
 241         return null;
 242     }
 243 
 244     public static void removeAll() {
 245         SYMBOL_STACK.clear();
 246         SYMBOL_STACK.push(new HashMap<>());
 247         VARIABLE_NUMBER = 0;
 248         FUNCTION_NUMBER = 0;
 249         if (!ProductionParams.disableExternalSymbols.value()) {
 250             initExternalSymbols();
 251         }
 252     }
 253 
 254     public static void push() {
 255         // Do deep cloning..
 256         HashMap<Type, ArrayList<Symbol>> prev = SYMBOL_STACK.peek();
 257         SYMBOL_STACK.push(new HashMap<>());
 258         HashMap<Type, ArrayList<Symbol>> top = SYMBOL_STACK.peek();
 259         for (Type type : prev.keySet()) {
 260             ArrayList<Symbol> prevArray = prev.get(type);
 261             top.put(type, new ArrayList<>(prevArray.size()));
 262             ArrayList<Symbol> topArray = top.get(type);
 263             for (Symbol symbol : prevArray) {
 264                 topArray.add(symbol.copy());
 265             }
 266         }
 267     }
 268 
 269     public static void merge() {
 270         // Merging means moving element at the top of stack one step down, while removing the
 271         // previous element.
 272         HashMap<Type, ArrayList<Symbol>> top = SYMBOL_STACK.pop();
 273         SYMBOL_STACK.pop();
 274         SYMBOL_STACK.push(top);
 275     }
 276 
 277     public static void pop() {
 278         SYMBOL_STACK.pop();
 279     }
 280 
 281     public static int getNextVariableNumber() {
 282         return ++VARIABLE_NUMBER;
 283     }
 284 
 285     public static int getNextFunctionNumber() {
 286         return ++FUNCTION_NUMBER;
 287     }
 288 
 289     @Override
 290     public String toString() {
 291         return SYMBOL_STACK.toString();
 292     }
 293 }