提交 e52f7476 编写于 作者: S stefank

8007074: SIGSEGV at ParMarkBitMap::verify_clear()

Summary: Replace the broken large pages implementation on Linux. New flag: -XX:+UseTransparentHugePages - Linux specific flag to turn on transparent huge page hinting with madvise(..., MAP_HUGETLB). Changed behavior: -XX:+UseLargePages - tries to use -XX:+UseTransparentHugePages before trying other large pages implementations (on Linux). Changed behavior: -XX:+UseHugeTLBFS - Use upfront allocation of Large Pages instead of using the broken implementation to dynamically committing large pages. Changed behavior: -XX:LargePageSizeInBytes - Turned off the ability to use this flag on Linux and provides warning to user if set to a value different than the OS chosen large page size. Changed behavior: Setting no large page size - Now defaults to use -XX:UseTransparentHugePages if the OS supports it. Previously, -XX:+UseHugeTLBFS was chosen if the OS was configured to use large pages.
Reviewed-by: tschatzl, dcubed, brutisso
上级 6379df31
......@@ -2325,7 +2325,9 @@ void os::large_page_init() {
}
char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) {
char* os::reserve_memory_special(size_t bytes, size_t alignment, char* req_addr, bool exec) {
fatal("This code is not used or maintained.");
// "exec" is passed in but not used. Creating the shared image for
// the code cache doesn't have an SHM_X executable permission to check.
assert(UseLargePages && UseSHM, "only for SHM large pages");
......@@ -4752,3 +4754,8 @@ int os::get_core_path(char* buffer, size_t bufferSize) {
return n;
}
#ifndef PRODUCT
void TestReserveMemorySpecial_test() {
// No tests available for this platform
}
#endif
......@@ -40,6 +40,9 @@
product(bool, UseHugeTLBFS, false, \
"Use MAP_HUGETLB for large pages") \
\
product(bool, UseTransparentHugePages, false, \
"Use MADV_HUGEPAGE for large pages") \
\
product(bool, LoadExecStackDllInVMThread, true, \
"Load DLLs with executable-stack attribute in the VM Thread") \
\
......
此差异已折叠。
......@@ -32,6 +32,7 @@ typedef int (*pthread_getattr_func_type) (pthread_t, pthread_attr_t *);
class Linux {
friend class os;
friend class TestReserveMemorySpecial;
// For signal-chaining
#define MAXSIGNUM 32
......@@ -92,8 +93,21 @@ class Linux {
static void rebuild_cpu_to_node_map();
static GrowableArray<int>* cpu_to_node() { return _cpu_to_node; }
static size_t find_large_page_size();
static size_t setup_large_page_size();
static bool setup_large_page_type(size_t page_size);
static bool transparent_huge_pages_sanity_check(bool warn, size_t pages_size);
static bool hugetlbfs_sanity_check(bool warn, size_t page_size);
static char* reserve_memory_special_shm(size_t bytes, size_t alignment, char* req_addr, bool exec);
static char* reserve_memory_special_huge_tlbfs(size_t bytes, size_t alignment, char* req_addr, bool exec);
static char* reserve_memory_special_huge_tlbfs_only(size_t bytes, char* req_addr, bool exec);
static char* reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t alignment, char* req_addr, bool exec);
static bool release_memory_special_shm(char* base, size_t bytes);
static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);
static void print_full_memory_info(outputStream* st);
static void print_distro_info(outputStream* st);
static void print_libversion_info(outputStream* st);
......
......@@ -3385,7 +3385,7 @@ bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) {
return true;
}
char* os::reserve_memory_special(size_t size, char* addr, bool exec) {
char* os::reserve_memory_special(size_t size, size_t alignment, char* addr, bool exec) {
fatal("os::reserve_memory_special should not be called on Solaris.");
return NULL;
}
......@@ -6601,3 +6601,9 @@ int os::get_core_path(char* buffer, size_t bufferSize) {
return strlen(buffer);
}
#ifndef PRODUCT
void TestReserveMemorySpecial_test() {
// No tests available for this platform
}
#endif
......@@ -3156,7 +3156,12 @@ bool os::can_execute_large_page_memory() {
return true;
}
char* os::reserve_memory_special(size_t bytes, char* addr, bool exec) {
char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, bool exec) {
assert(UseLargePages, "only for large pages");
if (!is_size_aligned(bytes, os::large_page_size()) || alignment > os::large_page_size()) {
return NULL; // Fallback to small pages.
}
const DWORD prot = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
const DWORD flags = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
......@@ -5638,3 +5643,9 @@ BOOL os::Advapi32Dll::AdvapiAvailable() {
}
#endif
#ifndef PRODUCT
void TestReserveMemorySpecial_test() {
// No tests available for this platform
}
#endif
......@@ -2006,10 +2006,12 @@ jint G1CollectedHeap::initialize() {
size_t init_byte_size = collector_policy()->initial_heap_byte_size();
size_t max_byte_size = collector_policy()->max_heap_byte_size();
size_t heap_alignment = collector_policy()->max_alignment();
// Ensure that the sizes are properly aligned.
Universe::check_alignment(init_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap");
_cg1r = new ConcurrentG1Refine(this);
......@@ -2026,12 +2028,8 @@ jint G1CollectedHeap::initialize() {
// If this happens then we could end up using a non-optimal
// compressed oops mode.
// Since max_byte_size is aligned to the size of a heap region (checked
// above).
Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
ReservedSpace heap_rs = Universe::reserve_heap(max_byte_size,
HeapRegion::GrainBytes);
heap_alignment);
// It is important to do this in a way such that concurrent readers can't
// temporarily think something is in the heap. (I've actually seen this
......
......@@ -313,7 +313,8 @@ G1CollectorPolicy::G1CollectorPolicy() :
void G1CollectorPolicy::initialize_flags() {
set_min_alignment(HeapRegion::GrainBytes);
size_t card_table_alignment = GenRemSet::max_alignment_constraint(rem_set_name());
set_max_alignment(MAX2(card_table_alignment, min_alignment()));
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
set_max_alignment(MAX3(card_table_alignment, min_alignment(), page_size));
if (SurvivorRatio < 1) {
vm_exit_during_initialization("Invalid survivor ratio specified");
}
......
......@@ -193,6 +193,8 @@ size_t GenCollectorPolicy::compute_max_alignment() {
alignment = lcm(os::large_page_size(), alignment);
}
assert(alignment >= min_alignment(), "Must be");
return alignment;
}
......
......@@ -95,13 +95,13 @@ jint GenCollectedHeap::initialize() {
guarantee(HeapWordSize == wordSize, "HeapWordSize must equal wordSize");
// The heap must be at least as aligned as generations.
size_t alignment = Generation::GenGrain;
size_t gen_alignment = Generation::GenGrain;
_gen_specs = gen_policy()->generations();
// Make sure the sizes are all aligned.
for (i = 0; i < _n_gens; i++) {
_gen_specs[i]->align(alignment);
_gen_specs[i]->align(gen_alignment);
}
// Allocate space for the heap.
......@@ -109,9 +109,11 @@ jint GenCollectedHeap::initialize() {
char* heap_address;
size_t total_reserved = 0;
int n_covered_regions = 0;
ReservedSpace heap_rs(0);
ReservedSpace heap_rs;
heap_address = allocate(alignment, &total_reserved,
size_t heap_alignment = collector_policy()->max_alignment();
heap_address = allocate(heap_alignment, &total_reserved,
&n_covered_regions, &heap_rs);
if (!heap_rs.is_reserved()) {
......@@ -168,6 +170,8 @@ char* GenCollectedHeap::allocate(size_t alignment,
const size_t pageSize = UseLargePages ?
os::large_page_size() : os::vm_page_size();
assert(alignment % pageSize == 0, "Must be");
for (int i = 0; i < _n_gens; i++) {
total_reserved += _gen_specs[i]->max_size();
if (total_reserved < _gen_specs[i]->max_size()) {
......@@ -175,24 +179,17 @@ char* GenCollectedHeap::allocate(size_t alignment,
}
n_covered_regions += _gen_specs[i]->n_covered_regions();
}
assert(total_reserved % pageSize == 0,
err_msg("Gen size; total_reserved=" SIZE_FORMAT ", pageSize="
SIZE_FORMAT, total_reserved, pageSize));
assert(total_reserved % alignment == 0,
err_msg("Gen size; total_reserved=" SIZE_FORMAT ", alignment="
SIZE_FORMAT, total_reserved, alignment));
// Needed until the cardtable is fixed to have the right number
// of covered regions.
n_covered_regions += 2;
if (UseLargePages) {
assert(total_reserved != 0, "total_reserved cannot be 0");
total_reserved = round_to(total_reserved, os::large_page_size());
if (total_reserved < os::large_page_size()) {
vm_exit_during_initialization(overflow_msg);
}
}
*_total_reserved = total_reserved;
*_n_covered_regions = n_covered_regions;
*_total_reserved = total_reserved;
*_n_covered_regions = n_covered_regions;
*heap_rs = Universe::reserve_heap(total_reserved, alignment);
return heap_rs->base();
}
......
......@@ -345,7 +345,7 @@ class VirtualSpaceNode : public CHeapObj<mtClass> {
};
// byte_size is the size of the associated virtualspace.
VirtualSpaceNode::VirtualSpaceNode(size_t byte_size) : _top(NULL), _next(NULL), _rs(0), _container_count(0) {
VirtualSpaceNode::VirtualSpaceNode(size_t byte_size) : _top(NULL), _next(NULL), _rs(), _container_count(0) {
// align up to vm allocation granularity
byte_size = align_size_up(byte_size, os::vm_allocation_granularity());
......
......@@ -681,17 +681,23 @@ static const uint64_t NarrowOopHeapMax = (uint64_t(max_juint) + 1);
// 32Gb
// OopEncodingHeapMax == NarrowOopHeapMax << LogMinObjAlignmentInBytes;
char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) {
char* Universe::preferred_heap_base(size_t heap_size, size_t alignment, NARROW_OOP_MODE mode) {
assert(is_size_aligned((size_t)OopEncodingHeapMax, alignment), "Must be");
assert(is_size_aligned((size_t)NarrowOopHeapMax, alignment), "Must be");
assert(is_size_aligned(heap_size, alignment), "Must be");
uintx heap_base_min_address_aligned = align_size_up(HeapBaseMinAddress, alignment);
size_t base = 0;
#ifdef _LP64
if (UseCompressedOops) {
assert(mode == UnscaledNarrowOop ||
mode == ZeroBasedNarrowOop ||
mode == HeapBasedNarrowOop, "mode is invalid");
const size_t total_size = heap_size + HeapBaseMinAddress;
const size_t total_size = heap_size + heap_base_min_address_aligned;
// Return specified base for the first request.
if (!FLAG_IS_DEFAULT(HeapBaseMinAddress) && (mode == UnscaledNarrowOop)) {
base = HeapBaseMinAddress;
base = heap_base_min_address_aligned;
// If the total size is small enough to allow UnscaledNarrowOop then
// just use UnscaledNarrowOop.
......@@ -742,6 +748,8 @@ char* Universe::preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode) {
}
}
#endif
assert(is_ptr_aligned((char*)base, alignment), "Must be");
return (char*)base; // also return NULL (don't care) for 32-bit VM
}
......@@ -867,27 +875,33 @@ ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) {
size_t total_reserved = align_size_up(heap_size, alignment);
assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())),
"heap size is too big for compressed oops");
char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
ReservedHeapSpace total_rs(total_reserved, alignment, UseLargePages, addr);
bool use_large_pages = UseLargePages && is_size_aligned(alignment, os::large_page_size());
assert(!UseLargePages
|| UseParallelOldGC
|| use_large_pages, "Wrong alignment to use large pages");
char* addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::UnscaledNarrowOop);
ReservedHeapSpace total_rs(total_reserved, alignment, use_large_pages, addr);
if (UseCompressedOops) {
if (addr != NULL && !total_rs.is_reserved()) {
// Failed to reserve at specified address - the requested memory
// region is taken already, for example, by 'java' launcher.
// Try again to reserver heap higher.
addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::ZeroBasedNarrowOop);
ReservedHeapSpace total_rs0(total_reserved, alignment,
UseLargePages, addr);
use_large_pages, addr);
if (addr != NULL && !total_rs0.is_reserved()) {
// Failed to reserve at specified address again - give up.
addr = Universe::preferred_heap_base(total_reserved, Universe::HeapBasedNarrowOop);
addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::HeapBasedNarrowOop);
assert(addr == NULL, "");
ReservedHeapSpace total_rs1(total_reserved, alignment,
UseLargePages, addr);
use_large_pages, addr);
total_rs = total_rs1;
} else {
total_rs = total_rs0;
......
......@@ -346,7 +346,7 @@ class Universe: AllStatic {
};
static NARROW_OOP_MODE narrow_oop_mode();
static const char* narrow_oop_mode_to_string(NARROW_OOP_MODE mode);
static char* preferred_heap_base(size_t heap_size, NARROW_OOP_MODE mode);
static char* preferred_heap_base(size_t heap_size, size_t alignment, NARROW_OOP_MODE mode);
static char* preferred_metaspace_base(size_t heap_size, NARROW_OOP_MODE mode);
static address narrow_oop_base() { return _narrow_oop._base; }
static bool is_narrow_oop_base(void* addr) { return (narrow_oop_base() == (address)addr); }
......
......@@ -5027,9 +5027,15 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) {
tty->print_cr("Running test: " #unit_test_function_call); \
unit_test_function_call
// Forward declaration
void TestReservedSpace_test();
void TestReserveMemorySpecial_test();
void execute_internal_vm_tests() {
if (ExecuteInternalVMTests) {
tty->print_cr("Running internal VM tests");
run_unit_test(TestReservedSpace_test());
run_unit_test(TestReserveMemorySpecial_test());
run_unit_test(GlobalDefinitions::test_globals());
run_unit_test(GCTimerAllTest::all());
run_unit_test(arrayOopDesc::test_max_array_length());
......
......@@ -1933,6 +1933,9 @@ class CommandLineFlags {
notproduct(bool, ExecuteInternalVMTests, false, \
"Enable execution of internal VM tests.") \
\
notproduct(bool, VerboseInternalVMTests, false, \
"Turn on logging for internal VM tests.") \
\
product_pd(bool, UseTLAB, "Use thread-local object allocation") \
\
product_pd(bool, ResizeTLAB, \
......
......@@ -328,8 +328,8 @@ class os: AllStatic {
static char* non_memory_address_word();
// reserve, commit and pin the entire memory region
static char* reserve_memory_special(size_t size, char* addr = NULL,
bool executable = false);
static char* reserve_memory_special(size_t size, size_t alignment,
char* addr, bool executable);
static bool release_memory_special(char* addr, size_t bytes);
static void large_page_init();
static size_t large_page_size();
......
......@@ -42,8 +42,19 @@
// ReservedSpace
// Dummy constructor
ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
_alignment(0), _special(false), _executable(false) {
}
ReservedSpace::ReservedSpace(size_t size) {
initialize(size, 0, false, NULL, 0, false);
size_t page_size = os::page_size_for_region(size, size, 1);
bool large_pages = page_size != (size_t)os::vm_page_size();
// Don't force the alignment to be large page aligned,
// since that will waste memory.
size_t alignment = os::vm_allocation_granularity();
initialize(size, alignment, large_pages, NULL, 0, false);
}
ReservedSpace::ReservedSpace(size_t size, size_t alignment,
......@@ -129,16 +140,18 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
if (special) {
base = os::reserve_memory_special(size, requested_address, executable);
base = os::reserve_memory_special(size, alignment, requested_address, executable);
if (base != NULL) {
if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
// OS ignored requested address. Try different address.
return;
}
// Check alignment constraints
// Check alignment constraints.
assert((uintptr_t) base % alignment == 0,
"Large pages returned a non-aligned address");
err_msg("Large pages returned a non-aligned address, base: "
PTR_FORMAT " alignment: " PTR_FORMAT,
base, (void*)(uintptr_t)alignment));
_special = true;
} else {
// failed; try to reserve regular memory below
......@@ -715,4 +728,188 @@ void VirtualSpace::print() {
tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary());
}
/////////////// Unit tests ///////////////
#ifndef PRODUCT
#define test_log(...) \
do {\
if (VerboseInternalVMTests) { \
tty->print_cr(__VA_ARGS__); \
tty->flush(); \
}\
} while (false)
class TestReservedSpace : AllStatic {
public:
static void small_page_write(void* addr, size_t size) {
size_t page_size = os::vm_page_size();
char* end = (char*)addr + size;
for (char* p = (char*)addr; p < end; p += page_size) {
*p = 1;
}
}
static void release_memory_for_test(ReservedSpace rs) {
if (rs.special()) {
guarantee(os::release_memory_special(rs.base(), rs.size()), "Shouldn't fail");
} else {
guarantee(os::release_memory(rs.base(), rs.size()), "Shouldn't fail");
}
}
static void test_reserved_space1(size_t size, size_t alignment) {
test_log("test_reserved_space1(%p)", (void*) (uintptr_t) size);
assert(is_size_aligned(size, alignment), "Incorrect input parameters");
ReservedSpace rs(size, // size
alignment, // alignment
UseLargePages, // large
NULL, // requested_address
0); // noacces_prefix
test_log(" rs.special() == %d", rs.special());
assert(rs.base() != NULL, "Must be");
assert(rs.size() == size, "Must be");
assert(is_ptr_aligned(rs.base(), alignment), "aligned sizes should always give aligned addresses");
assert(is_size_aligned(rs.size(), alignment), "aligned sizes should always give aligned addresses");
if (rs.special()) {
small_page_write(rs.base(), size);
}
release_memory_for_test(rs);
}
static void test_reserved_space2(size_t size) {
test_log("test_reserved_space2(%p)", (void*)(uintptr_t)size);
assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
ReservedSpace rs(size);
test_log(" rs.special() == %d", rs.special());
assert(rs.base() != NULL, "Must be");
assert(rs.size() == size, "Must be");
if (rs.special()) {
small_page_write(rs.base(), size);
}
release_memory_for_test(rs);
}
static void test_reserved_space3(size_t size, size_t alignment, bool maybe_large) {
test_log("test_reserved_space3(%p, %p, %d)",
(void*)(uintptr_t)size, (void*)(uintptr_t)alignment, maybe_large);
assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
assert(is_size_aligned(size, alignment), "Must be at least aligned against alignment");
bool large = maybe_large && UseLargePages && size >= os::large_page_size();
ReservedSpace rs(size, alignment, large, false);
test_log(" rs.special() == %d", rs.special());
assert(rs.base() != NULL, "Must be");
assert(rs.size() == size, "Must be");
if (rs.special()) {
small_page_write(rs.base(), size);
}
release_memory_for_test(rs);
}
static void test_reserved_space1() {
size_t size = 2 * 1024 * 1024;
size_t ag = os::vm_allocation_granularity();
test_reserved_space1(size, ag);
test_reserved_space1(size * 2, ag);
test_reserved_space1(size * 10, ag);
}
static void test_reserved_space2() {
size_t size = 2 * 1024 * 1024;
size_t ag = os::vm_allocation_granularity();
test_reserved_space2(size * 1);
test_reserved_space2(size * 2);
test_reserved_space2(size * 10);
test_reserved_space2(ag);
test_reserved_space2(size - ag);
test_reserved_space2(size);
test_reserved_space2(size + ag);
test_reserved_space2(size * 2);
test_reserved_space2(size * 2 - ag);
test_reserved_space2(size * 2 + ag);
test_reserved_space2(size * 3);
test_reserved_space2(size * 3 - ag);
test_reserved_space2(size * 3 + ag);
test_reserved_space2(size * 10);
test_reserved_space2(size * 10 + size / 2);
}
static void test_reserved_space3() {
size_t ag = os::vm_allocation_granularity();
test_reserved_space3(ag, ag , false);
test_reserved_space3(ag * 2, ag , false);
test_reserved_space3(ag * 3, ag , false);
test_reserved_space3(ag * 2, ag * 2, false);
test_reserved_space3(ag * 4, ag * 2, false);
test_reserved_space3(ag * 8, ag * 2, false);
test_reserved_space3(ag * 4, ag * 4, false);
test_reserved_space3(ag * 8, ag * 4, false);
test_reserved_space3(ag * 16, ag * 4, false);
if (UseLargePages) {
size_t lp = os::large_page_size();
// Without large pages
test_reserved_space3(lp, ag * 4, false);
test_reserved_space3(lp * 2, ag * 4, false);
test_reserved_space3(lp * 4, ag * 4, false);
test_reserved_space3(lp, lp , false);
test_reserved_space3(lp * 2, lp , false);
test_reserved_space3(lp * 3, lp , false);
test_reserved_space3(lp * 2, lp * 2, false);
test_reserved_space3(lp * 4, lp * 2, false);
test_reserved_space3(lp * 8, lp * 2, false);
// With large pages
test_reserved_space3(lp, ag * 4 , true);
test_reserved_space3(lp * 2, ag * 4, true);
test_reserved_space3(lp * 4, ag * 4, true);
test_reserved_space3(lp, lp , true);
test_reserved_space3(lp * 2, lp , true);
test_reserved_space3(lp * 3, lp , true);
test_reserved_space3(lp * 2, lp * 2, true);
test_reserved_space3(lp * 4, lp * 2, true);
test_reserved_space3(lp * 8, lp * 2, true);
}
}
static void test_reserved_space() {
test_reserved_space1();
test_reserved_space2();
test_reserved_space3();
}
};
void TestReservedSpace_test() {
TestReservedSpace::test_reserved_space();
}
#endif // PRODUCT
#endif
......@@ -53,6 +53,7 @@ class ReservedSpace VALUE_OBJ_CLASS_SPEC {
public:
// Constructor
ReservedSpace();
ReservedSpace(size_t size);
ReservedSpace(size_t size, size_t alignment, bool large,
char* requested_address = NULL,
......
......@@ -87,6 +87,8 @@ class MemTracker : AllStatic {
MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
static inline void record_virtual_memory_commit(address addr, size_t size,
address pc = 0, Thread* thread = NULL) { }
static inline void record_virtual_memory_release(address addr, size_t size,
Thread* thread = NULL) { }
static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
Thread* thread = NULL) { }
static inline Tracker get_realloc_tracker() { return _tkr; }
......@@ -372,6 +374,13 @@ class MemTracker : AllStatic {
tkr.record(addr, size, flags, pc);
}
static inline void record_virtual_memory_release(address addr, size_t size,
Thread* thread = NULL) {
if (is_on()) {
Tracker tkr(Tracker::Release, thread);
tkr.record(addr, size);
}
}
// record memory type on virtual memory base address
static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
......
......@@ -402,6 +402,14 @@ const jlong CompressedKlassPointersBase = NOT_LP64(0) LP64_ONLY(CONST64(0x800000
#define align_size_up_(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1))
inline bool is_size_aligned(size_t size, size_t alignment) {
return align_size_up_(size, alignment) == size;
}
inline bool is_ptr_aligned(void* ptr, size_t alignment) {
return align_size_up_((intptr_t)ptr, (intptr_t)alignment) == (intptr_t)ptr;
}
inline intptr_t align_size_up(intptr_t size, intptr_t alignment) {
return align_size_up_(size, alignment);
}
......@@ -414,6 +422,14 @@ inline intptr_t align_size_down(intptr_t size, intptr_t alignment) {
#define is_size_aligned_(size, alignment) ((size) == (align_size_up_(size, alignment)))
inline void* align_ptr_up(void* ptr, size_t alignment) {
return (void*)align_size_up((intptr_t)ptr, (intptr_t)alignment);
}
inline void* align_ptr_down(void* ptr, size_t alignment) {
return (void*)align_size_down((intptr_t)ptr, (intptr_t)alignment);
}
// Align objects by rounding up their size, in HeapWord units.
#define align_object_size_(size) align_size_up_(size, MinObjAlignment)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册