8314502: Change the comparator taking version of GrowableArray::find to be a template method

Reviewed-by: jsjolen, sspitsyn, stefank
This commit is contained in:
Afshin Zafari 2023-11-23 22:16:57 +00:00
parent 28026434f7
commit 14557e72ef
13 changed files with 123 additions and 57 deletions

View File

@ -142,6 +142,11 @@ size_t MutableNUMASpace::free_in_words() const {
return s; return s;
} }
int MutableNUMASpace::lgrp_space_index(int lgrp_id) const {
return lgrp_spaces()->find_if([&](LGRPSpace* space) {
return space->lgrp_id() == checked_cast<uint>(lgrp_id);
});
}
size_t MutableNUMASpace::tlab_capacity(Thread *thr) const { size_t MutableNUMASpace::tlab_capacity(Thread *thr) const {
guarantee(thr != nullptr, "No thread"); guarantee(thr != nullptr, "No thread");
@ -160,7 +165,7 @@ size_t MutableNUMASpace::tlab_capacity(Thread *thr) const {
} }
} }
// That's the normal case, where we know the locality group of the thread. // That's the normal case, where we know the locality group of the thread.
int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); int i = lgrp_space_index(lgrp_id);
if (i == -1) { if (i == -1) {
return 0; return 0;
} }
@ -179,7 +184,7 @@ size_t MutableNUMASpace::tlab_used(Thread *thr) const {
return 0; return 0;
} }
} }
int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); int i = lgrp_space_index(lgrp_id);
if (i == -1) { if (i == -1) {
return 0; return 0;
} }
@ -199,7 +204,7 @@ size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const {
return 0; return 0;
} }
} }
int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); int i = lgrp_space_index(lgrp_id);
if (i == -1) { if (i == -1) {
return 0; return 0;
} }
@ -569,7 +574,7 @@ HeapWord* MutableNUMASpace::cas_allocate(size_t size) {
thr->set_lgrp_id(lgrp_id); thr->set_lgrp_id(lgrp_id);
} }
int i = lgrp_spaces()->find(&lgrp_id, LGRPSpace::equals); int i = lgrp_space_index(lgrp_id);
// It is possible that a new CPU has been hotplugged and // It is possible that a new CPU has been hotplugged and
// we haven't reshaped the space accordingly. // we haven't reshaped the space accordingly.
if (i == -1) { if (i == -1) {

View File

@ -93,10 +93,6 @@ class MutableNUMASpace : public MutableSpace {
delete _alloc_rate; delete _alloc_rate;
} }
static bool equals(void* lgrp_id_value, LGRPSpace* p) {
return *(uint*)lgrp_id_value == p->lgrp_id();
}
// Report a failed allocation. // Report a failed allocation.
void set_allocation_failed() { _allocation_failed = true; } void set_allocation_failed() { _allocation_failed = true; }
@ -158,6 +154,8 @@ class MutableNUMASpace : public MutableSpace {
void select_tails(MemRegion new_region, MemRegion intersection, void select_tails(MemRegion new_region, MemRegion intersection,
MemRegion* bottom_region, MemRegion *top_region); MemRegion* bottom_region, MemRegion *top_region);
int lgrp_space_index(int lgrp_id) const;
public: public:
GrowableArray<LGRPSpace*>* lgrp_spaces() const { return _lgrp_spaces; } GrowableArray<LGRPSpace*>* lgrp_spaces() const { return _lgrp_spaces; }
MutableNUMASpace(size_t alignment); MutableNUMASpace(size_t alignment);

View File

@ -119,14 +119,6 @@ void GrowableCache::recache() {
_listener_fun(_this_obj,_cache); _listener_fun(_this_obj,_cache);
} }
bool GrowableCache::equals(void* v, GrowableElement *e2) {
GrowableElement *e1 = (GrowableElement *) v;
assert(e1 != nullptr, "e1 != nullptr");
assert(e2 != nullptr, "e2 != nullptr");
return e1->equals(e2);
}
// //
// class GrowableCache - public methods // class GrowableCache - public methods
// //
@ -163,8 +155,8 @@ GrowableElement* GrowableCache::at(int index) {
return e; return e;
} }
int GrowableCache::find(GrowableElement* e) { int GrowableCache::find(const GrowableElement* e) const {
return _elements->find(e, GrowableCache::equals); return _elements->find_if([&](const GrowableElement* other_e) { return e->equals(other_e); });
} }
// append a copy of the element to the end of the collection // append a copy of the element to the end of the collection
@ -216,7 +208,7 @@ void JvmtiBreakpoint::copy(JvmtiBreakpoint& bp) {
_class_holder = OopHandle(JvmtiExport::jvmti_oop_storage(), bp._class_holder.resolve()); _class_holder = OopHandle(JvmtiExport::jvmti_oop_storage(), bp._class_holder.resolve());
} }
bool JvmtiBreakpoint::equals(JvmtiBreakpoint& bp) { bool JvmtiBreakpoint::equals(const JvmtiBreakpoint& bp) const {
return _method == bp._method return _method == bp._method
&& _bci == bp._bci; && _bci == bp._bci;
} }

