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