Mercurial > hg > graal-jvmci-8
comparison jvmci/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMemoryAccessProviderImpl.java @ 24111:8abcd8e1285d
missing checks in HotSpotMemoryAccessProviderImpl can cause VM assertions to fail (JDK-8177673)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Thu, 30 Mar 2017 21:18:43 +0200 |
parents | 66059526b021 |
children | c0b9eb2b6715 |
comparison
equal
deleted
inserted
replaced
24110:a8378ff1936d | 24111:8abcd8e1285d |
---|---|
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.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; | |
26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; | |
25 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; | 27 import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; |
28 | |
29 import java.lang.reflect.Array; | |
30 | |
26 import jdk.vm.ci.meta.Constant; | 31 import jdk.vm.ci.meta.Constant; |
27 import jdk.vm.ci.meta.JavaConstant; | 32 import jdk.vm.ci.meta.JavaConstant; |
28 import jdk.vm.ci.meta.JavaKind; | 33 import jdk.vm.ci.meta.JavaKind; |
29 import jdk.vm.ci.meta.MemoryAccessProvider; | 34 import jdk.vm.ci.meta.MemoryAccessProvider; |
35 import jdk.vm.ci.meta.MetaAccessProvider; | |
30 import jdk.vm.ci.meta.PrimitiveConstant; | 36 import jdk.vm.ci.meta.PrimitiveConstant; |
37 import jdk.vm.ci.meta.ResolvedJavaField; | |
38 import jdk.vm.ci.meta.ResolvedJavaType; | |
31 | 39 |
32 /** | 40 /** |
33 * HotSpot implementation of {@link MemoryAccessProvider}. | 41 * HotSpot implementation of {@link MemoryAccessProvider}. |
34 */ | 42 */ |
35 class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider { | 43 class HotSpotMemoryAccessProviderImpl implements HotSpotMemoryAccessProvider { |
38 | 46 |
39 HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntimeProvider runtime) { | 47 HotSpotMemoryAccessProviderImpl(HotSpotJVMCIRuntimeProvider runtime) { |
40 this.runtime = runtime; | 48 this.runtime = runtime; |
41 } | 49 } |
42 | 50 |
43 private static Object asObject(Constant base) { | 51 /** |
52 * Gets the object boxed by {@code base} that is about to have a value of kind {@code kind} read | |
53 * from it at the offset {@code displacement}. | |
54 * | |
55 * @param base constant value containing the base address for a pending read | |
56 * @return {@code null} if {@code base} does not box an object otherwise the object boxed in | |
57 * {@code base} | |
58 * @throws IllegalArgumentException if {@code base} boxes an object and the read address does | |
59 * not correspond to a field or element within the object | |
60 */ | |
61 private static Object asObject(MetaAccessProvider metaAccess, Constant base, JavaKind kind, long displacement) { | |
44 if (base instanceof HotSpotObjectConstantImpl) { | 62 if (base instanceof HotSpotObjectConstantImpl) { |
45 return ((HotSpotObjectConstantImpl) base).object(); | 63 HotSpotObjectConstantImpl constant = (HotSpotObjectConstantImpl) base; |
46 } else { | 64 HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType(); |
47 return null; | 65 Object object = constant.object(); |
48 } | 66 if (type.isArray()) { |
67 ResolvedJavaType componentType = type.getComponentType(); | |
68 JavaKind componentKind = componentType.getJavaKind(); | |
69 final int headerSize = getArrayBaseOffset(componentKind); | |
70 int sizeOfElement = getArrayIndexScale(componentKind); | |
71 int length = Array.getLength(object); | |
72 int index = (int) ((displacement - headerSize) / sizeOfElement); | |
73 if (displacement < headerSize || index >= length || ((displacement - headerSize) % sizeOfElement) != 0) { | |
74 throw new IllegalArgumentException("Unsafe array access: reading element of kind " + kind + | |
75 " at offset " + displacement + " (index ~ " + index + ") in " + | |
76 type.toJavaName() + " object of length " + length); | |
77 } | |
78 } else { | |
79 ResolvedJavaField field = type.findInstanceFieldWithOffset(displacement, kind); | |
80 if (field == null && object instanceof Class) { | |
81 HotSpotResolvedObjectTypeImpl staticFieldsHolder = (HotSpotResolvedObjectTypeImpl) metaAccess.lookupJavaType((Class<?>) object); | |
82 field = staticFieldsHolder.findStaticFieldWithOffset(displacement, kind); | |
83 } | |
84 if (field == null) { | |
85 throw new IllegalArgumentException("Unsafe object access: field not found for read of kind " + kind + | |
86 " at offset " + displacement + " in " + | |
87 type.toJavaName() + " object"); | |
88 } | |
89 } | |
90 return object; | |
91 } | |
92 return null; | |
49 } | 93 } |
50 | 94 |
51 private boolean isValidObjectFieldDisplacement(Constant base, long displacement) { | 95 private boolean isValidObjectFieldDisplacement(Constant base, long displacement) { |
52 if (base instanceof HotSpotMetaspaceConstant) { | 96 if (base instanceof HotSpotMetaspaceConstant) { |
53 MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); | 97 MetaspaceWrapperObject metaspaceObject = HotSpotMetaspaceConstantImpl.getMetaspaceObject(base); |
77 } | 121 } |
78 } | 122 } |
79 throw new IllegalArgumentException(String.valueOf(base)); | 123 throw new IllegalArgumentException(String.valueOf(base)); |
80 } | 124 } |
81 | 125 |
82 private static long readRawValue(Constant baseConstant, long displacement, int bits) { | 126 private static long readRawValue(MetaAccessProvider metaAccess, Constant baseConstant, long displacement, JavaKind kind, int bits) { |
83 Object base = asObject(baseConstant); | 127 Object base = asObject(metaAccess, baseConstant, kind, displacement); |
84 if (base != null) { | 128 if (base != null) { |
85 switch (bits) { | 129 switch (bits) { |
86 case Byte.SIZE: | 130 case Byte.SIZE: |
87 return UNSAFE.getByte(base, displacement); | 131 return UNSAFE.getByte(base, displacement); |
88 case Short.SIZE: | 132 case Short.SIZE: |
125 return true; | 169 return true; |
126 } | 170 } |
127 | 171 |
128 private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) { | 172 private Object readRawObject(Constant baseConstant, long initialDisplacement, boolean compressed) { |
129 long displacement = initialDisplacement; | 173 long displacement = initialDisplacement; |
130 | |
131 Object ret; | 174 Object ret; |
132 Object base = asObject(baseConstant); | 175 Object base = asObject(runtime.getHostJVMCIBackend().getMetaAccess(), baseConstant, JavaKind.Object, displacement); |
133 if (base == null) { | 176 if (base == null) { |
134 assert !compressed; | 177 assert !compressed; |
135 displacement += asRawPointer(baseConstant); | 178 displacement += asRawPointer(baseConstant); |
136 ret = runtime.getCompilerToVM().readUncompressedOop(displacement); | 179 ret = runtime.getCompilerToVM().readUncompressedOop(displacement); |
137 assert verifyReadRawObject(ret, baseConstant, initialDisplacement); | 180 assert verifyReadRawObject(ret, baseConstant, initialDisplacement); |
150 * @param displacement the displacement within the object in bytes | 193 * @param displacement the displacement within the object in bytes |
151 * @return the read value encapsulated in a {@link JavaConstant} object, or {@code null} if the | 194 * @return the read value encapsulated in a {@link JavaConstant} object, or {@code null} if the |
152 * value cannot be read. | 195 * value cannot be read. |
153 * @throws IllegalArgumentException if {@code kind} is {@code null}, {@link JavaKind#Void}, not | 196 * @throws IllegalArgumentException if {@code kind} is {@code null}, {@link JavaKind#Void}, not |
154 * {@link JavaKind#Object} or not {@linkplain JavaKind#isPrimitive() primitive} kind | 197 * {@link JavaKind#Object} or not {@linkplain JavaKind#isPrimitive() primitive} kind |
198 * or if {@code baseConstant} is a boxed object and the read address does not denote | |
199 * a field or element within the object | |
155 */ | 200 */ |
156 JavaConstant readUnsafeConstant(JavaKind kind, JavaConstant baseConstant, long displacement) { | 201 JavaConstant readUnsafeConstant(JavaKind kind, JavaConstant baseConstant, long displacement) { |
157 if (kind == null) { | 202 if (kind == null) { |
158 throw new IllegalArgumentException("null JavaKind"); | 203 throw new IllegalArgumentException("null JavaKind"); |
159 } | 204 } |
167 } | 212 } |
168 | 213 |
169 @Override | 214 @Override |
170 public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) { | 215 public JavaConstant readPrimitiveConstant(JavaKind kind, Constant baseConstant, long initialDisplacement, int bits) { |
171 try { | 216 try { |
172 long rawValue = readRawValue(baseConstant, initialDisplacement, bits); | 217 long rawValue = readRawValue(runtime.getHostJVMCIBackend().getMetaAccess(), baseConstant, initialDisplacement, kind, bits); |
173 switch (kind) { | 218 switch (kind) { |
174 case Boolean: | 219 case Boolean: |
175 return JavaConstant.forBoolean(rawValue != 0); | 220 return JavaConstant.forBoolean(rawValue != 0); |
176 case Byte: | 221 case Byte: |
177 return JavaConstant.forByte((byte) rawValue); | 222 return JavaConstant.forByte((byte) rawValue); |
188 case Double: | 233 case Double: |
189 return JavaConstant.forDouble(Double.longBitsToDouble(rawValue)); | 234 return JavaConstant.forDouble(Double.longBitsToDouble(rawValue)); |
190 default: | 235 default: |
191 throw new IllegalArgumentException("Unsupported kind: " + kind); | 236 throw new IllegalArgumentException("Unsupported kind: " + kind); |
192 } | 237 } |
193 } catch (NullPointerException e) { | 238 } catch (IllegalArgumentException | NullPointerException e) { |
194 return null; | 239 return null; |
195 } | 240 } |
196 } | 241 } |
197 | 242 |
198 @Override | 243 @Override |