View File

@ -67,8 +67,8 @@ class GrowableElement : public CHeapObj<mtInternal> {
public: public:
virtual ~GrowableElement() {} virtual ~GrowableElement() {}
virtual address getCacheValue() =0; virtual address getCacheValue() =0;
virtual bool equals(GrowableElement* e) =0; virtual bool equals(const GrowableElement* e) const =0;
virtual GrowableElement *clone() =0; virtual GrowableElement* clone() =0;
}; };
class GrowableCache { class GrowableCache {
@ -88,8 +88,6 @@ private:
// (but NOT when cached elements are recomputed). // (but NOT when cached elements are recomputed).
void (*_listener_fun)(void *, address*); void (*_listener_fun)(void *, address*);
static bool equals(void *, GrowableElement *);
// recache all elements after size change, notify listener // recache all elements after size change, notify listener
void recache(); void recache();
@ -104,7 +102,7 @@ public:
// get the value of the index element in the collection // get the value of the index element in the collection
GrowableElement* at(int index); GrowableElement* at(int index);
// find the index of the element, -1 if it doesn't exist // find the index of the element, -1 if it doesn't exist
int find(GrowableElement* e); int find(const GrowableElement* e) const;
// append a copy of the element to the end of the collection, notify listener // append a copy of the element to the end of the collection, notify listener
void append(GrowableElement* e); void append(GrowableElement* e);
// remove the element at index, notify listener // remove the element at index, notify listener
@ -165,7 +163,7 @@ public:
JvmtiBreakpoint() : _method(nullptr), _bci(0) {} JvmtiBreakpoint() : _method(nullptr), _bci(0) {}
JvmtiBreakpoint(Method* m_method, jlocation location); JvmtiBreakpoint(Method* m_method, jlocation location);
virtual ~JvmtiBreakpoint(); virtual ~JvmtiBreakpoint();
bool equals(JvmtiBreakpoint& bp); bool equals(const JvmtiBreakpoint& bp) const;
void copy(JvmtiBreakpoint& bp); void copy(JvmtiBreakpoint& bp);
address getBcp() const; address getBcp() const;
void each_method_version_do(method_action meth_act); void each_method_version_do(method_action meth_act);
@ -177,7 +175,7 @@ public:
// GrowableElement implementation // GrowableElement implementation
address getCacheValue() { return getBcp(); } address getCacheValue() { return getBcp(); }
bool equals(GrowableElement* e) { return equals((JvmtiBreakpoint&) *e); } bool equals(const GrowableElement* e) const { return equals((const JvmtiBreakpoint&) *e); }
GrowableElement *clone() { GrowableElement *clone() {
JvmtiBreakpoint *bp = new JvmtiBreakpoint(); JvmtiBreakpoint *bp = new JvmtiBreakpoint();

View File

@ -185,6 +185,10 @@ void PerfData::create_entry(BasicType dtype, size_t dsize, size_t vlen) {
PerfMemory::mark_updated(); PerfMemory::mark_updated();
} }
bool PerfData::name_equals(const char* name) const {
return strcmp(name, this->name()) == 0;
}
PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v) PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v)
: PerfData(ns, namep, u, v) { : PerfData(ns, namep, u, v) {
@ -501,17 +505,9 @@ PerfDataList::~PerfDataList() {
} }
bool PerfDataList::by_name(void* name, PerfData* pd) {
if (pd == nullptr)
return false;
return strcmp((const char*)name, pd->name()) == 0;
}
PerfData* PerfDataList::find_by_name(const char* name) { PerfData* PerfDataList::find_by_name(const char* name) {
int i = _set->find((void*)name, PerfDataList::by_name); int i = _set->find_if([&](PerfData* pd) { return pd->name_equals(name); });
if (i >= 0 && i <= _set->length()) if (i >= 0 && i <= _set->length())
return _set->at(i); return _set->at(i);

View File

@ -319,7 +319,8 @@ class PerfData : public CHeapObj<mtInternal> {
// PerfData memory region. This redundancy is maintained for // PerfData memory region. This redundancy is maintained for
// security reasons as the PerfMemory region may be in shared // security reasons as the PerfMemory region may be in shared
// memory. // memory.
const char* name() { return _name; } const char* name() const { return _name; }
bool name_equals(const char* name) const;
// returns the variability classification associated with this item // returns the variability classification associated with this item
Variability variability() { return _v; } Variability variability() { return _v; }
@ -576,7 +577,7 @@ class PerfDataList : public CHeapObj<mtInternal> {
PerfDataArray* _set; PerfDataArray* _set;
// method to search for a instrumentation object by name // method to search for a instrumentation object by name
static bool by_name(void* name, PerfData* pd); static bool by_name(const char* name, PerfData* pd);
protected: protected:
// we expose the implementation here to facilitate the clone // we expose the implementation here to facilitate the clone

View File

@ -71,11 +71,6 @@ void UnhandledOops::register_unhandled_oop(oop* op) {
_oop_list->push(entry); _oop_list->push(entry);
} }
bool match_oop_entry(void *op, UnhandledOopEntry e) {
return (e.oop_ptr() == op);
}
// Mark unhandled oop as okay for GC - the containing struct has an oops_do and // Mark unhandled oop as okay for GC - the containing struct has an oops_do and
// for some reason the oop has to be on the stack. // for some reason the oop has to be on the stack.
// May not be called for the current thread, as in the case of // May not be called for the current thread, as in the case of
@ -83,7 +78,9 @@ bool match_oop_entry(void *op, UnhandledOopEntry e) {
void UnhandledOops::allow_unhandled_oop(oop* op) { void UnhandledOops::allow_unhandled_oop(oop* op) {
assert (CheckUnhandledOops, "should only be called with checking option"); assert (CheckUnhandledOops, "should only be called with checking option");
int i = _oop_list->find_from_end(op, match_oop_entry); int i = _oop_list->find_from_end_if([&](const UnhandledOopEntry& e) {
return e.match_oop_entry(op);
});
assert(i!=-1, "safe for gc oop not in unhandled_oop_list"); assert(i!=-1, "safe for gc oop not in unhandled_oop_list");
UnhandledOopEntry entry = _oop_list->at(i); UnhandledOopEntry entry = _oop_list->at(i);
@ -105,7 +102,9 @@ void UnhandledOops::unregister_unhandled_oop(oop* op) {
} }
_level--; _level--;
int i = _oop_list->find_from_end(op, match_oop_entry); int i = _oop_list->find_from_end_if([&](const UnhandledOopEntry& e) {
return e.match_oop_entry(op);
});
assert(i!=-1, "oop not in unhandled_oop_list"); assert(i!=-1, "oop not in unhandled_oop_list");
_oop_list->remove_at(i); _oop_list->remove_at(i);
} }

View File

@ -53,14 +53,17 @@ class UnhandledOopEntry : public CHeapObj<mtThread> {
private: private:
oop* _oop_ptr; oop* _oop_ptr;
bool _ok_for_gc; bool _ok_for_gc;
bool match_oop_entry(oop* op) const {
return _oop_ptr == op;
}
public: public:
oop* oop_ptr() { return _oop_ptr; }
UnhandledOopEntry() : _oop_ptr(nullptr), _ok_for_gc(false) {} UnhandledOopEntry() : _oop_ptr(nullptr), _ok_for_gc(false) {}
UnhandledOopEntry(oop* op) : UnhandledOopEntry(oop* op) :
_oop_ptr(op), _ok_for_gc(false) {} _oop_ptr(op), _ok_for_gc(false) {}
}; };
class UnhandledOops : public CHeapObj<mtThread> { class UnhandledOops : public CHeapObj<mtThread> {
friend class Thread; friend class Thread;
private: private:

View File

@ -144,9 +144,8 @@ bool DCmdArgIter::next(TRAPS) {
return _key_len != 0; return _key_len != 0;
} }
bool DCmdInfo::by_name(void* cmd_name, DCmdInfo* info) { bool DCmdInfo::name_equals(const char* name) const {
if (info == nullptr) return false; return strcmp(name, this->name()) == 0;
return strcmp((const char*)cmd_name, info->name()) == 0;
} }
void DCmdParser::add_dcmd_option(GenDCmdArgument* arg) { void DCmdParser::add_dcmd_option(GenDCmdArgument* arg) {

View File

@ -140,13 +140,12 @@ public:
: _name(name), _description(description), _impact(impact), _permission(permission), : _name(name), _description(description), _impact(impact), _permission(permission),
_num_arguments(num_arguments), _is_enabled(enabled) {} _num_arguments(num_arguments), _is_enabled(enabled) {}
const char* name() const { return _name; } const char* name() const { return _name; }
bool name_equals(const char* cmd_name) const;
const char* description() const { return _description; } const char* description() const { return _description; }
const char* impact() const { return _impact; } const char* impact() const { return _impact; }
const JavaPermission& permission() const { return _permission; } const JavaPermission& permission() const { return _permission; }
int num_arguments() const { return _num_arguments; } int num_arguments() const { return _num_arguments; }
bool is_enabled() const { return _is_enabled; } bool is_enabled() const { return _is_enabled; }
static bool by_name(void* name, DCmdInfo* info);
}; };
// A DCmdArgumentInfo instance provides a description of a diagnostic command // A DCmdArgumentInfo instance provides a description of a diagnostic command

View File

@ -2004,7 +2004,9 @@ JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds,
THROW_MSG(vmSymbols::java_lang_NullPointerException(), THROW_MSG(vmSymbols::java_lang_NullPointerException(),
"Command name cannot be null."); "Command name cannot be null.");
} }
int pos = info_list->find((void*)cmd_name,DCmdInfo::by_name); int pos = info_list->find_if([&](DCmdInfo* info) {
return info->name_equals(cmd_name);
});
if (pos == -1) { if (pos == -1) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Unknown diagnostic command"); "Unknown diagnostic command");

View File

@ -209,17 +209,29 @@ public:
return -1; return -1;
} }
int find(void* token, bool f(void*, E)) const { // Find first element that matches the given predicate.
//
// Predicate: bool predicate(const E& elem)
//
// Returns the index of the element or -1 if no element matches the predicate
template<typename Predicate>
int find_if(Predicate predicate) const {
for (int i = 0; i < _len; i++) { for (int i = 0; i < _len; i++) {
if (f(token, _data[i])) return i; if (predicate(_data[i])) return i;
} }
return -1; return -1;
} }
int find_from_end(void* token, bool f(void*, E)) const { // Find last element that matches the given predicate.
//
// Predicate: bool predicate(const E& elem)
//
// Returns the index of the element or -1 if no element matches the predicate
template<typename Predicate>
int find_from_end_if(Predicate predicate) const {
// start at the end of the array // start at the end of the array
for (int i = _len-1; i >= 0; i--) { for (int i = _len-1; i >= 0; i--) {
if (f(token, _data[i])) return i; if (predicate(_data[i])) return i;
} }
return -1; return -1;
} }

View File

@ -601,3 +601,65 @@ TEST(GrowableArrayCHeap, sanity) {
delete a; delete a;
} }
} }
TEST(GrowableArrayCHeap, find_if) {
struct Element {
int value;
};
GrowableArrayCHeap<Element, mtTest> array;
array.push({1});
array.push({2});
array.push({3});
{
int index = array.find_if([&](const Element& elem) {
return elem.value == 1;
});
ASSERT_EQ(index, 0);
}
{
int index = array.find_if([&](const Element& elem) {
return elem.value > 1;
});
ASSERT_EQ(index, 1);
}
{
int index = array.find_if([&](const Element& elem) {
return elem.value == 4;
});
ASSERT_EQ(index, -1);
}
}
TEST(GrowableArrayCHeap, find_from_end_if) {
struct Element {
int value;
};
GrowableArrayCHeap<Element, mtTest> array;
array.push({1});
array.push({2});
array.push({3});
{
int index = array.find_from_end_if([&](const Element& elem) {
return elem.value == 1;
});
ASSERT_EQ(index, 0);
}
{
int index = array.find_from_end_if([&](const Element& elem) {
return elem.value > 1;
});
ASSERT_EQ(index, 2);
}
{
int index = array.find_from_end_if([&](const Element& elem) {
return elem.value == 4;
});
ASSERT_EQ(index, -1);
}
}