@@ -254,6 +254,39 @@ public boolean isExact() {
254
254
return false ;
255
255
}
256
256
257
+ /**
258
+ * When dealing with arrays of primitives it's possible to store a larger value into a smaller
259
+ * component type array. For example a long value can be written into a byte array by storing
260
+ * the larger value in the first entry and storing {@code Illegal} in the slots whose value
261
+ * comes from the long value. So a long in a byte array would be a long value followed by 7
262
+ * {@code Illegal} values. That also means such a write much be treated as a group by arraycopy
263
+ * so reads and writes can't be performed in the middle of the illegal values.
264
+ * <p>
265
+ * So to ensure that an arraycopy properly treats these kinds of writes as group, it's
266
+ * sufficient to check that the first value is not {@code Illegal} and that the next value after
267
+ * the end is not {@code Illegal} since {@code Illegal} values only appear in the tail of these
268
+ * groups.
269
+ */
270
+ private static boolean ensureIllegalValuesCanBeRepresented (int length , int srcPos , int srcLength , int dstPos , int dstLength , VirtualObjectNode src , VirtualObjectNode dst , VirtualizerTool tool ) {
271
+ if (length <= 0 ) {
272
+ return true ;
273
+ }
274
+ // check source
275
+ ValueNode firstSrcEntry = tool .getEntry (src , srcPos );
276
+ ValueNode followingSrcEntry = srcPos + length < srcLength ? tool .getEntry (src , srcPos + length ) : null ;
277
+ if (firstSrcEntry .isIllegalConstant () || followingSrcEntry != null && followingSrcEntry .isIllegalConstant ()) {
278
+ return false ;
279
+ }
280
+
281
+ // check dst
282
+ ValueNode firstDstEntry = tool .getEntry (dst , dstPos );
283
+ ValueNode followingDstEntry = dstPos + length < dstLength ? tool .getEntry (dst , dstPos + length ) : null ;
284
+ if (firstDstEntry .isIllegalConstant () || followingDstEntry != null && followingDstEntry .isIllegalConstant ()) {
285
+ return false ;
286
+ }
287
+ return true ;
288
+ }
289
+
257
290
@ Override
258
291
public void virtualize (VirtualizerTool tool ) {
259
292
ValueNode sourcePosition = tool .getAlias (getSourcePosition ());
@@ -287,6 +320,9 @@ public void virtualize(VirtualizerTool tool) {
287
320
if (!checkEntryTypes (srcPosInt , len , srcVirtual , destVirtual .type ().getComponentType (), tool )) {
288
321
return ;
289
322
}
323
+ if (!ensureIllegalValuesCanBeRepresented (len , srcPosInt , srcVirtual .entryCount (), destPosInt , destVirtual .entryCount (), srcVirtual , destVirtual , tool )) {
324
+ return ;
325
+ }
290
326
if (srcVirtual == destVirtual && srcPosInt < destPosInt ) {
291
327
// must copy backwards to avoid losing elements
292
328
for (int i = len - 1 ; i >= 0 ; i --) {
0 commit comments