| /* |
| * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package jdk.vm.ci.hotspot; |
| |
| import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers; |
| import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; |
| |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.Field; |
| |
| import jdk.internal.vm.annotation.Stable; |
| import jdk.vm.ci.meta.JavaType; |
| import jdk.vm.ci.meta.ResolvedJavaType; |
| |
| /** |
| * Represents a field in a HotSpot type. |
| */ |
| class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { |
| |
| private final HotSpotResolvedObjectTypeImpl holder; |
| private final String name; |
| private JavaType type; |
| private final int offset; |
| |
| /** |
| * This value contains all flags as stored in the VM including internal ones. |
| */ |
| private final int modifiers; |
| |
| HotSpotResolvedJavaFieldImpl(HotSpotResolvedObjectTypeImpl holder, String name, JavaType type, long offset, int modifiers) { |
| this.holder = holder; |
| this.name = name; |
| this.type = type; |
| assert offset != -1; |
| assert offset == (int) offset : "offset larger than int"; |
| this.offset = (int) offset; |
| this.modifiers = modifiers; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj instanceof HotSpotResolvedJavaField) { |
| HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj; |
| if (that.offset != this.offset || that.isStatic() != this.isStatic()) { |
| return false; |
| } else if (this.holder.equals(that.holder)) { |
| assert this.name.equals(that.name) && this.type.equals(that.type); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return name.hashCode(); |
| } |
| |
| @Override |
| public int getModifiers() { |
| return modifiers & jvmFieldModifiers(); |
| } |
| |
| @Override |
| public boolean isInternal() { |
| return (modifiers & config().jvmAccFieldInternal) != 0; |
| } |
| |
| /** |
| * Determines if a given object contains this field. |
| * |
| * @return true iff this is a non-static field and its declaring class is assignable from |
| * {@code object}'s class |
| */ |
| public boolean isInObject(Object object) { |
| if (isStatic()) { |
| return false; |
| } |
| return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectTypeImpl.fromObjectClass(object.getClass())); |
| } |
| |
| @Override |
| public HotSpotResolvedObjectTypeImpl getDeclaringClass() { |
| return holder; |
| } |
| |
| @Override |
| public String getName() { |
| return name; |
| } |
| |
| @Override |
| public JavaType getType() { |
| // Pull field into local variable to prevent a race causing |
| // a ClassCastException below |
| JavaType currentType = type; |
| if (currentType instanceof HotSpotUnresolvedJavaType) { |
| // Don't allow unresolved types to hang around forever |
| HotSpotUnresolvedJavaType unresolvedType = (HotSpotUnresolvedJavaType) currentType; |
| ResolvedJavaType resolved = unresolvedType.reresolve(holder); |
| if (resolved != null) { |
| type = resolved; |
| } |
| } |
| return type; |
| } |
| |
| public int offset() { |
| return offset; |
| } |
| |
| @Override |
| public String toString() { |
| return format("HotSpotField<%H.%n %t:") + offset + ">"; |
| } |
| |
| @Override |
| public boolean isSynthetic() { |
| return (config().jvmAccSynthetic & modifiers) != 0; |
| } |
| |
| /** |
| * Checks if this field has the {@link Stable} annotation. |
| * |
| * @return true if field has {@link Stable} annotation, false otherwise |
| */ |
| public boolean isStable() { |
| return (config().jvmAccFieldStable & modifiers) != 0; |
| } |
| |
| @Override |
| public Annotation[] getAnnotations() { |
| Field javaField = toJava(); |
| if (javaField != null) { |
| return javaField.getAnnotations(); |
| } |
| return new Annotation[0]; |
| } |
| |
| @Override |
| public Annotation[] getDeclaredAnnotations() { |
| Field javaField = toJava(); |
| if (javaField != null) { |
| return javaField.getDeclaredAnnotations(); |
| } |
| return new Annotation[0]; |
| } |
| |
| @Override |
| public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
| Field javaField = toJava(); |
| if (javaField != null) { |
| return javaField.getAnnotation(annotationClass); |
| } |
| return null; |
| } |
| |
| private Field toJavaCache; |
| |
| private Field toJava() { |
| if (toJavaCache != null) { |
| return toJavaCache; |
| } |
| |
| if (isInternal()) { |
| return null; |
| } |
| try { |
| return toJavaCache = holder.mirror().getDeclaredField(name); |
| } catch (NoSuchFieldException | NoClassDefFoundError e) { |
| return null; |
| } |
| } |
| } |