1 /* 2 * Copyright (c) 2011, 2019, 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.HotSpotJVMCIRuntime.runtime; 26 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; 27 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; 28 import static jdk.internal.misc.Unsafe.ADDRESS_SIZE; 29 30 import java.lang.annotation.Annotation; 31 32 import jdk.internal.vm.annotation.Stable; 33 34 import jdk.vm.ci.meta.JavaConstant; 35 import jdk.vm.ci.meta.JavaType; 36 import jdk.vm.ci.meta.ResolvedJavaType; 37 import jdk.vm.ci.meta.UnresolvedJavaType; 38 39 /** 40 * Represents a field in a HotSpot type. 41 */ 42 class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { 43 44 private final HotSpotResolvedObjectTypeImpl holder; 45 private JavaType type; 46 47 /** 48 * Value of {@code fieldDescriptor::access_flags()}. 49 */ 50 private final int offset; 51 52 /** 53 * Value of {@code fieldDescriptor::index()}. 54 */ 55 private final short index; 56 57 /** 58 * This value contains all flags as stored in the VM including internal ones. 59 */ 60 private final int modifiers; 61 62 HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, JavaType type, long offset, int modifiers, int index) { 63 this.holder = holder; 64 this.type = type; 65 this.index = (short) index; 66 assert this.index == index; 67 assert offset != -1; 68 assert offset == (int) offset : "offset larger than int"; 69 this.offset = (int) offset; 70 this.modifiers = modifiers; 71 } 72 73 @Override 74 public boolean equals(Object obj) { 75 if (this == obj) { 76 return true; 77 } 78 if (obj instanceof HotSpotResolvedJavaFieldImpl) { 79 HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj; 80 if (that.offset != this.offset || that.isStatic() != this.isStatic()) { 81 return false; 82 } else if (this.holder.equals(that.holder)) { 83 return true; 84 } 85 } 86 return false; 87 } 88 89 @Override 90 public int hashCode() { 91 return holder.hashCode() ^ offset; 92 } 93 94 @Override 95 public int getModifiers() { 96 return modifiers & HotSpotModifiers.jvmFieldModifiers(); 97 } 98 99 @Override 100 public boolean isInternal() { 101 return (modifiers & config().jvmAccFieldInternal) != 0; 102 } 103 104 /** 105 * Determines if a given object contains this field. 106 * 107 * @return true iff this is a non-static field and its declaring class is assignable from 108 * {@code object}'s class 109 */ 110 @Override 111 public boolean isInObject(JavaConstant object) { 112 if (isStatic()) { 113 return false; 114 } 115 HotSpotObjectConstant constant = (HotSpotObjectConstant) object; 116 return getDeclaringClass().isAssignableFrom(constant.getType()); 117 } 118 119 @Override 120 public HotSpotResolvedObjectTypeImpl getDeclaringClass() { 121 return holder; 122 } 123 124 @Override 125 public String getName() { 126 return holder.createFieldInfo(index).getName(); 127 } 128 129 @Override 130 public JavaType getType() { 131 // Pull field into local variable to prevent a race causing 132 // a ClassCastException below 133 JavaType currentType = type; 134 if (currentType instanceof UnresolvedJavaType) { 135 // Don't allow unresolved types to hang around forever 136 UnresolvedJavaType unresolvedType = (UnresolvedJavaType) currentType; 137 JavaType resolved = HotSpotJVMCIRuntime.runtime().lookupType(unresolvedType.getName(), holder, false); 138 if (resolved instanceof ResolvedJavaType) { 139 type = resolved; 140 } 141 } 142 return type; 143 144 } 145 146 @Override 147 public int getOffset() { 148 return offset; 149 } 150 151 /** 152 * Gets the value of this field's index (i.e. {@code fieldDescriptor::index()} in the encoded 153 * fields of the declaring class. 154 */ 155 int getIndex() { 156 return index; 157 } 158 159 @Override 160 public String toString() { 161 return format("HotSpotResolvedJavaFieldImpl<%H.%n %t:") + offset + ">"; 162 } 163 164 @Override 165 public boolean isSynthetic() { 166 return (config().jvmAccSynthetic & modifiers) != 0; 167 } 168 169 /** 170 * Checks if this field has the {@link Stable} annotation. 171 * 172 * @return true if field has {@link Stable} annotation, false otherwise 173 */ 174 @Override 175 public boolean isStable() { 176 return (config().jvmAccFieldStable & modifiers) != 0; 177 } 178 179 private boolean hasAnnotations() { 180 if (!isInternal()) { 181 HotSpotVMConfig config = config(); 182 final long metaspaceAnnotations = UNSAFE.getAddress(holder.getMetaspaceKlass() + config.instanceKlassAnnotationsOffset); 183 if (metaspaceAnnotations != 0) { 184 long fieldsAnnotations = UNSAFE.getAddress(metaspaceAnnotations + config.annotationsFieldAnnotationsOffset); 185 if (fieldsAnnotations != 0) { 186 long fieldAnnotations = UNSAFE.getAddress(fieldsAnnotations + config.fieldsAnnotationsBaseOffset + (ADDRESS_SIZE * index)); 187 return fieldAnnotations != 0; 188 } 189 } 190 } 191 return false; 192 } 193 194 @Override 195 public Annotation[] getAnnotations() { 196 if (!hasAnnotations()) { 197 return new Annotation[0]; 198 } 199 return runtime().reflection.getFieldAnnotations(this); 200 } 201 202 @Override 203 public Annotation[] getDeclaredAnnotations() { 204 if (!hasAnnotations()) { 205 return new Annotation[0]; 206 } 207 return runtime().reflection.getFieldDeclaredAnnotations(this); 208 } 209 210 @Override 211 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 212 if (!hasAnnotations()) { 213 return null; 214 } 215 return runtime().reflection.getFieldAnnotation(this, annotationClass); 216 } 217 }