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