src/share/vm/memory/cardTableRS.cpp

Print this page


   1 /*
   2  * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 156          "We shouldn't be looking at clean cards, and this should "
 157          "be the only place they get cleaned.");
 158   assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card,
 159          "This should be possible in the sequential case.");
 160   *entry = CardTableRS::clean_card_val();
 161   return true;
 162 }
 163 
 164 ClearNoncleanCardWrapper::ClearNoncleanCardWrapper(
 165   DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct) :
 166     _dirty_card_closure(dirty_card_closure), _ct(ct) {
 167     // Cannot yet substitute active_workers for n_par_threads
 168     // in the case where parallelism is being turned off by
 169     // setting n_par_threads to 0.
 170     _is_par = (SharedHeap::heap()->n_par_threads() > 0);
 171     assert(!_is_par ||
 172            (SharedHeap::heap()->n_par_threads() ==
 173             SharedHeap::heap()->workers()->active_workers()), "Mismatch");
 174 }
 175 




 176 void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) {
 177   assert(mr.word_size() > 0, "Error");
 178   assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned");
 179   // mr.end() may not necessarily be card aligned.
 180   jbyte* cur_entry = _ct->byte_for(mr.last());
 181   const jbyte* limit = _ct->byte_for(mr.start());
 182   HeapWord* end_of_non_clean = mr.end();
 183   HeapWord* start_of_non_clean = end_of_non_clean;
 184   while (cur_entry >= limit) {
 185     HeapWord* cur_hw = _ct->addr_for(cur_entry);
 186     if ((*cur_entry != CardTableRS::clean_card_val()) && clear_card(cur_entry)) {
 187       // Continue the dirty range by opening the
 188       // dirty window one card to the left.
 189       start_of_non_clean = cur_hw;


 190     } else {
 191       // We hit a "clean" card; process any non-empty
 192       // "dirty" range accumulated so far.
 193       if (start_of_non_clean < end_of_non_clean) {
 194         const MemRegion mrd(start_of_non_clean, end_of_non_clean);
 195         _dirty_card_closure->do_MemRegion(mrd);
 196       }

















 197       // Reset the dirty window, while continuing to look
 198       // for the next dirty card that will start a
 199       // new dirty window.
 200       end_of_non_clean = cur_hw;
 201       start_of_non_clean = cur_hw;


 202     }
 203     // Note that "cur_entry" leads "start_of_non_clean" in
 204     // its leftward excursion after this point
 205     // in the loop and, when we hit the left end of "mr",
 206     // will point off of the left end of the card-table
 207     // for "mr".
 208     cur_entry--;
 209   }
 210   // If the first card of "mr" was dirty, we will have
 211   // been left with a dirty window, co-initial with "mr",
 212   // which we now process.
 213   if (start_of_non_clean < end_of_non_clean) {
 214     const MemRegion mrd(start_of_non_clean, end_of_non_clean);
 215     _dirty_card_closure->do_MemRegion(mrd);
 216   }
 217 }
 218 
 219 // clean (by dirty->clean before) ==> cur_younger_gen
 220 // dirty                          ==> cur_youngergen_and_prev_nonclean_card
 221 // precleaned                     ==> cur_youngergen_and_prev_nonclean_card
 222 // prev-younger-gen               ==> cur_youngergen_and_prev_nonclean_card
 223 // cur-younger-gen                ==> cur_younger_gen
 224 // cur_youngergen_and_prev_nonclean_card ==> no change.
 225 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
 226   jbyte* entry = ct_bs()->byte_for(field);
 227   do {
 228     jbyte entry_val = *entry;


   1 /*
   2  * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *


 156          "We shouldn't be looking at clean cards, and this should "
 157          "be the only place they get cleaned.");
 158   assert(entry_val != CardTableRS::cur_youngergen_and_prev_nonclean_card,
 159          "This should be possible in the sequential case.");
 160   *entry = CardTableRS::clean_card_val();
 161   return true;
 162 }
 163 
 164 ClearNoncleanCardWrapper::ClearNoncleanCardWrapper(
 165   DirtyCardToOopClosure* dirty_card_closure, CardTableRS* ct) :
 166     _dirty_card_closure(dirty_card_closure), _ct(ct) {
 167     // Cannot yet substitute active_workers for n_par_threads
 168     // in the case where parallelism is being turned off by
 169     // setting n_par_threads to 0.
 170     _is_par = (SharedHeap::heap()->n_par_threads() > 0);
 171     assert(!_is_par ||
 172            (SharedHeap::heap()->n_par_threads() ==
 173             SharedHeap::heap()->workers()->active_workers()), "Mismatch");
 174 }
 175 
 176 bool ClearNoncleanCardWrapper::is_word_aligned(jbyte* entry) {
 177   return (((intptr_t)entry) & (BytesPerWord-1)) == 0;
 178 }
 179 
 180 void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) {
 181   assert(mr.word_size() > 0, "Error");
 182   assert(_ct->is_aligned(mr.start()), "mr.start() should be card aligned");
 183   // mr.end() may not necessarily be card aligned.
 184   jbyte* cur_entry = _ct->byte_for(mr.last());
 185   const jbyte* limit = _ct->byte_for(mr.start());
 186   HeapWord* end_of_non_clean = mr.end();
 187   HeapWord* start_of_non_clean = end_of_non_clean;
 188   while (cur_entry >= limit) {
 189     HeapWord* cur_hw = _ct->addr_for(cur_entry);
 190     if ((*cur_entry != CardTableRS::clean_card_val()) && clear_card(cur_entry)) {
 191       // Continue the dirty range by opening the
 192       // dirty window one card to the left.
 193       start_of_non_clean = cur_hw;
 194 
 195       cur_entry--;
 196     } else {
 197       // We hit a "clean" card; process any non-empty
 198       // "dirty" range accumulated so far.
 199       if (start_of_non_clean < end_of_non_clean) {
 200         const MemRegion mrd(start_of_non_clean, end_of_non_clean);
 201         _dirty_card_closure->do_MemRegion(mrd);
 202       }
 203 
 204       // fast forward through potential continuous range of clean cards
 205       if (is_word_aligned(cur_entry)) {
 206         jbyte* cur_row = cur_entry - BytesPerWord;
 207         while(cur_row >= limit) {
 208           if (*((intptr_t*)cur_row) ==  CardTableRS::clean_card_row()) {
 209                 cur_row -= BytesPerWord;
 210             }
 211             else {
 212                 break;
 213             }
 214         }
 215         cur_entry = cur_row + (BytesPerWord - 1);
 216         HeapWord* last_hw = _ct->addr_for(cur_row + BytesPerWord);
 217         end_of_non_clean = last_hw;
 218         start_of_non_clean = last_hw;
 219       } else {
 220           // Reset the dirty window, while continuing to look
 221           // for the next dirty card that will start a
 222           // new dirty window.
 223           end_of_non_clean = cur_hw;
 224           start_of_non_clean = cur_hw;
 225           cur_entry--;
 226       }
 227     }
 228     // Note that "cur_entry" leads "start_of_non_clean" in
 229     // its leftward excursion after this point
 230     // in the loop and, when we hit the left end of "mr",
 231     // will point off of the left end of the card-table
 232     // for "mr".

 233   }
 234   // If the first card of "mr" was dirty, we will have
 235   // been left with a dirty window, co-initial with "mr",
 236   // which we now process.
 237   if (start_of_non_clean < end_of_non_clean) {
 238     const MemRegion mrd(start_of_non_clean, end_of_non_clean);
 239     _dirty_card_closure->do_MemRegion(mrd);
 240   }
 241 }
 242 
 243 // clean (by dirty->clean before) ==> cur_younger_gen
 244 // dirty                          ==> cur_youngergen_and_prev_nonclean_card
 245 // precleaned                     ==> cur_youngergen_and_prev_nonclean_card
 246 // prev-younger-gen               ==> cur_youngergen_and_prev_nonclean_card
 247 // cur-younger-gen                ==> cur_younger_gen
 248 // cur_youngergen_and_prev_nonclean_card ==> no change.
 249 void CardTableRS::write_ref_field_gc_par(void* field, oop new_val) {
 250   jbyte* entry = ct_bs()->byte_for(field);
 251   do {
 252     jbyte entry_val = *entry;