mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-19 10:34:38 +02:00
8231756: [JVMCI] need support for deoptimizing virtual byte arrays encoding non-byte primitives
Reviewed-by: kvn
This commit is contained in:
parent
430f8020fd
commit
12f8b52fb8
13 changed files with 332 additions and 72 deletions
|
@ -1032,6 +1032,80 @@ bool Deoptimization::realloc_objects(JavaThread* thread, frame* fr, RegisterMap*
|
|||
return failures;
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
/**
|
||||
* For primitive types whose kind gets "erased" at runtime (shorts become stack ints),
|
||||
* we need to somehow be able to recover the actual kind to be able to write the correct
|
||||
* amount of bytes.
|
||||
* For that purpose, this method assumes that, for an entry spanning n bytes at index i,
|
||||
* the entries at index n + 1 to n + i are 'markers'.
|
||||
* For example, if we were writing a short at index 4 of a byte array of size 8, the
|
||||
* expected form of the array would be:
|
||||
*
|
||||
* {b0, b1, b2, b3, INT, marker, b6, b7}
|
||||
*
|
||||
* Thus, in order to get back the size of the entry, we simply need to count the number
|
||||
* of marked entries
|
||||
*
|
||||
* @param virtualArray the virtualized byte array
|
||||
* @param i index of the virtual entry we are recovering
|
||||
* @return The number of bytes the entry spans
|
||||
*/
|
||||
static int count_number_of_bytes_for_entry(ObjectValue *virtualArray, int i) {
|
||||
int index = i;
|
||||
while (++index < virtualArray->field_size() &&
|
||||
virtualArray->field_at(index)->is_marker()) {}
|
||||
return index - i;
|
||||
}
|
||||
|
||||
/**
|
||||
* If there was a guarantee for byte array to always start aligned to a long, we could
|
||||
* do a simple check on the parity of the index. Unfortunately, that is not always the
|
||||
* case. Thus, we check alignment of the actual address we are writing to.
|
||||
* In the unlikely case index 0 is 5-aligned for example, it would then be possible to
|
||||
* write a long to index 3.
|
||||
*/
|
||||
static jbyte* check_alignment_get_addr(typeArrayOop obj, int index, int expected_alignment) {
|
||||
jbyte* res = obj->byte_at_addr(index);
|
||||
assert((((intptr_t) res) % expected_alignment) == 0, "Non-aligned write");
|
||||
return res;
|
||||
}
|
||||
|
||||
static void byte_array_put(typeArrayOop obj, intptr_t val, int index, int byte_count) {
|
||||
switch (byte_count) {
|
||||
case 1:
|
||||
obj->byte_at_put(index, (jbyte) *((jint *) &val));
|
||||
break;
|
||||
case 2:
|
||||
*((jshort *) check_alignment_get_addr(obj, index, 2)) = (jshort) *((jint *) &val);
|
||||
break;
|
||||
case 4:
|
||||
*((jint *) check_alignment_get_addr(obj, index, 4)) = (jint) *((jint *) &val);
|
||||
break;
|
||||
case 8: {
|
||||
#ifdef _LP64
|
||||
jlong res = (jlong) *((jlong *) &val);
|
||||
#else
|
||||
#ifdef SPARC
|
||||
// For SPARC we have to swap high and low words.
|
||||
jlong v = (jlong) *((jlong *) &val);
|
||||
jlong res = 0;
|
||||
res |= ((v & (jlong) 0xffffffff) << 32);
|
||||
res |= ((v >> 32) & (jlong) 0xffffffff);
|
||||
#else
|
||||
jlong res = (jlong) *((jlong *) &val);
|
||||
#endif // SPARC
|
||||
#endif
|
||||
*((jlong *) check_alignment_get_addr(obj, index, 8)) = res;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_JVMCI
|
||||
|
||||
|
||||
// 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;
|
||||
|
@ -1109,17 +1183,30 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma
|
|||
obj->char_at_put(index, (jchar)*((jint*)&val));
|
||||
break;
|
||||
|
||||
case T_BYTE:
|
||||
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
|
||||
int byte_count = count_number_of_bytes_for_entry(sv, i);
|
||||
byte_array_put(obj, val, 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));
|
||||
break;
|
||||
#endif // INCLUDE_JVMCI
|
||||
}
|
||||
|
||||
case T_BOOLEAN:
|
||||
case T_BOOLEAN: {
|
||||
assert(value->type() == T_INT, "Agreement.");
|
||||
val = value->get_int();
|
||||
obj->bool_at_put(index, (jboolean)*((jint*)&val));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
|
@ -1128,7 +1215,6 @@ void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_ma
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// restore fields of an eliminated object array
|
||||
void Deoptimization::reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj) {
|
||||
for (int i = 0; i < sv->field_size(); i++) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue