Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
/ jdk23u Public archive

Commit f949f3f

Browse files
nelanbuTobiHartmann
authored andcommitted
8340824: C2: Memory for TypeInterfaces not reclaimed by hashcons()
Backport-of: 90c944f
1 parent c644570 commit f949f3f

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
@@ -3260,23 +3260,28 @@ void TypeRawPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
32603260
// Convenience common pre-built type.
32613261
const TypeOopPtr *TypeOopPtr::BOTTOM;
32623262

3263-
TypeInterfaces::TypeInterfaces()
3264-
: Type(Interfaces), _list(Compile::current()->type_arena(), 0, 0, nullptr),
3263+
TypeInterfaces::TypeInterfaces(ciInstanceKlass** interfaces_base, int nb_interfaces)
3264+
: Type(Interfaces), _interfaces(interfaces_base, nb_interfaces),
32653265
_hash(0), _exact_klass(nullptr) {
3266-
DEBUG_ONLY(_initialized = true);
3267-
}
3268-
3269-
TypeInterfaces::TypeInterfaces(GrowableArray<ciInstanceKlass*>* interfaces)
3270-
: Type(Interfaces), _list(Compile::current()->type_arena(), interfaces->length(), 0, nullptr),
3271-
_hash(0), _exact_klass(nullptr) {
3272-
for (int i = 0; i < interfaces->length(); i++) {
3273-
add(interfaces->at(i));
3274-
}
3266+
_interfaces.sort(compare);
32753267
initialize();
32763268
}
32773269

32783270
const TypeInterfaces* TypeInterfaces::make(GrowableArray<ciInstanceKlass*>* interfaces) {
3279-
TypeInterfaces* result = (interfaces == nullptr) ? new TypeInterfaces() : new TypeInterfaces(interfaces);
3271+
// hashcons() can only delete the last thing that was allocated: to
3272+
// make sure all memory for the newly created TypeInterfaces can be
3273+
// freed if an identical one exists, allocate space for the array of
3274+
// interfaces right after the TypeInterfaces object so that they
3275+
// form a contiguous piece of memory.
3276+
int nb_interfaces = interfaces == nullptr ? 0 : interfaces->length();
3277+
size_t total_size = sizeof(TypeInterfaces) + nb_interfaces * sizeof(ciInstanceKlass*);
3278+
3279+
void* allocated_mem = operator new(total_size);
3280+
ciInstanceKlass** interfaces_base = (ciInstanceKlass**)((char*)allocated_mem + sizeof(TypeInterfaces));
3281+
for (int i = 0; i < nb_interfaces; ++i) {
3282+
interfaces_base[i] = interfaces->at(i);
3283+
}
3284+
TypeInterfaces* result = ::new (allocated_mem) TypeInterfaces(interfaces_base, nb_interfaces);
32803285
return (const TypeInterfaces*)result->hashcons();
32813286
}
32823287

@@ -3295,20 +3300,18 @@ int TypeInterfaces::compare(ciInstanceKlass* const& k1, ciInstanceKlass* const&
32953300
return 0;
32963301
}
32973302

