@@ -254,6 +254,39 @@ public boolean isExact() {
254254 return false ;
255255 }
256256
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+
257290 @ Override
258291 public void virtualize (VirtualizerTool tool ) {
259292 ValueNode sourcePosition = tool .getAlias (getSourcePosition ());
@@ -287,6 +320,9 @@ public void virtualize(VirtualizerTool tool) {
287320 if (!checkEntryTypes (srcPosInt , len , srcVirtual , destVirtual .type ().getComponentType (), tool )) {
288321 return ;
289322 }
323+ if (!ensureIllegalValuesCanBeRepresented (len , srcPosInt , srcVirtual .entryCount (), destPosInt , destVirtual .entryCount (), srcVirtual , destVirtual , tool )) {
324+ return ;
325+ }
290326 if (srcVirtual == destVirtual && srcPosInt < destPosInt ) {
291327 // must copy backwards to avoid losing elements
292328 for (int i = len - 1 ; i >= 0 ; i --) {
0 commit comments