Skip to content

Commit 5bc382f

Browse files
committed
8263976: Remove block allocation from BasicHashtable
Reviewed-by: lfoltan, iklam
1 parent fbd57bd commit 5bc382f

16 files changed

+47
-168
lines changed

src/hotspot/share/classfile/dictionary.cpp

+3-6
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,10 @@ Dictionary::~Dictionary() {
7474
}
7575
}
7676
assert(number_of_entries() == 0, "should have removed all entries");
77-
assert(new_entry_free_list() == NULL, "entry present on Dictionary's free list");
7877
}
7978

8079
DictionaryEntry* Dictionary::new_entry(unsigned int hash, InstanceKlass* klass) {
81-
DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::allocate_new_entry(hash, klass);
80+
DictionaryEntry* entry = (DictionaryEntry*)Hashtable<InstanceKlass*, mtClass>::new_entry(hash, klass);
8281
entry->set_pd_set(NULL);
8382
assert(klass->is_instance_klass(), "Must be");
8483
return entry;
@@ -95,9 +94,7 @@ void Dictionary::free_entry(DictionaryEntry* entry) {
9594
entry->set_pd_set(to_delete->next());
9695
delete to_delete;
9796
}
98-
// Unlink from the Hashtable prior to freeing
99-
unlink_entry(entry);
100-
FREE_C_HEAP_ARRAY(char, entry);
97+
BasicHashtable<mtClass>::free_entry(entry);
10198
}
10299

103100
const int _resize_load_trigger = 5; // load factor that will trigger the resize
@@ -551,7 +548,7 @@ void SymbolPropertyTable::methods_do(void f(Method*)) {
551548

552549
void SymbolPropertyTable::free_entry(SymbolPropertyEntry* entry) {
553550
entry->free_entry();
554-
Hashtable<Symbol*, mtSymbol>::free_entry(entry);
551+
BasicHashtable<mtSymbol>::free_entry(entry);
555552
}
556553

557554
void DictionaryEntry::verify_protection_domain_set() {

src/hotspot/share/classfile/dictionary.hpp

-8
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,6 @@ class Dictionary : public Hashtable<InstanceKlass*, mtClass> {
9292
return (DictionaryEntry**)Hashtable<InstanceKlass*, mtClass>::bucket_addr(i);
9393
}
9494

95-
void add_entry(int index, DictionaryEntry* new_entry) {
96-
Hashtable<InstanceKlass*, mtClass>::add_entry(index, (HashtableEntry<InstanceKlass*, mtClass>*)new_entry);
97-
}
98-
99-
void unlink_entry(DictionaryEntry* entry) {
100-
Hashtable<InstanceKlass*, mtClass>::unlink_entry((HashtableEntry<InstanceKlass*, mtClass>*)entry);
101-
}
102-
10395
void free_entry(DictionaryEntry* entry);
10496

10597
bool is_valid_protection_domain(unsigned int hash,

src/hotspot/share/classfile/loaderConstraints.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ LoaderConstraintEntry* LoaderConstraintTable::new_entry(
5858
void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) {
5959
// decrement name refcount before freeing
6060
entry->name()->decrement_refcount();
61-
Hashtable<InstanceKlass*, mtClass>::free_entry(entry);
61+
BasicHashtable<mtClass>::free_entry(entry);
6262
}
6363

6464
// The loaderConstraintTable must always be accessed with the

src/hotspot/share/classfile/moduleEntry.cpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,10 @@ ModuleEntryTable::~ModuleEntryTable() {
357357
if (to_remove->location() != NULL) {
358358
to_remove->location()->decrement_refcount();
359359
}
360-
361-
// Unlink from the Hashtable prior to freeing
362-
unlink_entry(to_remove);
363-
FREE_C_HEAP_ARRAY(char, to_remove);
360+
BasicHashtable<mtModule>::free_entry(to_remove);
364361
}
365362
}
366363
assert(number_of_entries() == 0, "should have removed all entries");
367-
assert(new_entry_free_list() == NULL, "entry present on ModuleEntryTable's free list");
368364
}
369365

370366
void ModuleEntry::set_loader_data(ClassLoaderData* cld) {
@@ -579,7 +575,7 @@ ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle
579575
Symbol* version, Symbol* location,
580576
ClassLoaderData* loader_data) {
581577
assert(Module_lock->owned_by_self(), "should have the Module_lock");
582-
ModuleEntry* entry = (ModuleEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name);
578+
ModuleEntry* entry = (ModuleEntry*)Hashtable<Symbol*, mtModule>::new_entry(hash, name);
583579

584580
// Initialize fields specific to a ModuleEntry
585581
entry->init();

src/hotspot/share/classfile/packageEntry.cpp

+2-5
Original file line numberDiff line numberDiff line change
@@ -187,13 +187,10 @@ PackageEntryTable::~PackageEntryTable() {
187187
to_remove->delete_qualified_exports();
188188
to_remove->name()->decrement_refcount();
189189

190-
// Unlink from the Hashtable prior to freeing
191-
unlink_entry(to_remove);
192-
FREE_C_HEAP_ARRAY(char, to_remove);
190+
BasicHashtable<mtModule>::free_entry(to_remove);
193191
}
194192
}
195193
assert(number_of_entries() == 0, "should have removed all entries");
196-
assert(new_entry_free_list() == NULL, "entry present on PackageEntryTable's free list");
197194
}
198195

