Returns the required array type for an array load or store
instruction, based on a given implied type and an observed
actual array type.
The interesting cases here have to do with object arrays,
byte[]
s, boolean[]
s, and
known-nulls.
In the case of arrays of objects, we want to narrow the type
to the actual array present on the stack, as long as what is
present is an object type. Similarly, due to a quirk of the
original bytecode representation, the instructions for dealing
with byte[]
and boolean[]
are
undifferentiated, and we aim here to return whichever one was
actually present on the stack.
In the case where there is a known-null on the stack where
an array is expected, we just fall back to the implied type of
the instruction. Due to the quirk described above, this means
that source code that uses boolean[]
might get
translated surprisingly -- but correctly -- into an instruction
that specifies a byte[]
. It will be correct,
because should the code actually execute, it will necessarily
throw a NullPointerException
, and it won't matter
what opcode variant is used to achieve that result.
if (foundArrayType == Type.KNOWN_NULL) {
return impliedType.getArrayType();
}
if ((impliedType == Type.OBJECT)
&& foundArrayType.isArray()
&& foundArrayType.getComponentType().isReference()) {
return foundArrayType;
}
if ((impliedType == Type.BYTE)
&& (foundArrayType == Type.BOOLEAN_ARRAY)) {
/*
* Per above, an instruction with implied byte[] is also
* allowed to be used on boolean[].
*/
return Type.BOOLEAN_ARRAY;
}
return impliedType.getArrayType();