src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,483 @@
     1.4 +/*
     1.5 + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "memory/allocation.inline.hpp"
    1.30 +#include "memory/cardTableModRefBS.hpp"
    1.31 +#include "memory/cardTableRS.hpp"
    1.32 +#include "memory/sharedHeap.hpp"
    1.33 +#include "memory/space.inline.hpp"
    1.34 +#include "memory/universe.hpp"
    1.35 +#include "oops/oop.inline.hpp"
    1.36 +#include "runtime/java.hpp"
    1.37 +#include "runtime/mutexLocker.hpp"
    1.38 +#include "runtime/virtualspace.hpp"
    1.39 +#include "runtime/vmThread.hpp"
    1.40 +
    1.41 +PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
    1.42 +
    1.43 +void CardTableModRefBS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
    1.44 +                                                             OopsInGenClosure* cl,
    1.45 +                                                             CardTableRS* ct,
    1.46 +                                                             int n_threads) {
    1.47 +  assert(n_threads > 0, "Error: expected n_threads > 0");
    1.48 +  assert((n_threads == 1 && ParallelGCThreads == 0) ||
    1.49 +         n_threads <= (int)ParallelGCThreads,
    1.50 +         "# worker threads != # requested!");
    1.51 +  assert(!Thread::current()->is_VM_thread() || (n_threads == 1), "There is only 1 VM thread");
    1.52 +  assert(UseDynamicNumberOfGCThreads ||
    1.53 +         !FLAG_IS_DEFAULT(ParallelGCThreads) ||
    1.54 +         n_threads == (int)ParallelGCThreads,
    1.55 +         "# worker threads != # requested!");
    1.56 +  // Make sure the LNC array is valid for the space.
    1.57 +  jbyte**   lowest_non_clean;
    1.58 +  uintptr_t lowest_non_clean_base_chunk_index;
    1.59 +  size_t    lowest_non_clean_chunk_size;
    1.60 +  get_LNC_array_for_space(sp, lowest_non_clean,
    1.61 +                          lowest_non_clean_base_chunk_index,
    1.62 +                          lowest_non_clean_chunk_size);
    1.63 +
    1.64 +  uint n_strides = n_threads * ParGCStridesPerThread;
    1.65 +  SequentialSubTasksDone* pst = sp->par_seq_tasks();
    1.66 +  // Sets the condition for completion of the subtask (how many threads
    1.67 +  // need to finish in order to be done).
    1.68 +  pst->set_n_threads(n_threads);
    1.69 +  pst->set_n_tasks(n_strides);
    1.70 +
    1.71 +  uint stride = 0;
    1.72 +  while (!pst->is_task_claimed(/* reference */ stride)) {
    1.73 +    process_stride(sp, mr, stride, n_strides, cl, ct,
    1.74 +                   lowest_non_clean,
    1.75 +                   lowest_non_clean_base_chunk_index,
    1.76 +                   lowest_non_clean_chunk_size);
    1.77 +  }
    1.78 +  if (pst->all_tasks_completed()) {
    1.79 +    // Clear lowest_non_clean array for next time.
    1.80 +    intptr_t first_chunk_index = addr_to_chunk_index(mr.start());
    1.81 +    uintptr_t last_chunk_index  = addr_to_chunk_index(mr.last());
    1.82 +    for (uintptr_t ch = first_chunk_index; ch <= last_chunk_index; ch++) {
    1.83 +      intptr_t ind = ch - lowest_non_clean_base_chunk_index;
    1.84 +      assert(0 <= ind && ind < (intptr_t)lowest_non_clean_chunk_size,
    1.85 +             "Bounds error");
    1.86 +      lowest_non_clean[ind] = NULL;
    1.87 +    }
    1.88 +  }
    1.89 +}
    1.90 +
    1.91 +void
    1.92 +CardTableModRefBS::
    1.93 +process_stride(Space* sp,
    1.94 +               MemRegion used,
    1.95 +               jint stride, int n_strides,
    1.96 +               OopsInGenClosure* cl,
    1.97 +               CardTableRS* ct,
    1.98 +               jbyte** lowest_non_clean,
    1.99 +               uintptr_t lowest_non_clean_base_chunk_index,
   1.100 +               size_t    lowest_non_clean_chunk_size) {
   1.101 +  // We go from higher to lower addresses here; it wouldn't help that much
   1.102 +  // because of the strided parallelism pattern used here.
   1.103 +
   1.104 +  // Find the first card address of the first chunk in the stride that is
   1.105 +  // at least "bottom" of the used region.
   1.106 +  jbyte*    start_card  = byte_for(used.start());
   1.107 +  jbyte*    end_card    = byte_after(used.last());
   1.108 +  uintptr_t start_chunk = addr_to_chunk_index(used.start());
   1.109 +  uintptr_t start_chunk_stride_num = start_chunk % n_strides;
   1.110 +  jbyte* chunk_card_start;
   1.111 +
   1.112 +  if ((uintptr_t)stride >= start_chunk_stride_num) {
   1.113 +    chunk_card_start = (jbyte*)(start_card +
   1.114 +                                (stride - start_chunk_stride_num) *
   1.115 +                                ParGCCardsPerStrideChunk);
   1.116 +  } else {
   1.117 +    // Go ahead to the next chunk group boundary, then to the requested stride.
   1.118 +    chunk_card_start = (jbyte*)(start_card +
   1.119 +                                (n_strides - start_chunk_stride_num + stride) *
   1.120 +                                ParGCCardsPerStrideChunk);
   1.121 +  }
   1.122 +
   1.123 +  while (chunk_card_start < end_card) {
   1.124 +    // Even though we go from lower to higher addresses below, the
   1.125 +    // strided parallelism can interleave the actual processing of the
   1.126 +    // dirty pages in various ways. For a specific chunk within this
   1.127 +    // stride, we take care to avoid double scanning or missing a card
   1.128 +    // by suitably initializing the "min_done" field in process_chunk_boundaries()
   1.129 +    // below, together with the dirty region extension accomplished in
   1.130 +    // DirtyCardToOopClosure::do_MemRegion().
   1.131 +    jbyte*    chunk_card_end = chunk_card_start + ParGCCardsPerStrideChunk;
   1.132 +    // Invariant: chunk_mr should be fully contained within the "used" region.
   1.133 +    MemRegion chunk_mr       = MemRegion(addr_for(chunk_card_start),
   1.134 +                                         chunk_card_end >= end_card ?
   1.135 +                                           used.end() : addr_for(chunk_card_end));
   1.136 +    assert(chunk_mr.word_size() > 0, "[chunk_card_start > used_end)");
   1.137 +    assert(used.contains(chunk_mr), "chunk_mr should be subset of used");
   1.138 +
   1.139 +    DirtyCardToOopClosure* dcto_cl = sp->new_dcto_cl(cl, precision(),
   1.140 +                                                     cl->gen_boundary());
   1.141 +    ClearNoncleanCardWrapper clear_cl(dcto_cl, ct);
   1.142 +
   1.143 +
   1.144 +    // Process the chunk.
   1.145 +    process_chunk_boundaries(sp,
   1.146 +                             dcto_cl,
   1.147 +                             chunk_mr,
   1.148 +                             used,
   1.149 +                             lowest_non_clean,
   1.150 +                             lowest_non_clean_base_chunk_index,
   1.151 +                             lowest_non_clean_chunk_size);
   1.152 +
   1.153 +    // We want the LNC array updates above in process_chunk_boundaries
   1.154 +    // to be visible before any of the card table value changes as a
   1.155 +    // result of the dirty card iteration below.
   1.156 +    OrderAccess::storestore();
   1.157 +
   1.158 +    // We do not call the non_clean_card_iterate_serial() version because
   1.159 +    // we want to clear the cards: clear_cl here does the work of finding
   1.160 +    // contiguous dirty ranges of cards to process and clear.
   1.161 +    clear_cl.do_MemRegion(chunk_mr);
   1.162 +
   1.163 +    // Find the next chunk of the stride.
   1.164 +    chunk_card_start += ParGCCardsPerStrideChunk * n_strides;
   1.165 +  }
   1.166 +}
   1.167 +
   1.168 +
   1.169 +// If you want a talkative process_chunk_boundaries,
   1.170 +// then #define NOISY(x) x
   1.171 +#ifdef NOISY
   1.172 +#error "Encountered a global preprocessor flag, NOISY, which might clash with local definition to follow"
   1.173 +#else
   1.174 +#define NOISY(x)
   1.175 +#endif
   1.176 +
   1.177 +void
   1.178 +CardTableModRefBS::
   1.179 +process_chunk_boundaries(Space* sp,
   1.180 +                         DirtyCardToOopClosure* dcto_cl,
   1.181 +                         MemRegion chunk_mr,
   1.182 +                         MemRegion used,
   1.183 +                         jbyte** lowest_non_clean,
   1.184 +                         uintptr_t lowest_non_clean_base_chunk_index,
   1.185 +                         size_t    lowest_non_clean_chunk_size)
   1.186 +{
   1.187 +  // We must worry about non-array objects that cross chunk boundaries,
   1.188 +  // because such objects are both precisely and imprecisely marked:
   1.189 +  // .. if the head of such an object is dirty, the entire object
   1.190 +  //    needs to be scanned, under the interpretation that this
   1.191 +  //    was an imprecise mark
   1.192 +  // .. if the head of such an object is not dirty, we can assume
   1.193 +  //    precise marking and it's efficient to scan just the dirty
   1.194 +  //    cards.
   1.195 +  // In either case, each scanned reference must be scanned precisely
   1.196 +  // once so as to avoid cloning of a young referent. For efficiency,
   1.197 +  // our closures depend on this property and do not protect against
   1.198 +  // double scans.
   1.199 +
   1.200 +  uintptr_t cur_chunk_index = addr_to_chunk_index(chunk_mr.start());
   1.201 +  cur_chunk_index           = cur_chunk_index - lowest_non_clean_base_chunk_index;
   1.202 +
   1.203 +  NOISY(tty->print_cr("===========================================================================");)
   1.204 +  NOISY(tty->print_cr(" process_chunk_boundary: Called with [" PTR_FORMAT "," PTR_FORMAT ")",
   1.205 +                      chunk_mr.start(), chunk_mr.end());)
   1.206 +
   1.207 +  // First, set "our" lowest_non_clean entry, which would be
   1.208 +  // used by the thread scanning an adjoining left chunk with
   1.209 +  // a non-array object straddling the mutual boundary.
   1.210 +  // Find the object that spans our boundary, if one exists.
   1.211 +  // first_block is the block possibly straddling our left boundary.
   1.212 +  HeapWord* first_block = sp->block_start(chunk_mr.start());
   1.213 +  assert((chunk_mr.start() != used.start()) || (first_block == chunk_mr.start()),
   1.214 +         "First chunk should always have a co-initial block");
   1.215 +  // Does the block straddle the chunk's left boundary, and is it
   1.216 +  // a non-array object?
   1.217 +  if (first_block < chunk_mr.start()        // first block straddles left bdry
   1.218 +      && sp->block_is_obj(first_block)      // first block is an object
   1.219 +      && !(oop(first_block)->is_objArray()  // first block is not an array (arrays are precisely dirtied)
   1.220 +           || oop(first_block)->is_typeArray())) {
   1.221 +    // Find our least non-clean card, so that a left neighbour
   1.222 +    // does not scan an object straddling the mutual boundary
   1.223 +    // too far to the right, and attempt to scan a portion of
   1.224 +    // that object twice.
   1.225 +    jbyte* first_dirty_card = NULL;
   1.226 +    jbyte* last_card_of_first_obj =
   1.227 +        byte_for(first_block + sp->block_size(first_block) - 1);
   1.228 +    jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start());
   1.229 +    jbyte* last_card_of_cur_chunk = byte_for(chunk_mr.last());
   1.230 +    jbyte* last_card_to_check =
   1.231 +      (jbyte*) MIN2((intptr_t) last_card_of_cur_chunk,
   1.232 +                    (intptr_t) last_card_of_first_obj);
   1.233 +    // Note that this does not need to go beyond our last card
   1.234 +    // if our first object completely straddles this chunk.
   1.235 +    for (jbyte* cur = first_card_of_cur_chunk;
   1.236 +         cur <= last_card_to_check; cur++) {
   1.237 +      jbyte val = *cur;
   1.238 +      if (card_will_be_scanned(val)) {
   1.239 +        first_dirty_card = cur; break;
   1.240 +      } else {
   1.241 +        assert(!card_may_have_been_dirty(val), "Error");
   1.242 +      }
   1.243 +    }
   1.244 +    if (first_dirty_card != NULL) {
   1.245 +      NOISY(tty->print_cr(" LNC: Found a dirty card at " PTR_FORMAT " in current chunk",
   1.246 +                    first_dirty_card);)
   1.247 +      assert(0 <= cur_chunk_index && cur_chunk_index < lowest_non_clean_chunk_size,
   1.248 +             "Bounds error.");
   1.249 +      assert(lowest_non_clean[cur_chunk_index] == NULL,
   1.250 +             "Write exactly once : value should be stable hereafter for this round");
   1.251 +      lowest_non_clean[cur_chunk_index] = first_dirty_card;
   1.252 +    } NOISY(else {
   1.253 +      tty->print_cr(" LNC: Found no dirty card in current chunk; leaving LNC entry NULL");
   1.254 +      // In the future, we could have this thread look for a non-NULL value to copy from its
   1.255 +      // right neighbour (up to the end of the first object).
   1.256 +      if (last_card_of_cur_chunk < last_card_of_first_obj) {
   1.257 +        tty->print_cr(" LNC: BEWARE!!! first obj straddles past right end of chunk:\n"
   1.258 +                      "   might be efficient to get value from right neighbour?");
   1.259 +      }
   1.260 +    })
   1.261 +  } else {
   1.262 +    // In this case we can help our neighbour by just asking them
   1.263 +    // to stop at our first card (even though it may not be dirty).
   1.264 +    NOISY(tty->print_cr(" LNC: first block is not a non-array object; setting LNC to first card of current chunk");)
   1.265 +    assert(lowest_non_clean[cur_chunk_index] == NULL, "Write once : value should be stable hereafter");
   1.266 +    jbyte* first_card_of_cur_chunk = byte_for(chunk_mr.start());
   1.267 +    lowest_non_clean[cur_chunk_index] = first_card_of_cur_chunk;
   1.268 +  }
   1.269 +  NOISY(tty->print_cr(" process_chunk_boundary: lowest_non_clean[" INTPTR_FORMAT "] = " PTR_FORMAT
   1.270 +                "   which corresponds to the heap address " PTR_FORMAT,
   1.271 +                cur_chunk_index, lowest_non_clean[cur_chunk_index],
   1.272 +                (lowest_non_clean[cur_chunk_index] != NULL)
   1.273 +                ? addr_for(lowest_non_clean[cur_chunk_index])
   1.274 +                : NULL);)
   1.275 +  NOISY(tty->print_cr("---------------------------------------------------------------------------");)
   1.276 +
   1.277 +  // Next, set our own max_to_do, which will strictly/exclusively bound
   1.278 +  // the highest address that we will scan past the right end of our chunk.
   1.279 +  HeapWord* max_to_do = NULL;
   1.280 +  if (chunk_mr.end() < used.end()) {
   1.281 +    // This is not the last chunk in the used region.
   1.282 +    // What is our last block? We check the first block of
   1.283 +    // the next (right) chunk rather than strictly check our last block
   1.284 +    // because it's potentially more efficient to do so.
   1.285 +    HeapWord* const last_block = sp->block_start(chunk_mr.end());
   1.286 +    assert(last_block <= chunk_mr.end(), "In case this property changes.");
   1.287 +    if ((last_block == chunk_mr.end())     // our last block does not straddle boundary
   1.288 +        || !sp->block_is_obj(last_block)   // last_block isn't an object
   1.289 +        || oop(last_block)->is_objArray()  // last_block is an array (precisely marked)
   1.290 +        || oop(last_block)->is_typeArray()) {
   1.291 +      max_to_do = chunk_mr.end();
   1.292 +      NOISY(tty->print_cr(" process_chunk_boundary: Last block on this card is not a non-array object;\n"
   1.293 +                         "   max_to_do left at " PTR_FORMAT, max_to_do);)
   1.294 +    } else {
   1.295 +      assert(last_block < chunk_mr.end(), "Tautology");
   1.296 +      // It is a non-array object that straddles the right boundary of this chunk.
   1.297 +      // last_obj_card is the card corresponding to the start of the last object
   1.298 +      // in the chunk.  Note that the last object may not start in
   1.299 +      // the chunk.
   1.300 +      jbyte* const last_obj_card = byte_for(last_block);
   1.301 +      const jbyte val = *last_obj_card;
   1.302 +      if (!card_will_be_scanned(val)) {
   1.303 +        assert(!card_may_have_been_dirty(val), "Error");
   1.304 +        // The card containing the head is not dirty.  Any marks on
   1.305 +        // subsequent cards still in this chunk must have been made
   1.306 +        // precisely; we can cap processing at the end of our chunk.
   1.307 +        max_to_do = chunk_mr.end();
   1.308 +        NOISY(tty->print_cr(" process_chunk_boundary: Head of last object on this card is not dirty;\n"
   1.309 +                            "   max_to_do left at " PTR_FORMAT,
   1.310 +                            max_to_do);)
   1.311 +      } else {
   1.312 +        // The last object must be considered dirty, and extends onto the
   1.313 +        // following chunk.  Look for a dirty card in that chunk that will
   1.314 +        // bound our processing.
   1.315 +        jbyte* limit_card = NULL;
   1.316 +        const size_t last_block_size = sp->block_size(last_block);
   1.317 +        jbyte* const last_card_of_last_obj =
   1.318 +          byte_for(last_block + last_block_size - 1);
   1.319 +        jbyte* const first_card_of_next_chunk = byte_for(chunk_mr.end());
   1.320 +        // This search potentially goes a long distance looking
   1.321 +        // for the next card that will be scanned, terminating
   1.322 +        // at the end of the last_block, if no earlier dirty card
   1.323 +        // is found.
   1.324 +        assert(byte_for(chunk_mr.end()) - byte_for(chunk_mr.start()) == ParGCCardsPerStrideChunk,
   1.325 +               "last card of next chunk may be wrong");
   1.326 +        for (jbyte* cur = first_card_of_next_chunk;
   1.327 +             cur <= last_card_of_last_obj; cur++) {
   1.328 +          const jbyte val = *cur;
   1.329 +          if (card_will_be_scanned(val)) {
   1.330 +            NOISY(tty->print_cr(" Found a non-clean card " PTR_FORMAT " with value 0x%x",
   1.331 +                                cur, (int)val);)
   1.332 +            limit_card = cur; break;
   1.333 +          } else {
   1.334 +            assert(!card_may_have_been_dirty(val), "Error: card can't be skipped");
   1.335 +          }
   1.336 +        }
   1.337 +        if (limit_card != NULL) {
   1.338 +          max_to_do = addr_for(limit_card);
   1.339 +          assert(limit_card != NULL && max_to_do != NULL, "Error");
   1.340 +          NOISY(tty->print_cr(" process_chunk_boundary: Found a dirty card at " PTR_FORMAT
   1.341 +                        "   max_to_do set at " PTR_FORMAT " which is before end of last block in chunk: "
   1.342 +                        PTR_FORMAT " + " PTR_FORMAT " = " PTR_FORMAT,
   1.343 +                        limit_card, max_to_do, last_block, last_block_size, (last_block+last_block_size));)
   1.344 +        } else {
   1.345 +          // The following is a pessimistic value, because it's possible
   1.346 +          // that a dirty card on a subsequent chunk has been cleared by
   1.347 +          // the time we get to look at it; we'll correct for that further below,
   1.348 +          // using the LNC array which records the least non-clean card
   1.349 +          // before cards were cleared in a particular chunk.
   1.350 +          limit_card = last_card_of_last_obj;
   1.351 +          max_to_do = last_block + last_block_size;
   1.352 +          assert(limit_card != NULL && max_to_do != NULL, "Error");
   1.353 +          NOISY(tty->print_cr(" process_chunk_boundary: Found no dirty card before end of last block in chunk\n"
   1.354 +                              "   Setting limit_card to " PTR_FORMAT
   1.355 +                              " and max_to_do " PTR_FORMAT " + " PTR_FORMAT " = " PTR_FORMAT,
   1.356 +                              limit_card, last_block, last_block_size, max_to_do);)
   1.357 +        }
   1.358 +        assert(0 < cur_chunk_index+1 && cur_chunk_index+1 < lowest_non_clean_chunk_size,
   1.359 +               "Bounds error.");
   1.360 +        // It is possible that a dirty card for the last object may have been
   1.361 +        // cleared before we had a chance to examine it. In that case, the value
   1.362 +        // will have been logged in the LNC for that chunk.
   1.363 +        // We need to examine as many chunks to the right as this object
   1.364 +        // covers. However, we need to bound this checking to the largest
   1.365 +        // entry in the LNC array: this is because the heap may expand
   1.366 +        // after the LNC array has been created but before we reach this point,
   1.367 +        // and the last block in our chunk may have been expanded to include
   1.368 +        // the expansion delta (and possibly subsequently allocated from, so
   1.369 +        // it wouldn't be sufficient to check whether that last block was
   1.370 +        // or was not an object at this point).
   1.371 +        uintptr_t last_chunk_index_to_check = addr_to_chunk_index(last_block + last_block_size - 1)
   1.372 +                                              - lowest_non_clean_base_chunk_index;
   1.373 +        const uintptr_t last_chunk_index    = addr_to_chunk_index(used.last())
   1.374 +                                              - lowest_non_clean_base_chunk_index;
   1.375 +        if (last_chunk_index_to_check > last_chunk_index) {
   1.376 +          assert(last_block + last_block_size > used.end(),
   1.377 +                 err_msg("Inconsistency detected: last_block [" PTR_FORMAT "," PTR_FORMAT "]"
   1.378 +                         " does not exceed used.end() = " PTR_FORMAT ","
   1.379 +                         " yet last_chunk_index_to_check " INTPTR_FORMAT
   1.380 +                         " exceeds last_chunk_index " INTPTR_FORMAT,
   1.381 +                         last_block, last_block + last_block_size,
   1.382 +                         used.end(),
   1.383 +                         last_chunk_index_to_check, last_chunk_index));
   1.384 +          assert(sp->used_region().end() > used.end(),
   1.385 +                 err_msg("Expansion did not happen: "
   1.386 +                         "[" PTR_FORMAT "," PTR_FORMAT ") -> [" PTR_FORMAT "," PTR_FORMAT ")",
   1.387 +                         sp->used_region().start(), sp->used_region().end(), used.start(), used.end()));
   1.388 +          NOISY(tty->print_cr(" process_chunk_boundary: heap expanded; explicitly bounding last_chunk");)
   1.389 +          last_chunk_index_to_check = last_chunk_index;
   1.390 +        }
   1.391 +        for (uintptr_t lnc_index = cur_chunk_index + 1;
   1.392 +             lnc_index <= last_chunk_index_to_check;
   1.393 +             lnc_index++) {
   1.394 +          jbyte* lnc_card = lowest_non_clean[lnc_index];
   1.395 +          if (lnc_card != NULL) {
   1.396 +            // we can stop at the first non-NULL entry we find
   1.397 +            if (lnc_card <= limit_card) {
   1.398 +              NOISY(tty->print_cr(" process_chunk_boundary: LNC card " PTR_FORMAT " is lower than limit_card " PTR_FORMAT,
   1.399 +                                  "   max_to_do will be lowered to " PTR_FORMAT " from " PTR_FORMAT,
   1.400 +                                  lnc_card, limit_card, addr_for(lnc_card), max_to_do);)
   1.401 +              limit_card = lnc_card;
   1.402 +              max_to_do = addr_for(limit_card);
   1.403 +              assert(limit_card != NULL && max_to_do != NULL, "Error");
   1.404 +            }
   1.405 +            // In any case, we break now
   1.406 +            break;
   1.407 +          }  // else continue to look for a non-NULL entry if any
   1.408 +        }
   1.409 +        assert(limit_card != NULL && max_to_do != NULL, "Error");
   1.410 +      }
   1.411 +      assert(max_to_do != NULL, "OOPS 1 !");
   1.412 +    }
   1.413 +    assert(max_to_do != NULL, "OOPS 2!");
   1.414 +  } else {
   1.415 +    max_to_do = used.end();
   1.416 +    NOISY(tty->print_cr(" process_chunk_boundary: Last chunk of this space;\n"
   1.417 +                  "   max_to_do left at " PTR_FORMAT,
   1.418 +                  max_to_do);)
   1.419 +  }
   1.420 +  assert(max_to_do != NULL, "OOPS 3!");
   1.421 +  // Now we can set the closure we're using so it doesn't to beyond
   1.422 +  // max_to_do.
   1.423 +  dcto_cl->set_min_done(max_to_do);
   1.424 +#ifndef PRODUCT
   1.425 +  dcto_cl->set_last_bottom(max_to_do);
   1.426 +#endif
   1.427 +  NOISY(tty->print_cr("===========================================================================\n");)
   1.428 +}
   1.429 +
   1.430 +#undef NOISY
   1.431 +
   1.432 +void
   1.433 +CardTableModRefBS::
   1.434 +get_LNC_array_for_space(Space* sp,
   1.435 +                        jbyte**& lowest_non_clean,
   1.436 +                        uintptr_t& lowest_non_clean_base_chunk_index,
   1.437 +                        size_t& lowest_non_clean_chunk_size) {
   1.438 +
   1.439 +  int       i        = find_covering_region_containing(sp->bottom());
   1.440 +  MemRegion covered  = _covered[i];
   1.441 +  size_t    n_chunks = chunks_to_cover(covered);
   1.442 +
   1.443 +  // Only the first thread to obtain the lock will resize the
   1.444 +  // LNC array for the covered region.  Any later expansion can't affect
   1.445 +  // the used_at_save_marks region.
   1.446 +  // (I observed a bug in which the first thread to execute this would
   1.447 +  // resize, and then it would cause "expand_and_allocate" that would
   1.448 +  // increase the number of chunks in the covered region.  Then a second
   1.449 +  // thread would come and execute this, see that the size didn't match,
   1.450 +  // and free and allocate again.  So the first thread would be using a
   1.451 +  // freed "_lowest_non_clean" array.)
   1.452 +
   1.453 +  // Do a dirty read here. If we pass the conditional then take the rare
   1.454 +  // event lock and do the read again in case some other thread had already
   1.455 +  // succeeded and done the resize.
   1.456 +  int cur_collection = Universe::heap()->total_collections();
   1.457 +  if (_last_LNC_resizing_collection[i] != cur_collection) {
   1.458 +    MutexLocker x(ParGCRareEvent_lock);
   1.459 +    if (_last_LNC_resizing_collection[i] != cur_collection) {
   1.460 +      if (_lowest_non_clean[i] == NULL ||
   1.461 +          n_chunks != _lowest_non_clean_chunk_size[i]) {
   1.462 +
   1.463 +        // Should we delete the old?
   1.464 +        if (_lowest_non_clean[i] != NULL) {
   1.465 +          assert(n_chunks != _lowest_non_clean_chunk_size[i],
   1.466 +                 "logical consequence");
   1.467 +          FREE_C_HEAP_ARRAY(CardPtr, _lowest_non_clean[i], mtGC);
   1.468 +          _lowest_non_clean[i] = NULL;
   1.469 +        }
   1.470 +        // Now allocate a new one if necessary.
   1.471 +        if (_lowest_non_clean[i] == NULL) {
   1.472 +          _lowest_non_clean[i]                  = NEW_C_HEAP_ARRAY(CardPtr, n_chunks, mtGC);
   1.473 +          _lowest_non_clean_chunk_size[i]       = n_chunks;
   1.474 +          _lowest_non_clean_base_chunk_index[i] = addr_to_chunk_index(covered.start());
   1.475 +          for (int j = 0; j < (int)n_chunks; j++)
   1.476 +            _lowest_non_clean[i][j] = NULL;
   1.477 +        }
   1.478 +      }
   1.479 +      _last_LNC_resizing_collection[i] = cur_collection;
   1.480 +    }
   1.481 +  }
   1.482 +  // In any case, now do the initialization.
   1.483 +  lowest_non_clean                  = _lowest_non_clean[i];
   1.484 +  lowest_non_clean_base_chunk_index = _lowest_non_clean_base_chunk_index[i];
   1.485 +  lowest_non_clean_chunk_size       = _lowest_non_clean_chunk_size[i];
   1.486 +}

mercurial