8267579: Thread::cooked_allocated_bytes() hits assert(left >= right) failed: avoid underflow

Reviewed-by: dcubed, stefank, kbarrett
This commit is contained in:
Markus Grönlund 2021-06-14 10:41:00 +00:00
parent 51f3427e9b
commit c4207355d3
3 changed files with 21 additions and 1 deletions

View file

@ -31,6 +31,7 @@
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "memory/universe.hpp" #include "memory/universe.hpp"
#include "oops/oop.inline.hpp" #include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/perfData.hpp" #include "runtime/perfData.hpp"
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/threadSMR.hpp" #include "runtime/threadSMR.hpp"
@ -473,3 +474,11 @@ size_t ThreadLocalAllocBuffer::end_reserve() {
size_t reserve_size = Universe::heap()->tlab_alloc_reserve(); size_t reserve_size = Universe::heap()->tlab_alloc_reserve();
return MAX2(reserve_size, (size_t)_reserve_for_allocation_prefetch); return MAX2(reserve_size, (size_t)_reserve_for_allocation_prefetch);
} }
const HeapWord* ThreadLocalAllocBuffer::start_relaxed() const {
return Atomic::load(&_start);
}
const HeapWord* ThreadLocalAllocBuffer::top_relaxed() const {
return Atomic::load(&_top);
}

View file

@ -129,6 +129,10 @@ public:
size_t refill_waste_limit() const { return _refill_waste_limit; } size_t refill_waste_limit() const { return _refill_waste_limit; }
size_t bytes_since_last_sample_point() const { return _bytes_since_last_sample_point; } size_t bytes_since_last_sample_point() const { return _bytes_since_last_sample_point; }
// For external inspection.
const HeapWord* start_relaxed() const;
const HeapWord* top_relaxed() const;
// Allocate size HeapWords. The memory is NOT initialized to zero. // Allocate size HeapWords. The memory is NOT initialized to zero.
inline HeapWord* allocate(size_t size); inline HeapWord* allocate(size_t size);

View file

@ -41,7 +41,14 @@
inline jlong Thread::cooked_allocated_bytes() { inline jlong Thread::cooked_allocated_bytes() {
jlong allocated_bytes = Atomic::load_acquire(&_allocated_bytes); jlong allocated_bytes = Atomic::load_acquire(&_allocated_bytes);
if (UseTLAB) { if (UseTLAB) {
size_t used_bytes = tlab().used_bytes(); // These reads are unsynchronized and unordered with the thread updating its tlab pointers.
// Use only if top > start && used_bytes <= max_tlab_size_bytes.
const HeapWord* const top = tlab().top_relaxed();
const HeapWord* const start = tlab().start_relaxed();
if (top <= start) {
return allocated_bytes;
}
const size_t used_bytes = pointer_delta(top, start, 1);
if (used_bytes <= ThreadLocalAllocBuffer::max_size_in_bytes()) { if (used_bytes <= ThreadLocalAllocBuffer::max_size_in_bytes()) {
// Comparing used_bytes with the maximum allowed size will ensure // Comparing used_bytes with the maximum allowed size will ensure
// that we don't add the used bytes from a semi-initialized TLAB // that we don't add the used bytes from a semi-initialized TLAB