mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8006542: JSR 292: the VM_RedefineClasses::append_entry() must support invokedynamic entry kinds
Need a support for invokedynamic entry kinds when new and old constant pools are merged. Reviewed-by: coleenp, twisti
This commit is contained in:
parent
733d5fdd65
commit
823c749bd1
2 changed files with 110 additions and 131 deletions
|
@ -278,76 +278,23 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp,
|
|||
case JVM_CONSTANT_NameAndType:
|
||||
{
|
||||
int name_ref_i = scratch_cp->name_ref_index_at(scratch_i);
|
||||
int new_name_ref_i = 0;
|
||||
bool match = (name_ref_i < *merge_cp_length_p) &&
|
||||
scratch_cp->compare_entry_to(name_ref_i, *merge_cp_p, name_ref_i,
|
||||
THREAD);
|
||||
if (!match) {
|
||||
// forward reference in *merge_cp_p or not a direct match
|
||||
|
||||
int found_i = scratch_cp->find_matching_entry(name_ref_i, *merge_cp_p,
|
||||
THREAD);
|
||||
if (found_i != 0) {
|
||||
guarantee(found_i != name_ref_i,
|
||||
"compare_entry_to() and find_matching_entry() do not agree");
|
||||
|
||||
// Found a matching entry somewhere else in *merge_cp_p so
|
||||
// just need a mapping entry.
|
||||
new_name_ref_i = found_i;
|
||||
map_index(scratch_cp, name_ref_i, found_i);
|
||||
} else {
|
||||
// no match found so we have to append this entry to *merge_cp_p
|
||||
append_entry(scratch_cp, name_ref_i, merge_cp_p, merge_cp_length_p,
|
||||
THREAD);
|
||||
// The above call to append_entry() can only append one entry
|
||||
// so the post call query of *merge_cp_length_p is only for
|
||||
// the sake of consistency.
|
||||
new_name_ref_i = *merge_cp_length_p - 1;
|
||||
}
|
||||
}
|
||||
int new_name_ref_i = find_or_append_indirect_entry(scratch_cp, name_ref_i, merge_cp_p,
|
||||
merge_cp_length_p, THREAD);
|
||||
|
||||
int signature_ref_i = scratch_cp->signature_ref_index_at(scratch_i);
|
||||
int new_signature_ref_i = 0;
|
||||
match = (signature_ref_i < *merge_cp_length_p) &&
|
||||
scratch_cp->compare_entry_to(signature_ref_i, *merge_cp_p,
|
||||
signature_ref_i, THREAD);
|
||||
if (!match) {
|
||||
// forward reference in *merge_cp_p or not a direct match
|
||||
|
||||
int found_i = scratch_cp->find_matching_entry(signature_ref_i,
|
||||
*merge_cp_p, THREAD);
|
||||
if (found_i != 0) {
|
||||
guarantee(found_i != signature_ref_i,
|
||||
"compare_entry_to() and find_matching_entry() do not agree");
|
||||
|
||||
// Found a matching entry somewhere else in *merge_cp_p so
|
||||
// just need a mapping entry.
|
||||
new_signature_ref_i = found_i;
|
||||
map_index(scratch_cp, signature_ref_i, found_i);
|
||||
} else {
|
||||
// no match found so we have to append this entry to *merge_cp_p
|
||||
append_entry(scratch_cp, signature_ref_i, merge_cp_p,
|
||||
merge_cp_length_p, THREAD);
|
||||
// The above call to append_entry() can only append one entry
|
||||
// so the post call query of *merge_cp_length_p is only for
|
||||
// the sake of consistency.
|
||||
new_signature_ref_i = *merge_cp_length_p - 1;
|
||||
}
|
||||
}
|
||||
int new_signature_ref_i = find_or_append_indirect_entry(scratch_cp, signature_ref_i,
|
||||
merge_cp_p, merge_cp_length_p,
|
||||
THREAD);
|
||||
|
||||
// If the referenced entries already exist in *merge_cp_p, then
|
||||
// both new_name_ref_i and new_signature_ref_i will both be 0.
|
||||
// In that case, all we are appending is the current entry.
|
||||
if (new_name_ref_i == 0) {
|
||||
new_name_ref_i = name_ref_i;
|
||||
} else {
|
||||
if (new_name_ref_i != name_ref_i) {
|
||||
RC_TRACE(0x00080000,
|
||||
("NameAndType entry@%d name_ref_index change: %d to %d",
|
||||
*merge_cp_length_p, name_ref_i, new_name_ref_i));
|
||||
}
|
||||
if (new_signature_ref_i == 0) {
|
||||
new_signature_ref_i = signature_ref_i;
|
||||
} else {
|
||||
if (new_signature_ref_i != signature_ref_i) {
|
||||
RC_TRACE(0x00080000,
|
||||
("NameAndType entry@%d signature_ref_index change: %d to %d",
|
||||
*merge_cp_length_p, signature_ref_i, new_signature_ref_i));
|
||||
|
@ -369,76 +316,12 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp,
|
|||
case JVM_CONSTANT_Methodref:
|
||||
{
|
||||
int klass_ref_i = scratch_cp->uncached_klass_ref_index_at(scratch_i);
|
||||
int new_klass_ref_i = 0;
|
||||
bool match = (klass_ref_i < *merge_cp_length_p) &&
|
||||
scratch_cp->compare_entry_to(klass_ref_i, *merge_cp_p, klass_ref_i,
|
||||
THREAD);
|
||||
if (!match) {
|
||||
// forward reference in *merge_cp_p or not a direct match
|
||||
int new_klass_ref_i = find_or_append_indirect_entry(scratch_cp, klass_ref_i,
|
||||
merge_cp_p, merge_cp_length_p, THREAD);
|
||||
|
||||
int found_i = scratch_cp->find_matching_entry(klass_ref_i, *merge_cp_p,
|
||||
THREAD);
|
||||
if (found_i != 0) {
|
||||
guarantee(found_i != klass_ref_i,
|
||||
"compare_entry_to() and find_matching_entry() do not agree");
|
||||
|
||||
// Found a matching entry somewhere else in *merge_cp_p so
|
||||
// just need a mapping entry.
|
||||
new_klass_ref_i = found_i;
|
||||
map_index(scratch_cp, klass_ref_i, found_i);
|
||||
} else {
|
||||
// no match found so we have to append this entry to *merge_cp_p
|
||||
append_entry(scratch_cp, klass_ref_i, merge_cp_p, merge_cp_length_p,
|
||||
THREAD);
|
||||
// The above call to append_entry() can only append one entry
|
||||
// so the post call query of *merge_cp_length_p is only for
|
||||
// the sake of consistency. Without the optimization where we
|
||||
// use JVM_CONSTANT_UnresolvedClass, then up to two entries
|
||||
// could be appended.
|
||||
new_klass_ref_i = *merge_cp_length_p - 1;
|
||||
}
|
||||
}
|
||||
|
||||
int name_and_type_ref_i =
|
||||
scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
|
||||
int new_name_and_type_ref_i = 0;
|
||||
match = (name_and_type_ref_i < *merge_cp_length_p) &&
|
||||
scratch_cp->compare_entry_to(name_and_type_ref_i, *merge_cp_p,
|
||||
name_and_type_ref_i, THREAD);
|
||||
if (!match) {
|
||||
// forward reference in *merge_cp_p or not a direct match
|
||||
|
||||
int found_i = scratch_cp->find_matching_entry(name_and_type_ref_i,
|
||||
*merge_cp_p, THREAD);
|
||||
if (found_i != 0) {
|
||||
guarantee(found_i != name_and_type_ref_i,
|
||||
"compare_entry_to() and find_matching_entry() do not agree");
|
||||
|
||||
// Found a matching entry somewhere else in *merge_cp_p so
|
||||
// just need a mapping entry.
|
||||
new_name_and_type_ref_i = found_i;
|
||||
map_index(scratch_cp, name_and_type_ref_i, found_i);
|
||||
} else {
|
||||
// no match found so we have to append this entry to *merge_cp_p
|
||||
append_entry(scratch_cp, name_and_type_ref_i, merge_cp_p,
|
||||
merge_cp_length_p, THREAD);
|
||||
// The above call to append_entry() can append more than
|
||||
// one entry so the post call query of *merge_cp_length_p
|
||||
// is required in order to get the right index for the
|
||||
// JVM_CONSTANT_NameAndType entry.
|
||||
new_name_and_type_ref_i = *merge_cp_length_p - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// If the referenced entries already exist in *merge_cp_p, then
|
||||
// both new_klass_ref_i and new_name_and_type_ref_i will both be
|
||||
// 0. In that case, all we are appending is the current entry.
|
||||
if (new_klass_ref_i == 0) {
|
||||
new_klass_ref_i = klass_ref_i;
|
||||
}
|
||||
if (new_name_and_type_ref_i == 0) {
|
||||
new_name_and_type_ref_i = name_and_type_ref_i;
|
||||
}
|
||||
int name_and_type_ref_i = scratch_cp->uncached_name_and_type_ref_index_at(scratch_i);
|
||||
int new_name_and_type_ref_i = find_or_append_indirect_entry(scratch_cp, name_and_type_ref_i,
|
||||
merge_cp_p, merge_cp_length_p, THREAD);
|
||||
|
||||
const char *entry_name;
|
||||
switch (scratch_cp->tag_at(scratch_i).value()) {
|
||||
|
@ -481,6 +364,72 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp,
|
|||
(*merge_cp_length_p)++;
|
||||
} break;
|
||||
|
||||
// this is an indirect CP entry so it needs special handling
|
||||
case JVM_CONSTANT_MethodType:
|
||||
{
|
||||
int ref_i = scratch_cp->method_type_index_at(scratch_i);
|
||||
int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
|
||||
merge_cp_length_p, THREAD);
|
||||
if (new_ref_i != ref_i) {
|
||||
RC_TRACE(0x00080000,
|
||||
("MethodType entry@%d ref_index change: %d to %d",
|
||||
*merge_cp_length_p, ref_i, new_ref_i));
|
||||
}
|
||||
(*merge_cp_p)->method_type_index_at_put(*merge_cp_length_p, new_ref_i);
|
||||
if (scratch_i != *merge_cp_length_p) {
|
||||
// The new entry in *merge_cp_p is at a different index than
|
||||
// the new entry in scratch_cp so we need to map the index values.
|
||||
map_index(scratch_cp, scratch_i, *merge_cp_length_p);
|
||||
}
|
||||
(*merge_cp_length_p)++;
|
||||
} break;
|
||||
|
||||
// this is an indirect CP entry so it needs special handling
|
||||
case JVM_CONSTANT_MethodHandle:
|
||||
{
|
||||
int ref_kind = scratch_cp->method_handle_ref_kind_at(scratch_i);
|
||||
int ref_i = scratch_cp->method_handle_index_at(scratch_i);
|
||||
int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
|
||||
merge_cp_length_p, THREAD);
|
||||
if (new_ref_i != ref_i) {
|
||||
RC_TRACE(0x00080000,
|
||||
("MethodHandle entry@%d ref_index change: %d to %d",
|
||||
*merge_cp_length_p, ref_i, new_ref_i));
|
||||
}
|
||||
(*merge_cp_p)->method_handle_index_at_put(*merge_cp_length_p, ref_kind, new_ref_i);
|
||||
if (scratch_i != *merge_cp_length_p) {
|
||||
// The new entry in *merge_cp_p is at a different index than
|
||||
// the new entry in scratch_cp so we need to map the index values.
|
||||
map_index(scratch_cp, scratch_i, *merge_cp_length_p);
|
||||
}
|
||||
(*merge_cp_length_p)++;
|
||||
} break;
|
||||
|
||||
// this is an indirect CP entry so it needs special handling
|
||||
case JVM_CONSTANT_InvokeDynamic:
|
||||
{
|
||||
// TBD: cross-checks and possible extra appends into CP and bsm operands
|
||||
// are needed as well. This issue is tracked by a separate bug 8007037.
|
||||
int bss_idx = scratch_cp->invoke_dynamic_bootstrap_specifier_index(scratch_i);
|
||||
|
||||
int ref_i = scratch_cp->invoke_dynamic_name_and_type_ref_index_at(scratch_i);
|
||||
int new_ref_i = find_or_append_indirect_entry(scratch_cp, ref_i, merge_cp_p,
|
||||
merge_cp_length_p, THREAD);
|
||||
if (new_ref_i != ref_i) {
|
||||
RC_TRACE(0x00080000,
|
||||
("InvokeDynamic entry@%d name_and_type ref_index change: %d to %d",
|
||||
*merge_cp_length_p, ref_i, new_ref_i));
|
||||
}
|
||||
|
||||
(*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, bss_idx, new_ref_i);
|
||||
if (scratch_i != *merge_cp_length_p) {
|
||||
// The new entry in *merge_cp_p is at a different index than
|
||||
// the new entry in scratch_cp so we need to map the index values.
|
||||
map_index(scratch_cp, scratch_i, *merge_cp_length_p);
|
||||
}
|
||||
(*merge_cp_length_p)++;
|
||||
} break;
|
||||
|
||||
// At this stage, Class or UnresolvedClass could be here, but not
|
||||
// ClassIndex
|
||||
case JVM_CONSTANT_ClassIndex: // fall through
|
||||
|
@ -507,6 +456,35 @@ void VM_RedefineClasses::append_entry(constantPoolHandle scratch_cp,
|
|||
} // end append_entry()
|
||||
|
||||
|
||||
int VM_RedefineClasses::find_or_append_indirect_entry(constantPoolHandle scratch_cp,
|
||||
int ref_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p, TRAPS) {
|
||||
|
||||
int new_ref_i = ref_i;
|
||||
bool match = (ref_i < *merge_cp_length_p) &&
|
||||
scratch_cp->compare_entry_to(ref_i, *merge_cp_p, ref_i, THREAD);
|
||||
|
||||
if (!match) {
|
||||
// forward reference in *merge_cp_p or not a direct match
|
||||
int found_i = scratch_cp->find_matching_entry(ref_i, *merge_cp_p, THREAD);
|
||||
if (found_i != 0) {
|
||||
guarantee(found_i != ref_i, "compare_entry_to() and find_matching_entry() do not agree");
|
||||
// Found a matching entry somewhere else in *merge_cp_p so just need a mapping entry.
|
||||
new_ref_i = found_i;
|
||||
map_index(scratch_cp, ref_i, found_i);
|
||||
} else {
|
||||
// no match found so we have to append this entry to *merge_cp_p
|
||||
append_entry(scratch_cp, ref_i, merge_cp_p, merge_cp_length_p, THREAD);
|
||||
// The above call to append_entry() can only append one entry
|
||||
// so the post call query of *merge_cp_length_p is only for
|
||||
// the sake of consistency.
|
||||
new_ref_i = *merge_cp_length_p - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return new_ref_i;
|
||||
} // end find_or_append_indirect_entry()
|
||||
|
||||
|
||||
void VM_RedefineClasses::swap_all_method_annotations(int i, int j, instanceKlassHandle scratch_class, TRAPS) {
|
||||
AnnotationArray* save;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue