Skip to content

Commit

Permalink
8312495: assert(0 <= i && i < _len) failed: illegal index after JDK-8…
Browse files Browse the repository at this point in the history
…287061 on big endian platforms

Reviewed-by: clanger, kvn, dlong
  • Loading branch information
reinrich committed Jul 27, 2023
1 parent 486c784 commit 8661b8e
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 80 deletions.
2 changes: 1 addition & 1 deletion src/hotspot/share/code/debugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/share/prims/stackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
76 changes: 31 additions & 45 deletions src/hotspot/share/runtime/deoptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:;
}
}
Expand Down Expand Up @@ -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();
Expand All @@ -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));
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}
}
Expand All @@ -1521,36 +1511,32 @@ 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;
}

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:
Expand Down
18 changes: 15 additions & 3 deletions src/hotspot/share/runtime/stackValue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
38 changes: 17 additions & 21 deletions src/hotspot/share/runtime/stackValueCollection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,21 @@
#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;
jint array[2];
} 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
}
Expand All @@ -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 {
Expand All @@ -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;
Expand All @@ -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
}

Expand All @@ -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;
Expand All @@ -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
}

Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/runtime/vframe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
Expand Down

1 comment on commit 8661b8e

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.