Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6651425

Browse files
committed
8244733: Add ResourceHashtable::xxx_if_absent
Reviewed-by: coleenp, iklam, rehn, dholmes
1 parent ac93f38 commit 6651425

File tree

7 files changed

+127
-56
lines changed

7 files changed

+127
-56
lines changed

src/hotspot/share/classfile/bytecodeAssembler.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@
3232
#include "utilities/bytes.hpp"
3333

3434
u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe) {
35-
u2 index;
36-
u2* probe = _indices.get(bcpe);
37-
if (probe == NULL) {
38-
index = _entries.length();
35+
36+
u2 index = _entries.length();
37+
bool created = false;
38+
u2* probe = _indices.put_if_absent(bcpe, index, &created);
39+
if (created) {
3940
_entries.append(bcpe);
40-
_indices.put(bcpe, index);
4141
} else {
4242
index = *probe;
4343
}

src/hotspot/share/classfile/classLoaderStats.cpp

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,27 +44,23 @@ class ClassStatsClosure : public KlassClosure {
4444
}
4545
};
4646

47-
4847
void ClassLoaderStatsClosure::do_cld(ClassLoaderData* cld) {
4948
oop cl = cld->class_loader();
50-
ClassLoaderStats* cls;
5149

5250
// The hashtable key is the ClassLoader oop since we want to account
5351
// for "real" classes and anonymous classes together
54-
ClassLoaderStats** cls_ptr = _stats->get(cl);
55-
if (cls_ptr == NULL) {
56-
cls = new ClassLoaderStats();
57-
_stats->put(cl, cls);
52+
bool added = false;
53+
ClassLoaderStats* cls = _stats->put_if_absent(cl, &added);
54+
if (added) {
55+
cls->_class_loader = cl;
5856
_total_loaders++;
59-
} else {
60-
cls = *cls_ptr;
6157
}
58+
assert(cls->_class_loader == cl, "Sanity");
6259

6360
if (!cld->has_class_mirror_holder()) {
6461
cls->_cld = cld;
6562
}
6663

67-
cls->_class_loader = cl;
6864
if (cl != NULL) {
6965
cls->_parent = java_lang_ClassLoader::parent(cl);
7066
addEmptyParents(cls->_parent);
@@ -105,25 +101,25 @@ void ClassLoaderStatsClosure::do_cld(ClassLoaderData* cld) {
105101
#endif
106102

107103

108-
bool ClassLoaderStatsClosure::do_entry(oop const& key, ClassLoaderStats* const& cls) {
109-
Klass* class_loader_klass = (cls->_class_loader == NULL ? NULL : cls->_class_loader->klass());
110-
Klass* parent_klass = (cls->_parent == NULL ? NULL : cls->_parent->klass());
104+
bool ClassLoaderStatsClosure::do_entry(oop const& key, ClassLoaderStats const& cls) {
105+
Klass* class_loader_klass = (cls._class_loader == NULL ? NULL : cls._class_loader->klass());
106+
Klass* parent_klass = (cls._parent == NULL ? NULL : cls._parent->klass());
111107

112108
_out->print(INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " ",
113-
p2i(class_loader_klass), p2i(parent_klass), p2i(cls->_cld),
114-
cls->_classes_count,
115-
cls->_chunk_sz, cls->_block_sz);
109+
p2i(class_loader_klass), p2i(parent_klass), p2i(cls._cld),
110+
cls._classes_count,
111+
cls._chunk_sz, cls._block_sz);
116112
if (class_loader_klass != NULL) {
117113
_out->print("%s", class_loader_klass->external_name());
118114
} else {
119115
_out->print("<boot class loader>");
120116
}
121117
_out->cr();
122-
if (cls->_hidden_classes_count > 0) {
118+
if (cls._hidden_classes_count > 0) {
123119
_out->print_cr(SPACE SPACE SPACE " " UINTX_FORMAT_W(6) " " SIZE_FORMAT_W(8) " " SIZE_FORMAT_W(8) " + hidden classes",
124120
"", "", "",
125-
cls->_hidden_classes_count,
126-
cls->_hidden_chunk_sz, cls->_hidden_block_sz);
121+
cls._hidden_classes_count,
122+
cls._hidden_chunk_sz, cls._hidden_block_sz);
127123
}
128124
return true;
129125
}
@@ -146,15 +142,14 @@ void ClassLoaderStatsClosure::print() {
146142
void ClassLoaderStatsClosure::addEmptyParents(oop cl) {
147143
while (cl != NULL && java_lang_ClassLoader::loader_data_acquire(cl) == NULL) {
148144
// This classloader has not loaded any classes
149-
ClassLoaderStats** cls_ptr = _stats->get(cl);
150-
if (cls_ptr == NULL) {
151-
// It does not exist in our table - add it
152-
ClassLoaderStats* cls = new ClassLoaderStats();
145+
bool added = false;
146+
ClassLoaderStats* cls = _stats->put_if_absent(cl, &added);
147+
if (added) {
153148
cls->_class_loader = cl;
154149
cls->_parent = java_lang_ClassLoader::parent(cl);
155-
_stats->put(cl, cls);
156150
_total_loaders++;
157151
}
152+
assert(cls->_class_loader == cl, "Sanity");
158153

159154
cl = java_lang_ClassLoader::parent(cl);
160155
}

src/hotspot/share/classfile/classLoaderStats.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ class ClassLoaderStatsClosure : public CLDClosure {
115115
return hash;
116116
}
117117

118-
typedef ResourceHashtable<oop, ClassLoaderStats*,
118+
typedef ResourceHashtable<oop, ClassLoaderStats,
119119
ClassLoaderStatsClosure::oop_hash, ClassLoaderStatsClosure::oop_equals> StatsTable;
120120

121121
outputStream* _out;
@@ -136,7 +136,7 @@ class ClassLoaderStatsClosure : public CLDClosure {
136136
}
137137

138138
virtual void do_cld(ClassLoaderData* cld);
139-
virtual bool do_entry(oop const& key, ClassLoaderStats* const& cls);
139+
virtual bool do_entry(oop const& key, ClassLoaderStats const& cls);
140140
void print();
141141

142142
private:

src/hotspot/share/classfile/systemDictionaryShared.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,14 @@ class DumpTimeSharedClassTable: public ResourceHashtable<
198198
int _unregistered_count;
199199
public:
200200
DumpTimeSharedClassInfo* find_or_allocate_info_for(InstanceKlass* k) {
201-
DumpTimeSharedClassInfo* p = get(k);
202-
if (p == NULL) {
201+
bool created = false;
202+
DumpTimeSharedClassInfo* p = put_if_absent(k, &created);
203+
if (created) {
203204
assert(!SystemDictionaryShared::no_class_loading_should_happen(),
204205
"no new classes can be loaded while dumping archive");
205-
put(k, DumpTimeSharedClassInfo());
206-
p = get(k);
207-
assert(p != NULL, "sanity");
208206
p->_klass = k;
207+
} else {
208+
assert(p->_klass == k, "Sanity");
209209
}
210210
return p;
211211
}
@@ -1041,19 +1041,16 @@ static ResourceHashtable<
10411041
ResourceObj::C_HEAP> _loaded_unregistered_classes;
10421042

10431043
bool SystemDictionaryShared::add_unregistered_class(InstanceKlass* k, TRAPS) {
1044+
// We don't allow duplicated unregistered classes of the same name.
10441045
assert(DumpSharedSpaces, "only when dumping");
1045-
10461046
Symbol* name = k->name();
1047-
if (_loaded_unregistered_classes.get(name) != NULL) {
1048-
// We don't allow duplicated unregistered classes of the same name.
1049-
return false;
1050-
} else {
1051-
bool isnew = _loaded_unregistered_classes.put(name, true);
1052-
assert(isnew, "sanity");
1047+
bool created = false;
1048+
_loaded_unregistered_classes.put_if_absent(name, true, &created);
1049+
if (created) {
10531050
MutexLocker mu_r(THREAD, Compile_lock); // add_to_hierarchy asserts this.
10541051
SystemDictionary::add_to_hierarchy(k, CHECK_false);
1055-
return true;
10561052
}
1053+
return created;
10571054
}
10581055

10591056
// This function is called to resolve the super/interfaces of shared classes for

src/hotspot/share/jfr/periodic/jfrPeriodic.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -468,21 +468,21 @@ class JfrClassLoaderStatsClosure : public ClassLoaderStatsClosure {
468468
public:
469469
JfrClassLoaderStatsClosure() : ClassLoaderStatsClosure(NULL) {}
470470

471-
bool do_entry(oop const& key, ClassLoaderStats* const& cls) {
472-
const ClassLoaderData* this_cld = cls->_class_loader != NULL ?
473-
java_lang_ClassLoader::loader_data_acquire(cls->_class_loader) : NULL;
474-
const ClassLoaderData* parent_cld = cls->_parent != NULL ?
475-
java_lang_ClassLoader::loader_data_acquire(cls->_parent) : NULL;
471+
bool do_entry(oop const& key, ClassLoaderStats const& cls) {
472+
const ClassLoaderData* this_cld = cls._class_loader != NULL ?
473+
java_lang_ClassLoader::loader_data_acquire(cls._class_loader) : NULL;
474+
const ClassLoaderData* parent_cld = cls._parent != NULL ?
475+
java_lang_ClassLoader::loader_data_acquire(cls._parent) : NULL;
476476
EventClassLoaderStatistics event;
477477
event.set_classLoader(this_cld);
478478
event.set_parentClassLoader(parent_cld);
479-
event.set_classLoaderData((intptr_t)cls->_cld);
480-
event.set_classCount(cls->_classes_count);
481-
event.set_chunkSize(cls->_chunk_sz);
482-
event.set_blockSize(cls->_block_sz);
483-
event.set_hiddenClassCount(cls->_hidden_classes_count);
484-
event.set_hiddenChunkSize(cls->_hidden_chunk_sz);
485-
event.set_hiddenBlockSize(cls->_hidden_block_sz);
479+
event.set_classLoaderData((intptr_t)cls._cld);
480+
event.set_classCount(cls._classes_count);
481+
event.set_chunkSize(cls._chunk_sz);
482+
event.set_blockSize(cls._block_sz);
483+
event.set_hiddenClassCount(cls._hidden_classes_count);
484+
event.set_hiddenChunkSize(cls._hidden_chunk_sz);
485+
event.set_hiddenBlockSize(cls._hidden_block_sz);
486486
event.commit();
487487
return true;
488488
}

src/hotspot/share/utilities/resourceHash.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ class ResourceHashtable : public ResourceObj {
5151

5252
Node(unsigned hash, K const& key, V const& value) :
5353
_hash(hash), _key(key), _value(value), _next(NULL) {}
54+
55+
// Create a node with a default-constructed value.
56+
Node(unsigned hash, K const& key) :
57+
_hash(hash), _key(key), _value(), _next(NULL) {}
58+
5459
};
5560

5661
Node* _table[SIZE];
@@ -124,6 +129,41 @@ class ResourceHashtable : public ResourceObj {
124129
}
125130
}
126131

132+
// Look up the key.
133+
// If an entry for the key exists, leave map unchanged and return a pointer to its value.
134+
// If no entry for the key exists, create a new entry from key and a default-created value
135+
// and return a pointer to the value.
136+
// *p_created is new if entry was created, false if entry pre-existed.
137+
V* put_if_absent(K const& key, bool* p_created) {
138+
unsigned hv = HASH(key);
139+
Node** ptr = lookup_node(hv, key);
140+
if (*ptr == NULL) {
141+
*ptr = new (ALLOC_TYPE, MEM_TYPE) Node(hv, key);
142+
*p_created = true;
143+
} else {
144+
*p_created = false;
145+
}
146+
return &(*ptr)->_value;
147+
}
148+
149+
// Look up the key.
150+
// If an entry for the key exists, leave map unchanged and return a pointer to its value.
151+
// If no entry for the key exists, create a new entry from key and value and return a
152+
// pointer to the value.
153+
// *p_created is new if entry was created, false if entry pre-existed.
154+
V* put_if_absent(K const& key, V const& value, bool* p_created) {
155+
unsigned hv = HASH(key);
156+
Node** ptr = lookup_node(hv, key);
157+
if (*ptr == NULL) {
158+
*ptr = new (ALLOC_TYPE, MEM_TYPE) Node(hv, key, value);
159+
*p_created = true;
160+
} else {
161+
*p_created = false;
162+
}
163+
return &(*ptr)->_value;
164+
}
165+
166+
127167
bool remove(K const& key) {
128168
unsigned hv = HASH(key);
129169
Node** ptr = lookup_node(hv, key);

test/hotspot/gtest/utilities/test_resourceHash.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@
2626
#include "memory/resourceArea.hpp"
2727
#include "unittest.hpp"
2828
#include "utilities/debug.hpp"
29+
#include "utilities/globalDefinitions.hpp"
2930
#include "utilities/resourceHash.hpp"
3031

3132
class CommonResourceHashtableTest : public ::testing::Test {
3233
protected:
3334
typedef void* K;
34-
typedef int V;
35+
typedef uintx V;
3536
const static MEMFLAGS MEM_TYPE = mtInternal;
3637

3738
static unsigned identity_hash(const K& k) {
@@ -58,6 +59,7 @@ class CommonResourceHashtableTest : public ::testing::Test {
5859
}
5960
}
6061
};
62+
6163
};
6264

6365
class SmallResourceHashtableTest : public CommonResourceHashtableTest {
@@ -96,7 +98,44 @@ class SmallResourceHashtableTest : public CommonResourceHashtableTest {
9698
}
9799

98100
ASSERT_TRUE(rh.remove(as_K(step)));
101+
ASSERT_FALSE(rh.contains(as_K(step)));
102+
rh.iterate(&et);
103+
104+
105+
// Test put_if_absent(key) (creating a default-created value)
106+
bool created = false;
107+
V* v = rh.put_if_absent(as_K(step), &created);
108+
ASSERT_TRUE(rh.contains(as_K(step)));
109+
ASSERT_TRUE(created);
110+
*v = (V)step;
111+
112+
// Calling this function a second time should yield the same value pointer
113+
V* v2 = rh.put_if_absent(as_K(step), &created);
114+
ASSERT_EQ(v, v2);
115+
ASSERT_EQ(*v2, *v);
116+
ASSERT_FALSE(created);
117+
118+
ASSERT_TRUE(rh.remove(as_K(step)));
119+
ASSERT_FALSE(rh.contains(as_K(step)));
99120
rh.iterate(&et);
121+
122+
// Test put_if_absent(key, value)
123+
v = rh.put_if_absent(as_K(step), step, &created);
124+
ASSERT_EQ(*v, step);
125+
ASSERT_TRUE(rh.contains(as_K(step)));
126+
ASSERT_TRUE(created);
127+
128+
v2 = rh.put_if_absent(as_K(step), step, &created);
129+
// Calling this function a second time should yield the same value pointer
130+
ASSERT_EQ(v, v2);
131+
ASSERT_EQ(*v2, (V)step);
132+
ASSERT_FALSE(created);
133+
134+
ASSERT_TRUE(rh.remove(as_K(step)));
135+
ASSERT_FALSE(rh.contains(as_K(step)));
136+
rh.iterate(&et);
137+
138+
100139
}
101140
};
102141
};

0 commit comments

Comments
 (0)