8301403: Eliminate memory allocations in JVMFlag::printFlags during signal handling

Reviewed-by: stuefe, jsjolen, dholmes
This commit is contained in:
Gerard Ziemski 2024-07-30 15:22:25 +00:00
parent 2c9fd9016f
commit a91f9ba849
4 changed files with 36 additions and 34 deletions
src/hotspot/share

@ -31,6 +31,7 @@
#include "runtime/flags/jvmFlagAccess.hpp"
#include "runtime/flags/jvmFlagLookup.hpp"
#include "runtime/globals_extension.hpp"
#include "utilities/bitMap.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/stringUtils.hpp"
@ -692,7 +693,7 @@ void JVMFlag::printFlags(outputStream* out, bool withComments, bool printRanges,
// called as part of error reporting, so handle native OOMs gracefully.
// The last entry is the null entry.
const size_t length = JVMFlag::numFlags - 1;
constexpr size_t length = (sizeof(flagTable) / sizeof(JVMFlag)) - 1;
// Print
if (!printRanges) {
@ -701,26 +702,26 @@ void JVMFlag::printFlags(outputStream* out, bool withComments, bool printRanges,
out->print_cr("[Global flags ranges]");
}
// Sort
JVMFlag** array = NEW_C_HEAP_ARRAY_RETURN_NULL(JVMFlag*, length, mtArguments);
if (array != nullptr) {
BitMap::bm_word_t iteratorArray[BitMap::calc_size_in_words(length)];
BitMapView iteratorMarkers(iteratorArray, length);
iteratorMarkers.clear_range(0, length);
// Print the flag with best sort value, then mark it.
for (size_t j = 0; j < length; j++) {
JVMFlag* bestFlag = nullptr;
size_t bestFlagIndex = 0;
for (size_t i = 0; i < length; i++) {
array[i] = &flagTable[i];
}
qsort(array, length, sizeof(JVMFlag*), compare_flags);
for (size_t i = 0; i < length; i++) {
if (array[i]->is_unlocked() && !(skipDefaults && array[i]->is_default())) {
array[i]->print_on(out, withComments, printRanges);
const bool skip = (skipDefaults && flagTable[i].is_default());
const bool visited = iteratorMarkers.at(i);
if (!visited && flagTable[i].is_unlocked() && !skip) {
if ((bestFlag == nullptr) || (strcmp(bestFlag->name(), flagTable[i].name()) > 0)) {
bestFlag = &flagTable[i];
bestFlagIndex = i;
}
}
}
FREE_C_HEAP_ARRAY(JVMFlag*, array);
} else {
// OOM? Print unsorted.
for (size_t i = 0; i < length; i++) {
if (flagTable[i].is_unlocked() && !(skipDefaults && flagTable[i].is_default())) {
flagTable[i].print_on(out, withComments, printRanges);
}
if (bestFlag != nullptr) {
bestFlag->print_on(out, withComments, printRanges);
iteratorMarkers.at_put(bestFlagIndex, true);
}
}
}

@ -197,11 +197,6 @@ bm_word_t* CHeapBitMap::reallocate(bm_word_t* map, size_t old_size_in_words, siz
}
#ifdef ASSERT
void BitMap::verify_size(idx_t size_in_bits) {
assert(size_in_bits <= max_size_in_bits(),
"out of bounds: " SIZE_FORMAT, size_in_bits);
}
void BitMap::verify_index(idx_t bit) const {
assert(bit < _size,
"BitMap index out of bounds: " SIZE_FORMAT " >= " SIZE_FORMAT,

@ -67,16 +67,16 @@ class BitMap {
protected:
// The maximum allowable size of a bitmap, in words or bits.
// Limit max_size_in_bits so aligning up to a word boundary never overflows.
static idx_t max_size_in_words() { return raw_to_words_align_down(~idx_t(0)); }
static idx_t max_size_in_bits() { return max_size_in_words() * BitsPerWord; }
constexpr static idx_t max_size_in_words() { return raw_to_words_align_down(~idx_t(0)); }
constexpr static idx_t max_size_in_bits() { return max_size_in_words() * BitsPerWord; }
// Assumes relevant validity checking for bit has already been done.
static idx_t raw_to_words_align_up(idx_t bit) {
constexpr static idx_t raw_to_words_align_up(idx_t bit) {
return raw_to_words_align_down(bit + (BitsPerWord - 1));
}
// Assumes relevant validity checking for bit has already been done.
static idx_t raw_to_words_align_down(idx_t bit) {
constexpr static idx_t raw_to_words_align_down(idx_t bit) {
return bit >> LogBitsPerWord;
}
@ -195,7 +195,7 @@ class BitMap {
void pretouch();
// Accessing
static idx_t calc_size_in_words(size_t size_in_bits) {
constexpr static idx_t calc_size_in_words(size_t size_in_bits) {
verify_size(size_in_bits);
return raw_to_words_align_up(size_in_bits);
}
@ -257,7 +257,13 @@ class BitMap {
// Verification.
// Verify size_in_bits does not exceed max_size_in_bits().
static void verify_size(idx_t size_in_bits) NOT_DEBUG_RETURN;
constexpr static void verify_size(idx_t size_in_bits) {
#ifdef ASSERT
assert(size_in_bits <= max_size_in_bits(),
"out of bounds: " SIZE_FORMAT, size_in_bits);
#endif
}
// Verify bit is less than size().
void verify_index(idx_t bit) const NOT_DEBUG_RETURN;
// Verify bit is not greater than size().

@ -222,9 +222,9 @@ FORBID_C_FUNCTION(void* reallocf(void *ptr, size_t size), "don't use");
const int LogBytesPerShort = 1;
const int LogBytesPerInt = 2;
#ifdef _LP64
const int LogBytesPerWord = 3;
constexpr int LogBytesPerWord = 3;
#else
const int LogBytesPerWord = 2;
constexpr int LogBytesPerWord = 2;
#endif
const int LogBytesPerLong = 3;
@ -233,16 +233,16 @@ const int BytesPerInt = 1 << LogBytesPerInt;
const int BytesPerWord = 1 << LogBytesPerWord;
const int BytesPerLong = 1 << LogBytesPerLong;
const int LogBitsPerByte = 3;
constexpr int LogBitsPerByte = 3;
const int LogBitsPerShort = LogBitsPerByte + LogBytesPerShort;
const int LogBitsPerInt = LogBitsPerByte + LogBytesPerInt;
const int LogBitsPerWord = LogBitsPerByte + LogBytesPerWord;
constexpr int LogBitsPerWord = LogBitsPerByte + LogBytesPerWord;
const int LogBitsPerLong = LogBitsPerByte + LogBytesPerLong;
const int BitsPerByte = 1 << LogBitsPerByte;
const int BitsPerShort = 1 << LogBitsPerShort;
const int BitsPerInt = 1 << LogBitsPerInt;
const int BitsPerWord = 1 << LogBitsPerWord;
constexpr int BitsPerWord = 1 << LogBitsPerWord;
const int BitsPerLong = 1 << LogBitsPerLong;
const int WordAlignmentMask = (1 << LogBytesPerWord) - 1;