< prev index next >

src/share/vm/gc/cms/parCardTableModRefBS.cpp

Print this page
rev 10742 : Make fields used in lock-free algorithms volatile

*** 44,54 **** assert(n_threads > 0, "expected n_threads > 0"); assert(n_threads <= ParallelGCThreads, "n_threads: %u > ParallelGCThreads: %u", n_threads, ParallelGCThreads); // Make sure the LNC array is valid for the space. ! jbyte** lowest_non_clean; uintptr_t lowest_non_clean_base_chunk_index; size_t lowest_non_clean_chunk_size; get_LNC_array_for_space(sp, lowest_non_clean, lowest_non_clean_base_chunk_index, lowest_non_clean_chunk_size); --- 44,54 ---- assert(n_threads > 0, "expected n_threads > 0"); assert(n_threads <= ParallelGCThreads, "n_threads: %u > ParallelGCThreads: %u", n_threads, ParallelGCThreads); // Make sure the LNC array is valid for the space. ! volatile jbyte** lowest_non_clean; uintptr_t lowest_non_clean_base_chunk_index; size_t lowest_non_clean_chunk_size; get_LNC_array_for_space(sp, lowest_non_clean, lowest_non_clean_base_chunk_index, lowest_non_clean_chunk_size);
*** 86,116 **** process_stride(Space* sp, MemRegion used, jint stride, int n_strides, OopsInGenClosure* cl, CardTableRS* ct, ! jbyte** lowest_non_clean, uintptr_t lowest_non_clean_base_chunk_index, size_t lowest_non_clean_chunk_size) { // We go from higher to lower addresses here; it wouldn't help that much // because of the strided parallelism pattern used here. // Find the first card address of the first chunk in the stride that is // at least "bottom" of the used region. ! jbyte* start_card = byte_for(used.start()); ! jbyte* end_card = byte_after(used.last()); uintptr_t start_chunk = addr_to_chunk_index(used.start()); uintptr_t start_chunk_stride_num = start_chunk % n_strides; ! jbyte* chunk_card_start; if ((uintptr_t)stride >= start_chunk_stride_num) { ! chunk_card_start = (jbyte*)(start_card + (stride - start_chunk_stride_num) * ParGCCardsPerStrideChunk); } else { // Go ahead to the next chunk group boundary, then to the requested stride. ! chunk_card_start = (jbyte*)(start_card + (n_strides - start_chunk_stride_num + stride) * ParGCCardsPerStrideChunk); } while (chunk_card_start < end_card) { --- 86,116 ---- process_stride(Space* sp, MemRegion used, jint stride, int n_strides, OopsInGenClosure* cl, CardTableRS* ct, ! volatile jbyte** lowest_non_clean, uintptr_t lowest_non_clean_base_chunk_index, size_t lowest_non_clean_chunk_size) { // We go from higher to lower addresses here; it wouldn't help that much // because of the strided parallelism pattern used here. // Find the first card address of the first chunk in the stride that is // at least "bottom" of the used region. ! volatile jbyte* start_card = byte_for(used.start()); ! volatile jbyte* end_card = byte_after(used.last()); uintptr_t start_chunk = addr_to_chunk_index(used.start()); uintptr_t start_chunk_stride_num = start_chunk % n_strides; ! volatile jbyte* chunk_card_start; if ((uintptr_t)stride >= start_chunk_stride_num) { ! chunk_card_start = (volatile jbyte*)(start_card + (stride - start_chunk_stride_num) * ParGCCardsPerStrideChunk); } else { // Go ahead to the next chunk group boundary, then to the requested stride. ! chunk_card_start = (volatile jbyte*)(start_card + (n_strides - start_chunk_stride_num + stride) * ParGCCardsPerStrideChunk); } while (chunk_card_start < end_card) {
*** 119,129 **** // dirty pages in various ways. For a specific chunk within this // stride, we take care to avoid double scanning or missing a card // by suitably initializing the "min_done" field in process_chunk_boundaries() // below, together with the dirty region extension accomplished in // DirtyCardToOopClosure::do_MemRegion(). ! jbyte* chunk_card_end = chunk_card_start + ParGCCardsPerStrideChunk; // Invariant: chunk_mr should be fully contained within the "used" region. MemRegion chunk_mr = MemRegion(addr_for(chunk_card_start), chunk_card_end >= end_card ? used.end() : addr_for(chunk_card_end)); assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)"); --- 119,129 ---- // dirty pages in various ways. For a specific chunk within this // stride, we take care to avoid double scanning or missing a card // by suitably initializing the "min_done" field in process_chunk_boundaries() // below, together with the dirty region extension accomplished in // DirtyCardToOopClosure::do_MemRegion(). ! volatile jbyte* chunk_card_end = chunk_card_start + ParGCCardsPerStrideChunk; // Invariant: chunk_mr should be fully contained within the "used" region. MemRegion chunk_mr = MemRegion(addr_for(chunk_card_start), chunk_card_end >= end_card ? used.end() : addr_for(chunk_card_end)); assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)");
*** 165,175 **** CardTableModRefBSForCTRS:: process_chunk_boundaries(Space* sp, DirtyCardToOopClosure* dcto_cl, MemRegion chunk_mr, MemRegion used, ! jbyte** lowest_non_clean, uintptr_t lowest_non_clean_base_chunk_index, size_t lowest_non_clean_chunk_size) { // We must worry about non-array objects that cross chunk boundaries, // because such objects are both precisely and imprecisely marked: --- 165,175 ---- CardTableModRefBSForCTRS:: process_chunk_boundaries(Space* sp, DirtyCardToOopClosure* dcto_cl, MemRegion chunk_mr, MemRegion used, ! volatile jbyte** lowest_non_clean, uintptr_t lowest_non_clean_base_chunk_index, size_t lowest_non_clean_chunk_size) { // We must worry about non-array objects that cross chunk boundaries, // because such objects are both precisely and imprecisely marked:
*** 204,224 **** || oop(first_block)->is_typeArray())) { // Find our least non-clean card, so that a left neighbor // does not scan an object straddling the mutual boundary // too far to the right, and attempt to scan a portion of // that object twice. ! jbyte* first_dirty_card = NULL; ! jbyte* last_card_of_first_obj = byte_for(first_block + sp->block_size(first_block) - 1); ! jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start()); ! jbyte* last_card_of_cur_chunk = byte_for(chunk_mr.last()); ! jbyte* last_card_to_check = ! (jbyte*) MIN2((intptr_t) last_card_of_cur_chunk, (intptr_t) last_card_of_first_obj); // Note that this does not need to go beyond our last card // if our first object completely straddles this chunk. ! for (jbyte* cur = first_card_of_cur_chunk; cur <= last_card_to_check; cur++) { jbyte val = *cur; if (card_will_be_scanned(val)) { first_dirty_card = cur; break; } else { --- 204,224 ---- || oop(first_block)->is_typeArray())) { // Find our least non-clean card, so that a left neighbor // does not scan an object straddling the mutual boundary // too far to the right, and attempt to scan a portion of // that object twice. ! volatile jbyte* first_dirty_card = NULL; ! volatile jbyte* last_card_of_first_obj = byte_for(first_block + sp->block_size(first_block) - 1); ! volatile jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start()); ! volatile jbyte* last_card_of_cur_chunk = byte_for(chunk_mr.last()); ! volatile jbyte* last_card_to_check = ! (volatile jbyte*) MIN2((intptr_t) last_card_of_cur_chunk, (intptr_t) last_card_of_first_obj); // Note that this does not need to go beyond our last card // if our first object completely straddles this chunk. ! for (volatile jbyte* cur = first_card_of_cur_chunk; cur <= last_card_to_check; cur++) { jbyte val = *cur; if (card_will_be_scanned(val)) { first_dirty_card = cur; break; } else {
*** 233,243 **** } } else { // In this case we can help our neighbor by just asking them // to stop at our first card (even though it may not be dirty). assert(lowest_non_clean[cur_chunk_index] == NULL, "Write once : value should be stable hereafter"); ! jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start()); lowest_non_clean[cur_chunk_index] = first_card_of_cur_chunk; } // Next, set our own max_to_do, which will strictly/exclusively bound // the highest address that we will scan past the right end of our chunk. --- 233,243 ---- } } else { // In this case we can help our neighbor by just asking them // to stop at our first card (even though it may not be dirty). assert(lowest_non_clean[cur_chunk_index] == NULL, "Write once : value should be stable hereafter"); ! volatile jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start()); lowest_non_clean[cur_chunk_index] = first_card_of_cur_chunk; } // Next, set our own max_to_do, which will strictly/exclusively bound // the highest address that we will scan past the right end of our chunk.
*** 258,268 **** assert(last_block < chunk_mr.end(), "Tautology"); // It is a non-array object that straddles the right boundary of this chunk. // last_obj_card is the card corresponding to the start of the last object // in the chunk. Note that the last object may not start in // the chunk. ! jbyte* const last_obj_card = byte_for(last_block); const jbyte val = *last_obj_card; if (!card_will_be_scanned(val)) { assert(!card_may_have_been_dirty(val), "Error"); // The card containing the head is not dirty. Any marks on // subsequent cards still in this chunk must have been made --- 258,268 ---- assert(last_block < chunk_mr.end(), "Tautology"); // It is a non-array object that straddles the right boundary of this chunk. // last_obj_card is the card corresponding to the start of the last object // in the chunk. Note that the last object may not start in // the chunk. ! volatile jbyte* const last_obj_card = byte_for(last_block); const jbyte val = *last_obj_card; if (!card_will_be_scanned(val)) { assert(!card_may_have_been_dirty(val), "Error"); // The card containing the head is not dirty. Any marks on // subsequent cards still in this chunk must have been made
*** 270,293 **** max_to_do = chunk_mr.end(); } else { // The last object must be considered dirty, and extends onto the // following chunk. Look for a dirty card in that chunk that will // bound our processing. ! jbyte* limit_card = NULL; const size_t last_block_size = sp->block_size(last_block); ! jbyte* const last_card_of_last_obj = byte_for(last_block + last_block_size - 1); ! jbyte* const first_card_of_next_chunk = byte_for(chunk_mr.end()); // This search potentially goes a long distance looking // for the next card that will be scanned, terminating // at the end of the last_block, if no earlier dirty card // is found. assert(byte_for(chunk_mr.end()) - byte_for(chunk_mr.start()) == ParGCCardsPerStrideChunk, "last card of next chunk may be wrong"); ! for (jbyte* cur = first_card_of_next_chunk; cur <= last_card_of_last_obj; cur++) { ! const jbyte val = *cur; if (card_will_be_scanned(val)) { limit_card = cur; break; } else { assert(!card_may_have_been_dirty(val), "Error: card can't be skipped"); } --- 270,293 ---- max_to_do = chunk_mr.end(); } else { // The last object must be considered dirty, and extends onto the // following chunk. Look for a dirty card in that chunk that will // bound our processing. ! volatile jbyte* limit_card = NULL; const size_t last_block_size = sp->block_size(last_block); ! volatile jbyte* const last_card_of_last_obj = byte_for(last_block + last_block_size - 1); ! volatile jbyte* const first_card_of_next_chunk = byte_for(chunk_mr.end()); // This search potentially goes a long distance looking // for the next card that will be scanned, terminating // at the end of the last_block, if no earlier dirty card // is found. assert(byte_for(chunk_mr.end()) - byte_for(chunk_mr.start()) == ParGCCardsPerStrideChunk, "last card of next chunk may be wrong"); ! for (volatile jbyte* cur = first_card_of_next_chunk; cur <= last_card_of_last_obj; cur++) { ! const volatile jbyte val = *cur; if (card_will_be_scanned(val)) { limit_card = cur; break; } else { assert(!card_may_have_been_dirty(val), "Error: card can't be skipped"); }
*** 339,349 **** last_chunk_index_to_check = last_chunk_index; } for (uintptr_t lnc_index = cur_chunk_index + 1; lnc_index <= last_chunk_index_to_check; lnc_index++) { ! jbyte* lnc_card = lowest_non_clean[lnc_index]; if (lnc_card != NULL) { // we can stop at the first non-NULL entry we find if (lnc_card <= limit_card) { limit_card = lnc_card; max_to_do = addr_for(limit_card); --- 339,349 ---- last_chunk_index_to_check = last_chunk_index; } for (uintptr_t lnc_index = cur_chunk_index + 1; lnc_index <= last_chunk_index_to_check; lnc_index++) { ! volatile jbyte* lnc_card = lowest_non_clean[lnc_index]; if (lnc_card != NULL) { // we can stop at the first non-NULL entry we find if (lnc_card <= limit_card) { limit_card = lnc_card; max_to_do = addr_for(limit_card);
*** 371,381 **** } void CardTableModRefBSForCTRS:: get_LNC_array_for_space(Space* sp, ! jbyte**& lowest_non_clean, uintptr_t& lowest_non_clean_base_chunk_index, size_t& lowest_non_clean_chunk_size) { int i = find_covering_region_containing(sp->bottom()); MemRegion covered = _covered[i]; --- 371,381 ---- } void CardTableModRefBSForCTRS:: get_LNC_array_for_space(Space* sp, ! volatile jbyte**& lowest_non_clean, uintptr_t& lowest_non_clean_base_chunk_index, size_t& lowest_non_clean_chunk_size) { int i = find_covering_region_containing(sp->bottom()); MemRegion covered = _covered[i];
< prev index next >