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.types;
  25 
  26 import java.util.Collection;
  27 import java.util.HashSet;
  28 import java.util.TreeSet;
  29 import jdk.test.lib.jittester.ProductionParams;
  30 import jdk.test.lib.jittester.Symbol;
  31 import jdk.test.lib.jittester.SymbolTable;
  32 import jdk.test.lib.jittester.Type;
  33 import jdk.test.lib.jittester.TypeList;
  34 
  35 public class TypeKlass extends Type {
  36     private TypeKlass parentKlass;
  37     private final HashSet<String> parentsList;
  38     private final HashSet<String> childrenList;
  39     private final HashSet<Symbol> symbolsSet;
  40     private int flags;
  41 
  42     public static final int NONE = 0x00;
  43     public static final int FINAL = 0x01;
  44     public static final int INTERFACE = 0x02;
  45     public static final int ABSTRACT = 0x04;
  46 
  47 
  48     public TypeKlass(String name) {
  49         this(name, NONE);
  50     }
  51 
  52     public TypeKlass(String name, int flags) {
  53         super(name);
  54         this.flags = flags;
  55         parentsList = new HashSet<>();
  56         childrenList = new HashSet<>();
  57         symbolsSet = new HashSet<>();
  58     }
  59 
  60     public boolean addSymbol(Symbol s) {
  61         return symbolsSet.add(s);
  62     }
  63 
  64     public boolean addAllSymbols(Collection<? extends Symbol> symbols) {
  65         return symbolsSet.addAll(symbols);
  66     }
  67 
  68     public boolean containsSymbol(Symbol s) {
  69         return symbolsSet.contains(s);
  70     }
  71 
  72     public boolean removeSymbol(Symbol s) {
  73         return symbolsSet.remove(s);
  74     }
  75 
  76     public boolean removeAllSymbols(Collection<? extends Symbol> symbols) {
  77         return symbolsSet.removeAll(symbols);
  78     }
  79 
  80     @Override
  81     protected void exportSymbols() {
  82         symbolsSet.stream().forEach(SymbolTable::add);
  83     }
  84 
  85     public void setParent(TypeKlass p) {
  86         parentKlass = p;
  87     }
  88 
  89     public void addParent(String p) {
  90         parentsList.add(p);
  91     }
  92 
  93     public void addChild(String c) {
  94         childrenList.add(c);
  95     }
  96 
  97     protected void removeParent(String p) {
  98         parentsList.remove(p);
  99     }
 100 
 101     protected void removeChild(String c) {
 102         childrenList.remove(c);
 103     }
 104 
 105     public HashSet<String> getParentsNames() {
 106         return parentsList;
 107     }
 108 
 109     public HashSet<String> getChildrenNames() {
 110         return childrenList;
 111     }
 112 
 113     @Override
 114     public boolean canCompareTo(Type t) {
 115         return false;
 116     }
 117 
 118     @Override
 119     public boolean canEquateTo(Type t) {
 120         return true;
 121     }
 122 
 123     public TreeSet<TypeKlass> getAllParents() {
 124         TreeSet<TypeKlass> result = new TreeSet<>();
 125         parentsList.stream()
 126                 .map(TypeList::find)
 127                 .filter(parentKlass -> parentKlass != null)
 128                 .map(parentKlass -> (TypeKlass) parentKlass)
 129                 .forEach(parentKlass -> {
 130                     result.add(parentKlass);
 131                     result.addAll(parentKlass.getAllParents());
 132         });
 133         return result;
 134     }
 135 
 136     public TreeSet<TypeKlass> getAllChildren() {
 137         TreeSet<TypeKlass> r = new TreeSet<>();
 138         childrenList.stream()
 139                 .map(TypeList::find)
 140                 .filter(childKlass -> childKlass != null)
 141                 .map(childKlass -> (TypeKlass) childKlass)
 142                 .forEach(childKlass -> {
 143                     r.add(childKlass);
 144                     r.addAll(childKlass.getAllChildren());
 145         });
 146         return r;
 147     }
 148 
 149     @Override
 150     public boolean canImplicitlyCastTo(Type t) {
 151         // We can implicitly cast to anything up the hierarchy and to self
 152         if (t instanceof TypeKlass) {
 153             return equals(t) || getAllParents().contains(t);
 154         }
 155         return false;
 156     }
 157 
 158     // If canExplicitlyCastTo() returns true in this case it doesn't mean that
 159     // it would really be successful. Since explicit casts are inherintly dynamic
 160     // we cannot guarantee that no exception will occur.
 161     @Override
 162     public boolean canExplicitlyCastTo(Type t) {
 163         if (equals(t)) {
 164             return true;
 165         }
 166         if (t instanceof TypeKlass && !ProductionParams.disableDowncasts.value()) {
 167             return getAllChildren().contains(t);
 168         }
 169 
 170         return false;
 171     }
 172 
 173     public boolean isFinal() {
 174         return (flags & FINAL) > 0;
 175     }
 176 
 177     public void setFinal() {
 178         flags |= FINAL;
 179     }
 180 
 181     public boolean isAbstract() {
 182         return (flags & ABSTRACT) > 0;
 183     }
 184 
 185     public void setAbstract() {
 186         flags |= ABSTRACT;
 187     }
 188 
 189     public boolean isInterface() {
 190         return (flags & INTERFACE) > 0;
 191     }
 192 
 193     public TypeKlass getParent() {
 194         return parentKlass;
 195     }
 196 }