< prev index next >

src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp

Print this page
rev 7557 : 8060025: Object copy time regressions after JDK-8031323 and JDK-8057536
Summary: Evaluate and improve object copy time by micro-optimizations and splitting out slow and fast paths aggressively.
Reviewed-by:
Contributed-by: Tony Printezis <tprintezis@twitter.com>, Thomas Schatzl <thomas.schatzl@oracle.com>
rev 7559 : imported patch mikael-refactor-cset-state
rev 7560 : imported patch kim-review


 144 void G1ParScanThreadState::trim_queue() {
 145   assert(_evac_failure_cl != NULL, "not set");
 146 
 147   StarTask ref;
 148   do {
 149     // Drain the overflow stack first, so other threads can steal.
 150     while (_refs->pop_overflow(ref)) {
 151       dispatch_reference(ref);
 152     }
 153 
 154     while (_refs->pop_local(ref)) {
 155       dispatch_reference(ref);
 156     }
 157   } while (!_refs->is_empty());
 158 }
 159 
 160 HeapWord* G1ParScanThreadState::allocate_in_next_plab(InCSetState const state,
 161                                                       InCSetState* dest,
 162                                                       size_t word_sz,
 163                                                       AllocationContext_t const context) {
 164   assert(state.is_in_cset_or_humongous(), err_msg("Unexpected state: %u", state.value()));
 165   assert(dest->is_in_cset_or_humongous(), err_msg("Unexpected dest: %u", dest->value()));
 166 
 167   // Right now we only have two types of regions (young / old) so
 168   // let's keep the logic here simple. We can generalize it when necessary.
 169   if (dest->is_young()) {
 170     HeapWord* const obj_ptr = _g1_par_allocator->allocate(InCSetState::Old,
 171                                                           word_sz, context);
 172     if (obj_ptr == NULL) {
 173       return NULL;
 174     }
 175     // Make sure that we won't attempt to copy any other objects out
 176     // of a survivor region (given that apparently we cannot allocate
 177     // any new ones) to avoid coming into this slow path.
 178     _tenuring_threshold = 0;
 179     dest->set_old();
 180     return obj_ptr;
 181   } else {
 182     assert(dest->is_old(), err_msg("Unexpected dest: %u", dest->value()));
 183     // no other space to try.
 184     return NULL;
 185   }
 186 }
 187 
 188 InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop const m, uint& age) {
 189   if (state.is_young()) {
 190     age = !m->has_displaced_mark_helper() ? m->age()
 191                                           : m->displaced_mark_helper()->age();
 192     if (age < _tenuring_threshold) {
 193       return state;
 194     }
 195   }
 196   return dest(state);
 197 }
 198 
 199 oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
 200                                                  oop const old,
 201                                                  markOop const old_mark) {
 202   const size_t word_sz = old->size();




 144 void G1ParScanThreadState::trim_queue() {
 145   assert(_evac_failure_cl != NULL, "not set");
 146 
 147   StarTask ref;
 148   do {
 149     // Drain the overflow stack first, so other threads can steal.
 150     while (_refs->pop_overflow(ref)) {
 151       dispatch_reference(ref);
 152     }
 153 
 154     while (_refs->pop_local(ref)) {
 155       dispatch_reference(ref);
 156     }
 157   } while (!_refs->is_empty());
 158 }
 159 
 160 HeapWord* G1ParScanThreadState::allocate_in_next_plab(InCSetState const state,
 161                                                       InCSetState* dest,
 162                                                       size_t word_sz,
 163                                                       AllocationContext_t const context) {
 164   assert(state.is_in_cset_or_humongous(), err_msg("Unexpected state: " CSETSTATE_FORMAT, state.value()));
 165   assert(dest->is_in_cset_or_humongous(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
 166 
 167   // Right now we only have two types of regions (young / old) so
 168   // let's keep the logic here simple. We can generalize it when necessary.
 169   if (dest->is_young()) {
 170     HeapWord* const obj_ptr = _g1_par_allocator->allocate(InCSetState::Old,
 171                                                           word_sz, context);
 172     if (obj_ptr == NULL) {
 173       return NULL;
 174     }
 175     // Make sure that we won't attempt to copy any other objects out
 176     // of a survivor region (given that apparently we cannot allocate
 177     // any new ones) to avoid coming into this slow path.
 178     _tenuring_threshold = 0;
 179     dest->set_old();
 180     return obj_ptr;
 181   } else {
 182     assert(dest->is_old(), err_msg("Unexpected dest: " CSETSTATE_FORMAT, dest->value()));
 183     // no other space to try.
 184     return NULL;
 185   }
 186 }
 187 
 188 InCSetState G1ParScanThreadState::next_state(InCSetState const state, markOop const m, uint& age) {
 189   if (state.is_young()) {
 190     age = !m->has_displaced_mark_helper() ? m->age()
 191                                           : m->displaced_mark_helper()->age();
 192     if (age < _tenuring_threshold) {
 193       return state;
 194     }
 195   }
 196   return dest(state);
 197 }
 198 
 199 oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state,
 200                                                  oop const old,
 201                                                  markOop const old_mark) {
 202   const size_t word_sz = old->size();


< prev index next >