Skip to content

Commit 8e8e584

Browse files
committed
8257588: Make os::_page_sizes a bitmask
Reviewed-by: tschatzl, stefank
1 parent 566d77a commit 8e8e584

File tree

7 files changed

+198
-57
lines changed

7 files changed

+198
-57
lines changed

src/hotspot/os/aix/os_aix.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2441,7 +2441,7 @@ void os::init(void) {
24412441

24422442
// For now UseLargePages is just ignored.
24432443
FLAG_SET_ERGO(UseLargePages, false);
2444-
_page_sizes[0] = 0;
2444+
_page_sizes.add(Aix::_page_size);
24452445

24462446
// debug trace
24472447
trcVerbose("os::vm_page_size %s", describe_pagesize(os::vm_page_size()));

src/hotspot/os/bsd/os_bsd.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2093,7 +2093,7 @@ void os::init(void) {
20932093
if (Bsd::page_size() == -1) {
20942094
fatal("os_bsd.cpp: os::init: sysconf failed (%s)", os::strerror(errno));
20952095
}
2096-
init_page_sizes((size_t) Bsd::page_size());
2096+
_page_sizes.add(Bsd::page_size());
20972097

20982098
Bsd::initialize_system_info();
20992099

src/hotspot/os/linux/os_linux.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3769,9 +3769,7 @@ size_t os::Linux::setup_large_page_size() {
37693769

37703770
const size_t default_page_size = (size_t)Linux::page_size();
37713771
if (_large_page_size > default_page_size) {
3772-
_page_sizes[0] = _large_page_size;
3773-
_page_sizes[1] = default_page_size;
3774-
_page_sizes[2] = 0;
3772+
_page_sizes.add(_large_page_size);
37753773
}
37763774

37773775
return _large_page_size;
@@ -4399,7 +4397,7 @@ void os::init(void) {
43994397
fatal("os_linux.cpp: os::init: sysconf failed (%s)",
44004398
os::strerror(errno));
44014399
}
4402-
init_page_sizes((size_t) Linux::page_size());
4400+
_page_sizes.add(Linux::page_size());
44034401

44044402
Linux::initialize_system_info();
44054403

src/hotspot/os/windows/os_windows.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,12 +3118,9 @@ void os::large_page_init() {
31183118
}
31193119

31203120
_large_page_size = large_page_init_decide_size();
3121-
31223121
const size_t default_page_size = (size_t) vm_page_size();
31233122
if (_large_page_size > default_page_size) {
3124-
_page_sizes[0] = _large_page_size;
3125-
_page_sizes[1] = default_page_size;
3126-
_page_sizes[2] = 0;
3123+
_page_sizes.add(_large_page_size);
31273124
}
31283125

31293126
UseLargePages = _large_page_size != 0;
@@ -4167,7 +4164,7 @@ void os::init(void) {
41674164

41684165
win32::initialize_system_info();
41694166
win32::setmode_streams();
4170-
init_page_sizes((size_t) win32::vm_page_size());
4167+
_page_sizes.add(win32::vm_page_size());
41714168

41724169
// This may be overridden later when argument processing is done.
41734170
FLAG_SET_ERGO(UseLargePagesIndividualAllocation, false);

src/hotspot/share/runtime/os.cpp

Lines changed: 75 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@
6464
#include "services/nmtCommon.hpp"
6565
#include "services/threadService.hpp"
6666
#include "utilities/align.hpp"
67+
#include "utilities/count_trailing_zeros.hpp"
6768
#include "utilities/defaultStream.hpp"
6869
#include "utilities/events.hpp"
70+
#include "utilities/powerOfTwo.hpp"
6971

7072
# include <signal.h>
7173
# include <errno.h>
@@ -75,7 +77,7 @@ address os::_polling_page = NULL;
7577
volatile unsigned int os::_rand_seed = 1234567;
7678
int os::_processor_count = 0;
7779
int os::_initial_active_processor_count = 0;
78-
size_t os::_page_sizes[os::page_sizes_max];
80+
os::PageSizes os::_page_sizes;
7981

8082
#ifndef PRODUCT
8183
julong os::num_mallocs = 0; // # of calls to malloc/realloc
@@ -1390,8 +1392,8 @@ size_t os::page_size_for_region(size_t region_size, size_t min_pages, bool must_
13901392
if (UseLargePages) {
13911393
const size_t max_page_size = region_size / min_pages;
13921394

1393-
for (size_t i = 0; _page_sizes[i] != 0; ++i) {
1394-
const size_t page_size = _page_sizes[i];
1395+
for (size_t page_size = page_sizes().largest(); page_size != 0;
1396+
page_size = page_sizes().next_smaller(page_size)) {
13951397
if (page_size <= max_page_size) {
13961398
if (!must_be_aligned || is_aligned(region_size, page_size)) {
13971399
return page_size;
@@ -1536,19 +1538,6 @@ const char* os::errno_name(int e) {
15361538
return errno_to_string(e, true);
15371539
}
15381540

1539-
void os::trace_page_sizes(const char* str, const size_t* page_sizes, int count) {
1540-
LogTarget(Info, pagesize) log;
1541-
if (log.is_enabled()) {
1542-
LogStream out(log);
1543-
1544-
out.print("%s: ", str);
1545-
for (int i = 0; i < count; ++i) {
1546-
out.print(" " SIZE_FORMAT, page_sizes[i]);
1547-
}
1548-
out.cr();
1549-
}
1550-
}
1551-
15521541
#define trace_page_size_params(size) byte_size_in_exact_unit(size), exact_unit_for_byte_size(size)
15531542

15541543
void os::trace_page_sizes(const char* str,
@@ -1862,3 +1851,73 @@ void os::naked_sleep(jlong millis) {
18621851
}
18631852
naked_short_sleep(millis);
18641853
}
1854+
1855+
1856+
////// Implementation of PageSizes
1857+
1858+
void os::PageSizes::add(size_t page_size) {
1859+
assert(is_power_of_2(page_size), "page_size must be a power of 2: " SIZE_FORMAT_HEX, page_size);
1860+
_v |= page_size;
1861+
}
1862+
1863+
bool os::PageSizes::contains(size_t page_size) const {
1864+
assert(is_power_of_2(page_size), "page_size must be a power of 2: " SIZE_FORMAT_HEX, page_size);
1865+
return (_v & page_size) != 0;
1866+
}
1867+
1868+
size_t os::PageSizes::next_smaller(size_t page_size) const {
1869+
assert(is_power_of_2(page_size), "page_size must be a power of 2: " SIZE_FORMAT_HEX, page_size);
1870+
size_t v2 = _v & (page_size - 1);
1871+
if (v2 == 0) {
1872+
return 0;
1873+
}
1874+
return round_down_power_of_2(v2);
1875+
}
1876+
1877+
size_t os::PageSizes::next_larger(size_t page_size) const {
1878+
assert(is_power_of_2(page_size), "page_size must be a power of 2: " SIZE_FORMAT_HEX, page_size);
1879+
if (page_size == max_power_of_2<size_t>()) { // Shift by 32/64 would be UB
1880+
return 0;
1881+
}
1882+
// Remove current and smaller page sizes
1883+
size_t v2 = _v & ~(page_size + (page_size - 1));
1884+
if (v2 == 0) {
1885+
return 0;
1886+
}
1887+
return (size_t)1 << count_trailing_zeros(v2);
1888+
}
1889+
1890+
size_t os::PageSizes::largest() const {
1891+
const size_t max = max_power_of_2<size_t>();
1892+
if (contains(max)) {
1893+
return max;
1894+
}
1895+
return next_smaller(max);
1896+
}
1897+
1898+
size_t os::PageSizes::smallest() const {
1899+
// Strictly speaking the set should not contain sizes < os::vm_page_size().
1900+
// But this is not enforced.
1901+
return next_larger(1);
1902+
}
1903+
1904+
void os::PageSizes::print_on(outputStream* st) const {
1905+
bool first = true;
1906+
for (size_t sz = smallest(); sz != 0; sz = next_larger(sz)) {
1907+
if (first) {
1908+
first = false;
1909+
} else {
1910+
st->print_raw(", ");
1911+
}
1912+
if (sz < M) {
1913+
st->print(SIZE_FORMAT "k", sz / K);
1914+
} else if (sz < G) {
1915+
st->print(SIZE_FORMAT "M", sz / M);
1916+
} else {
1917+
st->print(SIZE_FORMAT "G", sz / G);
1918+
}
1919+
}
1920+
if (first) {
1921+
st->print("empty");
1922+
}
1923+
}

src/hotspot/share/runtime/os.hpp

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,30 @@ class os: AllStatic {
100100
#endif
101101

102102
public:
103-
enum { page_sizes_max = 9 }; // Size of _page_sizes array (8 plus a sentinel)
103+
104+
// A simple value class holding a set of page sizes (similar to sigset_t)
105+
class PageSizes {
106+
size_t _v; // actually a bitmap.
107+
public:
108+
PageSizes() : _v(0) {}
109+
void add(size_t pagesize);
110+
bool contains(size_t pagesize) const;
111+
// Given a page size, return the next smaller page size in this set, or 0.
112+
size_t next_smaller(size_t pagesize) const;
113+
// Given a page size, return the next larger page size in this set, or 0.
114+
size_t next_larger(size_t pagesize) const;
115+
// Returns the largest page size in this set, or 0 if set is empty.
116+
size_t largest() const;
117+
// Returns the smallest page size in this set, or 0 if set is empty.
118+
size_t smallest() const;
119+
// Prints one line of comma separated, human readable page sizes, "empty" if empty.
120+
void print_on(outputStream* st) const;
121+
};
104122

105123
private:
106124
static OSThread* _starting_thread;
107125
static address _polling_page;
108-
public:
109-
static size_t _page_sizes[page_sizes_max];
110-
111-
private:
112-
static void init_page_sizes(size_t default_page_size) {
113-
_page_sizes[0] = default_page_size;
114-
_page_sizes[1] = 0; // sentinel
115-
}
126+
static PageSizes _page_sizes;
116127

117128
static char* pd_reserve_memory(size_t bytes);
118129

@@ -274,6 +285,10 @@ class os: AllStatic {
274285
// Return the default page size.
275286
static int vm_page_size();
276287

288+
// The set of page sizes which the VM is allowed to use (may be a subset of
289+
// the page sizes actually available on the platform).
290+
static const PageSizes& page_sizes() { return _page_sizes; }
291+
277292
// Returns the page size to use for a region of memory.
278293
// region_size / min_pages will always be greater than or equal to the
279294
// returned value. The returned value will divide region_size.
@@ -285,10 +300,7 @@ class os: AllStatic {
285300
static size_t page_size_for_region_unaligned(size_t region_size, size_t min_pages);
286301

287302
// Return the largest page size that can be used
288-
static size_t max_page_size() {
289-
// The _page_sizes array is sorted in descending order.
290-
return _page_sizes[0];
291-
}
303+
static size_t max_page_size() { return page_sizes().largest(); }
292304

293305
// Return a lower bound for page sizes. Also works before os::init completed.
294306
static size_t min_page_size() { return 4 * K; }

0 commit comments

Comments
 (0)