提交 ab994026 编写于 作者: J johnc

7069863: G1: SIGSEGV running SPECjbb2011 and -UseBiasedLocking

Summary: Align the reserved size of the heap and perm to the heap region size to get a preferred heap base that is aligned to the region size, and call the correct heap reservation constructor. Also add a check in the heap reservation code that the reserved space starts at the requested address (if any).
Reviewed-by: kvn, ysr
上级 519da0f6
...@@ -1901,11 +1901,26 @@ jint G1CollectedHeap::initialize() { ...@@ -1901,11 +1901,26 @@ jint G1CollectedHeap::initialize() {
PermanentGenerationSpec* pgs = collector_policy()->permanent_generation(); PermanentGenerationSpec* pgs = collector_policy()->permanent_generation();
// Includes the perm-gen. // Includes the perm-gen.
const size_t total_reserved = max_byte_size + pgs->max_size(); // When compressed oops are enabled, the preferred heap base
// is calculated by subtracting the requested size from the
// 32Gb boundary and using the result as the base address for
// heap reservation. If the requested size is not aligned to
// HeapRegion::GrainBytes (i.e. the alignment that is passed
// into the ReservedHeapSpace constructor) then the actual
// base of the reserved heap may end up differing from the
// address that was requested (i.e. the preferred heap base).
// 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), we also need to align the perm gen size as it might not be.
const size_t total_reserved = max_byte_size +
align_size_up(pgs->max_size(), HeapRegion::GrainBytes);
Universe::check_alignment(total_reserved, HeapRegion::GrainBytes, "g1 heap and perm");
char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop); char* addr = Universe::preferred_heap_base(total_reserved, Universe::UnscaledNarrowOop);
ReservedSpace heap_rs(max_byte_size + pgs->max_size(), ReservedHeapSpace heap_rs(total_reserved, HeapRegion::GrainBytes,
HeapRegion::GrainBytes,
UseLargePages, addr); UseLargePages, addr);
if (UseCompressedOops) { if (UseCompressedOops) {
...@@ -1914,13 +1929,16 @@ jint G1CollectedHeap::initialize() { ...@@ -1914,13 +1929,16 @@ jint G1CollectedHeap::initialize() {
// region is taken already, for example, by 'java' launcher. // region is taken already, for example, by 'java' launcher.
// Try again to reserver heap higher. // Try again to reserver heap higher.
addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop); addr = Universe::preferred_heap_base(total_reserved, Universe::ZeroBasedNarrowOop);
ReservedSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
ReservedHeapSpace heap_rs0(total_reserved, HeapRegion::GrainBytes,
UseLargePages, addr); UseLargePages, addr);
if (addr != NULL && !heap_rs0.is_reserved()) { if (addr != NULL && !heap_rs0.is_reserved()) {
// Failed to reserve at specified address again - give up. // 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, Universe::HeapBasedNarrowOop);
assert(addr == NULL, ""); assert(addr == NULL, "");
ReservedSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
ReservedHeapSpace heap_rs1(total_reserved, HeapRegion::GrainBytes,
UseLargePages, addr); UseLargePages, addr);
heap_rs = heap_rs1; heap_rs = heap_rs1;
} else { } else {
......
/* /*
* Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -68,7 +68,7 @@ ReservedSpace::align_reserved_region(char* addr, const size_t len, ...@@ -68,7 +68,7 @@ ReservedSpace::align_reserved_region(char* addr, const size_t len,
assert(len >= required_size, "len too small"); assert(len >= required_size, "len too small");
const size_t s = size_t(addr); const size_t s = size_t(addr);
const size_t beg_ofs = s + prefix_size & suffix_align - 1; const size_t beg_ofs = (s + prefix_size) & (suffix_align - 1);
const size_t beg_delta = beg_ofs == 0 ? 0 : suffix_align - beg_ofs; const size_t beg_delta = beg_ofs == 0 ? 0 : suffix_align - beg_ofs;
if (len < beg_delta + required_size) { if (len < beg_delta + required_size) {
...@@ -113,8 +113,8 @@ char* ReservedSpace::reserve_and_align(const size_t reserve_size, ...@@ -113,8 +113,8 @@ char* ReservedSpace::reserve_and_align(const size_t reserve_size,
assert(res >= raw, "alignment decreased start addr"); assert(res >= raw, "alignment decreased start addr");
assert(res + prefix_size + suffix_size <= raw + reserve_size, assert(res + prefix_size + suffix_size <= raw + reserve_size,
"alignment increased end addr"); "alignment increased end addr");
assert((res & prefix_align - 1) == 0, "bad alignment of prefix"); assert((res & (prefix_align - 1)) == 0, "bad alignment of prefix");
assert((res + prefix_size & suffix_align - 1) == 0, assert(((res + prefix_size) & (suffix_align - 1)) == 0,
"bad alignment of suffix"); "bad alignment of suffix");
} }
#endif #endif
...@@ -135,7 +135,7 @@ static bool failed_to_reserve_as_requested(char* base, char* requested_address, ...@@ -135,7 +135,7 @@ static bool failed_to_reserve_as_requested(char* base, char* requested_address,
assert(UseCompressedOops, "currently requested address used only for compressed oops"); assert(UseCompressedOops, "currently requested address used only for compressed oops");
if (PrintCompressedOopsMode) { if (PrintCompressedOopsMode) {
tty->cr(); tty->cr();
tty->print_cr("Reserved memory at not requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address); tty->print_cr("Reserved memory not at requested address: " PTR_FORMAT " vs " PTR_FORMAT, base, requested_address);
} }
// OS ignored requested address. Try different address. // OS ignored requested address. Try different address.
if (special) { if (special) {
...@@ -162,11 +162,11 @@ ReservedSpace::ReservedSpace(const size_t prefix_size, ...@@ -162,11 +162,11 @@ ReservedSpace::ReservedSpace(const size_t prefix_size,
assert(prefix_align != 0, "sanity"); assert(prefix_align != 0, "sanity");
assert(suffix_size != 0, "sanity"); assert(suffix_size != 0, "sanity");
assert(suffix_align != 0, "sanity"); assert(suffix_align != 0, "sanity");
assert((prefix_size & prefix_align - 1) == 0, assert((prefix_size & (prefix_align - 1)) == 0,
"prefix_size not divisible by prefix_align"); "prefix_size not divisible by prefix_align");
assert((suffix_size & suffix_align - 1) == 0, assert((suffix_size & (suffix_align - 1)) == 0,
"suffix_size not divisible by suffix_align"); "suffix_size not divisible by suffix_align");
assert((suffix_align & prefix_align - 1) == 0, assert((suffix_align & (prefix_align - 1)) == 0,
"suffix_align not divisible by prefix_align"); "suffix_align not divisible by prefix_align");
// Assert that if noaccess_prefix is used, it is the same as prefix_align. // Assert that if noaccess_prefix is used, it is the same as prefix_align.
...@@ -210,8 +210,8 @@ ReservedSpace::ReservedSpace(const size_t prefix_size, ...@@ -210,8 +210,8 @@ ReservedSpace::ReservedSpace(const size_t prefix_size,
if (addr == NULL) return; if (addr == NULL) return;
// Check whether the result has the needed alignment (unlikely unless // Check whether the result has the needed alignment (unlikely unless
// prefix_align == suffix_align). // prefix_align < suffix_align).
const size_t ofs = size_t(addr) + adjusted_prefix_size & suffix_align - 1; const size_t ofs = (size_t(addr) + adjusted_prefix_size) & (suffix_align - 1);
if (ofs != 0) { if (ofs != 0) {
// Wrong alignment. Release, allocate more space and do manual alignment. // Wrong alignment. Release, allocate more space and do manual alignment.
// //
...@@ -232,6 +232,15 @@ ReservedSpace::ReservedSpace(const size_t prefix_size, ...@@ -232,6 +232,15 @@ ReservedSpace::ReservedSpace(const size_t prefix_size,
addr = reserve_and_align(size + suffix_align, adjusted_prefix_size, addr = reserve_and_align(size + suffix_align, adjusted_prefix_size,
prefix_align, suffix_size, suffix_align); prefix_align, suffix_size, suffix_align);
} }
if (requested_address != 0 &&
failed_to_reserve_as_requested(addr, requested_address, size, false)) {
// As a result of the alignment constraints, the allocated addr differs
// from the requested address. Return back to the caller who can
// take remedial action (like try again without a requested address).
assert(_base == NULL, "should be");
return;
}
} }
_base = addr; _base = addr;
...@@ -245,13 +254,19 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, ...@@ -245,13 +254,19 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
const size_t noaccess_prefix, const size_t noaccess_prefix,
bool executable) { bool executable) {
const size_t granularity = os::vm_allocation_granularity(); const size_t granularity = os::vm_allocation_granularity();
assert((size & granularity - 1) == 0, assert((size & (granularity - 1)) == 0,
"size not aligned to os::vm_allocation_granularity()"); "size not aligned to os::vm_allocation_granularity()");
assert((alignment & granularity - 1) == 0, assert((alignment & (granularity - 1)) == 0,
"alignment not aligned to os::vm_allocation_granularity()"); "alignment not aligned to os::vm_allocation_granularity()");
assert(alignment == 0 || is_power_of_2((intptr_t)alignment), assert(alignment == 0 || is_power_of_2((intptr_t)alignment),
"not a power of 2"); "not a power of 2");
alignment = MAX2(alignment, (size_t)os::vm_page_size());
// Assert that if noaccess_prefix is used, it is the same as alignment.
assert(noaccess_prefix == 0 ||
noaccess_prefix == alignment, "noaccess prefix wrong");
_base = NULL; _base = NULL;
_size = 0; _size = 0;
_special = false; _special = false;
...@@ -282,10 +297,8 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, ...@@ -282,10 +297,8 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
return; return;
} }
// Check alignment constraints // Check alignment constraints
if (alignment > 0) {
assert((uintptr_t) base % alignment == 0, assert((uintptr_t) base % alignment == 0,
"Large pages returned a non-aligned address"); "Large pages returned a non-aligned address");
}
_special = true; _special = true;
} else { } else {
// failed; try to reserve regular memory below // failed; try to reserve regular memory below
...@@ -321,7 +334,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, ...@@ -321,7 +334,7 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
if (base == NULL) return; if (base == NULL) return;
// Check alignment constraints // Check alignment constraints
if (alignment > 0 && ((size_t)base & alignment - 1) != 0) { if ((((size_t)base + noaccess_prefix) & (alignment - 1)) != 0) {
// Base not aligned, retry // Base not aligned, retry
if (!os::release_memory(base, size)) fatal("os::release_memory failed"); if (!os::release_memory(base, size)) fatal("os::release_memory failed");
// Reserve size large enough to do manual alignment and // Reserve size large enough to do manual alignment and
...@@ -338,12 +351,21 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large, ...@@ -338,12 +351,21 @@ void ReservedSpace::initialize(size_t size, size_t alignment, bool large,
os::release_memory(extra_base, extra_size); os::release_memory(extra_base, extra_size);
base = os::reserve_memory(size, base); base = os::reserve_memory(size, base);
} while (base == NULL); } while (base == NULL);
if (requested_address != 0 &&
failed_to_reserve_as_requested(base, requested_address, size, false)) {
// As a result of the alignment constraints, the allocated base differs
// from the requested address. Return back to the caller who can
// take remedial action (like try again without a requested address).
assert(_base == NULL, "should be");
return;
}
} }
} }
// Done // Done
_base = base; _base = base;
_size = size; _size = size;
_alignment = MAX2(alignment, (size_t) os::vm_page_size()); _alignment = alignment;
_noaccess_prefix = noaccess_prefix; _noaccess_prefix = noaccess_prefix;
// Assert that if noaccess_prefix is used, it is the same as alignment. // Assert that if noaccess_prefix is used, it is the same as alignment.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册