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