< prev index next >
src/share/vm/gc/g1/g1ParScanThreadState.cpp
Print this page
rev 8789 : [mq]: 8073052-Rename-and-clean-up-the-allocation-manager-hierarchy-in-g1Allocator
rev 8790 : imported patch 8003237-no-wait-for-free-list
rev 8791 : imported patch jon-fast-evac-failure
*** 39,49 ****
_g1_rem(g1h->g1_rem_set()),
_hash_seed(17), _queue_num(queue_num),
_term_attempts(0),
_tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
_age_table(false), _scanner(g1h, rp),
! _strong_roots_time(0), _term_time(0) {
_scanner.set_par_scan_thread_state(this);
// we allocate G1YoungSurvRateNumRegions plus one entries, since
// we "sacrifice" entry 0 to keep track of surviving bytes for
// non-young regions (where the age is -1)
// We also add a few elements at the beginning and at the end in
--- 39,51 ----
_g1_rem(g1h->g1_rem_set()),
_hash_seed(17), _queue_num(queue_num),
_term_attempts(0),
_tenuring_threshold(g1h->g1_policy()->tenuring_threshold()),
_age_table(false), _scanner(g1h, rp),
! _strong_roots_time(0), _term_time(0),
! _last_gen_is_full(false)
! {
_scanner.set_par_scan_thread_state(this);
// we allocate G1YoungSurvRateNumRegions plus one entries, since
// we "sacrifice" entry 0 to keep track of surviving bytes for
// non-young regions (where the age is -1)
// We also add a few elements at the beginning and at the end in
*** 158,187 ****
}
HeapWord* G1ParScanThreadState::allocate_in_next_plab(InCSetState const state,
InCSetState* dest,
size_t word_sz,
! AllocationContext_t const context) {
assert(state.is_in_cset_or_humongous(), err_msg("Unexpected state: " CSETSTATE_FORMAT, state.value()));
assert(dest->is_in_cset_or_humongous(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
// Right now we only have two types of regions (young / old) so
// let's keep the logic here simple. We can generalize it when necessary.
if (dest->is_young()) {
HeapWord* const obj_ptr = _plab_allocator->allocate(InCSetState::Old,
word_sz,
! context);
! if (obj_ptr == NULL) {
! return NULL;
! }
// Make sure that we won't attempt to copy any other objects out
// of a survivor region (given that apparently we cannot allocate
! // any new ones) to avoid coming into this slow path.
_tenuring_threshold = 0;
dest->set_old();
return obj_ptr;
} else {
assert(dest->is_old(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
// no other space to try.
return NULL;
}
}
--- 160,201 ----
}
HeapWord* G1ParScanThreadState::allocate_in_next_plab(InCSetState const state,
InCSetState* dest,
size_t word_sz,
! AllocationContext_t const context,
! bool previous_plab_refill_failed) {
assert(state.is_in_cset_or_humongous(), err_msg("Unexpected state: " CSETSTATE_FORMAT, state.value()));
assert(dest->is_in_cset_or_humongous(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
// Right now we only have two types of regions (young / old) so
// let's keep the logic here simple. We can generalize it when necessary.
if (dest->is_young()) {
+ bool plab_refill_in_old_failed = false;
HeapWord* const obj_ptr = _plab_allocator->allocate(InCSetState::Old,
word_sz,
! context,
! &plab_refill_in_old_failed);
// Make sure that we won't attempt to copy any other objects out
// of a survivor region (given that apparently we cannot allocate
! // any new ones) to avoid coming into this slow path again and again.
! // Only consider failed PLAB refill here: failed inline allocations are
! // typically large, so not indicative of remaining space.
! if (previous_plab_refill_failed) {
_tenuring_threshold = 0;
+ }
+
+ if (obj_ptr != NULL) {
dest->set_old();
+ } else {
+ // We just failed to allocate in old gen. The same idea as explained above
+ // for making survivor gen unavailable for allocation applies for old gen.
+ _last_gen_is_full = plab_refill_in_old_failed;
+ }
return obj_ptr;
} else {
+ _last_gen_is_full = previous_plab_refill_failed;
assert(dest->is_old(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
// no other space to try.
return NULL;
}
}
*** 208,225 ****
(!from_region->is_young() && young_index == 0), "invariant" );
const AllocationContext_t context = from_region->allocation_context();
uint age = 0;
InCSetState dest_state = next_state(state, old_mark, age);
HeapWord* obj_ptr = _plab_allocator->plab_allocate(dest_state, word_sz, context);
// PLAB allocations should succeed most of the time, so we'll
// normally check against NULL once and that's it.
if (obj_ptr == NULL) {
! obj_ptr = _plab_allocator->allocate_direct_or_new_plab(dest_state, word_sz, context);
if (obj_ptr == NULL) {
! obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context);
if (obj_ptr == NULL) {
// This will either forward-to-self, or detect that someone else has
// installed a forwarding pointer.
return handle_evacuation_failure_par(old, old_mark);
}
--- 222,245 ----
(!from_region->is_young() && young_index == 0), "invariant" );
const AllocationContext_t context = from_region->allocation_context();
uint age = 0;
InCSetState dest_state = next_state(state, old_mark, age);
+ // The second clause is to prevent premature evacuation failure in case there
+ // is still space in survivor, but old gen is full.
+ if (_last_gen_is_full && dest_state.is_old()) {
+ return handle_evacuation_failure_par(old, old_mark);
+ }
HeapWord* obj_ptr = _plab_allocator->plab_allocate(dest_state, word_sz, context);
// PLAB allocations should succeed most of the time, so we'll
// normally check against NULL once and that's it.
if (obj_ptr == NULL) {
! bool plab_refill_failed = false;
! obj_ptr = _plab_allocator->allocate_inline_or_new_plab(dest_state, word_sz, context, &plab_refill_failed);
if (obj_ptr == NULL) {
! obj_ptr = allocate_in_next_plab(state, &dest_state, word_sz, context, plab_refill_failed);
if (obj_ptr == NULL) {
// This will either forward-to-self, or detect that someone else has
// installed a forwarding pointer.
return handle_evacuation_failure_par(old, old_mark);
}
< prev index next >