# HG changeset patch # User shade # Date 1557953154 -7200 # Node ID f2f11d7f7f4e7128f8aba6ffa576cfa76fbf7d1a # Parent 53d51822f287bc8ae31ccf9e95750a6dce6e4397 8223980: Shenandoah: Refactor and fix ObjArrayChunkedTask verification Reviewed-by: rkennke diff -r 53d51822f287 -r f2f11d7f7f4e src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Tue May 07 16:18:21 2019 -0700 +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp Wed May 15 22:45:54 2019 +0200 @@ -29,7 +29,6 @@ #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.hpp" -#include "gc/shenandoah/shenandoahTaskqueue.hpp" #include "utilities/defaultStream.hpp" void ShenandoahArguments::initialize() { @@ -54,17 +53,6 @@ FLAG_SET_DEFAULT(ShenandoahVerifyOptoBarriers, false); #endif -#ifdef _LP64 - // The optimized ObjArrayChunkedTask takes some bits away from the full 64 addressable - // bits, fail if we ever attempt to address more than we can. Only valid on 64bit. - if (MaxHeapSize >= ObjArrayChunkedTask::max_addressable()) { - jio_fprintf(defaultStream::error_stream(), - "Shenandoah GC cannot address more than " SIZE_FORMAT " bytes, and " SIZE_FORMAT " bytes heap requested.", - ObjArrayChunkedTask::max_addressable(), MaxHeapSize); - vm_exit(1); - } -#endif - if (UseLargePages && (MaxHeapSize / os::large_page_size()) < ShenandoahHeapRegion::MIN_NUM_REGIONS) { warning("Large pages size (" SIZE_FORMAT "K) is too large to afford page-sized regions, disabling uncommit", os::large_page_size() / K); diff -r 53d51822f287 -r f2f11d7f7f4e src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Tue May 07 16:18:21 2019 -0700 +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp Wed May 15 22:45:54 2019 +0200 @@ -54,6 +54,7 @@ #include "gc/shenandoah/shenandoahPacer.inline.hpp" #include "gc/shenandoah/shenandoahRootProcessor.hpp" #include "gc/shenandoah/shenandoahStringDedup.hpp" +#include "gc/shenandoah/shenandoahTaskqueue.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" #include "gc/shenandoah/shenandoahCodeRoots.hpp" @@ -186,6 +187,18 @@ assert((((size_t) base()) & ShenandoahHeapRegion::region_size_bytes_mask()) == 0, "Misaligned heap: " PTR_FORMAT, p2i(base())); +#if SHENANDOAH_OPTIMIZED_OBJTASK + // The optimized ObjArrayChunkedTask takes some bits away from the full object bits. + // Fail if we ever attempt to address more than we can. + if ((uintptr_t)heap_rs.end() >= ObjArrayChunkedTask::max_addressable()) { + FormatBuffer<512> buf("Shenandoah reserved [" PTR_FORMAT ", " PTR_FORMAT") for the heap, \n" + "but max object address is " PTR_FORMAT ". Try to reduce heap size, or try other \n" + "VM options that allocate heap at lower addresses (HeapBaseMinAddress, AllocateHeapAt, etc).", + p2i(heap_rs.base()), p2i(heap_rs.end()), ObjArrayChunkedTask::max_addressable()); + vm_exit_during_initialization("Fatal Error", buf); + } +#endif + ReservedSpace sh_rs = heap_rs.first_part(max_byte_size); if (!_heap_region_special) { os::commit_memory_or_exit(sh_rs.base(), _initial_size, heap_alignment, false, diff -r 53d51822f287 -r f2f11d7f7f4e src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp Tue May 07 16:18:21 2019 -0700 +++ b/src/hotspot/share/gc/shenandoah/shenandoahTaskqueue.hpp Wed May 15 22:45:54 2019 +0200 @@ -109,7 +109,7 @@ // some bits back if chunks are counted in ObjArrayMarkingStride units. // // There is also a fallback version that uses plain fields, when we don't have enough space to steal the -// bits from the native pointer. It is useful to debug the _LP64 version. +// bits from the native pointer. It is useful to debug the optimized version. // #ifdef _MSC_VER @@ -119,6 +119,12 @@ #endif #ifdef _LP64 +#define SHENANDOAH_OPTIMIZED_OBJTASK 1 +#else +#define SHENANDOAH_OPTIMIZED_OBJTASK 0 +#endif + +#if SHENANDOAH_OPTIMIZED_OBJTASK class ObjArrayChunkedTask { public: @@ -135,17 +141,14 @@ public: ObjArrayChunkedTask(oop o = NULL) { - _obj = ((uintptr_t)(void*) o) << oop_shift; + assert(oopDesc::equals_raw(decode_oop(encode_oop(o)), o), "oop can be encoded: " PTR_FORMAT, p2i(o)); + _obj = encode_oop(o); } - ObjArrayChunkedTask(oop o, int chunk, int mult) { - assert(0 <= chunk && chunk < nth_bit(chunk_bits), "chunk is sane: %d", chunk); - assert(0 <= mult && mult < nth_bit(pow_bits), "pow is sane: %d", mult); - uintptr_t t_b = ((uintptr_t) chunk) << chunk_shift; - uintptr_t t_m = ((uintptr_t) mult) << pow_shift; - uintptr_t obj = (uintptr_t)(void*)o; - assert(obj < nth_bit(oop_bits), "obj ref is sane: " PTR_FORMAT, obj); - intptr_t t_o = obj << oop_shift; - _obj = t_o | t_m | t_b; + ObjArrayChunkedTask(oop o, int chunk, int pow) { + assert(oopDesc::equals_raw(decode_oop(encode_oop(o)), o), "oop can be encoded: " PTR_FORMAT, p2i(o)); + assert(decode_chunk(encode_chunk(chunk)) == chunk, "chunk can be encoded: %d", chunk); + assert(decode_pow(encode_pow(pow)) == pow, "pow can be encoded: %d", pow); + _obj = encode_oop(o) | encode_chunk(chunk) | encode_pow(pow); } ObjArrayChunkedTask(const ObjArrayChunkedTask& t): _obj(t._obj) { } @@ -159,14 +162,38 @@ return *this; } - inline oop obj() const { return (oop) reinterpret_cast((_obj >> oop_shift) & right_n_bits(oop_bits)); } - inline int chunk() const { return (int) (_obj >> chunk_shift) & right_n_bits(chunk_bits); } - inline int pow() const { return (int) ((_obj >> pow_shift) & right_n_bits(pow_bits)); } + inline oop decode_oop(uintptr_t val) const { + return (oop) reinterpret_cast((val >> oop_shift) & right_n_bits(oop_bits)); + } + + inline int decode_chunk(uintptr_t val) const { + return (int) ((val >> chunk_shift) & right_n_bits(chunk_bits)); + } + + inline int decode_pow(uintptr_t val) const { + return (int) ((val >> pow_shift) & right_n_bits(pow_bits)); + } + + inline uintptr_t encode_oop(oop obj) const { + return ((uintptr_t)(void*) obj) << oop_shift; + } + + inline uintptr_t encode_chunk(int chunk) const { + return ((uintptr_t) chunk) << chunk_shift; + } + + inline uintptr_t encode_pow(int pow) const { + return ((uintptr_t) pow) << pow_shift; + } + + inline oop obj() const { return decode_oop(_obj); } + inline int chunk() const { return decode_chunk(_obj); } + inline int pow() const { return decode_pow(_obj); } inline bool is_not_chunked() const { return (_obj & ~right_n_bits(oop_bits + pow_bits)) == 0; } DEBUG_ONLY(bool is_valid() const); // Tasks to be pushed/popped must be valid. - static size_t max_addressable() { + static uintptr_t max_addressable() { return nth_bit(oop_bits); } @@ -229,7 +256,7 @@ int _chunk; int _pow; }; -#endif +#endif // SHENANDOAH_OPTIMIZED_OBJTASK #ifdef _MSC_VER #pragma warning(pop)