@@ -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