Skip to content

Commit b544b8b

Browse files
committedJun 3, 2022
8276789: Support C++ lambda in ResourceHashtable::iterate
Reviewed-by: stefank, coleenp
1 parent ba9ee8c commit b544b8b

File tree

5 files changed

+74
-83
lines changed

5 files changed

+74
-83
lines changed
 

‎src/hotspot/share/cds/dumpTimeClassInfo.cpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -193,21 +193,20 @@ class CountClassByCategory : StackObj {
193193
DumpTimeSharedClassTable* _table;
194194
public:
195195
CountClassByCategory(DumpTimeSharedClassTable* table) : _table(table) {}
196-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
196+
void do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
197197
if (!info.is_excluded()) {
198198
if (info.is_builtin()) {
199199
_table->inc_builtin_count();
200200
} else {
201201
_table->inc_unregistered_count();
202202
}
203203
}
204-
return true; // keep on iterating
205204
}
206205
};
207206

208207
void DumpTimeSharedClassTable::update_counts() {
209208
_builtin_count = 0;
210209
_unregistered_count = 0;
211210
CountClassByCategory counter(this);
212-
iterate(&counter);
211+
iterate_all_live_classes(&counter);
213212
}

‎src/hotspot/share/cds/dumpTimeClassInfo.hpp

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
/*
32
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
43
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -209,10 +208,17 @@ class DumpTimeSharedClassTable: public DumpTimeSharedClassTableBaseType
209208
}
210209
}
211210

212-
// Overrides ResourceHashtable<>::iterate(ITER*)
213-
template<class ITER> void iterate(ITER* iter) const;
211+
template<class ITER> void iterate_all_live_classes(ITER* iter) const;
212+
template<typename Function> void iterate_all_live_classes(Function function) const;
213+
214214
private:
215-
template<class ITER> class IterationHelper;
215+
// It's unsafe to iterate on classes whose loader is dead.
216+
// Declare these private and don't implement them. This forces users of
217+
// DumpTimeSharedClassTable to use the iterate_all_live_classes() methods
218+
// instead.
219+
template<class ITER> void iterate(ITER* iter) const;
220+
template<typename Function> void iterate(Function function) const;
221+
template<typename Function> void iterate_all(Function function) const;
216222
};
217223

218224
#endif // SHARED_CDS_DUMPTIMESHAREDCLASSINFO_HPP

‎src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp

+16-20
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
/*
3-
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -35,38 +35,34 @@
3535

3636
#if INCLUDE_CDS
3737

38-
// For safety, only iterate over a class if it loader is alive.
39-
// IterationHelper and DumpTimeSharedClassTable::iterate
40-
// must be used only inside a safepoint, where the value of
38+
// For safety, only iterate over a class if its loader is alive.
39+
// This function must be called only inside a safepoint, where the value of
4140
// k->is_loader_alive() will not change.
42-
template<class ITER>
43-
class DumpTimeSharedClassTable::IterationHelper {
44-
ITER* _iter;
45-
public:
46-
IterationHelper(ITER* iter) {
47-
_iter = iter;
48-
}
49-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
41+
template<typename Function>
42+
void DumpTimeSharedClassTable::iterate_all_live_classes(Function function) const {
43+
auto wrapper = [&] (InstanceKlass* k, DumpTimeClassInfo& info) {
5044
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
5145
assert_lock_strong(DumpTimeTable_lock);
5246
if (k->is_loader_alive()) {
53-
bool result = _iter->do_entry(k, info);
47+
function(k, info);
5448
assert(k->is_loader_alive(), "must not change");
55-
return result;
5649
} else {
5750
if (!SystemDictionaryShared::is_excluded_class(k)) {
5851
SystemDictionaryShared::warn_excluded(k, "Class loader not alive");
5952
SystemDictionaryShared::set_excluded_locked(k);
6053
}
61-
return true;
6254
}
63-
}
64-
};
55+
};
56+
DumpTimeSharedClassTableBaseType::iterate_all(wrapper);
57+
}
58+
6559

6660
template<class ITER>
67-
void DumpTimeSharedClassTable::iterate(ITER* iter) const {
68-
IterationHelper<ITER> helper(iter);
69-
DumpTimeSharedClassTableBaseType::iterate(&helper);
61+
void DumpTimeSharedClassTable::iterate_all_live_classes(ITER* iter) const {
62+
auto function = [&] (InstanceKlass* k, DumpTimeClassInfo& v) {
63+
iter->do_entry(k, v);
64+
};
65+
iterate_all_live_classes(function);
7066
}
7167

7268
#endif // INCLUDE_CDS

‎src/hotspot/share/classfile/systemDictionaryShared.cpp

+26-54
Original file line numberDiff line numberDiff line change
@@ -617,11 +617,10 @@ class UnregisteredClassesDuplicationChecker : StackObj {
617617
public:
618618
UnregisteredClassesDuplicationChecker() : _thread(Thread::current()) {}
619619

620-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
620+
void do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
621621
if (!SystemDictionaryShared::is_builtin(k)) {
622622
_list.append(k);
623623
}
624-
return true; // keep on iterating
625624
}
626625

627626
static int compare_by_loader(InstanceKlass** a, InstanceKlass** b) {
@@ -653,29 +652,23 @@ class UnregisteredClassesDuplicationChecker : StackObj {
653652
}
654653
};
655654

656-
class ExcludeDumpTimeSharedClasses : StackObj {
657-
public:
658-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
659-
SystemDictionaryShared::check_for_exclusion(k, &info);
660-
return true; // keep on iterating
661-
}
662-
};
663-
664655
void SystemDictionaryShared::check_excluded_classes() {
665656
assert(no_class_loading_should_happen(), "sanity");
666657
assert_lock_strong(DumpTimeTable_lock);
667658

668659
if (DynamicDumpSharedSpaces) {
669660
// Do this first -- if a base class is excluded due to duplication,
670-
// all of its subclasses will also be excluded by ExcludeDumpTimeSharedClasses
661+
// all of its subclasses will also be excluded.
671662
ResourceMark rm;
672663
UnregisteredClassesDuplicationChecker dup_checker;
673-
_dumptime_table->iterate(&dup_checker);
664+
_dumptime_table->iterate_all_live_classes(&dup_checker);
674665
dup_checker.mark_duplicated_classes();
675666
}
676667

677-
ExcludeDumpTimeSharedClasses excl;
678-
_dumptime_table->iterate(&excl);
668+
auto check_for_exclusion = [&] (InstanceKlass* k, DumpTimeClassInfo& info) {
669+
SystemDictionaryShared::check_for_exclusion(k, &info);
670+
};
671+
_dumptime_table->iterate_all_live_classes(check_for_exclusion);
679672
_dumptime_table->update_counts();
680673

681674
cleanup_lambda_proxy_class_dictionary();
@@ -725,42 +718,24 @@ bool SystemDictionaryShared::has_class_failed_verification(InstanceKlass* ik) {
725718
return (p == NULL) ? false : p->failed_verification();
726719
}
727720

728-
class IterateDumpTimeSharedClassTable : StackObj {
729-
MetaspaceClosure *_it;
730-
public:
731-
IterateDumpTimeSharedClassTable(MetaspaceClosure* it) : _it(it) {}
721+
void SystemDictionaryShared::dumptime_classes_do(class MetaspaceClosure* it) {
722+
assert_lock_strong(DumpTimeTable_lock);
732723

733-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
734-
assert_lock_strong(DumpTimeTable_lock);
724+
auto do_klass = [&] (InstanceKlass* k, DumpTimeClassInfo& info) {
735725
if (k->is_loader_alive() && !info.is_excluded()) {
736-
info.metaspace_pointers_do(_it);
726+
info.metaspace_pointers_do(it);
737727
}
738-
return true; // keep on iterating
739-
}
740-
};
728+
};
729+
_dumptime_table->iterate_all_live_classes(do_klass);
741730

742-
class IterateDumpTimeLambdaProxyClassDictionary : StackObj {
743-
MetaspaceClosure *_it;
744-
public:
745-
IterateDumpTimeLambdaProxyClassDictionary(MetaspaceClosure* it) : _it(it) {}
746-
747-
bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
748-
assert_lock_strong(DumpTimeTable_lock);
749-
if (key.caller_ik()->is_loader_alive()) {
750-
info.metaspace_pointers_do(_it);
751-
key.metaspace_pointers_do(_it);
752-
}
753-
return true; // keep on iterating
754-
}
755-
};
756-
757-
void SystemDictionaryShared::dumptime_classes_do(class MetaspaceClosure* it) {
758-
assert_lock_strong(DumpTimeTable_lock);
759-
IterateDumpTimeSharedClassTable iter(it);
760-
_dumptime_table->iterate(&iter);
761731
if (_dumptime_lambda_proxy_class_dictionary != NULL) {
762-
IterateDumpTimeLambdaProxyClassDictionary iter_lambda(it);
763-
_dumptime_lambda_proxy_class_dictionary->iterate(&iter_lambda);
732+
auto do_lambda = [&] (LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
733+
if (key.caller_ik()->is_loader_alive()) {
734+
info.metaspace_pointers_do(it);
735+
key.metaspace_pointers_do(it);
736+
}
737+
};
738+
_dumptime_lambda_proxy_class_dictionary->iterate_all(do_lambda);
764739
}
765740
}
766741

@@ -1172,12 +1147,11 @@ class EstimateSizeForArchive : StackObj {
11721147
_num_unregistered_klasses = 0;
11731148
}
11741149

1175-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
1150+
void do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
11761151
if (!info.is_excluded()) {
11771152
size_t byte_size = info.runtime_info_bytesize();
11781153
_shared_class_info_size += align_up(byte_size, SharedSpaceObjectAlignment);
11791154
}
1180-
return true; // keep on iterating
11811155
}
11821156

11831157
size_t total() {
@@ -1187,7 +1161,7 @@ class EstimateSizeForArchive : StackObj {
11871161

11881162
size_t SystemDictionaryShared::estimate_size_for_archive() {
11891163
EstimateSizeForArchive est;
1190-
_dumptime_table->iterate(&est);
1164+
_dumptime_table->iterate_all_live_classes(&est);
11911165
size_t total_size = est.total() +
11921166
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(true)) +
11931167
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(false));
@@ -1281,7 +1255,7 @@ class CopySharedClassInfoToArchive : StackObj {
12811255
bool is_builtin)
12821256
: _writer(writer), _is_builtin(is_builtin), _builder(ArchiveBuilder::current()) {}
12831257

1284-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
1258+
void do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
12851259
if (!info.is_excluded() && info.is_builtin() == _is_builtin) {
12861260
size_t byte_size = info.runtime_info_bytesize();
12871261
RunTimeClassInfo* record;
@@ -1305,7 +1279,6 @@ class CopySharedClassInfoToArchive : StackObj {
13051279
// Save this for quick runtime lookup of InstanceKlass* -> RunTimeClassInfo*
13061280
RunTimeClassInfo::set_for(info._klass, record);
13071281
}
1308-
return true; // keep on iterating
13091282
}
13101283
};
13111284

@@ -1325,7 +1298,7 @@ void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionar
13251298
CompactHashtableWriter writer(_dumptime_table->count_of(is_builtin), &stats);
13261299
CopySharedClassInfoToArchive copy(&writer, is_builtin);
13271300
assert_lock_strong(DumpTimeTable_lock);
1328-
_dumptime_table->iterate(&copy);
1301+
_dumptime_table->iterate_all_live_classes(&copy);
13291302
writer.dump(dictionary, is_builtin ? "builtin dictionary" : "unregistered dictionary");
13301303
}
13311304

@@ -1558,12 +1531,11 @@ class CloneDumpTimeClassTable: public StackObj {
15581531
assert(_table != NULL, "_dumptime_table is NULL");
15591532
assert(_cloned_table != NULL, "_cloned_table is NULL");
15601533
}
1561-
bool do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
1534+
void do_entry(InstanceKlass* k, DumpTimeClassInfo& info) {
15621535
if (!info.is_excluded()) {
15631536
bool created;
15641537
_cloned_table->put_if_absent(k, info.clone(), &created);
15651538
}
1566-
return true; // keep on iterating
15671539
}
15681540
};
15691541

@@ -1596,7 +1568,7 @@ void SystemDictionaryShared::clone_dumptime_tables() {
15961568
assert(_cloned_dumptime_table == NULL, "_cloned_dumptime_table must be cleaned");
15971569
_cloned_dumptime_table = new (ResourceObj::C_HEAP, mtClass) DumpTimeSharedClassTable;
15981570
CloneDumpTimeClassTable copy_classes(_dumptime_table, _cloned_dumptime_table);
1599-
_dumptime_table->iterate(&copy_classes);
1571+
_dumptime_table->iterate_all_live_classes(&copy_classes);
16001572
_cloned_dumptime_table->update_counts();
16011573
}
16021574
if (_dumptime_lambda_proxy_class_dictionary != NULL) {

‎src/hotspot/share/utilities/resourceHash.hpp

+20-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2022, 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
@@ -203,19 +203,37 @@ class ResourceHashtableBase : public STORAGE {
203203
// the iteration is cancelled.
204204
template<class ITER>
205205
void iterate(ITER* iter) const {
206+
auto function = [&] (K& k, V& v) {
207+
return iter->do_entry(k, v);
208+
};
209+
iterate(function);
210+
}
211+
212+
template<typename Function>
213+
void iterate(Function function) const { // lambda enabled API
206214
Node* const* bucket = table();
207215
const unsigned sz = table_size();
208216
while (bucket < bucket_at(sz)) {
209217
Node* node = *bucket;
210218
while (node != NULL) {
211-
bool cont = iter->do_entry(node->_key, node->_value);
219+
bool cont = function(node->_key, node->_value);
212220
if (!cont) { return; }
213221
node = node->_next;
214222
}
215223
++bucket;
216224
}
217225
}
218226

227+
// same as above, but unconditionally iterate all entries
228+
template<typename Function>
229+
void iterate_all(Function function) const { // lambda enabled API
230+
auto wrapper = [&] (K& k, V& v) {
231+
function(k, v);
232+
return true;
233+
};
234+
iterate(wrapper);
235+
}
236+
219237
// ITER contains bool do_entry(K const&, V const&), which will be
220238
// called for each entry in the table. If do_entry() returns true,
221239
// the entry is deleted.

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on Jun 3, 2022

@openjdk-notifier[bot]
Please sign in to comment.