1 /* |
1 /* |
2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
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 |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. |
7 * published by the Free Software Foundation. |
20 * or visit www.oracle.com if you need additional information or have any |
20 * or visit www.oracle.com if you need additional information or have any |
21 * questions. |
21 * questions. |
22 */ |
22 */ |
23 package jdk.vm.ci.hotspot; |
23 package jdk.vm.ci.hotspot; |
24 |
24 |
25 import static jdk.internal.misc.Unsafe.ADDRESS_SIZE; |
25 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; |
26 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; |
|
27 import static jdk.vm.ci.hotspot.HotSpotModifiers.jvmFieldModifiers; |
|
28 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; |
26 import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; |
29 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; |
27 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; |
|
28 import static jdk.internal.misc.Unsafe.ADDRESS_SIZE; |
30 |
29 |
31 import java.lang.annotation.Annotation; |
30 import java.lang.annotation.Annotation; |
32 import java.lang.reflect.Field; |
31 |
33 import java.util.HashMap; |
32 import jdk.internal.vm.annotation.Stable; |
34 |
33 |
35 import jdk.vm.ci.meta.JavaConstant; |
34 import jdk.vm.ci.meta.JavaConstant; |
36 import jdk.vm.ci.meta.JavaType; |
35 import jdk.vm.ci.meta.JavaType; |
37 import jdk.vm.ci.meta.ResolvedJavaType; |
36 import jdk.vm.ci.meta.ResolvedJavaType; |
38 import jdk.vm.ci.meta.UnresolvedJavaType; |
37 import jdk.vm.ci.meta.UnresolvedJavaType; |
42 */ |
41 */ |
43 class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { |
42 class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { |
44 |
43 |
45 private final HotSpotResolvedObjectTypeImpl holder; |
44 private final HotSpotResolvedObjectTypeImpl holder; |
46 private JavaType type; |
45 private JavaType type; |
|
46 |
|
47 /** |
|
48 * Value of {@code fieldDescriptor::access_flags()}. |
|
49 */ |
47 private final int offset; |
50 private final int offset; |
|
51 |
|
52 /** |
|
53 * Value of {@code fieldDescriptor::index()}. |
|
54 */ |
48 private final short index; |
55 private final short index; |
49 |
56 |
50 /** |
57 /** |
51 * This value contains all flags as stored in the VM including internal ones. |
58 * This value contains all flags as stored in the VM including internal ones. |
52 */ |
59 */ |
66 @Override |
73 @Override |
67 public boolean equals(Object obj) { |
74 public boolean equals(Object obj) { |
68 if (this == obj) { |
75 if (this == obj) { |
69 return true; |
76 return true; |
70 } |
77 } |
71 if (obj instanceof HotSpotResolvedJavaField) { |
78 if (obj instanceof HotSpotResolvedJavaFieldImpl) { |
72 HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj; |
79 HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj; |
73 if (that.offset != this.offset || that.isStatic() != this.isStatic()) { |
80 if (that.offset != this.offset || that.isStatic() != this.isStatic()) { |
74 return false; |
81 return false; |
75 } else if (this.holder.equals(that.holder)) { |
82 } else if (this.holder.equals(that.holder)) { |
76 return true; |
83 return true; |
84 return holder.hashCode() ^ offset; |
91 return holder.hashCode() ^ offset; |
85 } |
92 } |
86 |
93 |
87 @Override |
94 @Override |
88 public int getModifiers() { |
95 public int getModifiers() { |
89 return modifiers & jvmFieldModifiers(); |
96 return modifiers & HotSpotModifiers.jvmFieldModifiers(); |
90 } |
97 } |
91 |
98 |
92 @Override |
99 @Override |
93 public boolean isInternal() { |
100 public boolean isInternal() { |
94 return (modifiers & config().jvmAccFieldInternal) != 0; |
101 return (modifiers & config().jvmAccFieldInternal) != 0; |
99 * |
106 * |
100 * @return true iff this is a non-static field and its declaring class is assignable from |
107 * @return true iff this is a non-static field and its declaring class is assignable from |
101 * {@code object}'s class |
108 * {@code object}'s class |
102 */ |
109 */ |
103 @Override |
110 @Override |
104 public boolean isInObject(JavaConstant constant) { |
111 public boolean isInObject(JavaConstant object) { |
105 if (isStatic()) { |
112 if (isStatic()) { |
106 return false; |
113 return false; |
107 } |
114 } |
108 Object object = ((HotSpotObjectConstantImpl) constant).object(); |
115 HotSpotObjectConstant constant = (HotSpotObjectConstant) object; |
109 return getDeclaringClass().isAssignableFrom(HotSpotResolvedObjectTypeImpl.fromObjectClass(object.getClass())); |
116 return getDeclaringClass().isAssignableFrom(constant.getType()); |
110 } |
117 } |
111 |
118 |
112 @Override |
119 @Override |
113 public HotSpotResolvedObjectTypeImpl getDeclaringClass() { |
120 public HotSpotResolvedObjectTypeImpl getDeclaringClass() { |
114 return holder; |
121 return holder; |
125 // a ClassCastException below |
132 // a ClassCastException below |
126 JavaType currentType = type; |
133 JavaType currentType = type; |
127 if (currentType instanceof UnresolvedJavaType) { |
134 if (currentType instanceof UnresolvedJavaType) { |
128 // Don't allow unresolved types to hang around forever |
135 // Don't allow unresolved types to hang around forever |
129 UnresolvedJavaType unresolvedType = (UnresolvedJavaType) currentType; |
136 UnresolvedJavaType unresolvedType = (UnresolvedJavaType) currentType; |
130 ResolvedJavaType resolved = holder.lookupType(unresolvedType, false); |
137 JavaType resolved = HotSpotJVMCIRuntime.runtime().lookupType(unresolvedType.getName(), holder, false); |
131 if (resolved != null) { |
138 if (resolved instanceof ResolvedJavaType) { |
132 type = resolved; |
139 type = resolved; |
133 } |
140 } |
134 } |
141 } |
135 return type; |
142 return type; |
|
143 |
136 } |
144 } |
137 |
145 |
138 @Override |
146 @Override |
139 public int getOffset() { |
147 public int getOffset() { |
140 return offset; |
148 return offset; |
141 } |
149 } |
142 |
150 |
|
151 /** |
|
152 * Gets the value of this field's index (i.e. {@code fieldDescriptor::index()} in the encoded |
|
153 * fields of the declaring class. |
|
154 */ |
|
155 int getIndex() { |
|
156 return index; |
|
157 } |
|
158 |
143 @Override |
159 @Override |
144 public String toString() { |
160 public String toString() { |
145 return format("HotSpotField<%H.%n %t:") + offset + ">"; |
161 return format("HotSpotResolvedJavaFieldImpl<%H.%n %t:") + offset + ">"; |
146 } |
162 } |
147 |
163 |
148 @Override |
164 @Override |
149 public boolean isSynthetic() { |
165 public boolean isSynthetic() { |
150 return (config().jvmAccSynthetic & modifiers) != 0; |
166 return (config().jvmAccSynthetic & modifiers) != 0; |
151 } |
167 } |
152 |
168 |
153 /** |
169 /** |
154 * Checks if this field has the {@code Stable} annotation. |
170 * Checks if this field has the {@link Stable} annotation. |
155 * |
171 * |
156 * @return true if field has {@code Stable} annotation, false otherwise |
172 * @return true if field has {@link Stable} annotation, false otherwise |
157 */ |
173 */ |
158 @Override |
174 @Override |
159 public boolean isStable() { |
175 public boolean isStable() { |
160 return (config().jvmAccFieldStable & modifiers) != 0; |
176 return (config().jvmAccFieldStable & modifiers) != 0; |
161 } |
177 } |
178 @Override |
194 @Override |
179 public Annotation[] getAnnotations() { |
195 public Annotation[] getAnnotations() { |
180 if (!hasAnnotations()) { |
196 if (!hasAnnotations()) { |
181 return new Annotation[0]; |
197 return new Annotation[0]; |
182 } |
198 } |
183 return toJava().getAnnotations(); |
199 return runtime().reflection.getFieldAnnotations(this); |
184 } |
200 } |
185 |
201 |
186 @Override |
202 @Override |
187 public Annotation[] getDeclaredAnnotations() { |
203 public Annotation[] getDeclaredAnnotations() { |
188 if (!hasAnnotations()) { |
204 if (!hasAnnotations()) { |
189 return new Annotation[0]; |
205 return new Annotation[0]; |
190 } |
206 } |
191 return toJava().getDeclaredAnnotations(); |
207 return runtime().reflection.getFieldDeclaredAnnotations(this); |
192 } |
208 } |
193 |
209 |
194 @Override |
210 @Override |
195 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
211 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
196 if (!hasAnnotations()) { |
212 if (!hasAnnotations()) { |
197 return null; |
213 return null; |
198 } |
214 } |
199 return toJava().getAnnotation(annotationClass); |
215 return runtime().reflection.getFieldAnnotation(this, annotationClass); |
200 } |
|
201 |
|
202 /** |
|
203 * Gets a {@link Field} object corresponding to this object. This method always returns the same |
|
204 * {@link Field} object for a given {@link HotSpotResolvedJavaFieldImpl}. This ensures |
|
205 * {@link #getDeclaredAnnotations()}, {@link #getAnnotations()} and |
|
206 * {@link #getAnnotation(Class)} are stable with respect to the identity of the |
|
207 * {@link Annotation} objects they return. |
|
208 */ |
|
209 private Field toJava() { |
|
210 synchronized (holder) { |
|
211 HashMap<HotSpotResolvedJavaFieldImpl, Field> cache = holder.reflectionFieldCache; |
|
212 if (cache == null) { |
|
213 cache = new HashMap<>(); |
|
214 holder.reflectionFieldCache = cache; |
|
215 } |
|
216 Field reflect = cache.get(this); |
|
217 if (reflect == null) { |
|
218 reflect = compilerToVM().asReflectionField(holder, index); |
|
219 cache.put(this, reflect); |
|
220 } |
|
221 return reflect; |
|
222 } |
|
223 } |
216 } |
224 } |
217 } |