199196
#if INCLUDE_CDS_JAVA_HEAP
@@ -322,7 +319,7 @@ void PackageEntryTable::load_archived_entries(Array<PackageEntry*>* archived_pac
322319

323320
PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
324321
assert(Module_lock->owned_by_self(), "should have the Module_lock");
325-
PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::allocate_new_entry(hash, name);
322+
PackageEntry* entry = (PackageEntry*)Hashtable<Symbol*, mtModule>::new_entry(hash, name);
326323

327324
JFR_ONLY(INIT_ID(entry);)
328325

src/hotspot/share/classfile/placeholders.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ void PlaceholderTable::free_entry(PlaceholderEntry* entry) {
193193
// decrement Symbol refcount here because Hashtable doesn't.
194194
entry->literal()->decrement_refcount();
195195
if (entry->supername() != NULL) entry->supername()->decrement_refcount();
196-
Hashtable<Symbol*, mtClass>::free_entry(entry);
196+
BasicHashtable<mtClass>::free_entry(entry);
197197
}
198198

199199

src/hotspot/share/classfile/resolutionErrors.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) {
137137
if (entry->nest_host_error() != NULL) {
138138
FREE_C_HEAP_ARRAY(char, entry->nest_host_error());
139139
}
140-
Hashtable<ConstantPool*, mtClass>::free_entry(entry);
140+
BasicHashtable<mtClass>::free_entry(entry);
141141
}
142142

143143

src/hotspot/share/classfile/systemDictionary.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -1576,13 +1576,14 @@ InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handl
15761576
// Other cases fall through, and may run into duplicate defines
15771577
// caught by finding an entry in the SystemDictionary
15781578
if (is_parallelDefine(class_loader) && (probe->instance_klass() != NULL)) {
1579+
InstanceKlass* ik = probe->instance_klass();
15791580
placeholders()->find_and_remove(name_hash, name_h, loader_data, PlaceholderTable::DEFINE_CLASS, THREAD);
15801581
SystemDictionary_lock->notify_all();
15811582
#ifdef ASSERT
15821583
InstanceKlass* check = dictionary->find_class(name_hash, name_h);
15831584
assert(check != NULL, "definer missed recording success");
15841585
#endif
1585-
return probe->instance_klass();
1586+
return ik;
15861587
} else {
15871588
// This thread will define the class (even if earlier thread tried and had an error)
15881589
probe->set_definer(THREAD);

src/hotspot/share/gc/g1/g1CodeCacheRemSet.cpp

+3-18
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -45,14 +45,7 @@ size_t G1CodeRootSetTable::mem_size() {
4545

4646
G1CodeRootSetTable::Entry* G1CodeRootSetTable::new_entry(nmethod* nm) {
4747
unsigned int hash = compute_hash(nm);
48-
Entry* entry = (Entry*) new_entry_free_list();
49-
if (entry == NULL) {
50-
entry = (Entry*) NEW_C_HEAP_ARRAY2(char, entry_size(), mtGC, CURRENT_PC);
51-
}
52-
entry->set_next(NULL);
53-
entry->set_hash(hash);
54-
entry->set_literal(nm);
55-
return entry;
48+
return (Entry*)Hashtable<nmethod*, mtGC>::new_entry(hash, nm);
5649
}
5750

5851
void G1CodeRootSetTable::remove_entry(Entry* e, Entry* previous) {
@@ -73,17 +66,10 @@ G1CodeRootSetTable::~G1CodeRootSetTable() {
7366
Entry* to_remove = e;
7467
// read next before freeing.
7568
e = e->next();
76-
unlink_entry(to_remove);
77-
FREE_C_HEAP_ARRAY(char, to_remove);
69+
BasicHashtable<mtGC>::free_entry(to_remove);
7870
}
7971
}
8072
assert(number_of_entries() == 0, "should have removed all entries");
81-
// Each of the entries in new_entry_free_list() have been allocated in
82-
// G1CodeRootSetTable::new_entry(). We never call the block allocator
83-
// in BasicHashtable::new_entry().
84-
for (BasicHashtableEntry<mtGC>* e = new_entry_free_list(); e != NULL; e = new_entry_free_list()) {
85-
FREE_C_HEAP_ARRAY(char, e);
86-
}
8773
}
8874

8975
bool G1CodeRootSetTable::add(nmethod* nm) {
@@ -124,7 +110,6 @@ void G1CodeRootSetTable::copy_to(G1CodeRootSetTable* new_table) {
124110
new_table->add(e->literal());
125111
}
126112
}
127-
new_table->copy_freelist(this);
128113
}
129114

