src/share/vm/gc/shared/cardTableRS.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/gc/shared

src/share/vm/gc/shared/cardTableRS.cpp

Print this page




 327   if (!to_be_cleared_mr.is_empty()) {
 328     clear(to_be_cleared_mr);
 329   }
 330   invalidate(used_mr);
 331 }
 332 
 333 
 334 class VerifyCleanCardClosure: public OopClosure {
 335 private:
 336   HeapWord* _boundary;
 337   HeapWord* _begin;
 338   HeapWord* _end;
 339 protected:
 340   template <class T> void do_oop_work(T* p) {
 341     HeapWord* jp = (HeapWord*)p;
 342     assert(jp >= _begin && jp < _end,
 343            err_msg("Error: jp " PTR_FORMAT " should be within "
 344                    "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")",
 345                    p2i(jp), p2i(_begin), p2i(_end)));
 346     oop obj = oopDesc::load_decode_heap_oop(p);
 347     guarantee(obj == NULL || (HeapWord*)obj >= _boundary,
 348               err_msg("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
 349                       "clean card crosses boundary" PTR_FORMAT,
 350                       p2i((HeapWord*)obj), p2i(jp), p2i(_boundary)));





 351   }
 352 
 353 public:


 354   VerifyCleanCardClosure(HeapWord* b, HeapWord* begin, HeapWord* end) :
 355     _boundary(b), _begin(begin), _end(end) {
 356     assert(b <= begin,
 357            err_msg("Error: boundary " PTR_FORMAT " should be at or below begin " PTR_FORMAT,
 358                    p2i(b), p2i(begin)));
 359     assert(begin <= end,
 360            err_msg("Error: begin " PTR_FORMAT " should be strictly below end " PTR_FORMAT,
 361                    p2i(begin), p2i(end)));
 362   }
 363 
 364   virtual void do_oop(oop* p)       { VerifyCleanCardClosure::do_oop_work(p); }
 365   virtual void do_oop(narrowOop* p) { VerifyCleanCardClosure::do_oop_work(p); }
 366 };
 367 
 368 class VerifyCTSpaceClosure: public SpaceClosure {
 369 private:
 370   CardTableRS* _ct;
 371   HeapWord* _boundary;
 372 public:
 373   VerifyCTSpaceClosure(CardTableRS* ct, HeapWord* boundary) :
 374     _ct(ct), _boundary(boundary) {}
 375   virtual void do_space(Space* s) { _ct->verify_space(s, _boundary); }


 377 
 378 class VerifyCTGenClosure: public GenCollectedHeap::GenClosure {
 379   CardTableRS* _ct;
 380 public:
 381   VerifyCTGenClosure(CardTableRS* ct) : _ct(ct) {}
 382   void do_generation(Generation* gen) {
 383     // Skip the youngest generation.
 384     if (GenCollectedHeap::heap()->is_young_gen(gen)) {
 385       return;
 386     }
 387     // Normally, we're interested in pointers to younger generations.
 388     VerifyCTSpaceClosure blk(_ct, gen->reserved().start());
 389     gen->space_iterate(&blk, true);
 390   }
 391 };
 392 
 393 void CardTableRS::verify_space(Space* s, HeapWord* gen_boundary) {
 394   // We don't need to do young-gen spaces.
 395   if (s->end() <= gen_boundary) return;
 396   MemRegion used = s->used_region();

 397 
 398   jbyte* cur_entry = byte_for(used.start());
 399   jbyte* limit = byte_after(used.last());
 400   while (cur_entry < limit) {
 401     if (*cur_entry == clean_card_val()) {
 402       jbyte* first_dirty = cur_entry+1;
 403       while (first_dirty < limit &&
 404              *first_dirty == clean_card_val()) {
 405         first_dirty++;
 406       }
 407       // If the first object is a regular object, and it has a
 408       // young-to-old field, that would mark the previous card.
 409       HeapWord* boundary = addr_for(cur_entry);
 410       HeapWord* end = (first_dirty >= limit) ? used.end() : addr_for(first_dirty);
 411       HeapWord* boundary_block = s->block_start(boundary);
 412       HeapWord* begin = boundary;             // Until proven otherwise.
 413       HeapWord* start_block = boundary_block; // Until proven otherwise.
 414       if (boundary_block < boundary) {
 415         if (s->block_is_obj(boundary_block) && s->obj_is_alive(boundary_block)) {
 416           oop boundary_obj = oop(boundary_block);
 417           if (!boundary_obj->is_objArray() &&
 418               !boundary_obj->is_typeArray()) {
 419             guarantee(cur_entry > byte_for(used.start()),
 420                       "else boundary would be boundary_block");
 421             if (*byte_for(boundary_block) != clean_card_val()) {
 422               begin = boundary_block + s->block_size(boundary_block);
 423               start_block = begin;
 424             }
 425           }
 426         }
 427       }
 428       // Now traverse objects until end.
 429       if (begin < end) {
 430         MemRegion mr(begin, end);
 431         VerifyCleanCardClosure verify_blk(gen_boundary, begin, end);
 432         for (HeapWord* cur = start_block; cur < end; cur += s->block_size(cur)) {
 433           if (s->block_is_obj(cur) && s->obj_is_alive(cur)) {
 434             oop(cur)->oop_iterate_no_header(&verify_blk, mr);







 435           }
 436         }
 437       }
 438       cur_entry = first_dirty;
 439     } else {
 440       // We'd normally expect that cur_youngergen_and_prev_nonclean_card
 441       // is a transient value, that cannot be in the card table
 442       // except during GC, and thus assert that:
 443       // guarantee(*cur_entry != cur_youngergen_and_prev_nonclean_card,
 444       //        "Illegal CT value");
 445       // That however, need not hold, as will become clear in the
 446       // following...
 447 
 448       // We'd normally expect that if we are in the parallel case,
 449       // we can't have left a prev value (which would be different
 450       // from the current value) in the card table, and so we'd like to
 451       // assert that:
 452       // guarantee(cur_youngergen_card_val() == youngergen_card
 453       //           || !is_prev_youngergen_card_val(*cur_entry),
 454       //           "Illegal CT value");


 575       // However, one can obtain a Loose upper bound on the redundant
 576       // work as a result of such stale values. Note first that any
 577       // time a stale card lies in the occupied part of the space at
 578       // the start of the collection, it is scanned by younger refs
 579       // code and we can define a rank function on card values that
 580       // declines when this is so. Note also that when a card does not
 581       // lie in the occupied part of the space at the beginning of a
 582       // young collection, its rank can either decline or stay unchanged.
 583       // In this case, no extra work is done in terms of redundant
 584       // younger refs scanning of that card.
 585       // Then, the case analysis above reveals that, in the worst case,
 586       // any such stale card will be scanned unnecessarily at most twice.
 587       //
 588       // It is nonetheless advisable to try and get rid of some of this
 589       // redundant work in a subsequent (low priority) re-design of
 590       // the card-scanning code, if only to simplify the underlying
 591       // state machine analysis/proof. ysr 1/28/2002. XXX
 592       cur_entry++;
 593     }
 594   }

 595 }
 596 
 597 void CardTableRS::verify() {
 598   // At present, we only know how to verify the card table RS for
 599   // generational heaps.
 600   VerifyCTGenClosure blk(this);
 601   GenCollectedHeap::heap()->generation_iterate(&blk, false);
 602   _ct_bs->verify();
 603 }


 327   if (!to_be_cleared_mr.is_empty()) {
 328     clear(to_be_cleared_mr);
 329   }
 330   invalidate(used_mr);
 331 }
 332 
 333 
 334 class VerifyCleanCardClosure: public OopClosure {
 335 private:
 336   HeapWord* _boundary;
 337   HeapWord* _begin;
 338   HeapWord* _end;
 339 protected:
 340   template <class T> void do_oop_work(T* p) {
 341     HeapWord* jp = (HeapWord*)p;
 342     assert(jp >= _begin && jp < _end,
 343            err_msg("Error: jp " PTR_FORMAT " should be within "
 344                    "[_begin, _end) = [" PTR_FORMAT "," PTR_FORMAT ")",
 345                    p2i(jp), p2i(_begin), p2i(_end)));
 346     oop obj = oopDesc::load_decode_heap_oop(p);
 347     if (!(obj == NULL || (HeapWord*)obj >= _boundary)) {
 348       tty->print_cr("pointer " PTR_FORMAT " at " PTR_FORMAT " on "
 349                     "clean card crosses boundary" PTR_FORMAT,
 350                     p2i((HeapWord*)obj), p2i(jp), p2i(_boundary));
 351 #ifndef PRODUCT
 352       obj->print();
 353 #endif
 354       had_error = true;
 355     }
 356   }
 357 
 358 public:
 359   bool had_error;
 360   
 361   VerifyCleanCardClosure(HeapWord* b, HeapWord* begin, HeapWord* end) :
 362     _boundary(b), _begin(begin), _end(end), had_error(false) {
 363     assert(b <= begin,
 364            err_msg("Error: boundary " PTR_FORMAT " should be at or below begin " PTR_FORMAT,
 365                    p2i(b), p2i(begin)));
 366     assert(begin <= end,
 367            err_msg("Error: begin " PTR_FORMAT " should be strictly below end " PTR_FORMAT,
 368                    p2i(begin), p2i(end)));
 369   }
 370 
 371   virtual void do_oop(oop* p)       { VerifyCleanCardClosure::do_oop_work(p); }
 372   virtual void do_oop(narrowOop* p) { VerifyCleanCardClosure::do_oop_work(p); }
 373 };
 374 
 375 class VerifyCTSpaceClosure: public SpaceClosure {
 376 private:
 377   CardTableRS* _ct;
 378   HeapWord* _boundary;
 379 public:
 380   VerifyCTSpaceClosure(CardTableRS* ct, HeapWord* boundary) :
 381     _ct(ct), _boundary(boundary) {}
 382   virtual void do_space(Space* s) { _ct->verify_space(s, _boundary); }


 384 
 385 class VerifyCTGenClosure: public GenCollectedHeap::GenClosure {
 386   CardTableRS* _ct;
 387 public:
 388   VerifyCTGenClosure(CardTableRS* ct) : _ct(ct) {}
 389   void do_generation(Generation* gen) {
 390     // Skip the youngest generation.
 391     if (GenCollectedHeap::heap()->is_young_gen(gen)) {
 392       return;
 393     }
 394     // Normally, we're interested in pointers to younger generations.
 395     VerifyCTSpaceClosure blk(_ct, gen->reserved().start());
 396     gen->space_iterate(&blk, true);
 397   }
 398 };
 399 
 400 void CardTableRS::verify_space(Space* s, HeapWord* gen_boundary) {
 401   // We don't need to do young-gen spaces.
 402   if (s->end() <= gen_boundary) return;
 403   MemRegion used = s->used_region();
 404   bool had_error = false;
 405 
 406   jbyte* cur_entry = byte_for(used.start());
 407   jbyte* limit = byte_after(used.last());
 408   while (cur_entry < limit) {
 409     if (*cur_entry == clean_card_val()) {
 410       jbyte* first_dirty = cur_entry+1;
 411       while (first_dirty < limit &&
 412              *first_dirty == clean_card_val()) {
 413         first_dirty++;
 414       }
 415       // If the first object is a regular object, and it has a
 416       // young-to-old field, that would mark the previous card.
 417       HeapWord* boundary = addr_for(cur_entry);
 418       HeapWord* end = (first_dirty >= limit) ? used.end() : addr_for(first_dirty);
 419       HeapWord* boundary_block = s->block_start(boundary);
 420       HeapWord* begin = boundary;             // Until proven otherwise.
 421       HeapWord* start_block = boundary_block; // Until proven otherwise.
 422       if (boundary_block < boundary) {
 423         if (s->block_is_obj(boundary_block) && s->obj_is_alive(boundary_block)) {
 424           oop boundary_obj = oop(boundary_block);
 425           if (!boundary_obj->is_objArray() &&
 426               !boundary_obj->is_typeArray()) {
 427             guarantee(cur_entry > byte_for(used.start()),
 428                       "else boundary would be boundary_block");
 429             if (*byte_for(boundary_block) != clean_card_val()) {
 430               begin = boundary_block + s->block_size(boundary_block);
 431               start_block = begin;
 432             }
 433           }
 434         }
 435       }
 436       // Now traverse objects until end.
 437       if (begin < end) {
 438         MemRegion mr(begin, end);
 439         VerifyCleanCardClosure verify_blk(gen_boundary, begin, end);
 440         for (HeapWord* cur = start_block; cur < end; cur += s->block_size(cur)) {
 441           if (s->block_is_obj(cur) && s->obj_is_alive(cur)) {
 442             oop(cur)->oop_iterate_no_header(&verify_blk, mr);
 443             had_error |= verify_blk.had_error;
 444             if (verify_blk.had_error) {
 445               verify_blk.had_error = false;
 446 #ifndef PRODUCT
 447               oop(cur)->print();
 448 #endif
 449             }
 450           }
 451         }
 452       }
 453       cur_entry = first_dirty;
 454     } else {
 455       // We'd normally expect that cur_youngergen_and_prev_nonclean_card
 456       // is a transient value, that cannot be in the card table
 457       // except during GC, and thus assert that:
 458       // guarantee(*cur_entry != cur_youngergen_and_prev_nonclean_card,
 459       //        "Illegal CT value");
 460       // That however, need not hold, as will become clear in the
 461       // following...
 462 
 463       // We'd normally expect that if we are in the parallel case,
 464       // we can't have left a prev value (which would be different
 465       // from the current value) in the card table, and so we'd like to
 466       // assert that:
 467       // guarantee(cur_youngergen_card_val() == youngergen_card
 468       //           || !is_prev_youngergen_card_val(*cur_entry),
 469       //           "Illegal CT value");


 590       // However, one can obtain a Loose upper bound on the redundant
 591       // work as a result of such stale values. Note first that any
 592       // time a stale card lies in the occupied part of the space at
 593       // the start of the collection, it is scanned by younger refs
 594       // code and we can define a rank function on card values that
 595       // declines when this is so. Note also that when a card does not
 596       // lie in the occupied part of the space at the beginning of a
 597       // young collection, its rank can either decline or stay unchanged.
 598       // In this case, no extra work is done in terms of redundant
 599       // younger refs scanning of that card.
 600       // Then, the case analysis above reveals that, in the worst case,
 601       // any such stale card will be scanned unnecessarily at most twice.
 602       //
 603       // It is nonetheless advisable to try and get rid of some of this
 604       // redundant work in a subsequent (low priority) re-design of
 605       // the card-scanning code, if only to simplify the underlying
 606       // state machine analysis/proof. ysr 1/28/2002. XXX
 607       cur_entry++;
 608     }
 609   }
 610   guarantee(!had_error, "Card table errors found");
 611 }
 612 
 613 void CardTableRS::verify() {
 614   // At present, we only know how to verify the card table RS for
 615   // generational heaps.
 616   VerifyCTGenClosure blk(this);
 617   GenCollectedHeap::heap()->generation_iterate(&blk, false);
 618   _ct_bs->verify();
 619 }
src/share/vm/gc/shared/cardTableRS.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File