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