8266973: Migrate to ClassHierarchyIterator when enumerating subclasses
Reviewed-by: kvn, coleenp
This commit is contained in:
parent
02507bc40d
commit
9d168e25d1
@ -1647,16 +1647,14 @@ bool Dependencies::is_concrete_method(Method* m, Klass* k) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Klass* Dependencies::find_finalizable_subclass(Klass* k) {
|
||||
if (k->is_interface()) return NULL;
|
||||
if (k->has_finalizer()) return k;
|
||||
k = k->subklass();
|
||||
while (k != NULL) {
|
||||
Klass* result = find_finalizable_subclass(k);
|
||||
if (result != NULL) return result;
|
||||
k = k->next_sibling();
|
||||
Klass* Dependencies::find_finalizable_subclass(InstanceKlass* ik) {
|
||||
for (ClassHierarchyIterator iter(ik); !iter.done(); iter.next()) {
|
||||
Klass* sub = iter.klass();
|
||||
if (sub->has_finalizer() && !sub->is_interface()) {
|
||||
return sub;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return NULL; // not found
|
||||
}
|
||||
|
||||
bool Dependencies::is_concrete_klass(ciInstanceKlass* k) {
|
||||
@ -1895,9 +1893,10 @@ Method* Dependencies::find_unique_concrete_method(InstanceKlass* ctxk, Method* m
|
||||
}
|
||||
|
||||
Klass* Dependencies::check_has_no_finalizable_subclasses(InstanceKlass* ctxk, NewKlassDepChange* changes) {
|
||||
Klass* search_at = ctxk;
|
||||
if (changes != NULL)
|
||||
InstanceKlass* search_at = ctxk;
|
||||
if (changes != NULL) {
|
||||
search_at = changes->new_type(); // just look at the new bit
|
||||
}
|
||||
return find_finalizable_subclass(search_at);
|
||||
}
|
||||
|
||||
|
@ -382,7 +382,7 @@ class Dependencies: public ResourceObj {
|
||||
// and abstract (as defined by the Java language and VM).
|
||||
static bool is_concrete_klass(Klass* k); // k is instantiable
|
||||
static bool is_concrete_method(Method* m, Klass* k); // m is invocable
|
||||
static Klass* find_finalizable_subclass(Klass* k);
|
||||
static Klass* find_finalizable_subclass(InstanceKlass* ik);
|
||||
|
||||
// These versions of the concreteness queries work through the CI.
|
||||
// The CI versions are allowed to skew sometimes from the VM
|
||||
|
@ -324,29 +324,12 @@ static bool is_classloader_klass_allowed(const Klass* k) {
|
||||
}
|
||||
|
||||
static void do_classloaders() {
|
||||
Stack<const Klass*, mtTracing> mark_stack;
|
||||
mark_stack.push(vmClasses::ClassLoader_klass()->subklass());
|
||||
|
||||
while (!mark_stack.is_empty()) {
|
||||
const Klass* const current = mark_stack.pop();
|
||||
assert(current != NULL, "null element in stack!");
|
||||
if (is_classloader_klass_allowed(current)) {
|
||||
do_loader_klass(current);
|
||||
}
|
||||
|
||||
// subclass (depth)
|
||||
const Klass* next_klass = current->subklass();
|
||||
if (next_klass != NULL) {
|
||||
mark_stack.push(next_klass);
|
||||
}
|
||||
|
||||
// siblings (breadth)
|
||||
next_klass = current->next_sibling();
|
||||
if (next_klass != NULL) {
|
||||
mark_stack.push(next_klass);
|
||||
for (ClassHierarchyIterator iter(vmClasses::ClassLoader_klass()); !iter.done(); iter.next()) {
|
||||
Klass* subk = iter.klass();
|
||||
if (is_classloader_klass_allowed(subk)) {
|
||||
do_loader_klass(subk);
|
||||
}
|
||||
}
|
||||
assert(mark_stack.is_empty(), "invariant");
|
||||
}
|
||||
|
||||
static int primitives_count = 9;
|
||||
|
@ -76,35 +76,17 @@ static bool is_allowed(const Klass* k) {
|
||||
return !(k->is_abstract() || k->should_be_initialized());
|
||||
}
|
||||
|
||||
static void fill_klasses(GrowableArray<const void*>& event_subklasses, const Klass* event_klass, JavaThread* thread) {
|
||||
static void fill_klasses(GrowableArray<const void*>& event_subklasses, const InstanceKlass* event_klass, JavaThread* thread) {
|
||||
assert(event_subklasses.length() == 0, "invariant");
|
||||
assert(event_klass != NULL, "invariant");
|
||||
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(thread));
|
||||
|
||||
Stack<const Klass*, mtTracing> mark_stack;
|
||||
mark_stack.push(event_klass->subklass());
|
||||
|
||||
while (!mark_stack.is_empty()) {
|
||||
const Klass* const current = mark_stack.pop();
|
||||
assert(current != NULL, "null element in stack!");
|
||||
|
||||
if (is_allowed(current)) {
|
||||
event_subklasses.append(current);
|
||||
}
|
||||
|
||||
// subclass (depth)
|
||||
const Klass* next_klass = current->subklass();
|
||||
if (next_klass != NULL) {
|
||||
mark_stack.push(next_klass);
|
||||
}
|
||||
|
||||
// siblings (breadth)
|
||||
next_klass = current->next_sibling();
|
||||
if (next_klass != NULL) {
|
||||
mark_stack.push(next_klass);
|
||||
for (ClassHierarchyIterator iter(const_cast<InstanceKlass*>(event_klass)); !iter.done(); iter.next()) {
|
||||
Klass* subk = iter.klass();
|
||||
if (is_allowed(subk)) {
|
||||
event_subklasses.append(subk);
|
||||
}
|
||||
}
|
||||
assert(mark_stack.is_empty(), "invariant");
|
||||
}
|
||||
|
||||
static void transform_klasses_to_local_jni_handles(GrowableArray<const void*>& event_subklasses, JavaThread* thread) {
|
||||
@ -132,6 +114,7 @@ jobject JdkJfrEvent::get_all_klasses(TRAPS) {
|
||||
|
||||
const Klass* const klass = SystemDictionary::resolve_or_null(event_klass_name, THREAD);
|
||||
assert(klass != NULL, "invariant");
|
||||
assert(klass->is_instance_klass(), "invariant");
|
||||
assert(JdkJfrEvent::is(klass), "invariant");
|
||||
|
||||
if (klass->subklass() == NULL) {
|
||||
@ -140,7 +123,7 @@ jobject JdkJfrEvent::get_all_klasses(TRAPS) {
|
||||
|
||||
ResourceMark rm(THREAD);
|
||||
GrowableArray<const void*> event_subklasses(initial_array_size);
|
||||
fill_klasses(event_subklasses, klass, THREAD);
|
||||
fill_klasses(event_subklasses, InstanceKlass::cast(klass), THREAD);
|
||||
|
||||
if (event_subklasses.is_empty()) {
|
||||
return empty_java_util_arraylist;
|
||||
|
@ -827,7 +827,11 @@ C2V_END
|
||||
C2V_VMENTRY_0(jboolean, hasFinalizableSubclass,(JNIEnv* env, jobject, jobject jvmci_type))
|
||||
Klass* klass = JVMCIENV->asKlass(jvmci_type);
|
||||
assert(klass != NULL, "method must not be called for primitive types");
|
||||
return Dependencies::find_finalizable_subclass(klass) != NULL;
|
||||
if (!klass->is_instance_klass()) {
|
||||
return false;
|
||||
}
|
||||
InstanceKlass* iklass = InstanceKlass::cast(klass);
|
||||
return Dependencies::find_finalizable_subclass(iklass) != NULL;
|
||||
C2V_END
|
||||
|
||||
C2V_VMENTRY_NULL(jobject, getClassInitializer, (JNIEnv* env, jobject, jobject jvmci_type))
|
||||
|
@ -514,24 +514,14 @@ oop Universe::swap_reference_pending_list(oop list) {
|
||||
#undef assert_pll_locked
|
||||
#undef assert_pll_ownership
|
||||
|
||||
static void reinitialize_vtable_of(Klass* ko) {
|
||||
// init vtable of k and all subclasses
|
||||
ko->vtable().initialize_vtable();
|
||||
if (ko->is_instance_klass()) {
|
||||
for (Klass* sk = ko->subklass();
|
||||
sk != NULL;
|
||||
sk = sk->next_sibling()) {
|
||||
reinitialize_vtable_of(sk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void reinitialize_vtables() {
|
||||
// The vtables are initialized by starting at java.lang.Object and
|
||||
// initializing through the subclass links, so that the super
|
||||
// classes are always initialized first.
|
||||
Klass* ok = vmClasses::Object_klass();
|
||||
reinitialize_vtable_of(ok);
|
||||
for (ClassHierarchyIterator iter(vmClasses::Object_klass()); !iter.done(); iter.next()) {
|
||||
Klass* sub = iter.klass();
|
||||
sub->vtable().initialize_vtable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1406,7 +1406,6 @@ class ClassHierarchyIterator : public StackObj {
|
||||
|
||||
public:
|
||||
ClassHierarchyIterator(InstanceKlass* root) : _root(root), _current(root), _visit_subclasses(true) {
|
||||
assert(!root->is_interface(), "no subclasses");
|
||||
assert(_root == _current, "required"); // initial state
|
||||
}
|
||||
|
||||
|
@ -4420,7 +4420,7 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas
|
||||
the_class->oop_map_cache()->flush_obsolete_entries();
|
||||
}
|
||||
|
||||
increment_class_counter((InstanceKlass *)the_class);
|
||||
increment_class_counter(the_class);
|
||||
|
||||
if (EventClassRedefinition::is_enabled()) {
|
||||
EventClassRedefinition event;
|
||||
@ -4449,24 +4449,20 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas
|
||||
|
||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||
// and in all direct and indirect subclasses.
|
||||
void VM_RedefineClasses::increment_class_counter(InstanceKlass *ik) {
|
||||
oop class_mirror = ik->java_mirror();
|
||||
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
|
||||
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
|
||||
java_lang_Class::set_classRedefinedCount(class_mirror, new_count);
|
||||
void VM_RedefineClasses::increment_class_counter(InstanceKlass* ik) {
|
||||
for (ClassHierarchyIterator iter(ik); !iter.done(); iter.next()) {
|
||||
// Only update instanceKlasses
|
||||
Klass* sub = iter.klass();
|
||||
if (sub->is_instance_klass()) {
|
||||
oop class_mirror = InstanceKlass::cast(sub)->java_mirror();
|
||||
Klass* class_oop = java_lang_Class::as_Klass(class_mirror);
|
||||
int new_count = java_lang_Class::classRedefinedCount(class_mirror) + 1;
|
||||
java_lang_Class::set_classRedefinedCount(class_mirror, new_count);
|
||||
|
||||
if (class_oop != _the_class) {
|
||||
// _the_class count is printed at end of redefine_single_class()
|
||||
log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count);
|
||||
}
|
||||
|
||||
for (Klass *subk = ik->subklass(); subk != NULL;
|
||||
subk = subk->next_sibling()) {
|
||||
if (subk->is_instance_klass()) {
|
||||
// Only update instanceKlasses
|
||||
InstanceKlass *subik = InstanceKlass::cast(subk);
|
||||
// recursively do subclasses of the current subclass
|
||||
increment_class_counter(subik);
|
||||
if (class_oop != _the_class) {
|
||||
// _the_class count is printed at end of redefine_single_class()
|
||||
log_debug(redefine, class, subclass)("updated count in subclass=%s to %d", ik->external_name(), new_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ class VM_RedefineClasses: public VM_Operation {
|
||||
|
||||
// Increment the classRedefinedCount field in the specific InstanceKlass
|
||||
// and in all direct and indirect subclasses.
|
||||
void increment_class_counter(InstanceKlass *ik);
|
||||
void increment_class_counter(InstanceKlass* ik);
|
||||
|
||||
// Support for constant pool merging (these routines are in alpha order):
|
||||
void append_entry(const constantPoolHandle& scratch_cp, int scratch_i,
|
||||
|
Loading…
x
Reference in New Issue
Block a user