Skip to content

Commit 1f6b401

Browse files
committed
8340824: C2: Memory for TypeInterfaces not reclaimed by hashcons()
Backport-of: 90c944fefe4a7827c08a8e6a81f137c3157a749b
1 parent c2c40df commit 1f6b401

File tree

2 files changed

+78
-75
lines changed

2 files changed

+78
-75
lines changed

src/hotspot/share/opto/type.cpp

+73-70
Original file line numberDiff line numberDiff line change
@@ -3253,23 +3253,28 @@ void TypeRawPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
32533253
// Convenience common pre-built type.
32543254
const TypeOopPtr *TypeOopPtr::BOTTOM;
32553255

3256-
TypeInterfaces::TypeInterfaces()
3257-
: Type(Interfaces), _list(Compile::current()->type_arena(), 0, 0, nullptr),
3256+
TypeInterfaces::TypeInterfaces(ciInstanceKlass** interfaces_base, int nb_interfaces)
3257+
: Type(Interfaces), _interfaces(interfaces_base, nb_interfaces),
32583258
_hash(0), _exact_klass(nullptr) {
3259-
DEBUG_ONLY(_initialized = true);
3260-
}
3261-
3262-
TypeInterfaces::TypeInterfaces(GrowableArray<ciInstanceKlass*>* interfaces)
3263-
: Type(Interfaces), _list(Compile::current()->type_arena(), interfaces->length(), 0, nullptr),
3264-
_hash(0), _exact_klass(nullptr) {
3265-
for (int i = 0; i < interfaces->length(); i++) {
3266-
add(interfaces->at(i));
3267-
}
3259+
_interfaces.sort(compare);
32683260
initialize();
32693261
}
32703262

32713263
const TypeInterfaces* TypeInterfaces::make(GrowableArray<ciInstanceKlass*>* interfaces) {
3272-
TypeInterfaces* result = (interfaces == nullptr) ? new TypeInterfaces() : new TypeInterfaces(interfaces);
3264+
// hashcons() can only delete the last thing that was allocated: to
3265+
// make sure all memory for the newly created TypeInterfaces can be
3266+
// freed if an identical one exists, allocate space for the array of
3267+
// interfaces right after the TypeInterfaces object so that they
3268+
// form a contiguous piece of memory.
3269+
int nb_interfaces = interfaces == nullptr ? 0 : interfaces->length();
3270+
size_t total_size = sizeof(TypeInterfaces) + nb_interfaces * sizeof(ciInstanceKlass*);
3271+
3272+
void* allocated_mem = operator new(total_size);
3273+
ciInstanceKlass** interfaces_base = (ciInstanceKlass**)((char*)allocated_mem + sizeof(TypeInterfaces));
3274+
for (int i = 0; i < nb_interfaces; ++i) {
3275+
interfaces_base[i] = interfaces->at(i);
3276+
}
3277+
TypeInterfaces* result = ::new (allocated_mem) TypeInterfaces(interfaces_base, nb_interfaces);
32733278
return (const TypeInterfaces*)result->hashcons();
32743279
}
32753280

@@ -3288,20 +3293,18 @@ int TypeInterfaces::compare(ciInstanceKlass* const& k1, ciInstanceKlass* const&
32883293
return 0;
32893294
}
32903295

