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