Skip to content
Permalink
Browse files
8262028: Make InstanceKlass::implementor return InstanceKlass
Reviewed-by: coleenp, ccheung, vlivanov
  • Loading branch information
Harold Seigel committed Mar 1, 2021
1 parent fe8e370 commit 75bf10610f977786c46086f76b56392bd3bbfc3d
@@ -1342,7 +1342,7 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(InstanceKlass* context_type,
return NULL; // no implementors
} else if (nof_impls == 1) { // unique implementor
assert(context_type != context_type->implementor(), "not unique");
context_type = InstanceKlass::cast(context_type->implementor());
context_type = context_type->implementor();
} else { // nof_impls >= 2
// Avoid this case: *I.m > { A.m, C }; B.m > C
// Here, I.m has 2 concrete implementations, but m appears unique
@@ -1223,37 +1223,37 @@ void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS)
}
}

Klass* InstanceKlass::implementor() const {
Klass* volatile* k = adr_implementor();
if (k == NULL) {
InstanceKlass* InstanceKlass::implementor() const {
InstanceKlass* volatile* ik = adr_implementor();
if (ik == NULL) {
return NULL;
} else {
// This load races with inserts, and therefore needs acquire.
Klass* kls = Atomic::load_acquire(k);
if (kls != NULL && !kls->is_loader_alive()) {
InstanceKlass* ikls = Atomic::load_acquire(ik);
if (ikls != NULL && !ikls->is_loader_alive()) {
return NULL; // don't return unloaded class
} else {
return kls;
return ikls;
}
}
}


void InstanceKlass::set_implementor(Klass* k) {
void InstanceKlass::set_implementor(InstanceKlass* ik) {
assert_locked_or_safepoint(Compile_lock);
assert(is_interface(), "not interface");
Klass* volatile* addr = adr_implementor();
InstanceKlass* volatile* addr = adr_implementor();
assert(addr != NULL, "null addr");
if (addr != NULL) {
Atomic::release_store(addr, k);
Atomic::release_store(addr, ik);
}
}

int InstanceKlass::nof_implementors() const {
Klass* k = implementor();
if (k == NULL) {
InstanceKlass* ik = implementor();
if (ik == NULL) {
return 0;
} else if (k != this) {
} else if (ik != this) {
return 1;
} else {
return 2;
@@ -1269,37 +1269,37 @@ int InstanceKlass::nof_implementors() const {
// self - more than one implementor
//
// The _implementor field only exists for interfaces.
void InstanceKlass::add_implementor(Klass* k) {
void InstanceKlass::add_implementor(InstanceKlass* ik) {
if (Universe::is_fully_initialized()) {
assert_lock_strong(Compile_lock);
}
assert(is_interface(), "not interface");
// Filter out my subinterfaces.
// (Note: Interfaces are never on the subklass list.)
if (InstanceKlass::cast(k)->is_interface()) return;
if (ik->is_interface()) return;

// Filter out subclasses whose supers already implement me.
// (Note: CHA must walk subclasses of direct implementors
// in order to locate indirect implementors.)
Klass* sk = k->super();
if (sk != NULL && InstanceKlass::cast(sk)->implements_interface(this))
InstanceKlass* super_ik = ik->java_super();
if (super_ik != NULL && super_ik->implements_interface(this))
// We only need to check one immediate superclass, since the
// implements_interface query looks at transitive_interfaces.
// Any supers of the super have the same (or fewer) transitive_interfaces.
return;

Klass* ik = implementor();
if (ik == NULL) {
set_implementor(k);
} else if (ik != this && ik != k) {
InstanceKlass* iklass = implementor();
if (iklass == NULL) {
set_implementor(ik);
} else if (iklass != this && iklass != ik) {
// There is already an implementor. Use itself as an indicator of
// more than one implementors.
set_implementor(this);
}

// The implementor also implements the transitive_interfaces
for (int index = 0; index < local_interfaces()->length(); index++) {
InstanceKlass::cast(local_interfaces()->at(index))->add_implementor(k);
local_interfaces()->at(index)->add_implementor(ik);
}
}

@@ -1314,7 +1314,7 @@ void InstanceKlass::process_interfaces() {
// link this class into the implementors list of every interface it implements
for (int i = local_interfaces()->length() - 1; i >= 0; i--) {
assert(local_interfaces()->at(i)->is_klass(), "must be a klass");
InstanceKlass* interf = InstanceKlass::cast(local_interfaces()->at(i));
InstanceKlass* interf = local_interfaces()->at(i);
assert(interf->is_interface(), "expected interface");
interf->add_implementor(this);
}
@@ -2344,11 +2344,11 @@ void InstanceKlass::clean_implementors_list() {
assert (ClassUnloading, "only called for ClassUnloading");
for (;;) {
// Use load_acquire due to competing with inserts
Klass* impl = Atomic::load_acquire(adr_implementor());
InstanceKlass* impl = Atomic::load_acquire(adr_implementor());
if (impl != NULL && !impl->is_loader_alive()) {
// NULL this field, might be an unloaded klass or NULL
Klass* volatile* klass = adr_implementor();
if (Atomic::cmpxchg(klass, impl, (Klass*)NULL) == impl) {
// NULL this field, might be an unloaded instance klass or NULL
InstanceKlass* volatile* iklass = adr_implementor();
if (Atomic::cmpxchg(iklass, impl, (InstanceKlass*)NULL) == impl) {
// Successfully unlinking implementor.
if (log_is_enabled(Trace, class, unload)) {
ResourceMark rm;
@@ -327,7 +327,7 @@ class InstanceKlass: public Klass {
// embedded nonstatic oop-map blocks follows here
// embedded implementor of this interface follows here
// The embedded implementor only exists if the current klass is an
// iterface. The possible values of the implementor fall into following
// interface. The possible values of the implementor fall into following
// three cases:
// NULL: no implementor.
// A Klass* that's not itself: one implementor.
@@ -1016,10 +1016,10 @@ class InstanceKlass: public Klass {
#endif

// Access to the implementor of an interface.
Klass* implementor() const;
void set_implementor(Klass* k);
InstanceKlass* implementor() const;
void set_implementor(InstanceKlass* ik);
int nof_implementors() const;
void add_implementor(Klass* k); // k is a new class that implements this interface
void add_implementor(InstanceKlass* ik); // ik is a new class that implements this interface
void init_implementor(); // initialize

// link this class into the implementors list of every interface it implements
@@ -1087,7 +1087,7 @@ class InstanceKlass: public Klass {
inline OopMapBlock* start_of_nonstatic_oop_maps() const;
inline Klass** end_of_nonstatic_oop_maps() const;

inline Klass* volatile* adr_implementor() const;
inline InstanceKlass* volatile* adr_implementor() const;
inline InstanceKlass** adr_unsafe_anonymous_host() const;
inline address adr_fingerprint() const;

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -74,9 +74,9 @@ inline Klass** InstanceKlass::end_of_nonstatic_oop_maps() const {
nonstatic_oop_map_count());
}

inline Klass* volatile* InstanceKlass::adr_implementor() const {
inline InstanceKlass* volatile* InstanceKlass::adr_implementor() const {
if (is_interface()) {
return (Klass* volatile*)end_of_nonstatic_oop_maps();
return (InstanceKlass* volatile*)end_of_nonstatic_oop_maps();
} else {
return NULL;
}
@@ -102,7 +102,7 @@ inline address InstanceKlass::adr_fingerprint() const {
return (address)(adr_host + 1);
}

Klass* volatile* adr_impl = adr_implementor();
InstanceKlass* volatile* adr_impl = adr_implementor();
if (adr_impl != NULL) {
return (address)(adr_impl + 1);
}

1 comment on commit 75bf106

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 75bf106 Mar 1, 2021

Please sign in to comment.