130115
void G1CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) {

src/hotspot/share/prims/jvm.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
#include "services/threadService.hpp"
9595
#include "utilities/copy.hpp"
9696
#include "utilities/defaultStream.hpp"
97+
#include "utilities/dtrace.hpp"
9798
#include "utilities/events.hpp"
9899
#include "utilities/macros.hpp"
99100
#include "utilities/utf8.hpp"

src/hotspot/share/prims/jvmtiTagMapTable.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ void JvmtiTagMapTable::clear() {
6464
*p = NULL; // clear out buckets.
6565
}
6666
assert(number_of_entries() == 0, "should have removed all entries");
67-
assert(new_entry_free_list() == NULL, "entry present on JvmtiTagMapTable's free list");
6867
}
6968

7069
JvmtiTagMapTable::~JvmtiTagMapTable() {
@@ -74,15 +73,14 @@ JvmtiTagMapTable::~JvmtiTagMapTable() {
7473

7574
// Entries are C_Heap allocated
7675
JvmtiTagMapEntry* JvmtiTagMapTable::new_entry(unsigned int hash, WeakHandle w, jlong tag) {
77-
JvmtiTagMapEntry* entry = (JvmtiTagMapEntry*)Hashtable<WeakHandle, mtServiceability>::allocate_new_entry(hash, w);
76+
JvmtiTagMapEntry* entry = (JvmtiTagMapEntry*)Hashtable<WeakHandle, mtServiceability>::new_entry(hash, w);
7877
entry->set_tag(tag);
7978
return entry;
8079
}
8180

8281
void JvmtiTagMapTable::free_entry(JvmtiTagMapEntry* entry) {
83-
unlink_entry(entry);
8482
entry->literal().release(JvmtiExport::weak_tag_storage()); // release to OopStorage
85-
FREE_C_HEAP_ARRAY(char, entry);
83+
BasicHashtable<mtServiceability>::free_entry(entry);
8684
}
8785

8886
unsigned int JvmtiTagMapTable::compute_hash(oop obj) {

src/hotspot/share/runtime/vmStructs.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -491,10 +491,6 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
491491
\
492492
nonstatic_field(BasicHashtable<mtInternal>, _table_size, int) \
493493
nonstatic_field(BasicHashtable<mtInternal>, _buckets, HashtableBucket<mtInternal>*) \
494-
volatile_nonstatic_field(BasicHashtable<mtInternal>, _free_list, BasicHashtableEntry<mtInternal>*) \
495-
nonstatic_field(BasicHashtable<mtInternal>, _first_free_entry, char*) \
496-
nonstatic_field(BasicHashtable<mtInternal>, _end_block, char*) \
497-
nonstatic_field(BasicHashtable<mtInternal>, _entry_size, int) \
498494
\
499495
/*******************/ \
500496
/* ClassLoaderData */ \

src/hotspot/share/utilities/hashtable.cpp

+12-49
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,19 @@
2323
*/
2424

2525
#include "precompiled.hpp"
26-
#include "classfile/altHashing.hpp"
2726
#include "classfile/dictionary.hpp"
2827
#include "classfile/javaClasses.inline.hpp"
2928
#include "classfile/moduleEntry.hpp"
3029
#include "classfile/packageEntry.hpp"
3130
#include "classfile/placeholders.hpp"
3231
#include "classfile/protectionDomainCache.hpp"
33-
#include "classfile/stringTable.hpp"
3432
#include "classfile/vmClasses.hpp"
3533
#include "code/nmethod.hpp"
3634
#include "logging/log.hpp"
3735
#include "memory/allocation.inline.hpp"
3836
#include "memory/resourceArea.hpp"
3937
#include "oops/oop.inline.hpp"
38+
#include "oops/symbol.hpp"
4039
#include "oops/weakHandle.inline.hpp"
4140
#include "prims/jvmtiTagMapTable.hpp"
4241
#include "runtime/safepoint.hpp"
@@ -45,67 +44,31 @@
4544
#include "utilities/hashtable.inline.hpp"
4645
#include "utilities/numberSeq.hpp"
4746

48-
4947
// This hashtable is implemented as an open hash table with a fixed number of buckets.
5048

51-
template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry_free_list() {
52-
BasicHashtableEntry<F>* entry = NULL;
53-
if (_free_list != NULL) {
54-
entry = _free_list;
55-
_free_list = _free_list->next();
56-
}
57-
return entry;
58-
}
49+
// Hashtable entry allocates in the C heap directly.
5950

60-
// HashtableEntrys are allocated in blocks to reduce the space overhead.
6151
template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsigned int hashValue) {
62-
BasicHashtableEntry<F>* entry = new_entry_free_list();
63-
64-
if (entry == NULL) {
65-
if (_first_free_entry + _entry_size >= _end_block) {
66-
int block_size = MAX2((int)_table_size / 2, (int)_number_of_entries); // pick a reasonable value
67-
block_size = clamp(block_size, 2, 512); // but never go out of this range
68-
int len = round_down_power_of_2(_entry_size * block_size);
69-
assert(len >= _entry_size, "");
70-
_first_free_entry = NEW_C_HEAP_ARRAY2(char, len, F, CURRENT_PC);
71-
_entry_blocks.append(_first_free_entry);
72-
_end_block = _first_free_entry + len;
73-
}
74-
entry = (BasicHashtableEntry<F>*)_first_free_entry;
75-
_first_free_entry += _entry_size;
76-
}
77-
78-
assert(_entry_size % HeapWordSize == 0, "");
79-
entry->set_hash(hashValue);
52+
BasicHashtableEntry<F>* entry = ::new (NEW_C_HEAP_ARRAY(char, this->entry_size(), F))
53+
BasicHashtableEntry<F>(hashValue);
8054
return entry;
8155
}
8256

8357

8458
template <class T, MEMFLAGS F> HashtableEntry<T, F>* Hashtable<T, F>::new_entry(unsigned int hashValue, T obj) {
85-
HashtableEntry<T, F>* entry;
86-
87-
entry = (HashtableEntry<T, F>*)BasicHashtable<F>::new_entry(hashValue);
88-
entry->set_literal(obj);
59+
HashtableEntry<T, F>* entry = ::new (NEW_C_HEAP_ARRAY(char, this->entry_size(), F))
60+
HashtableEntry<T, F>(hashValue, obj);
8961
return entry;
9062
}
9163

92-
// Version of hashtable entry allocation that allocates in the C heap directly.
93-
// The block allocator in BasicHashtable has less fragmentation, but the memory is not freed until
94-
// the whole table is freed. Use allocate_new_entry() if you want to individually free the memory
95-
// used by each entry
96-
template <class T, MEMFLAGS F> HashtableEntry<T, F>* Hashtable<T, F>::allocate_new_entry(unsigned int hashValue, T obj) {
97-
HashtableEntry<T, F>* entry = (HashtableEntry<T, F>*) NEW_C_HEAP_ARRAY(char, this->entry_size(), F);
98-
99-
if (DumpSharedSpaces) {
100-
// Avoid random bits in structure padding so we can have deterministic content in CDS archive
101-
memset((void*)entry, 0, this->entry_size());
102-
}
103-
entry->set_hash(hashValue);
104-
entry->set_literal(obj);
105-
entry->set_next(NULL);
106-
return entry;
64+
template <MEMFLAGS F> inline void BasicHashtable<F>::free_entry(BasicHashtableEntry<F>* entry) {
65+
// Unlink from the Hashtable prior to freeing
66+
unlink_entry(entry);
67+
FREE_C_HEAP_ARRAY(char, entry);
68+
JFR_ONLY(_stats_rate.remove();)
10769
}
10870

71+
10972
template <MEMFLAGS F> void BasicHashtable<F>::free_buckets() {
11073
FREE_C_HEAP_ARRAY(HashtableBucket, _buckets);
11174
_buckets = NULL;

0 commit comments

Comments
 (0)