Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6977970

CMS: concurrentMarkSweepGeneration.cpp:7947 assert(addr <= _limit) failed: sweep invariant

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P2 P2
    • hs19
    • hs19
    • hotspot
    • gc
    • b06
    • b06
    • generic
    • generic
    • Not verified

        This is an old bug that was uncovered as a result of a change that went into
        CR 6948538. The specific change was that since the product build used
        -XX:-BlockOffsetArrayUseUnallocatedBlock, the fastdebug builds were also
        changed (from trueInDebug to false) so that the same code paths were
        exercised in both, so we were testing the product bits. This revealed
        a long-standing bug in the code that tripped an assertion that was a tad
        too strong. Note that the bug itself exists in the product builds preceding
        6948538; it was just that the bug was not revealed until the recent change in the
        setting of the flag for debug builds.

        More specifically, the CMS sweep is limited to the high water mark (if any)
        of allocation at the point at which the concurrent marking cycle was started.
        When we do not use +BlockOffsetArrayUseUnallocatedBlock, this is the "end"
        of the committed space for a CMS generation. If the CMS generation is not
        fully committed at this point and is expanded during the sweep, then the
        newly expanded portion is coalesced with the previously co-terminal chunk
        in order to limit fragmentation. That means that a previously recorded
        "limit" (being the address of the previous "end") is no longer a block
        boundary and may not be encountered by the sweep, which may skip over that
        specific address. This fell afoul of the code and assertion in question,
        which is reproduced below:-

             7936 size_t SweepClosure::do_blk_careful(HeapWord* addr) {

             7937 FreeChunk* fc = (FreeChunk*)addr;

             7938 size_t res;

             7939

             7940 // check if we are done sweepinrg

             7941 if (addr == _limit) { // we have swept up to the limit, do nothing more

             7942 assert(_limit >= _sp->bottom() && _limit <= _sp->end(),

             7943 "sweep _limit out of bounds");

             7944 // help the closure application finish

             7945 return pointer_delta(_sp->end(), _limit);

             7946 }

             7947 assert(addr <= _limit, "sweep invariant");


        The fix is to relax the code to allow a "skipping over" the limit,
        rather than "stepping on the limit", see suggested fix section.

              ysr Y. Ramakrishna
              ysr Y. Ramakrishna
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: