6688799: Second fix for Guarantee failure "Unexpected dirty card found"

Tue, 10 Jun 2008 07:26:42 -0700

author
jmasa
date
Tue, 10 Jun 2008 07:26:42 -0700
changeset 643
35ca13d63fe8
parent 625
d1635bf93939
child 644
4fab66d72627

6688799: Second fix for Guarantee failure "Unexpected dirty card found"
Summary: Expand cardtable without committing over existing regions.
Reviewed-by: apetrusenko

src/share/vm/memory/cardTableModRefBS.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/memory/cardTableModRefBS.cpp	Mon Jun 09 07:18:59 2008 -0700
     1.2 +++ b/src/share/vm/memory/cardTableModRefBS.cpp	Tue Jun 10 07:26:42 2008 -0700
     1.3 @@ -196,6 +196,8 @@
     1.4    assert(_whole_heap.contains(new_region),
     1.5             "attempt to cover area not in reserved area");
     1.6    debug_only(verify_guard();)
     1.7 +  // collided is true if the expansion would push into another committed region
     1.8 +  debug_only(bool collided = false;)
     1.9    int const ind = find_covering_region_by_base(new_region.start());
    1.10    MemRegion const old_region = _covered[ind];
    1.11    assert(old_region.start() == new_region.start(), "just checking");
    1.12 @@ -211,12 +213,36 @@
    1.13      }
    1.14      // Align the end up to a page size (starts are already aligned).
    1.15      jbyte* const new_end = byte_after(new_region.last());
    1.16 -    HeapWord* const new_end_aligned =
    1.17 +    HeapWord* new_end_aligned =
    1.18        (HeapWord*) align_size_up((uintptr_t)new_end, _page_size);
    1.19      assert(new_end_aligned >= (HeapWord*) new_end,
    1.20             "align up, but less");
    1.21 +    int ri = 0;
    1.22 +    for (ri = 0; ri < _cur_covered_regions; ri++) {
    1.23 +      if (ri != ind) {
    1.24 +        if (_committed[ri].contains(new_end_aligned)) {
    1.25 +          assert((new_end_aligned >= _committed[ri].start()) &&
    1.26 +                 (_committed[ri].start() > _committed[ind].start()),
    1.27 +                 "New end of committed region is inconsistent");
    1.28 +          new_end_aligned = _committed[ri].start();
    1.29 +          assert(new_end_aligned > _committed[ind].start(),
    1.30 +            "New end of committed region is before start");
    1.31 +          debug_only(collided = true;)
    1.32 +          // Should only collide with 1 region
    1.33 +          break;
    1.34 +        }
    1.35 +      }
    1.36 +    }
    1.37 +#ifdef ASSERT
    1.38 +    for (++ri; ri < _cur_covered_regions; ri++) {
    1.39 +      assert(!_committed[ri].contains(new_end_aligned),
    1.40 +        "New end of committed region is in a second committed region");
    1.41 +    }
    1.42 +#endif
    1.43      // The guard page is always committed and should not be committed over.
    1.44 -    HeapWord* const new_end_for_commit = MIN2(new_end_aligned, _guard_region.start());
    1.45 +    HeapWord* const new_end_for_commit = MIN2(new_end_aligned,
    1.46 +                                              _guard_region.start());
    1.47 +
    1.48      if (new_end_for_commit > cur_committed.end()) {
    1.49        // Must commit new pages.
    1.50        MemRegion const new_committed =
    1.51 @@ -239,9 +265,11 @@
    1.52        if (!uncommit_region.is_empty()) {
    1.53          if (!os::uncommit_memory((char*)uncommit_region.start(),
    1.54                                   uncommit_region.byte_size())) {
    1.55 -          // Do better than this for Merlin
    1.56 -          vm_exit_out_of_memory(uncommit_region.byte_size(),
    1.57 -            "card table contraction");
    1.58 +          assert(false, "Card table contraction failed");
    1.59 +          // The call failed so don't change the end of the
    1.60 +          // committed region.  This is better than taking the
    1.61 +          // VM down.
    1.62 +          new_end_aligned = _committed[ind].end();
    1.63          }
    1.64        }
    1.65      }
    1.66 @@ -257,8 +285,25 @@
    1.67      }
    1.68      assert(index_for(new_region.last()) < (int) _guard_index,
    1.69        "The guard card will be overwritten");
    1.70 -    jbyte* const end = byte_after(new_region.last());
    1.71 +    // This line commented out cleans the newly expanded region and
    1.72 +    // not the aligned up expanded region.
    1.73 +    // jbyte* const end = byte_after(new_region.last());
    1.74 +    jbyte* const end = (jbyte*) new_end_for_commit;
    1.75 +    assert((end >= byte_after(new_region.last())) || collided,
    1.76 +      "Expect to be beyond new region unless impacting another region");
    1.77      // do nothing if we resized downward.
    1.78 +#ifdef ASSERT
    1.79 +    for (int ri = 0; ri < _cur_covered_regions; ri++) {
    1.80 +      if (ri != ind) {
    1.81 +        // The end of the new committed region should not
    1.82 +        // be in any existing region unless it matches
    1.83 +        // the start of the next region.
    1.84 +        assert(!_committed[ri].contains(end) ||
    1.85 +               (_committed[ri].start() == (HeapWord*) end),
    1.86 +               "Overlapping committed regions");
    1.87 +      }
    1.88 +    }
    1.89 +#endif
    1.90      if (entry < end) {
    1.91        memset(entry, clean_card, pointer_delta(end, entry, sizeof(jbyte)));
    1.92      }

mercurial