HeapWord* ConcEdenSpace::par_allocate(size_t size) { do { // The invariant is top() should be read before end() because // top() can't be greater than end(), so if an update of _soft_end // occurs between 'end_val = end();' and 'top_val = top();' top() // also can grow up to the new end() and the condition // 'top_val > end_val' is true. To ensure the loading order // OrderAccess::loadload() is required after top() read. HeapWord* obj = top(); OrderAccess::loadload(); if (pointer_delta(*soft_end_addr(), obj) >= size) { HeapWord* new_top = obj + size; HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, top_addr(), obj); // result can be one of two: // the old top value: the exchange succeeded // otherwise: the new value of the top is returned. if (result == obj) { assert(is_aligned(obj) && is_aligned(new_top), "checking alignment"); return obj; } } else { return NULL; } } while (true); }
// This version is lock-free. inline HeapWord* ContiguousSpace::par_allocate_impl(size_t size, HeapWord* const end_value) { do { HeapWord* obj = top(); if (pointer_delta(end_value, obj) >= size) { HeapWord* new_top = obj + size; HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, top_addr(), obj); // result can be one of two: // the old top value: the exchange succeeded // otherwise: the new value of the top is returned. if (result == obj) { return obj; } } else { return NULL; } } while (true); }