8340824: C2: Memory for TypeInterfaces not reclaimed by hashcons()
Reviewed-by: vlivanov, qamai
This commit is contained in:
parent
39c17b3926
commit
90c944fefe
@ -3260,23 +3260,28 @@ void TypeRawPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
|
||||
// Convenience common pre-built type.
|
||||
const TypeOopPtr *TypeOopPtr::BOTTOM;
|
||||
|
||||
TypeInterfaces::TypeInterfaces()
|
||||
: Type(Interfaces), _list(Compile::current()->type_arena(), 0, 0, nullptr),
|
||||
TypeInterfaces::TypeInterfaces(ciInstanceKlass** interfaces_base, int nb_interfaces)
|
||||
: Type(Interfaces), _interfaces(interfaces_base, nb_interfaces),
|
||||
_hash(0), _exact_klass(nullptr) {
|
||||
DEBUG_ONLY(_initialized = true);
|
||||
}
|
||||
|
||||
TypeInterfaces::TypeInterfaces(GrowableArray<ciInstanceKlass*>* interfaces)
|
||||
: Type(Interfaces), _list(Compile::current()->type_arena(), interfaces->length(), 0, nullptr),
|
||||
_hash(0), _exact_klass(nullptr) {
|
||||
for (int i = 0; i < interfaces->length(); i++) {
|
||||
add(interfaces->at(i));
|
||||
}
|
||||
_interfaces.sort(compare);
|
||||
initialize();
|
||||
}
|
||||
|
||||
const TypeInterfaces* TypeInterfaces::make(GrowableArray<ciInstanceKlass*>* interfaces) {
|
||||
TypeInterfaces* result = (interfaces == nullptr) ? new TypeInterfaces() : new TypeInterfaces(interfaces);
|
||||
// hashcons() can only delete the last thing that was allocated: to
|
||||
// make sure all memory for the newly created TypeInterfaces can be
|
||||
// freed if an identical one exists, allocate space for the array of
|
||||
// interfaces right after the TypeInterfaces object so that they
|
||||
// form a contiguous piece of memory.
|
||||
int nb_interfaces = interfaces == nullptr ? 0 : interfaces->length();
|
||||
size_t total_size = sizeof(TypeInterfaces) + nb_interfaces * sizeof(ciInstanceKlass*);
|
||||
|
||||
void* allocated_mem = operator new(total_size);
|
||||
ciInstanceKlass** interfaces_base = (ciInstanceKlass**)((char*)allocated_mem + sizeof(TypeInterfaces));
|
||||
for (int i = 0; i < nb_interfaces; ++i) {
|
||||
interfaces_base[i] = interfaces->at(i);
|
||||
}
|
||||
TypeInterfaces* result = ::new (allocated_mem) TypeInterfaces(interfaces_base, nb_interfaces);
|
||||
return (const TypeInterfaces*)result->hashcons();
|
||||
}
|
||||
|
||||
@ -3295,20 +3300,18 @@ int TypeInterfaces::compare(ciInstanceKlass* const& k1, ciInstanceKlass* const&
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TypeInterfaces::add(ciInstanceKlass* interface) {
|
||||
assert(interface->is_interface(), "for interfaces only");
|
||||
_list.insert_sorted<compare>(interface);
|
||||
verify();
|
||||
int TypeInterfaces::compare(ciInstanceKlass** k1, ciInstanceKlass** k2) {
|
||||
return compare(*k1, *k2);
|
||||
}
|
||||
|
||||
bool TypeInterfaces::eq(const Type* t) const {
|
||||
const TypeInterfaces* other = (const TypeInterfaces*)t;
|
||||
if (_list.length() != other->_list.length()) {
|
||||
if (_interfaces.length() != other->_interfaces.length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < _list.length(); i++) {
|
||||
ciKlass* k1 = _list.at(i);
|
||||
ciKlass* k2 = other->_list.at(i);
|
||||
for (int i = 0; i < _interfaces.length(); i++) {
|
||||
ciKlass* k1 = _interfaces.at(i);
|
||||
ciKlass* k2 = other->_interfaces.at(i);
|
||||
if (!k1->equals(k2)) {
|
||||
return false;
|
||||
}
|
||||
@ -3319,12 +3322,12 @@ bool TypeInterfaces::eq(const Type* t) const {
|
||||
bool TypeInterfaces::eq(ciInstanceKlass* k) const {
|
||||
assert(k->is_loaded(), "should be loaded");
|
||||
GrowableArray<ciInstanceKlass *>* interfaces = k->transitive_interfaces();
|
||||
if (_list.length() != interfaces->length()) {
|
||||
if (_interfaces.length() != interfaces->length()) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < interfaces->length(); i++) {
|
||||
bool found = false;
|
||||
_list.find_sorted<ciInstanceKlass*, compare>(interfaces->at(i), found);
|
||||
_interfaces.find_sorted<ciInstanceKlass*, compare>(interfaces->at(i), found);
|
||||
if (!found) {
|
||||
return false;
|
||||
}
|
||||
@ -3344,8 +3347,8 @@ const Type* TypeInterfaces::xdual() const {
|
||||
|
||||
void TypeInterfaces::compute_hash() {
|
||||
uint hash = 0;
|
||||
for (int i = 0; i < _list.length(); i++) {
|
||||
ciKlass* k = _list.at(i);
|
||||
for (int i = 0; i < _interfaces.length(); i++) {
|
||||
ciKlass* k = _interfaces.at(i);
|
||||
hash += k->hash();
|
||||
}
|
||||
_hash = hash;
|
||||
@ -3356,13 +3359,13 @@ static int compare_interfaces(ciInstanceKlass** k1, ciInstanceKlass** k2) {
|
||||
}
|
||||
|
||||
void TypeInterfaces::dump(outputStream* st) const {
|
||||
if (_list.length() == 0) {
|
||||
if (_interfaces.length() == 0) {
|
||||
return;
|
||||
}
|
||||
ResourceMark rm;
|
||||
st->print(" (");
|
||||
GrowableArray<ciInstanceKlass*> interfaces;
|
||||
interfaces.appendAll(&_list);
|
||||
interfaces.appendAll(&_interfaces);
|
||||
// Sort the interfaces so they are listed in the same order from one run to the other of the same compilation
|
||||
interfaces.sort(compare_interfaces);
|
||||
for (int i = 0; i < interfaces.length(); i++) {
|
||||
@ -3377,9 +3380,9 @@ void TypeInterfaces::dump(outputStream* st) const {
|
||||
|
||||
#ifdef ASSERT
|
||||
void TypeInterfaces::verify() const {
|
||||
for (int i = 1; i < _list.length(); i++) {
|
||||
ciInstanceKlass* k1 = _list.at(i-1);
|
||||
ciInstanceKlass* k2 = _list.at(i);
|
||||
for (int i = 1; i < _interfaces.length(); i++) {
|
||||
ciInstanceKlass* k1 = _interfaces.at(i-1);
|
||||
ciInstanceKlass* k2 = _interfaces.at(i);
|
||||
assert(compare(k2, k1) > 0, "should be ordered");
|
||||
assert(k1 != k2, "no duplicate");
|
||||
}
|
||||
@ -3390,23 +3393,23 @@ const TypeInterfaces* TypeInterfaces::union_with(const TypeInterfaces* other) co
|
||||
GrowableArray<ciInstanceKlass*> result_list;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (i < _list.length() || j < other->_list.length()) {
|
||||
while (i < _list.length() &&
|
||||
(j >= other->_list.length() ||
|
||||
compare(_list.at(i), other->_list.at(j)) < 0)) {
|
||||
result_list.push(_list.at(i));
|
||||
while (i < _interfaces.length() || j < other->_interfaces.length()) {
|
||||
while (i < _interfaces.length() &&
|
||||
(j >= other->_interfaces.length() ||
|
||||
compare(_interfaces.at(i), other->_interfaces.at(j)) < 0)) {
|
||||
result_list.push(_interfaces.at(i));
|
||||
i++;
|
||||
}
|
||||
while (j < other->_list.length() &&
|
||||
(i >= _list.length() ||
|
||||
compare(other->_list.at(j), _list.at(i)) < 0)) {
|
||||
result_list.push(other->_list.at(j));
|
||||
while (j < other->_interfaces.length() &&
|
||||
(i >= _interfaces.length() ||
|
||||
compare(other->_interfaces.at(j), _interfaces.at(i)) < 0)) {
|
||||
result_list.push(other->_interfaces.at(j));
|
||||
j++;
|
||||
}
|
||||
if (i < _list.length() &&
|
||||
j < other->_list.length() &&
|
||||
_list.at(i) == other->_list.at(j)) {
|
||||
result_list.push(_list.at(i));
|
||||
if (i < _interfaces.length() &&
|
||||
j < other->_interfaces.length() &&
|
||||
_interfaces.at(i) == other->_interfaces.at(j)) {
|
||||
result_list.push(_interfaces.at(i));
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
@ -3414,14 +3417,14 @@ const TypeInterfaces* TypeInterfaces::union_with(const TypeInterfaces* other) co
|
||||
const TypeInterfaces* result = TypeInterfaces::make(&result_list);
|
||||
#ifdef ASSERT
|
||||
result->verify();
|
||||
for (int i = 0; i < _list.length(); i++) {
|
||||
assert(result->_list.contains(_list.at(i)), "missing");
|
||||
for (int i = 0; i < _interfaces.length(); i++) {
|
||||
assert(result->_interfaces.contains(_interfaces.at(i)), "missing");
|
||||
}
|
||||
for (int i = 0; i < other->_list.length(); i++) {
|
||||
assert(result->_list.contains(other->_list.at(i)), "missing");
|
||||
for (int i = 0; i < other->_interfaces.length(); i++) {
|
||||
assert(result->_interfaces.contains(other->_interfaces.at(i)), "missing");
|
||||
}
|
||||
for (int i = 0; i < result->_list.length(); i++) {
|
||||
assert(_list.contains(result->_list.at(i)) || other->_list.contains(result->_list.at(i)), "missing");
|
||||
for (int i = 0; i < result->_interfaces.length(); i++) {
|
||||
assert(_interfaces.contains(result->_interfaces.at(i)) || other->_interfaces.contains(result->_interfaces.at(i)), "missing");
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
@ -3431,21 +3434,21 @@ const TypeInterfaces* TypeInterfaces::intersection_with(const TypeInterfaces* ot
|
||||
GrowableArray<ciInstanceKlass*> result_list;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (i < _list.length() || j < other->_list.length()) {
|
||||
while (i < _list.length() &&
|
||||
(j >= other->_list.length() ||
|
||||
compare(_list.at(i), other->_list.at(j)) < 0)) {
|
||||
while (i < _interfaces.length() || j < other->_interfaces.length()) {
|
||||
while (i < _interfaces.length() &&
|
||||
(j >= other->_interfaces.length() ||
|
||||
compare(_interfaces.at(i), other->_interfaces.at(j)) < 0)) {
|
||||
i++;
|
||||
}
|
||||
while (j < other->_list.length() &&
|
||||
(i >= _list.length() ||
|
||||
compare(other->_list.at(j), _list.at(i)) < 0)) {
|
||||
while (j < other->_interfaces.length() &&
|
||||
(i >= _interfaces.length() ||
|
||||
compare(other->_interfaces.at(j), _interfaces.at(i)) < 0)) {
|
||||
j++;
|
||||
}
|
||||
if (i < _list.length() &&
|
||||
j < other->_list.length() &&
|
||||
_list.at(i) == other->_list.at(j)) {
|
||||
result_list.push(_list.at(i));
|
||||
if (i < _interfaces.length() &&
|
||||
j < other->_interfaces.length() &&
|
||||
_interfaces.at(i) == other->_interfaces.at(j)) {
|
||||
result_list.push(_interfaces.at(i));
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
@ -3453,14 +3456,14 @@ const TypeInterfaces* TypeInterfaces::intersection_with(const TypeInterfaces* ot
|
||||
const TypeInterfaces* result = TypeInterfaces::make(&result_list);
|
||||
#ifdef ASSERT
|
||||
result->verify();
|
||||
for (int i = 0; i < _list.length(); i++) {
|
||||
assert(!other->_list.contains(_list.at(i)) || result->_list.contains(_list.at(i)), "missing");
|
||||
for (int i = 0; i < _interfaces.length(); i++) {
|
||||
assert(!other->_interfaces.contains(_interfaces.at(i)) || result->_interfaces.contains(_interfaces.at(i)), "missing");
|
||||
}
|
||||
for (int i = 0; i < other->_list.length(); i++) {
|
||||
assert(!_list.contains(other->_list.at(i)) || result->_list.contains(other->_list.at(i)), "missing");
|
||||
for (int i = 0; i < other->_interfaces.length(); i++) {
|
||||
assert(!_interfaces.contains(other->_interfaces.at(i)) || result->_interfaces.contains(other->_interfaces.at(i)), "missing");
|
||||
}
|
||||
for (int i = 0; i < result->_list.length(); i++) {
|
||||
assert(_list.contains(result->_list.at(i)) && other->_list.contains(result->_list.at(i)), "missing");
|
||||
for (int i = 0; i < result->_interfaces.length(); i++) {
|
||||
assert(_interfaces.contains(result->_interfaces.at(i)) && other->_interfaces.contains(result->_interfaces.at(i)), "missing");
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
@ -3473,13 +3476,13 @@ ciInstanceKlass* TypeInterfaces::exact_klass() const {
|
||||
}
|
||||
|
||||
void TypeInterfaces::compute_exact_klass() {
|
||||
if (_list.length() == 0) {
|
||||
if (_interfaces.length() == 0) {
|
||||
_exact_klass = nullptr;
|
||||
return;
|
||||
}
|
||||
ciInstanceKlass* res = nullptr;
|
||||
for (int i = 0; i < _list.length(); i++) {
|
||||
ciInstanceKlass* interface = _list.at(i);
|
||||
for (int i = 0; i < _interfaces.length(); i++) {
|
||||
ciInstanceKlass* interface = _interfaces.at(i);
|
||||
if (eq(interface)) {
|
||||
assert(res == nullptr, "");
|
||||
res = interface;
|
||||
@ -3490,8 +3493,8 @@ void TypeInterfaces::compute_exact_klass() {
|
||||
|
||||
#ifdef ASSERT
|
||||
void TypeInterfaces::verify_is_loaded() const {
|
||||
for (int i = 0; i < _list.length(); i++) {
|
||||
ciKlass* interface = _list.at(i);
|
||||
for (int i = 0; i < _interfaces.length(); i++) {
|
||||
ciKlass* interface = _interfaces.at(i);
|
||||
assert(interface->is_loaded(), "Interface not loaded");
|
||||
}
|
||||
}
|
||||
|
@ -877,19 +877,18 @@ public:
|
||||
// Set of implemented interfaces. Referenced from TypeOopPtr and TypeKlassPtr.
|
||||
class TypeInterfaces : public Type {
|
||||
private:
|
||||
GrowableArray<ciInstanceKlass*> _list;
|
||||
GrowableArrayFromArray<ciInstanceKlass*> _interfaces;
|
||||
uint _hash;
|
||||
ciInstanceKlass* _exact_klass;
|
||||
DEBUG_ONLY(bool _initialized;)
|
||||
|
||||
void initialize();
|
||||
|
||||
void add(ciInstanceKlass* interface);
|
||||
void verify() const NOT_DEBUG_RETURN;
|
||||
void compute_hash();
|
||||
void compute_exact_klass();
|
||||
TypeInterfaces();
|
||||
TypeInterfaces(GrowableArray<ciInstanceKlass*>* interfaces);
|
||||
|
||||
TypeInterfaces(ciInstanceKlass** interfaces_base, int nb_interfaces);
|
||||
|
||||
NONCOPYABLE(TypeInterfaces);
|
||||
public:
|
||||
@ -904,12 +903,13 @@ public:
|
||||
bool contains(const TypeInterfaces* other) const {
|
||||
return intersection_with(other)->eq(other);
|
||||
}
|
||||
bool empty() const { return _list.length() == 0; }
|
||||
bool empty() const { return _interfaces.length() == 0; }
|
||||
|
||||
ciInstanceKlass* exact_klass() const;
|
||||
void verify_is_loaded() const NOT_DEBUG_RETURN;
|
||||
|
||||
static int compare(ciInstanceKlass* const& k1, ciInstanceKlass* const& k2);
|
||||
static int compare(ciInstanceKlass** k1, ciInstanceKlass** k2);
|
||||
|
||||
const Type* xmeet(const Type* t) const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user