6626217: Fixed loader constraint array handling
Loader constraints track array elements, not arrays themselves. Reviewed-by: dcubed, kevinw
This commit is contained in:
parent
d19aa4e217
commit
8101e71766
@ -375,30 +375,6 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
|
|||||||
return get_object(found_klass)->as_klass();
|
return get_object(found_klass)->as_klass();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we fail to find an array klass, look again for its element type.
|
|
||||||
// The element type may be available either locally or via constraints.
|
|
||||||
// In either case, if we can find the element type in the system dictionary,
|
|
||||||
// we must build an array type around it. The CI requires array klasses
|
|
||||||
// to be loaded if their element klasses are loaded, except when memory
|
|
||||||
// is exhausted.
|
|
||||||
if (sym->byte_at(0) == '[' &&
|
|
||||||
(sym->byte_at(1) == '[' || sym->byte_at(1) == 'L')) {
|
|
||||||
// We have an unloaded array.
|
|
||||||
// Build it on the fly if the element class exists.
|
|
||||||
symbolOop elem_sym = oopFactory::new_symbol(sym->as_utf8()+1,
|
|
||||||
sym->utf8_length()-1,
|
|
||||||
KILL_COMPILE_ON_FATAL_(fail_type));
|
|
||||||
// Get element ciKlass recursively.
|
|
||||||
ciKlass* elem_klass =
|
|
||||||
get_klass_by_name_impl(accessing_klass,
|
|
||||||
get_object(elem_sym)->as_symbol(),
|
|
||||||
require_local);
|
|
||||||
if (elem_klass != NULL && elem_klass->is_loaded()) {
|
|
||||||
// Now make an array for it
|
|
||||||
return ciObjArrayKlass::make_impl(elem_klass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require_local) return NULL;
|
if (require_local) return NULL;
|
||||||
// Not yet loaded into the VM, or not governed by loader constraints.
|
// Not yet loaded into the VM, or not governed by loader constraints.
|
||||||
// Make a CI representative for it.
|
// Make a CI representative for it.
|
||||||
|
@ -334,33 +334,6 @@ klassOop LoaderConstraintTable::find_constrained_klass(symbolHandle name,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
klassOop LoaderConstraintTable::find_constrained_elem_klass(symbolHandle name,
|
|
||||||
symbolHandle elem_name,
|
|
||||||
Handle loader,
|
|
||||||
TRAPS) {
|
|
||||||
LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
|
|
||||||
if (p != NULL) {
|
|
||||||
assert(p->klass() == NULL, "Expecting null array klass");
|
|
||||||
|
|
||||||
// The array name has a constraint, but it will not have a class. Check
|
|
||||||
// each loader for an associated elem
|
|
||||||
for (int i = 0; i < p->num_loaders(); i++) {
|
|
||||||
Handle no_protection_domain;
|
|
||||||
|
|
||||||
klassOop k = SystemDictionary::find(elem_name, p->loader(i), no_protection_domain, THREAD);
|
|
||||||
if (k != NULL) {
|
|
||||||
// Return the first elem klass found.
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No constraints, or else no klass loaded yet.
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LoaderConstraintTable::ensure_loader_constraint_capacity(
|
void LoaderConstraintTable::ensure_loader_constraint_capacity(
|
||||||
LoaderConstraintEntry *p,
|
LoaderConstraintEntry *p,
|
||||||
int nfree) {
|
int nfree) {
|
||||||
|
@ -66,9 +66,6 @@ public:
|
|||||||
// bool is_method, TRAPS)
|
// bool is_method, TRAPS)
|
||||||
|
|
||||||
klassOop find_constrained_klass(symbolHandle name, Handle loader);
|
klassOop find_constrained_klass(symbolHandle name, Handle loader);
|
||||||
klassOop find_constrained_elem_klass(symbolHandle name, symbolHandle elem_name,
|
|
||||||
Handle loader, TRAPS);
|
|
||||||
|
|
||||||
|
|
||||||
// Class loader constraints
|
// Class loader constraints
|
||||||
|
|
||||||
|
@ -2164,9 +2164,8 @@ klassOop SystemDictionary::find_constrained_instance_or_array_klass(
|
|||||||
// a loader constraint that would require this loader to return the
|
// a loader constraint that would require this loader to return the
|
||||||
// klass that is already loaded.
|
// klass that is already loaded.
|
||||||
if (FieldType::is_array(class_name())) {
|
if (FieldType::is_array(class_name())) {
|
||||||
// Array classes are hard because their klassOops are not kept in the
|
// For array classes, their klassOops are not kept in the
|
||||||
// constraint table. The array klass may be constrained, but the elem class
|
// constraint table. The element klassOops are.
|
||||||
// may not be.
|
|
||||||
jint dimension;
|
jint dimension;
|
||||||
symbolOop object_key;
|
symbolOop object_key;
|
||||||
BasicType t = FieldType::get_array_info(class_name(), &dimension,
|
BasicType t = FieldType::get_array_info(class_name(), &dimension,
|
||||||
@ -2176,8 +2175,9 @@ klassOop SystemDictionary::find_constrained_instance_or_array_klass(
|
|||||||
} else {
|
} else {
|
||||||
symbolHandle elem_name(THREAD, object_key);
|
symbolHandle elem_name(THREAD, object_key);
|
||||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||||
klass = constraints()->find_constrained_elem_klass(class_name, elem_name, class_loader, THREAD);
|
klass = constraints()->find_constrained_klass(elem_name, class_loader);
|
||||||
}
|
}
|
||||||
|
// If element class already loaded, allocate array klass
|
||||||
if (klass != NULL) {
|
if (klass != NULL) {
|
||||||
klass = Klass::cast(klass)->array_klass_or_null(dimension);
|
klass = Klass::cast(klass)->array_klass_or_null(dimension);
|
||||||
}
|
}
|
||||||
@ -2195,21 +2195,37 @@ bool SystemDictionary::add_loader_constraint(symbolHandle class_name,
|
|||||||
Handle class_loader1,
|
Handle class_loader1,
|
||||||
Handle class_loader2,
|
Handle class_loader2,
|
||||||
Thread* THREAD) {
|
Thread* THREAD) {
|
||||||
unsigned int d_hash1 = dictionary()->compute_hash(class_name, class_loader1);
|
symbolHandle constraint_name;
|
||||||
|
if (!FieldType::is_array(class_name())) {
|
||||||
|
constraint_name = class_name;
|
||||||
|
} else {
|
||||||
|
// For array classes, their klassOops are not kept in the
|
||||||
|
// constraint table. The element classes are.
|
||||||
|
jint dimension;
|
||||||
|
symbolOop object_key;
|
||||||
|
BasicType t = FieldType::get_array_info(class_name(), &dimension,
|
||||||
|
&object_key, CHECK_(false));
|
||||||
|
// primitive types always pass
|
||||||
|
if (t != T_OBJECT) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
constraint_name = symbolHandle(THREAD, object_key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsigned int d_hash1 = dictionary()->compute_hash(constraint_name, class_loader1);
|
||||||
int d_index1 = dictionary()->hash_to_index(d_hash1);
|
int d_index1 = dictionary()->hash_to_index(d_hash1);
|
||||||
|
|
||||||
unsigned int d_hash2 = dictionary()->compute_hash(class_name, class_loader2);
|
unsigned int d_hash2 = dictionary()->compute_hash(constraint_name, class_loader2);
|
||||||
int d_index2 = dictionary()->hash_to_index(d_hash2);
|
int d_index2 = dictionary()->hash_to_index(d_hash2);
|
||||||
|
|
||||||
{
|
{
|
||||||
MutexLocker mu_s(SystemDictionary_lock, THREAD);
|
MutexLocker mu_s(SystemDictionary_lock, THREAD);
|
||||||
|
|
||||||
// Better never do a GC while we're holding these oops
|
// Better never do a GC while we're holding these oops
|
||||||
No_Safepoint_Verifier nosafepoint;
|
No_Safepoint_Verifier nosafepoint;
|
||||||
|
|
||||||
klassOop klass1 = find_class(d_index1, d_hash1, class_name, class_loader1);
|
klassOop klass1 = find_class(d_index1, d_hash1, constraint_name, class_loader1);
|
||||||
klassOop klass2 = find_class(d_index2, d_hash2, class_name, class_loader2);
|
klassOop klass2 = find_class(d_index2, d_hash2, constraint_name, class_loader2);
|
||||||
return constraints()->add_entry(class_name, klass1, class_loader1,
|
return constraints()->add_entry(constraint_name, klass1, class_loader1,
|
||||||
klass2, class_loader2);
|
klass2, class_loader2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2287,6 +2303,7 @@ symbolOop SystemDictionary::find_resolution_error(constantPoolHandle pool, int w
|
|||||||
// Returns the name of the type that failed a loader constraint check, or
|
// Returns the name of the type that failed a loader constraint check, or
|
||||||
// NULL if no constraint failed. The returned C string needs cleaning up
|
// NULL if no constraint failed. The returned C string needs cleaning up
|
||||||
// with a ResourceMark in the caller. No exception except OOME is thrown.
|
// with a ResourceMark in the caller. No exception except OOME is thrown.
|
||||||
|
// Arrays are not added to the loader constraint table, their elements are.
|
||||||
char* SystemDictionary::check_signature_loaders(symbolHandle signature,
|
char* SystemDictionary::check_signature_loaders(symbolHandle signature,
|
||||||
Handle loader1, Handle loader2,
|
Handle loader1, Handle loader2,
|
||||||
bool is_method, TRAPS) {
|
bool is_method, TRAPS) {
|
||||||
|
Loading…
Reference in New Issue
Block a user