Skip to content

Commit 3e26fd9

Browse files
TianminShialvdavi
authored andcommitted
8272014: Better array indexing
Reviewed-by: andrew
1 parent 7793e1a commit 3e26fd9

File tree

1 file changed

+26
-2
lines changed

1 file changed

+26
-2
lines changed

hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,32 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o
166166
LIR_Address* addr;
167167
if (index_opr->is_constant()) {
168168
int elem_size = type2aelembytes(type);
169-
addr = new LIR_Address(array_opr,
170-
offset_in_bytes + index_opr->as_jint() * elem_size, type);
169+
#ifdef _LP64
170+
jint index = index_opr->as_jint();
171+
jlong disp = offset_in_bytes + (jlong)(index) * elem_size;
172+
if (disp > max_jint) {
173+
// Displacement overflow. Cannot directly use instruction with 32-bit displacement for 64-bit addresses.
174+
// Convert array index to long to do array offset computation with 64-bit values.
175+
index_opr = new_register(T_LONG);
176+
__ move(LIR_OprFact::longConst(index), index_opr);
177+
addr = new LIR_Address(array_opr, index_opr, LIR_Address::scale(type), offset_in_bytes, type);
178+
} else {
179+
addr = new LIR_Address(array_opr, disp, type);
180+
}
181+
#else
182+
// A displacement overflow can also occur for x86 but that is not a problem due to the 32-bit address range!
183+
// Let's assume an array 'a' and an access with displacement 'disp'. When disp overflows, then "a + disp" will
184+
// always be negative (i.e. underflows the 32-bit address range):
185+
// Let N = 2^32: a + signed_overflow(disp) = a + disp - N.
186+
// "a + disp" is always smaller than N. If an index was chosen which would point to an address beyond N, then
187+
// range checks would catch that and throw an exception. Thus, a + disp < 0 holds which means that it always
188+
// underflows the 32-bit address range:
189+
// unsigned_underflow(a + signed_overflow(disp)) = unsigned_underflow(a + disp - N)
190+
// = (a + disp - N) + N = a + disp
191+
// This shows that we still end up at the correct address with a displacement overflow due to the 32-bit address
192+
// range limitation. This overflow only needs to be handled if addresses can be larger as on 64-bit platforms.
193+
addr = new LIR_Address(array_opr, offset_in_bytes + index_opr->as_jint() * elem_size, type);
194+
#endif // _LP64
171195
} else {
172196
#ifdef _LP64
173197
if (index_opr->type() == T_INT) {

0 commit comments

Comments
 (0)