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 = holder.lookupType(unresolvedType, false);
 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 }