1 /* 2 * Copyright (c) 2016, 2016, 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 package org.graalvm.compiler.core.common.type; 24 25 import jdk.vm.ci.meta.Assumptions; 26 import jdk.vm.ci.meta.ResolvedJavaType; 27 28 /** 29 * This class represents a reference to a Java type and whether this reference is referring only to 30 * the represented type or also to its sub types in the class hierarchy. When creating a type 31 * reference, the following options have to be considered: 32 * 33 * <ul> 34 * <li>The reference should always only refer to the given concrete type. Use 35 * {@link #createExactTrusted(ResolvedJavaType)} for this purpose.</li> 36 * <li>The reference should be created without assumptions about the class hierarchy. The returned 37 * reference is exact only when the type is a leaf type (i.e., it cannot have subclasses). Depending 38 * on whether interface types can be trusted for this type reference use 39 * {@link #createWithoutAssumptions} or {@link #createTrustedWithoutAssumptions}.</li> 40 * <li>The reference should be created using assumptions about the class hierarchy. The returned 41 * reference is also exact, when there is only a single concrete sub type for the given type. 42 * Depending on whether interface types can be trusted for this type reference use {@link #create} 43 * or {@link #createTrusted}.</li> 44 * </ul> 45 * 46 * For the methods with untrusted interface types, a {@code null} reference will be constructed for 47 * untrusted interface types. Examples for interface types that cannot be trusted are types for 48 * parameters, fields, and return values. They are not checked by the Java verifier. 49 * 50 */ 51 public final class TypeReference { 52 private final ResolvedJavaType type; 53 private final boolean exactReference; 54 55 private TypeReference(ResolvedJavaType type, boolean exactReference) { 56 this.type = type; 57 this.exactReference = exactReference; 58 } 59 60 /** 61 * Creates an exact type reference using the given type. 62 */ 63 public static TypeReference createExactTrusted(ResolvedJavaType type) { 64 if (type == null) { 65 return null; 66 } 67 return new TypeReference(type, true); 68 } 69 70 /** 71 * Creates a type reference using the given type without assumptions and without trusting 72 * interface types. 73 */ 74 public static TypeReference createWithoutAssumptions(ResolvedJavaType type) { 75 return create(null, type); 76 } 77 78 /** 79 * Creates a type reference using the given type without assumptions and trusting interface 80 * types. 81 */ 82 public static TypeReference createTrustedWithoutAssumptions(ResolvedJavaType type) { 83 return createTrusted(null, type); 84 } 85 86 /** 87 * Creates a type reference using the given type with assumptions and without trusting interface 88 * types. 89 */ 90 public static TypeReference create(Assumptions assumptions, ResolvedJavaType type) { 91 return createTrusted(assumptions, filterInterfaceTypesOut(type)); 92 } 93 94 /** 95 * Create a type reference using the given type with assumptions and trusting interface types. 96 */ 97 public static TypeReference createTrusted(Assumptions assumptions, ResolvedJavaType type) { 98 if (type == null) { 99 return null; 100 } 101 ResolvedJavaType exactType = type.isLeaf() ? type : null; 102 if (exactType == null) { 103 Assumptions.AssumptionResult<ResolvedJavaType> leafConcreteSubtype = type.findLeafConcreteSubtype(); 104 if (leafConcreteSubtype != null && leafConcreteSubtype.canRecordTo(assumptions)) { 105 leafConcreteSubtype.recordTo(assumptions); 106 exactType = leafConcreteSubtype.getResult(); 107 } 108 } 109 if (exactType == null) { 110 return new TypeReference(type, false); 111 } 112 return new TypeReference(exactType, true); 113 } 114 115 /** 116 * The type this reference refers to. 117 */ 118 public ResolvedJavaType getType() { 119 return type; 120 } 121 122 /** 123 * @return {@code true} if this reference is exact and only refers to the given type and 124 * {@code false} if it also refers to its sub types. 125 */ 126 public boolean isExact() { 127 return exactReference; 128 } 129 130 /** 131 * @return A new reference that is guaranteed to be exact. 132 */ 133 public TypeReference asExactReference() { 134 if (isExact()) { 135 return this; 136 } 137 return new TypeReference(type, true); 138 } 139 140 private static ResolvedJavaType filterInterfaceTypesOut(ResolvedJavaType type) { 141 if (type != null) { 142 if (type.isArray()) { 143 ResolvedJavaType componentType = filterInterfaceTypesOut(type.getComponentType()); 144 if (componentType != null) { 145 return componentType.getArrayClass(); 146 } 147 // Returns Object[].class 148 return type.getSuperclass().getArrayClass(); 149 } 150 if (type.isInterface()) { 151 return null; 152 } 153 } 154 return type; 155 } 156 157 @Override 158 public String toString() { 159 return (isExact() ? "#" : "") + type; 160 } 161 }