< 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 >