// Failed to relocate object. Wait for a worker thread to complete // relocation of this page, and then forward the object. If the GC // aborts the relocation phase before the page has been relocated, // then wait return false and we just forward the object in-place.
if (!forwarding->wait_page_released()) { // Forward object in-place return forwarding_insert(forwarding, from_addr, from_addr, &cursor);
}
}
static ZPage* alloc_page(const ZForwarding* forwarding) {
if (ZStressRelocateInPlace) { // Simulate failure to allocate a new page. This will // cause the page being relocated to be relocated in-place. return NULL;
}
staticbool should_free_target_page(ZPage* page) { // Free target page if it is empty. We can end up with an empty target // page if we allocated a new target page, and then lost the race to // relocate the remaining objects, leaving the target page empty when // relocation completed. return page != NULL && page->top() == page->start();
}
class ZRelocateSmallAllocator { private: volatile size_t _in_place_count;
// Wait for any ongoing in-place relocation to complete while (_in_place) {
_lock.wait();
}
// Allocate a new page only if the shared page is the same as the // current target page. The shared page will be different from the // current target page if another thread shared a page, or allocated // a new page.
if (_shared == target) {
_shared = alloc_page(forwarding);
if (_shared == NULL) {
Atomic::inc(&_in_place_count);
_in_place = true;
}
}
// Copy object. Use conjoint copying if we are relocating // in-place and the new object overlapps with the old object.
if (_forwarding->in_place() && to_addr + size > from_addr) {
ZUtils::object_copy_conjoint(from_addr, to_addr, size);
} else {
ZUtils::object_copy_disjoint(from_addr, to_addr, size);
}
while (!relocate_object(addr)) { // Allocate a new target page, or if that fails, use the page being // relocated as the new target, which will cause it to be relocated // in-place.
_target = _allocator->alloc_target_page(_forwarding, _target);
if (_target != NULL) { continue;
}
// Claim the page being relocated to block other threads from accessing // it, or its forwarding table, until it has been released (relocation // completed).
_target = _forwarding->claim_page();
_target->reset_for_in_place_relocation();
_forwarding->set_in_place();
}
}
if (_forwarding->in_place()) { // The relocated page has been relocated in-place and should not // be freed. Keep it as target page until it is full, and offer to // share it with other worker threads.
_allocator->share_target_page(_target);
} else { // Detach and free relocated page
ZPage* const page = _forwarding->detach_page();
_allocator->free_relocated_page(page);
}
}
};
class ZRelocateTask : public ZTask { private:
ZRelocationSetParallelIterator _iter;
ZRelocateSmallAllocator _small_allocator;
ZRelocateMediumAllocator _medium_allocator;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.