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 }
|