3291-
void TypeInterfaces::add(ciInstanceKlass* interface) {
3292-
assert(interface->is_interface(), "for interfaces only");
3293-
_list.insert_sorted<compare>(interface);
3294-
verify();
3296+
int TypeInterfaces::compare(ciInstanceKlass** k1, ciInstanceKlass** k2) {
3297+
return compare(*k1, *k2);
32953298
}
32963299

32973300
bool TypeInterfaces::eq(const Type* t) const {
32983301
const TypeInterfaces* other = (const TypeInterfaces*)t;
3299-
if (_list.length() != other->_list.length()) {
3302+
if (_interfaces.length() != other->_interfaces.length()) {
33003303
return false;
33013304
}
3302-
for (int i = 0; i < _list.length(); i++) {
3303-
ciKlass* k1 = _list.at(i);
3304-
ciKlass* k2 = other->_list.at(i);
3305+
for (int i = 0; i < _interfaces.length(); i++) {
3306+
ciKlass* k1 = _interfaces.at(i);
3307+
ciKlass* k2 = other->_interfaces.at(i);
33053308
if (!k1->equals(k2)) {
33063309
return false;
33073310
}
@@ -3312,12 +3315,12 @@ bool TypeInterfaces::eq(const Type* t) const {
33123315
bool TypeInterfaces::eq(ciInstanceKlass* k) const {
33133316
assert(k->is_loaded(), "should be loaded");
33143317
GrowableArray<ciInstanceKlass *>* interfaces = k->transitive_interfaces();
3315-
if (_list.length() != interfaces->length()) {
3318+
if (_interfaces.length() != interfaces->length()) {
33163319
return false;
33173320
}
33183321
for (int i = 0; i < interfaces->length(); i++) {
33193322
bool found = false;
3320-
_list.find_sorted<ciInstanceKlass*, compare>(interfaces->at(i), found);
3323+
_interfaces.find_sorted<ciInstanceKlass*, compare>(interfaces->at(i), found);
33213324
if (!found) {
33223325
return false;
33233326
}
@@ -3337,8 +3340,8 @@ const Type* TypeInterfaces::xdual() const {
33373340

33383341
void TypeInterfaces::compute_hash() {
33393342
uint hash = 0;
3340-
for (int i = 0; i < _list.length(); i++) {
3341-
ciKlass* k = _list.at(i);
3343+
for (int i = 0; i < _interfaces.length(); i++) {
3344+
ciKlass* k = _interfaces.at(i);
33423345
hash += k->hash();
33433346
}
33443347
_hash = hash;
@@ -3349,13 +3352,13 @@ static int compare_interfaces(ciInstanceKlass** k1, ciInstanceKlass** k2) {
33493352
}
33503353

33513354
void TypeInterfaces::dump(outputStream* st) const {
3352-
if (_list.length() == 0) {
3355+
if (_interfaces.length() == 0) {
33533356
return;
33543357
}
33553358
ResourceMark rm;
33563359
st->print(" (");
33573360
GrowableArray<ciInstanceKlass*> interfaces;
3358-
interfaces.appendAll(&_list);
3361+
interfaces.appendAll(&_interfaces);
33593362
// Sort the interfaces so they are listed in the same order from one run to the other of the same compilation
33603363
interfaces.sort(compare_interfaces);
33613364
for (int i = 0; i < interfaces.length(); i++) {
@@ -3370,9 +3373,9 @@ void TypeInterfaces::dump(outputStream* st) const {
33703373

33713374
#ifdef ASSERT
33723375
void TypeInterfaces::verify() const {
3373-
for (int i = 1; i < _list.length(); i++) {
3374-
ciInstanceKlass* k1 = _list.at(i-1);
3375-
ciInstanceKlass* k2 = _list.at(i);
3376+
for (int i = 1; i < _interfaces.length(); i++) {
3377+
ciInstanceKlass* k1 = _interfaces.at(i-1);
3378+
ciInstanceKlass* k2 = _interfaces.at(i);
33763379
assert(compare(k2, k1) > 0, "should be ordered");
33773380
assert(k1 != k2, "no duplicate");
33783381
}
@@ -3383,38 +3386,38 @@ const TypeInterfaces* TypeInterfaces::union_with(const TypeInterfaces* other) co
33833386
GrowableArray<ciInstanceKlass*> result_list;
33843387
int i = 0;
33853388
int j = 0;
3386-
while (i < _list.length() || j < other->_list.length()) {
3387-
while (i < _list.length() &&
3388-
(j >= other->_list.length() ||
3389-
compare(_list.at(i), other->_list.at(j)) < 0)) {
3390-
result_list.push(_list.at(i));
3389+
while (i < _interfaces.length() || j < other->_interfaces.length()) {
3390+
while (i < _interfaces.length() &&
3391+
(j >= other->_interfaces.length() ||
3392+
compare(_interfaces.at(i), other->_interfaces.at(j)) < 0)) {
3393+
result_list.push(_interfaces.at(i));
33913394
i++;
33923395
}
3393-
while (j < other->_list.length() &&
3394-
(i >= _list.length() ||
3395-
compare(other->_list.at(j), _list.at(i)) < 0)) {
3396-
result_list.push(other->_list.at(j));
3396+
while (j < other->_interfaces.length() &&
3397+
(i >= _interfaces.length() ||
3398+
compare(other->_interfaces.at(j), _interfaces.at(i)) < 0)) {
3399+
result_list.push(other->_interfaces.at(j));
33973400
j++;
33983401
}
3399-
if (i < _list.length() &&
3400-
j < other->_list.length() &&
3401-
_list.at(i) == other->_list.at(j)) {
3402-
result_list.push(_list.at(i));
3402+
if (i < _interfaces.length() &&
3403+
j < other->_interfaces.length() &&
3404+
_interfaces.at(i) == other->_interfaces.at(j)) {
3405+
result_list.push(_interfaces.at(i));
34033406
i++;
34043407
j++;
34053408
}
34063409
}
34073410
const TypeInterfaces* result = TypeInterfaces::make(&result_list);
34083411
#ifdef ASSERT
34093412
result->verify();
3410-
for (int i = 0; i < _list.length(); i++) {
3411-
assert(result->_list.contains(_list.at(i)), "missing");
3413+
for (int i = 0; i < _interfaces.length(); i++) {
3414+
assert(result->_interfaces.contains(_interfaces.at(i)), "missing");
34123415
}
3413-
for (int i = 0; i < other->_list.length(); i++) {
3414-
assert(result->_list.contains(other->_list.at(i)), "missing");
3416+
for (int i = 0; i < other->_interfaces.length(); i++) {
3417+
assert(result->_interfaces.contains(other->_interfaces.at(i)), "missing");
34153418
}
3416-
for (int i = 0; i < result->_list.length(); i++) {
3417-
assert(_list.contains(result->_list.at(i)) || other->_list.contains(result->_list.at(i)), "missing");
3419+
for (int i = 0; i < result->_interfaces.length(); i++) {
3420+
assert(_interfaces.contains(result->_interfaces.at(i)) || other->_interfaces.contains(result->_interfaces.at(i)), "missing");
34183421
}
34193422
#endif
34203423
return result;
@@ -3424,36 +3427,36 @@ const TypeInterfaces* TypeInterfaces::intersection_with(const TypeInterfaces* ot
34243427
GrowableArray<ciInstanceKlass*> result_list;
34253428
int i = 0;
34263429
int j = 0;
3427-
while (i < _list.length() || j < other->_list.length()) {
3428-
while (i < _list.length() &&
3429-
(j >= other->_list.length() ||
3430-
compare(_list.at(i), other->_list.at(j)) < 0)) {
3430+
while (i < _interfaces.length() || j < other->_interfaces.length()) {
3431+
while (i < _interfaces.length() &&
3432+
(j >= other->_interfaces.length() ||
3433+
compare(_interfaces.at(i), other->_interfaces.at(j)) < 0)) {
34313434
i++;
34323435
}
3433-
while (j < other->_list.length() &&
3434-
(i >= _list.length() ||
3435-
compare(other->_list.at(j), _list.at(i)) < 0)) {
3436+
while (j < other->_interfaces.length() &&
3437+
(i >= _interfaces.length() ||
3438+
compare(other->_interfaces.at(j), _interfaces.at(i)) < 0)) {
34363439
j++;
34373440
}
3438-
if (i < _list.length() &&
3439-
j < other->_list.length() &&
3440-
_list.at(i) == other->_list.at(j)) {
3441-
result_list.push(_list.at(i));
3441+
if (i < _interfaces.length() &&
3442+
j < other->_interfaces.length() &&
3443+
_interfaces.at(i) == other->_interfaces.at(j)) {
3444+
result_list.push(_interfaces.at(i));
34423445
i++;
34433446
j++;
34443447
}
34453448
}
34463449
const TypeInterfaces* result = TypeInterfaces::make(&result_list);
34473450
#ifdef ASSERT
34483451
result->verify();
3449-
for (int i = 0; i < _list.length(); i++) {
3450-
assert(!other->_list.contains(_list.at(i)) || result->_list.contains(_list.at(i)), "missing");
3452+
for (int i = 0; i < _interfaces.length(); i++) {
3453+
assert(!other->_interfaces.contains(_interfaces.at(i)) || result->_interfaces.contains(_interfaces.at(i)), "missing");
34513454
}
3452-
for (int i = 0; i < other->_list.length(); i++) {
3453-
assert(!_list.contains(other->_list.at(i)) || result->_list.contains(other->_list.at(i)), "missing");
3455+
for (int i = 0; i < other->_interfaces.length(); i++) {
3456+
assert(!_interfaces.contains(other->_interfaces.at(i)) || result->_interfaces.contains(other->_interfaces.at(i)), "missing");
34543457
}
3455-
for (int i = 0; i < result->_list.length(); i++) {
3456-
assert(_list.contains(result->_list.at(i)) && other->_list.contains(result->_list.at(i)), "missing");
3458+
for (int i = 0; i < result->_interfaces.length(); i++) {
3459+
assert(_interfaces.contains(result->_interfaces.at(i)) && other->_interfaces.contains(result->_interfaces.at(i)), "missing");
34573460
}
34583461
#endif
34593462
return result;
@@ -3466,13 +3469,13 @@ ciInstanceKlass* TypeInterfaces::exact_klass() const {
34663469
}
34673470

34683471
void TypeInterfaces::compute_exact_klass() {
3469-
if (_list.length() == 0) {
3472+
if (_interfaces.length() == 0) {
34703473
_exact_klass = nullptr;
34713474
return;
34723475
}
34733476
ciInstanceKlass* res = nullptr;
3474-
for (int i = 0; i < _list.length(); i++) {
3475-
ciInstanceKlass* interface = _list.at(i);
3477+
for (int i = 0; i < _interfaces.length(); i++) {
3478+
ciInstanceKlass* interface = _interfaces.at(i);
34763479
if (eq(interface)) {
34773480
assert(res == nullptr, "");
34783481
res = interface;
@@ -3483,8 +3486,8 @@ void TypeInterfaces::compute_exact_klass() {
34833486

34843487
#ifdef ASSERT
34853488
void TypeInterfaces::verify_is_loaded() const {
3486-
for (int i = 0; i < _list.length(); i++) {
3487-
ciKlass* interface = _list.at(i);
3489+
for (int i = 0; i < _interfaces.length(); i++) {
3490+
ciKlass* interface = _interfaces.at(i);
34883491
assert(interface->is_loaded(), "Interface not loaded");
34893492
}
34903493
}

src/hotspot/share/opto/type.hpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -877,19 +877,18 @@ class TypeVectMask : public TypeVect {
877877
// Set of implemented interfaces. Referenced from TypeOopPtr and TypeKlassPtr.
878878
class TypeInterfaces : public Type {
879879
private:
880-
GrowableArray<ciInstanceKlass*> _list;
880+
GrowableArrayFromArray<ciInstanceKlass*> _interfaces;
881881
uint _hash;
882882
ciInstanceKlass* _exact_klass;
883883
DEBUG_ONLY(bool _initialized;)
884884

885885
void initialize();
886886

887-
void add(ciInstanceKlass* interface);
888887
void verify() const NOT_DEBUG_RETURN;
889888
void compute_hash();
890889
void compute_exact_klass();
891-
TypeInterfaces();
892-
TypeInterfaces(GrowableArray<ciInstanceKlass*>* interfaces);
890+
891+
TypeInterfaces(ciInstanceKlass** interfaces_base, int nb_interfaces);
893892

894893
NONCOPYABLE(TypeInterfaces);
895894
public:
@@ -904,12 +903,13 @@ class TypeInterfaces : public Type {
904903
bool contains(const TypeInterfaces* other) const {
905904
return intersection_with(other)->eq(other);
906905
}
907-
bool empty() const { return _list.length() == 0; }
906+
bool empty() const { return _interfaces.length() == 0; }
908907

909908
ciInstanceKlass* exact_klass() const;
910909
void verify_is_loaded() const NOT_DEBUG_RETURN;
911910

912911
static int compare(ciInstanceKlass* const& k1, ciInstanceKlass* const& k2);
912+
static int compare(ciInstanceKlass** k1, ciInstanceKlass** k2);
913913

914914
const Type* xmeet(const Type* t) const;
915915

0 commit comments

Comments
 (0)