3298-
void TypeInterfaces::add(ciInstanceKlass* interface) {
3299-
assert(interface->is_interface(), "for interfaces only");
3300-
_list.insert_sorted<compare>(interface);
3301-
verify();
3303+
int TypeInterfaces::compare(ciInstanceKlass** k1, ciInstanceKlass** k2) {
3304+
return compare(*k1, *k2);
33023305
}
33033306

33043307
bool TypeInterfaces::eq(const Type* t) const {
33053308
const TypeInterfaces* other = (const TypeInterfaces*)t;
3306-
if (_list.length() != other->_list.length()) {
3309+
if (_interfaces.length() != other->_interfaces.length()) {
33073310
return false;
33083311
}
3309-
for (int i = 0; i < _list.length(); i++) {
3310-
ciKlass* k1 = _list.at(i);
3311-
ciKlass* k2 = other->_list.at(i);
3312+
for (int i = 0; i < _interfaces.length(); i++) {
3313+
ciKlass* k1 = _interfaces.at(i);
3314+
ciKlass* k2 = other->_interfaces.at(i);
33123315
if (!k1->equals(k2)) {
33133316
return false;
33143317
}
@@ -3319,12 +3322,12 @@ bool TypeInterfaces::eq(const Type* t) const {
33193322
bool TypeInterfaces::eq(ciInstanceKlass* k) const {
33203323
assert(k->is_loaded(), "should be loaded");
33213324
GrowableArray<ciInstanceKlass *>* interfaces = k->transitive_interfaces();
3322-
if (_list.length() != interfaces->length()) {
3325+
if (_interfaces.length() != interfaces->length()) {
33233326
return false;
33243327
}
33253328
for (int i = 0; i < interfaces->length(); i++) {
33263329
bool found = false;
3327-
_list.find_sorted<ciInstanceKlass*, compare>(interfaces->at(i), found);
3330+
_interfaces.find_sorted<ciInstanceKlass*, compare>(interfaces->at(i), found);
33283331
if (!found) {
33293332
return false;
33303333
}
@@ -3344,8 +3347,8 @@ const Type* TypeInterfaces::xdual() const {
33443347

33453348
void TypeInterfaces::compute_hash() {
33463349
uint hash = 0;
3347-
for (int i = 0; i < _list.length(); i++) {
3348-
ciKlass* k = _list.at(i);
3350+
for (int i = 0; i < _interfaces.length(); i++) {
3351+
ciKlass* k = _interfaces.at(i);
33493352
hash += k->hash();
33503353
}
33513354
_hash = hash;
@@ -3356,13 +3359,13 @@ static int compare_interfaces(ciInstanceKlass** k1, ciInstanceKlass** k2) {
33563359
}
33573360

33583361
void TypeInterfaces::dump(outputStream* st) const {
3359-
if (_list.length() == 0) {
3362+
if (_interfaces.length() == 0) {
33603363
return;
33613364
}
33623365
ResourceMark rm;
33633366
st->print(" (");
33643367
GrowableArray<ciInstanceKlass*> interfaces;
3365-
interfaces.appendAll(&_list);
3368+
interfaces.appendAll(&_interfaces);
33663369
// Sort the interfaces so they are listed in the same order from one run to the other of the same compilation
33673370
interfaces.sort(compare_interfaces);
33683371
for (int i = 0; i < interfaces.length(); i++) {
@@ -3377,9 +3380,9 @@ void TypeInterfaces::dump(outputStream* st) const {
33773380

33783381
#ifdef ASSERT
33793382
void TypeInterfaces::verify() const {
3380-
for (int i = 1; i < _list.length(); i++) {
3381-
ciInstanceKlass* k1 = _list.at(i-1);
3382-
ciInstanceKlass* k2 = _list.at(i);
3383+
for (int i = 1; i < _interfaces.length(); i++) {
3384+
ciInstanceKlass* k1 = _interfaces.at(i-1);
3385+
ciInstanceKlass* k2 = _interfaces.at(i);
33833386
assert(compare(k2, k1) > 0, "should be ordered");
33843387
assert(k1 != k2, "no duplicate");
33853388
}
@@ -3390,38 +3393,38 @@ const TypeInterfaces* TypeInterfaces::union_with(const TypeInterfaces* other) co
33903393
GrowableArray<ciInstanceKlass*> result_list;
33913394
int i = 0;
33923395
int j = 0;
3393-
while (i < _list.length() || j < other->_list.length()) {
3394-
while (i < _list.length() &&
3395-
(j >= other->_list.length() ||
3396-
compare(_list.at(i), other->_list.at(j)) < 0)) {
3397-
result_list.push(_list.at(i));
3396+
while (i < _interfaces.length() || j < other->_interfaces.length()) {
3397+
while (i < _interfaces.length() &&
3398+
(j >= other->_interfaces.length() ||
3399+
compare(_interfaces.at(i), other->_interfaces.at(j)) < 0)) {
3400+
result_list.push(_interfaces.at(i));
33983401
i++;
33993402
}
3400-
while (j < other->_list.length() &&
3401-
(i >= _list.length() ||
3402-
compare(other->_list.at(j), _list.at(i)) < 0)) {
3403-
result_list.push(other->_list.at(j));
3403+
while (j < other->_interfaces.length() &&
3404+
(i >= _interfaces.length() ||
3405+
compare(other->_interfaces.at(j), _interfaces.at(i)) < 0)) {
3406+
result_list.push(other->_interfaces.at(j));
34043407
j++;
34053408
}
3406-
if (i < _list.length() &&
3407-
j < other->_list.length() &&
3408-
_list.at(i) == other->_list.at(j)) {
3409-
result_list.push(_list.at(i));
3409+
if (i < _interfaces.length() &&
3410+
j < other->_interfaces.length() &&
3411+
_interfaces.at(i) == other->_interfaces.at(j)) {
3412+
result_list.push(_interfaces.at(i));
34103413
i++;
34113414
j++;
34123415
}
34133416
}
34143417
const TypeInterfaces* result = TypeInterfaces::make(&result_list);
34153418
#ifdef ASSERT
34163419
result->verify();
3417-
for (int i = 0; i < _list.length(); i++) {
3418-
assert(result->_list.contains(_list.at(i)), "missing");
3420+
for (int i = 0; i < _interfaces.length(); i++) {
3421+
assert(result->_interfaces.contains(_interfaces.at(i)), "missing");
34193422
}
3420-
for (int i = 0; i < other->_list.length(); i++) {
3421-
assert(result->_list.contains(other->_list.at(i)), "missing");
3423+
for (int i = 0; i < other->_interfaces.length(); i++) {
3424+
assert(result->_interfaces.contains(other->_interfaces.at(i)), "missing");
34223425
}
3423-
for (int i = 0; i < result->_list.length(); i++) {
3424-
assert(_list.contains(result->_list.at(i)) || other->_list.contains(result->_list.at(i)), "missing");
3426+
for (int i = 0; i < result->_interfaces.length(); i++) {
3427+
assert(_interfaces.contains(result->_interfaces.at(i)) || other->_interfaces.contains(result->_interfaces.at(i)), "missing");
34253428
}
34263429
#endif
34273430
return result;
@@ -3431,36 +3434,36 @@ const TypeInterfaces* TypeInterfaces::intersection_with(const TypeInterfaces* ot
34313434
GrowableArray<ciInstanceKlass*> result_list;
34323435
int i = 0;
34333436
int j = 0;
3434-
while (i < _list.length() || j < other->_list.length()) {
3435-
while (i < _list.length() &&
3436-
(j >= other->_list.length() ||
3437-
compare(_list.at(i), other->_list.at(j)) < 0)) {
3437+
while (i < _interfaces.length() || j < other->_interfaces.length()) {
3438+
while (i < _interfaces.length() &&
3439+
(j >= other->_interfaces.length() ||
3440+
compare(_interfaces.at(i), other->_interfaces.at(j)) < 0)) {
34383441
i++;
34393442
}
3440-
while (j < other->_list.length() &&
3441-
(i >= _list.length() ||
3442-
compare(other->_list.at(j), _list.at(i)) < 0)) {
3443+
while (j < other->_interfaces.length() &&
3444+
(i >= _interfaces.length() ||
3445+
compare(other->_interfaces.at(j), _interfaces.at(i)) < 0)) {
34433446
j++;
34443447
}
3445-
if (i < _list.length() &&
3446-
j < other->_list.length() &&
3447-
_list.at(i) == other->_list.at(j)) {
3448-
result_list.push(_list.at(i));
3448+
if (i < _interfaces.length() &&
3449+
j < other->_interfaces.length() &&
3450+
_interfaces.at(i) == other->_interfaces.at(j)) {
3451+
result_list.push(_interfaces.at(i));
34493452
i++;
34503453
j++;
34513454
}
34523455
}
34533456
const TypeInterfaces* result = TypeInterfaces::make(&result_list);
34543457
#ifdef ASSERT
34553458
result->verify();
3456-
for (int i = 0; i < _list.length(); i++) {
3457-
assert(!other->_list.contains(_list.at(i)) || result->_list.contains(_list.at(i)), "missing");
3459+
for (int i = 0; i < _interfaces.length(); i++) {
3460+
assert(!other->_interfaces.contains(_interfaces.at(i)) || result->_interfaces.contains(_interfaces.at(i)), "missing");
34583461
}
3459-
for (int i = 0; i < other->_list.length(); i++) {
3460-
assert(!_list.contains(other->_list.at(i)) || result->_list.contains(other->_list.at(i)), "missing");
3462+
for (int i = 0; i < other->_interfaces.length(); i++) {
3463+
assert(!_interfaces.contains(other->_interfaces.at(i)) || result->_interfaces.contains(other->_interfaces.at(i)), "missing");
34613464
}
3462-
for (int i = 0; i < result->_list.length(); i++) {
3463-
assert(_list.contains(result->_list.at(i)) && other->_list.contains(result->_list.at(i)), "missing");
3465+
for (int i = 0; i < result->_interfaces.length(); i++) {
3466+
assert(_interfaces.contains(result->_interfaces.at(i)) && other->_interfaces.contains(result->_interfaces.at(i)), "missing");
34643467
}
34653468
#endif
34663469
return result;
@@ -3473,13 +3476,13 @@ ciInstanceKlass* TypeInterfaces::exact_klass() const {
34733476
}
34743477

34753478
void TypeInterfaces::compute_exact_klass() {
3476-
if (_list.length() == 0) {
3479+
if (_interfaces.length() == 0) {
34773480
_exact_klass = nullptr;
34783481
return;
34793482
}
34803483
ciInstanceKlass* res = nullptr;
3481-
for (int i = 0; i < _list.length(); i++) {
3482-
ciInstanceKlass* interface = _list.at(i);
3484+
for (int i = 0; i < _interfaces.length(); i++) {
3485+
ciInstanceKlass* interface = _interfaces.at(i);
34833486
if (eq(interface)) {
34843487
assert(res == nullptr, "");
34853488
res = interface;
@@ -3490,8 +3493,8 @@ void TypeInterfaces::compute_exact_klass() {
34903493

34913494
#ifdef ASSERT
34923495
void TypeInterfaces::verify_is_loaded() const {
3493-
for (int i = 0; i < _list.length(); i++) {
3494-
ciKlass* interface = _list.at(i);
3496+
for (int i = 0; i < _interfaces.length(); i++) {
3497+
ciKlass* interface = _interfaces.at(i);
34953498
assert(interface->is_loaded(), "Interface not loaded");
34963499
}
34973500
}

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)