--- old/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp 2018-05-11 17:07:52.158072537 +0200 +++ new/src/hotspot/share/gc/shared/threadLocalAllocBuffer.hpp 2018-05-11 17:07:51.883060562 +0200 @@ -79,6 +79,8 @@ size_t remaining() const { return end() == NULL ? 0 : pointer_delta(hard_end(), top()); } + bool contains(HeapWord* obj, size_t size) { return (obj >= start()) && (obj + size <= top()); } + // Make parsable and release it. void reset(); @@ -129,6 +131,9 @@ // Allocate size HeapWords. The memory is NOT initialized to zero. inline HeapWord* allocate(size_t size); + // Undo last allocation. + inline bool undo_allocate(HeapWord* obj, size_t size); + // Reserve space at the end of TLAB static size_t end_reserve() { int reserve_size = typeArrayOopDesc::header_size(T_INT); --- old/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp 2018-05-11 17:07:52.516088125 +0200 +++ new/src/hotspot/share/gc/shared/threadLocalAllocBuffer.inline.hpp 2018-05-11 17:07:52.245076325 +0200 @@ -53,6 +53,23 @@ return NULL; } +inline bool ThreadLocalAllocBuffer::undo_allocate(HeapWord* obj, size_t size) { + invariants(); + + // The object might not be allocated in this TLAB + if (!contains(obj, size)) { + return false; + } + + // Make sure the object is the last one allocated in this TLAB + assert(pointer_delta(top(), obj) == size, "Bad undo"); + + set_top(obj); + + invariants(); + return true; +} + inline size_t ThreadLocalAllocBuffer::compute_size(size_t obj_size) { // Compute the size for the new TLAB. // The "last" tlab may be smaller to reduce fragmentation.