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