8312495: assert(0 <= i && i < _len) failed: illegal index after JDK-8287061 on big endian platforms

Reviewed-by: clanger, kvn, dlong
This commit is contained in:
Richard Reingruber 2023-07-27 13:40:23 +00:00
parent 486c7844f9
commit 8661b8e115
7 changed files with 74 additions and 80 deletions

View File

@ -242,7 +242,7 @@ void ObjectValue::print_fields_on(outputStream* st) const {
// of the object.
ObjectValue* ObjectMergeValue::select(frame& fr, RegisterMap& reg_map) {
StackValue* sv_selector = StackValue::create_stack_value(&fr, &reg_map, _selector);
jint selector = sv_selector->get_int();
jint selector = sv_selector->get_jint();
// If the selector is '-1' it means that execution followed the path
// where no scalar replacement happened.

View File

@ -331,9 +331,9 @@ objArrayHandle LiveFrameStream::values_to_object_array(StackValueCollection* val
int index = i;
#ifdef _LP64
if (type != T_OBJECT && type != T_CONFLICT) {
intptr_t ret = st->get_int(); // read full 64-bit slot
type = T_LONG; // treat as long
index--; // undo +1 in StackValueCollection::long_at
intptr_t ret = st->get_intptr(); // read full 64-bit slot
type = T_LONG; // treat as long
index--; // undo +1 in StackValueCollection::long_at
}
#endif
oop obj = create_primitive_slot_instance(values, index, type, CHECK_(empty));

View File

@ -1186,12 +1186,12 @@ oop Deoptimization::get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMa
if (box_type != T_OBJECT) {
StackValue* value = StackValue::create_stack_value(fr, reg_map, bv->field_at(box_type == T_LONG ? 1 : 0));
switch(box_type) {
case T_INT: return IntegerBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_CHAR: return CharacterBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_SHORT: return ShortBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_BYTE: return ByteBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_BOOLEAN: return BooleanBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_LONG: return LongBoxCache::singleton(THREAD)->lookup_raw(value->get_int(), cache_init_error);
case T_INT: return IntegerBoxCache::singleton(THREAD)->lookup_raw(value->get_intptr(), cache_init_error);
case T_CHAR: return CharacterBoxCache::singleton(THREAD)->lookup_raw(value->get_intptr(), cache_init_error);
case T_SHORT: return ShortBoxCache::singleton(THREAD)->lookup_raw(value->get_intptr(), cache_init_error);
case T_BYTE: return ByteBoxCache::singleton(THREAD)->lookup_raw(value->get_intptr(), cache_init_error);
case T_BOOLEAN: return BooleanBoxCache::singleton(THREAD)->lookup_raw(value->get_intptr(), cache_init_error);
case T_LONG: return LongBoxCache::singleton(THREAD)->lookup_raw(value->get_intptr(), cache_init_error);
default:;
}
}
@ -1313,19 +1313,19 @@ static jbyte* check_alignment_get_addr(typeArrayOop obj, int index, int expected
return res;
}
static void byte_array_put(typeArrayOop obj, intptr_t val, int index, int byte_count) {
static void byte_array_put(typeArrayOop obj, StackValue* value, int index, int byte_count) {
switch (byte_count) {
case 1:
obj->byte_at_put(index, (jbyte) *((jint *) &val));
obj->byte_at_put(index, (jbyte) value->get_jint());
break;
case 2:
*((jshort *) check_alignment_get_addr(obj, index, 2)) = (jshort) *((jint *) &val);
*((jshort *) check_alignment_get_addr(obj, index, 2)) = (jshort) value->get_jint();
break;
case 4:
*((jint *) check_alignment_get_addr(obj, index, 4)) = (jint) *((jint *) &val);
*((jint *) check_alignment_get_addr(obj, index, 4)) = value->get_jint();
break;
case 8:
*((jlong *) check_alignment_get_addr(obj, index, 8)) = (jlong) *((jlong *) &val);
*((jlong *) check_alignment_get_addr(obj, index, 8)) = (jlong) value->get_intptr();
break;
default:
ShouldNotReachHere();
@ -1337,7 +1337,6 @@ static void byte_array_put(typeArrayOop obj, intptr_t val, int index, int byte_c
// restore elements of an eliminated type array
void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type) {
int index = 0;
intptr_t val;
for (int i = 0; i < sv->field_size(); i++) {
StackValue* value = StackValue::create_stack_value(fr, reg_map, sv->field_at(i));
@ -1347,15 +1346,14 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma
StackValue* low =
StackValue::create_stack_value(fr, reg_map, sv->field_at(++i));
#ifdef _LP64
jlong res = (jlong)low->get_int();
jlong res = (jlong)low->get_intptr();
#else
jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
jlong res = jlong_from(value->get_jint(), low->get_jint());
#endif
obj->long_at_put(index, res);
break;
}
// Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
case T_INT: case T_FLOAT: { // 4 bytes.
assert(value->type() == T_INT, "Agreement.");
bool big_value = false;
@ -1376,53 +1374,48 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma
if (big_value) {
StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++i));
#ifdef _LP64
jlong res = (jlong)low->get_int();
jlong res = (jlong)low->get_intptr();
#else
jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
jlong res = jlong_from(value->get_jint(), low->get_jint());
#endif
obj->int_at_put(index, (jint)*((jint*)&res));
obj->int_at_put(++index, (jint)*(((jint*)&res) + 1));
obj->int_at_put(index, *(jint*)&res);
obj->int_at_put(++index, *((jint*)&res + 1));
} else {
val = value->get_int();
obj->int_at_put(index, (jint)*((jint*)&val));
obj->int_at_put(index, value->get_jint());
}
break;
}
case T_SHORT:
assert(value->type() == T_INT, "Agreement.");
val = value->get_int();
obj->short_at_put(index, (jshort)*((jint*)&val));
obj->short_at_put(index, (jshort)value->get_jint());
break;
case T_CHAR:
assert(value->type() == T_INT, "Agreement.");
val = value->get_int();
obj->char_at_put(index, (jchar)*((jint*)&val));
obj->char_at_put(index, (jchar)value->get_jint());
break;
case T_BYTE: {
assert(value->type() == T_INT, "Agreement.");
// The value we get is erased as a regular int. We will need to find its actual byte count 'by hand'.
val = value->get_int();
#if INCLUDE_JVMCI
// The value we get is erased as a regular int. We will need to find its actual byte count 'by hand'.
int byte_count = count_number_of_bytes_for_entry(sv, i);
byte_array_put(obj, val, index, byte_count);
byte_array_put(obj, value, index, byte_count);
// According to byte_count contract, the values from i + 1 to i + byte_count are illegal values. Skip.
i += byte_count - 1; // Balance the loop counter.
index += byte_count;
// index has been updated so continue at top of loop
continue;
#else
obj->byte_at_put(index, (jbyte)*((jint*)&val));
obj->byte_at_put(index, (jbyte)value->get_jint());
break;
#endif // INCLUDE_JVMCI
}
case T_BOOLEAN: {
assert(value->type() == T_INT, "Agreement.");
val = value->get_int();
obj->bool_at_put(index, (jboolean)*((jint*)&val));
obj->bool_at_put(index, (jboolean)value->get_jint());
break;
}
@ -1475,7 +1468,6 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
}
fields->sort(compare);
for (int i = 0; i < fields->length(); i++) {
intptr_t val;
ScopeValue* scope_field = sv->field_at(svIndex);
StackValue* value = StackValue::create_stack_value(fr, reg_map, scope_field);
int offset = fields->at(i)._offset;
@ -1486,7 +1478,6 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
obj->obj_field_put(offset, value->get_obj()());
break;
// Have to cast to INT (32 bits) pointer to avoid little/big-endian problem.
case T_INT: case T_FLOAT: { // 4 bytes.
assert(value->type() == T_INT, "Agreement.");
bool big_value = false;
@ -1510,8 +1501,7 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
assert(i < fields->length(), "second T_INT field needed");
assert(fields->at(i)._type == T_INT, "T_INT field needed");
} else {
val = value->get_int();
obj->int_field_put(offset, (jint)*((jint*)&val));
obj->int_field_put(offset, value->get_jint());
break;
}
}
@ -1521,9 +1511,9 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
assert(value->type() == T_INT, "Agreement.");
StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++svIndex));
#ifdef _LP64
jlong res = (jlong)low->get_int();
jlong res = (jlong)low->get_intptr();
#else
jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int());
jlong res = jlong_from(value->get_jint(), low->get_jint());
#endif
obj->long_field_put(offset, res);
break;
@ -1531,26 +1521,22 @@ static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap
case T_SHORT:
assert(value->type() == T_INT, "Agreement.");
val = value->get_int();
obj->short_field_put(offset, (jshort)*((jint*)&val));
obj->short_field_put(offset, (jshort)value->get_jint());
break;
case T_CHAR:
assert(value->type() == T_INT, "Agreement.");
val = value->get_int();
obj->char_field_put(offset, (jchar)*((jint*)&val));
obj->char_field_put(offset, (jchar)value->get_jint());
break;
case T_BYTE:
assert(value->type() == T_INT, "Agreement.");
val = value->get_int();
obj->byte_field_put(offset, (jbyte)*((jint*)&val));
obj->byte_field_put(offset, (jbyte)value->get_jint());
break;
case T_BOOLEAN:
assert(value->type() == T_INT, "Agreement.");
val = value->get_int();
obj->bool_field_put(offset, (jboolean)*((jint*)&val));
obj->bool_field_put(offset, (jboolean)value->get_jint());
break;
default:

View File

@ -79,22 +79,34 @@ class StackValue : public ResourceObj {
_handle_value = value;
}
intptr_t get_int() const {
intptr_t get_intptr() const {
assert(type() == T_INT, "type check");
return _integer_value;
}
// For special case in deopt.
intptr_t get_int(BasicType t) const {
intptr_t get_intptr(BasicType t) const {
assert(t == T_OBJECT && type() == T_OBJECT, "type check");
return _integer_value;
}
void set_int(intptr_t value) {
void set_intptr(intptr_t value) {
assert(type() == T_INT, "type check");
_integer_value = value;
}
// The jint value is always at offset 0 of the stack slot. On big endian platforms
// this is the location of the high word therefore we cannot just cast to jint.
jint get_jint() const {
assert(type() == T_INT, "type check");
return *(jint*)&_integer_value;
}
void set_jint(jint value) {
assert(type() == T_INT, "type check");
*(jint*)&_integer_value = value;
}
BasicType type() const { return _type; }
bool equal(StackValue *value) {

View File

@ -26,14 +26,12 @@
#include "runtime/stackValueCollection.hpp"
jint StackValueCollection::int_at(int slot) const {
intptr_t val = at(slot)->get_int();
jint ival = *((jint*) (&val));
return ival;
return at(slot)->get_jint();
}
jlong StackValueCollection::long_at(int slot) const {
#ifdef _LP64
return at(slot+1)->get_int();
return at(slot+1)->get_intptr();
#else
union {
jlong jl;
@ -41,8 +39,8 @@ jlong StackValueCollection::long_at(int slot) const {
} value;
// Interpreter stack is reversed in memory:
// low memory location is in higher java local slot.
value.array[0] = at(slot+1)->get_int();
value.array[1] = at(slot )->get_int();
value.array[0] = at(slot+1)->get_intptr();
value.array[1] = at(slot )->get_intptr();
return value.jl;
#endif
}
@ -52,13 +50,13 @@ Handle StackValueCollection::obj_at(int slot) const {
}
jfloat StackValueCollection::float_at(int slot) const {
intptr_t res = at(slot)->get_int();
intptr_t res = at(slot)->get_intptr();
return *((jfloat*) (&res));
}
jdouble StackValueCollection::double_at(int slot) const {
#ifdef _LP64
intptr_t res = at(slot+1)->get_int();
intptr_t res = at(slot+1)->get_intptr();
return *((jdouble*) (&res));
#else
union {
@ -67,21 +65,19 @@ jdouble StackValueCollection::double_at(int slot) const {
} value;
// Interpreter stack is reversed in memory:
// low memory location is in higher java local slot.
value.array[0] = at(slot+1)->get_int();
value.array[1] = at(slot )->get_int();
value.array[0] = at(slot+1)->get_intptr();
value.array[1] = at(slot )->get_intptr();
return value.jd;
#endif
}
void StackValueCollection::set_int_at(int slot, jint value) {
intptr_t val;
*((jint*) (&val)) = value;
at(slot)->set_int(val);
at(slot)->set_jint(value);
}
void StackValueCollection::set_long_at(int slot, jlong value) {
#ifdef _LP64
at(slot+1)->set_int(value);
at(slot+1)->set_intptr(value);
#else
union {
jlong jl;
@ -90,8 +86,8 @@ void StackValueCollection::set_long_at(int slot, jlong value) {
// Interpreter stack is reversed in memory:
// low memory location is in higher java local slot.
x.jl = value;
at(slot+1)->set_int(x.array[0]);
at(slot+0)->set_int(x.array[1]);
at(slot+1)->set_intptr(x.array[0]);
at(slot+0)->set_intptr(x.array[1]);
#endif
}
@ -108,15 +104,15 @@ void StackValueCollection::set_float_at(int slot, jfloat value) {
// Interpreter stores 32 bit floats in first half of 64 bit word.
val.array[0] = *(jint*)(&value);
val.array[1] = 0;
at(slot)->set_int(val.jd);
at(slot)->set_intptr(val.jd);
#else
at(slot)->set_int(*(jint*)(&value));
at(slot)->set_intptr(*(jint*)(&value));
#endif
}
void StackValueCollection::set_double_at(int slot, jdouble value) {
#ifdef _LP64
at(slot+1)->set_int(*(intptr_t*)(&value));
at(slot+1)->set_intptr(*(intptr_t*)(&value));
#else
union {
jdouble jd;
@ -125,8 +121,8 @@ void StackValueCollection::set_double_at(int slot, jdouble value) {
// Interpreter stack is reversed in memory:
// low memory location is in higher java local slot.
x.jd = value;
at(slot+1)->set_int(x.array[0]);
at(slot+0)->set_int(x.array[1]);
at(slot+1)->set_intptr(x.array[0]);
at(slot+0)->set_intptr(x.array[1]);
#endif
}

View File

@ -453,7 +453,7 @@ void interpretedVFrame::set_locals(StackValueCollection* values) const {
if (sv->type() == T_OBJECT) {
*(oop *) addr = (sv->get_obj())();
} else { // integer
*addr = sv->get_int();
*addr = sv->get_intptr();
}
}
}

View File

@ -133,7 +133,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
_locals->add( new StackValue());
break;
case T_INT:
_locals->add( new StackValue(value->get_int()));
_locals->add( new StackValue(value->get_intptr()));
break;
default:
ShouldNotReachHere();
@ -160,7 +160,7 @@ void vframeArrayElement::fill_in(compiledVFrame* vf, bool realloc_failures) {
_expressions->add( new StackValue());
break;
case T_INT:
_expressions->add( new StackValue(value->get_int()));
_expressions->add( new StackValue(value->get_intptr()));
break;
default:
ShouldNotReachHere();
@ -342,7 +342,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
assert(!is_bottom_frame || !(caller->is_compiled_caller() && addr >= caller->unextended_sp()), "overwriting caller frame!");
switch(value->type()) {
case T_INT:
*addr = value->get_int();
*addr = value->get_intptr();
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
tty->print_cr(" - Reconstructed expression %d (INT): %d", i, (int)(*addr));
@ -350,7 +350,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
#endif // !PRODUCT
break;
case T_OBJECT:
*addr = value->get_int(T_OBJECT);
*addr = value->get_intptr(T_OBJECT);
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
tty->print(" - Reconstructed expression %d (OBJECT): ", i);
@ -386,7 +386,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
assert(!is_bottom_frame || !(caller->is_compiled_caller() && addr >= caller->unextended_sp()), "overwriting caller frame!");
switch(value->type()) {
case T_INT:
*addr = value->get_int();
*addr = value->get_intptr();
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
tty->print_cr(" - Reconstructed local %d (INT): %d", i, (int)(*addr));
@ -394,7 +394,7 @@ void vframeArrayElement::unpack_on_stack(int caller_actual_parameters,
#endif // !PRODUCT
break;
case T_OBJECT:
*addr = value->get_int(T_OBJECT);
*addr = value->get_intptr(T_OBJECT);
#ifndef PRODUCT
if (PrintDeoptimizationDetails) {
tty->print(" - Reconstructed local %d (OBJECT): ", i);