1 /* 2 * Copyright (c) 2011, 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 package jdk.vm.ci.hotspot; 24 25 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; 26 27 import java.lang.annotation.Annotation; 28 import java.lang.reflect.Field; 29 30 import jdk.internal.vm.annotation.Stable; 31 import jdk.vm.ci.common.JVMCIError; 32 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; 33 import jdk.vm.ci.meta.JavaType; 34 import jdk.vm.ci.meta.LocationIdentity; 35 import jdk.vm.ci.meta.MetaAccessProvider; 36 import jdk.vm.ci.meta.ModifiersProvider; 37 import jdk.vm.ci.meta.ResolvedJavaField; 38 import jdk.vm.ci.meta.ResolvedJavaType; 39 40 /** 41 * Represents a field in a HotSpot type. 42 */ 43 class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField, HotSpotProxified { 44 45 private final HotSpotResolvedObjectTypeImpl holder; 46 private final String name; 47 private JavaType type; 48 private final int offset; 49 50 /** 51 * This value contains all flags as stored in the VM including internal ones. 52 */ 53 private final int modifiers; 54 private final LocationIdentity locationIdentity = new FieldLocationIdentity(this); 55 56 public static class FieldLocationIdentity extends LocationIdentity { 57 HotSpotResolvedJavaField inner; 58 59 FieldLocationIdentity(HotSpotResolvedJavaFieldImpl inner) { 60 this.inner = inner; 61 } 62 63 @Override 64 public boolean isImmutable() { 65 return false; 66 } 67 68 @Override 69 public boolean equals(Object obj) { 70 if (this == obj) { 71 return true; 72 } 73 if (obj instanceof FieldLocationIdentity) { 74 FieldLocationIdentity fieldLocationIdentity = (FieldLocationIdentity) obj; 75 return inner.equals(fieldLocationIdentity.inner); 76 77 } 78 return false; 79 } 80 81 @Override 82 public int hashCode() { 83 return inner.hashCode(); 84 } 85 86 @Override 87 public String toString() { 88 return inner.getName(); 89 } 90 } 91 92 HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) { 93 this.holder = holder; 94 this.name = name; 95 this.type = type; 96 assert offset != -1; 97 assert offset == (int) offset : "offset larger than int"; 98 this.offset = (int) offset; 99 this.modifiers = modifiers; 100 } 101 102 @Override 103 public boolean equals(Object obj) { 104 if (this == obj) { 105 return true; 106 } 107 if (obj instanceof HotSpotResolvedJavaField) { 108 HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj; 109 if (that.offset != this.offset || that.isStatic() != this.isStatic()) { 110 return false; 111 } else if (this.holder.equals(that.holder)) { 112 assert this.name.equals(that.name) && this.type.equals(that.type); 113 return true; 114 } 115 } 116 return false; 117 } 118 119 @Override 120 public int hashCode() { 121 return name.hashCode(); 122 } 123 124 @Override 125 public int getModifiers() { 126 return modifiers & ModifiersProvider.jvmFieldModifiers(); 127 } 128 129 @Override 130 public boolean isInternal() { 131 return (modifiers & config().jvmAccFieldInternal) != 0; 132 } 133 134 /** 135 * Determines if a given object contains this field. 136 * 137 * @return true iff this is a non-static field and its declaring class is assignable from 138 * {@code object}'s class 139 */ 140 public boolean isInObject(Object object) { 141 if (isStatic()) { 142 return false; 143 } 144 return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectTypeImpl.fromObjectClass(object.getClass())); 145 } 146 147 @Override 148 public HotSpotResolvedObjectTypeImpl getDeclaringClass() { 149 return holder; 150 } 151 152 @Override 153 public String getName() { 154 return name; 155 } 156 157 @Override 158 public JavaType getType() { 159 // Pull field into local variable to prevent a race causing 160 // a ClassCastException below 161 JavaType currentType = type; 162 if (currentType instanceof HotSpotUnresolvedJavaType) { 163 // Don't allow unresolved types to hang around forever 164 HotSpotUnresolvedJavaType unresolvedType = (HotSpotUnresolvedJavaType) currentType; 165 ResolvedJavaType resolved = unresolvedType.reresolve(holder); 166 if (resolved != null) { 167 type = resolved; 168 } 169 } 170 return type; 171 } 172 173 public int offset() { 174 return offset; 175 } 176 177 @Override 178 public String toString() { 179 return format("HotSpotField<%H.%n %t:") + offset + ">"; 180 } 181 182 @Override 183 public boolean isSynthetic() { 184 return (config().jvmAccSynthetic & modifiers) != 0; 185 } 186 187 /** 188 * Checks if this field has the {@link Stable} annotation. 189 * 190 * @return true if field has {@link Stable} annotation, false otherwise 191 */ 192 public boolean isStable() { 193 return (config().jvmAccFieldStable & modifiers) != 0; 194 } 195 196 @Override 197 public Annotation[] getAnnotations() { 198 Field javaField = toJava(); 199 if (javaField != null) { 200 return javaField.getAnnotations(); 201 } 202 return new Annotation[0]; 203 } 204 205 @Override 206 public Annotation[] getDeclaredAnnotations() { 207 Field javaField = toJava(); 208 if (javaField != null) { 209 return javaField.getDeclaredAnnotations(); 210 } 211 return new Annotation[0]; 212 } 213 214 @Override 215 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 216 Field javaField = toJava(); 217 if (javaField != null) { 218 return javaField.getAnnotation(annotationClass); 219 } 220 return null; 221 } 222 223 private Field toJavaCache; 224 225 private Field toJava() { 226 if (toJavaCache != null) { 227 return toJavaCache; 228 } 229 230 if (isInternal()) { 231 return null; 232 } 233 try { 234 return toJavaCache = holder.mirror().getDeclaredField(name); 235 } catch (NoSuchFieldException | NoClassDefFoundError e) { 236 return null; 237 } 238 } 239 240 public LocationIdentity getLocationIdentity() { 241 return locationIdentity; 242 } 243 }