Mercurial > hg > truffle
comparison src/share/vm/gc_implementation/g1/heapRegion.cpp @ 2133:2250ee17e258
7007068: G1: refine the BOT during evac failure handling
Summary: During evacuation failure handling we refine the BOT to reflect the location of all the objects in the regions we scan. The changeset includes some minor cleanup: a) non-product print_on() method on the G1 BOT class, b) added more complete BOT verification during heap / region verification, c) slight modification to the BOT set up for humongous regions to be more consistent with the BOT set up during evac failure handling, and d) removed a couple of unused methods.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 12 Jan 2011 13:06:00 -0500 |
parents | f95d63e2154a |
children | 0fa27f37d4d4 |
comparison
equal
deleted
inserted
replaced
2132:4947ee68d19c | 2133:2250ee17e258 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
384 _gc_efficiency = (double) garbage_bytes() / | 384 _gc_efficiency = (double) garbage_bytes() / |
385 g1h->predict_region_elapsed_time_ms(this, false); | 385 g1h->predict_region_elapsed_time_ms(this, false); |
386 } | 386 } |
387 // </PREDICTION> | 387 // </PREDICTION> |
388 | 388 |
389 void HeapRegion::set_startsHumongous(HeapWord* new_end) { | 389 void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) { |
390 assert(end() == _orig_end, | 390 assert(end() == _orig_end, |
391 "Should be normal before the humongous object allocation"); | 391 "Should be normal before the humongous object allocation"); |
392 assert(top() == bottom(), "should be empty"); | 392 assert(top() == bottom(), "should be empty"); |
393 assert(bottom() <= new_top && new_top <= new_end, "pre-condition"); | |
393 | 394 |
394 _humongous_type = StartsHumongous; | 395 _humongous_type = StartsHumongous; |
395 _humongous_start_region = this; | 396 _humongous_start_region = this; |
396 | 397 |
397 set_end(new_end); | 398 set_end(new_end); |
398 _offsets.set_for_starts_humongous(new_end); | 399 _offsets.set_for_starts_humongous(new_top); |
399 } | 400 } |
400 | 401 |
401 void HeapRegion::set_continuesHumongous(HeapRegion* start) { | 402 void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) { |
402 assert(end() == _orig_end, | 403 assert(end() == _orig_end, |
403 "Should be normal before the humongous object allocation"); | 404 "Should be normal before the humongous object allocation"); |
404 assert(top() == bottom(), "should be empty"); | 405 assert(top() == bottom(), "should be empty"); |
405 assert(start->startsHumongous(), "pre-condition"); | 406 assert(first_hr->startsHumongous(), "pre-condition"); |
406 | 407 |
407 _humongous_type = ContinuesHumongous; | 408 _humongous_type = ContinuesHumongous; |
408 _humongous_start_region = start; | 409 _humongous_start_region = first_hr; |
409 } | 410 } |
410 | 411 |
411 bool HeapRegion::claimHeapRegion(jint claimValue) { | 412 bool HeapRegion::claimHeapRegion(jint claimValue) { |
412 jint current = _claimed; | 413 jint current = _claimed; |
413 if (current != claimValue) { | 414 if (current != claimValue) { |
780 void HeapRegion::verify(bool allow_dirty) const { | 781 void HeapRegion::verify(bool allow_dirty) const { |
781 bool dummy = false; | 782 bool dummy = false; |
782 verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy); | 783 verify(allow_dirty, /* use_prev_marking */ true, /* failures */ &dummy); |
783 } | 784 } |
784 | 785 |
785 #define OBJ_SAMPLE_INTERVAL 0 | |
786 #define BLOCK_SAMPLE_INTERVAL 100 | |
787 | |
788 // This really ought to be commoned up into OffsetTableContigSpace somehow. | 786 // This really ought to be commoned up into OffsetTableContigSpace somehow. |
789 // We would need a mechanism to make that code skip dead objects. | 787 // We would need a mechanism to make that code skip dead objects. |
790 | 788 |
791 void HeapRegion::verify(bool allow_dirty, | 789 void HeapRegion::verify(bool allow_dirty, |
792 bool use_prev_marking, | 790 bool use_prev_marking, |
793 bool* failures) const { | 791 bool* failures) const { |
794 G1CollectedHeap* g1 = G1CollectedHeap::heap(); | 792 G1CollectedHeap* g1 = G1CollectedHeap::heap(); |
795 *failures = false; | 793 *failures = false; |
796 HeapWord* p = bottom(); | 794 HeapWord* p = bottom(); |
797 HeapWord* prev_p = NULL; | 795 HeapWord* prev_p = NULL; |
798 int objs = 0; | |
799 int blocks = 0; | |
800 VerifyLiveClosure vl_cl(g1, use_prev_marking); | 796 VerifyLiveClosure vl_cl(g1, use_prev_marking); |
801 bool is_humongous = isHumongous(); | 797 bool is_humongous = isHumongous(); |
798 bool do_bot_verify = !is_young(); | |
802 size_t object_num = 0; | 799 size_t object_num = 0; |
803 while (p < top()) { | 800 while (p < top()) { |
804 size_t size = oop(p)->size(); | 801 oop obj = oop(p); |
805 if (is_humongous != g1->isHumongous(size)) { | 802 size_t obj_size = obj->size(); |
803 object_num += 1; | |
804 | |
805 if (is_humongous != g1->isHumongous(obj_size)) { | |
806 gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size (" | 806 gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size (" |
807 SIZE_FORMAT" words) in a %shumongous region", | 807 SIZE_FORMAT" words) in a %shumongous region", |
808 p, g1->isHumongous(size) ? "" : "non-", | 808 p, g1->isHumongous(obj_size) ? "" : "non-", |
809 size, is_humongous ? "" : "non-"); | 809 obj_size, is_humongous ? "" : "non-"); |
810 *failures = true; | 810 *failures = true; |
811 } | 811 return; |
812 object_num += 1; | 812 } |
813 if (blocks == BLOCK_SAMPLE_INTERVAL) { | 813 |
814 HeapWord* res = block_start_const(p + (size/2)); | 814 // If it returns false, verify_for_object() will output the |
815 if (p != res) { | 815 // appropriate messasge. |
816 gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and " | 816 if (do_bot_verify && !_offsets.verify_for_object(p, obj_size)) { |
817 SIZE_FORMAT" returned "PTR_FORMAT, | 817 *failures = true; |
818 p, size, res); | 818 return; |
819 } | |
820 | |
821 if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) { | |
822 if (obj->is_oop()) { | |
823 klassOop klass = obj->klass(); | |
824 if (!klass->is_perm()) { | |
825 gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " | |
826 "not in perm", klass, obj); | |
827 *failures = true; | |
828 return; | |
829 } else if (!klass->is_klass()) { | |
830 gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " | |
831 "not a klass", klass, obj); | |
832 *failures = true; | |
833 return; | |
834 } else { | |
835 vl_cl.set_containing_obj(obj); | |
836 obj->oop_iterate(&vl_cl); | |
837 if (vl_cl.failures()) { | |
838 *failures = true; | |
839 } | |
840 if (G1MaxVerifyFailures >= 0 && | |
841 vl_cl.n_failures() >= G1MaxVerifyFailures) { | |
842 return; | |
843 } | |
844 } | |
845 } else { | |
846 gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj); | |
819 *failures = true; | 847 *failures = true; |
820 return; | 848 return; |
821 } | 849 } |
822 blocks = 0; | |
823 } else { | |
824 blocks++; | |
825 } | |
826 if (objs == OBJ_SAMPLE_INTERVAL) { | |
827 oop obj = oop(p); | |
828 if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) { | |
829 if (obj->is_oop()) { | |
830 klassOop klass = obj->klass(); | |
831 if (!klass->is_perm()) { | |
832 gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " | |
833 "not in perm", klass, obj); | |
834 *failures = true; | |
835 return; | |
836 } else if (!klass->is_klass()) { | |
837 gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " | |
838 "not a klass", klass, obj); | |
839 *failures = true; | |
840 return; | |
841 } else { | |
842 vl_cl.set_containing_obj(obj); | |
843 obj->oop_iterate(&vl_cl); | |
844 if (vl_cl.failures()) { | |
845 *failures = true; | |
846 } | |
847 if (G1MaxVerifyFailures >= 0 && | |
848 vl_cl.n_failures() >= G1MaxVerifyFailures) { | |
849 return; | |
850 } | |
851 } | |
852 } else { | |
853 gclog_or_tty->print_cr(PTR_FORMAT" no an oop", obj); | |
854 *failures = true; | |
855 return; | |
856 } | |
857 } | |
858 objs = 0; | |
859 } else { | |
860 objs++; | |
861 } | 850 } |
862 prev_p = p; | 851 prev_p = p; |
863 p += size; | 852 p += obj_size; |
864 } | 853 } |
865 HeapWord* rend = end(); | 854 |
866 HeapWord* rtop = top(); | 855 if (p != top()) { |
867 if (rtop < rend) { | 856 gclog_or_tty->print_cr("end of last object "PTR_FORMAT" " |
868 HeapWord* res = block_start_const(rtop + (rend - rtop) / 2); | 857 "does not match top "PTR_FORMAT, p, top()); |
869 if (res != rtop) { | 858 *failures = true; |
870 gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and " | 859 return; |
871 PTR_FORMAT" returned "PTR_FORMAT, | 860 } |
872 rtop, rend, res); | 861 |
862 HeapWord* the_end = end(); | |
863 assert(p == top(), "it should still hold"); | |
864 // Do some extra BOT consistency checking for addresses in the | |
865 // range [top, end). BOT look-ups in this range should yield | |
866 // top. No point in doing that if top == end (there's nothing there). | |
867 if (p < the_end) { | |
868 // Look up top | |
869 HeapWord* addr_1 = p; | |
870 HeapWord* b_start_1 = _offsets.block_start_const(addr_1); | |
871 if (b_start_1 != p) { | |
872 gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" " | |
873 " yielded "PTR_FORMAT", expecting "PTR_FORMAT, | |
874 addr_1, b_start_1, p); | |
875 *failures = true; | |
876 return; | |
877 } | |
878 | |
879 // Look up top + 1 | |
880 HeapWord* addr_2 = p + 1; | |
881 if (addr_2 < the_end) { | |
882 HeapWord* b_start_2 = _offsets.block_start_const(addr_2); | |
883 if (b_start_2 != p) { | |
884 gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" " | |
885 " yielded "PTR_FORMAT", expecting "PTR_FORMAT, | |
886 addr_2, b_start_2, p); | |
873 *failures = true; | 887 *failures = true; |
874 return; | 888 return; |
889 } | |
890 } | |
891 | |
892 // Look up an address between top and end | |
893 size_t diff = pointer_delta(the_end, p) / 2; | |
894 HeapWord* addr_3 = p + diff; | |
895 if (addr_3 < the_end) { | |
896 HeapWord* b_start_3 = _offsets.block_start_const(addr_3); | |
897 if (b_start_3 != p) { | |
898 gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" " | |
899 " yielded "PTR_FORMAT", expecting "PTR_FORMAT, | |
900 addr_3, b_start_3, p); | |
901 *failures = true; | |
902 return; | |
903 } | |
904 } | |
905 | |
906 // Loook up end - 1 | |
907 HeapWord* addr_4 = the_end - 1; | |
908 HeapWord* b_start_4 = _offsets.block_start_const(addr_4); | |
909 if (b_start_4 != p) { | |
910 gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" " | |
911 " yielded "PTR_FORMAT", expecting "PTR_FORMAT, | |
912 addr_4, b_start_4, p); | |
913 *failures = true; | |
914 return; | |
875 } | 915 } |
876 } | 916 } |
877 | 917 |
878 if (is_humongous && object_num > 1) { | 918 if (is_humongous && object_num > 1) { |
879 gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is humongous " | 919 gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is humongous " |
880 "but has "SIZE_FORMAT", objects", | 920 "but has "SIZE_FORMAT", objects", |
881 bottom(), end(), object_num); | 921 bottom(), end(), object_num); |
882 *failures = true; | |
883 } | |
884 | |
885 if (p != top()) { | |
886 gclog_or_tty->print_cr("end of last object "PTR_FORMAT" " | |
887 "does not match top "PTR_FORMAT, p, top()); | |
888 *failures = true; | 922 *failures = true; |
889 return; | 923 return; |
890 } | 924 } |
891 } | 925 } |
892 | 926 |