void HeapRegion::print_on(outputStream* st) const { if (isHumongous()) { if (startsHumongous()) st->print(" HS"); else st->print(" HC"); } else { st->print(" "); } if (in_collection_set()) st->print(" CS"); else if (is_gc_alloc_region()) st->print(" A "); else st->print(" "); if (is_young()) st->print(is_survivor() ? " SU" : " Y "); else st->print(" "); if (is_empty()) st->print(" F"); else st->print(" "); st->print(" %5d", _gc_time_stamp); st->print(" PTAMS "PTR_FORMAT" NTAMS "PTR_FORMAT, prev_top_at_mark_start(), next_top_at_mark_start()); G1OffsetTableContigSpace::print_on(st); }
HeapWord* HeapRegion:: oops_on_card_seq_iterate_careful(MemRegion mr, FilterOutOfRegionClosure* cl, bool filter_young) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If we're within a stop-world GC, then we might look at a card in a // GC alloc region that extends onto a GC LAB, which may not be // parseable. Stop such at the "saved_mark" of the region. if (G1CollectedHeap::heap()->is_gc_active()) { mr = mr.intersection(used_region_at_save_marks()); } else { mr = mr.intersection(used_region()); } if (mr.is_empty()) return NULL; // Otherwise, find the obj that extends onto mr.start(). // The intersection of the incoming mr (for the card) and the // allocated part of the region is non-empty. This implies that // we have actually allocated into this region. The code in // G1CollectedHeap.cpp that allocates a new region sets the // is_young tag on the region before allocating. Thus we // safely know if this region is young. if (is_young() && filter_young) { return NULL; } assert(!is_young(), "check value of filter_young"); // We used to use "block_start_careful" here. But we're actually happy // to update the BOT while we do this... HeapWord* cur = block_start(mr.start()); assert(cur <= mr.start(), "Postcondition"); while (cur <= mr.start()) { if (oop(cur)->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; } // Otherwise... int sz = oop(cur)->size(); if (cur + sz > mr.start()) break; // Otherwise, go on. cur = cur + sz; } oop obj; obj = oop(cur); // If we finish this loop... assert(cur <= mr.start() && obj->klass_or_null() != NULL && cur + obj->size() > mr.start(), "Loop postcondition"); if (!g1h->is_obj_dead(obj)) { obj->oop_iterate(cl, mr); } HeapWord* next; while (cur < mr.end()) { obj = oop(cur); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; }; // Otherwise: next = (cur + obj->size()); if (!g1h->is_obj_dead(obj)) { if (next < mr.end()) { obj->oop_iterate(cl); } else { // this obj spans the boundary. If it's an array, stop at the // boundary. if (obj->is_objArray()) { obj->oop_iterate(cl, mr); } else { obj->oop_iterate(cl); } } } cur = next; } return NULL; }
inline HeapWord* HeapRegion::allocate_no_bot_updates(size_t word_size) { assert(is_young(), "we can only skip BOT updates on young regions"); return allocate_impl(word_size, end()); }
void HeapRegion::verify(VerifyOption vo, bool* failures) const { G1CollectedHeap* g1 = G1CollectedHeap::heap(); *failures = false; HeapWord* p = bottom(); HeapWord* prev_p = NULL; VerifyLiveClosure vl_cl(g1, vo); bool is_humongous = isHumongous(); bool do_bot_verify = !is_young(); size_t object_num = 0; while (p < top()) { oop obj = oop(p); size_t obj_size = obj->size(); object_num += 1; if (is_humongous != g1->isHumongous(obj_size)) { gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size (" SIZE_FORMAT" words) in a %shumongous region", p, g1->isHumongous(obj_size) ? "" : "non-", obj_size, is_humongous ? "" : "non-"); *failures = true; return; } // If it returns false, verify_for_object() will output the // appropriate messasge. if (do_bot_verify && !_offsets.verify_for_object(p, obj_size)) { *failures = true; return; } if (!g1->is_obj_dead_cond(obj, this, vo)) { if (obj->is_oop()) { Klass* klass = obj->klass(); if (!klass->is_metaspace_object()) { gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " "not metadata", klass, (void *)obj); *failures = true; return; } else if (!klass->is_klass()) { gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " "not a klass", klass, (void *)obj); *failures = true; return; } else { vl_cl.set_containing_obj(obj); obj->oop_iterate_no_header(&vl_cl); if (vl_cl.failures()) { *failures = true; } if (G1MaxVerifyFailures >= 0 && vl_cl.n_failures() >= G1MaxVerifyFailures) { return; } } } else { gclog_or_tty->print_cr(PTR_FORMAT" no an oop", (void *)obj); *failures = true; return; } } prev_p = p; p += obj_size; } if (p != top()) { gclog_or_tty->print_cr("end of last object "PTR_FORMAT" " "does not match top "PTR_FORMAT, p, top()); *failures = true; return; } HeapWord* the_end = end(); assert(p == top(), "it should still hold"); // Do some extra BOT consistency checking for addresses in the // range [top, end). BOT look-ups in this range should yield // top. No point in doing that if top == end (there's nothing there). if (p < the_end) { // Look up top HeapWord* addr_1 = p; HeapWord* b_start_1 = _offsets.block_start_const(addr_1); if (b_start_1 != p) { gclog_or_tty->print_cr("BOT look up for top: "PTR_FORMAT" " " yielded "PTR_FORMAT", expecting "PTR_FORMAT, addr_1, b_start_1, p); *failures = true; return; } // Look up top + 1 HeapWord* addr_2 = p + 1; if (addr_2 < the_end) { HeapWord* b_start_2 = _offsets.block_start_const(addr_2); if (b_start_2 != p) { gclog_or_tty->print_cr("BOT look up for top + 1: "PTR_FORMAT" " " yielded "PTR_FORMAT", expecting "PTR_FORMAT, addr_2, b_start_2, p); *failures = true; return; } } // Look up an address between top and end size_t diff = pointer_delta(the_end, p) / 2; HeapWord* addr_3 = p + diff; if (addr_3 < the_end) { HeapWord* b_start_3 = _offsets.block_start_const(addr_3); if (b_start_3 != p) { gclog_or_tty->print_cr("BOT look up for top + diff: "PTR_FORMAT" " " yielded "PTR_FORMAT", expecting "PTR_FORMAT, addr_3, b_start_3, p); *failures = true; return; } } // Loook up end - 1 HeapWord* addr_4 = the_end - 1; HeapWord* b_start_4 = _offsets.block_start_const(addr_4); if (b_start_4 != p) { gclog_or_tty->print_cr("BOT look up for end - 1: "PTR_FORMAT" " " yielded "PTR_FORMAT", expecting "PTR_FORMAT, addr_4, b_start_4, p); *failures = true; return; } } if (is_humongous && object_num > 1) { gclog_or_tty->print_cr("region ["PTR_FORMAT","PTR_FORMAT"] is humongous " "but has "SIZE_FORMAT", objects", bottom(), end(), object_num); *failures = true; return; } verify_strong_code_roots(vo, failures); }
HeapWord* HeapRegion:: oops_on_card_seq_iterate_careful(MemRegion mr, FilterOutOfRegionClosure* cl, bool filter_young, jbyte* card_ptr) { // Currently, we should only have to clean the card if filter_young // is true and vice versa. if (filter_young) { assert(card_ptr != NULL, "pre-condition"); } else { assert(card_ptr == NULL, "pre-condition"); } G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If we're within a stop-world GC, then we might look at a card in a // GC alloc region that extends onto a GC LAB, which may not be // parseable. Stop such at the "saved_mark" of the region. if (g1h->is_gc_active()) { mr = mr.intersection(used_region_at_save_marks()); } else { mr = mr.intersection(used_region()); } if (mr.is_empty()) return NULL; // Otherwise, find the obj that extends onto mr.start(). // The intersection of the incoming mr (for the card) and the // allocated part of the region is non-empty. This implies that // we have actually allocated into this region. The code in // G1CollectedHeap.cpp that allocates a new region sets the // is_young tag on the region before allocating. Thus we // safely know if this region is young. if (is_young() && filter_young) { return NULL; } assert(!is_young(), "check value of filter_young"); // We can only clean the card here, after we make the decision that // the card is not young. And we only clean the card if we have been // asked to (i.e., card_ptr != NULL). if (card_ptr != NULL) { *card_ptr = CardTableModRefBS::clean_card_val(); // We must complete this write before we do any of the reads below. OrderAccess::storeload(); } // Cache the boundaries of the memory region in some const locals HeapWord* const start = mr.start(); HeapWord* const end = mr.end(); // We used to use "block_start_careful" here. But we're actually happy // to update the BOT while we do this... HeapWord* cur = block_start(start); assert(cur <= start, "Postcondition"); oop obj; HeapWord* next = cur; while (next <= start) { cur = next; obj = oop(cur); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; } // Otherwise... next = (cur + obj->size()); } // If we finish the above loop...We have a parseable object that // begins on or before the start of the memory region, and ends // inside or spans the entire region. assert(obj == oop(cur), "sanity"); assert(cur <= start && obj->klass_or_null() != NULL && (cur + obj->size()) > start, "Loop postcondition"); if (!g1h->is_obj_dead(obj)) { obj->oop_iterate(cl, mr); } while (cur < end) { obj = oop(cur); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; }; // Otherwise: next = (cur + obj->size()); if (!g1h->is_obj_dead(obj)) { if (next < end || !obj->is_objArray()) { // This object either does not span the MemRegion // boundary, or if it does it's not an array. // Apply closure to whole object. obj->oop_iterate(cl); } else { // This obj is an array that spans the boundary. // Stop at the boundary. obj->oop_iterate(cl, mr); } } cur = next; } return NULL; }
HeapWord* HeapRegion:: oops_on_card_seq_iterate_careful(MemRegion mr, FilterOutOfRegionClosure* cl, bool filter_young, jbyte* card_ptr) { // Currently, we should only have to clean the card if filter_young // is true and vice versa. if (filter_young) { assert(card_ptr != NULL, "pre-condition"); } else { assert(card_ptr == NULL, "pre-condition"); } G1CollectedHeap* g1h = G1CollectedHeap::heap(); // If we're within a stop-world GC, then we might look at a card in a // GC alloc region that extends onto a GC LAB, which may not be // parseable. Stop such at the "scan_top" of the region. if (g1h->is_gc_active()) { mr = mr.intersection(MemRegion(bottom(), scan_top())); } else { mr = mr.intersection(used_region()); } if (mr.is_empty()) return NULL; // Otherwise, find the obj that extends onto mr.start(). // The intersection of the incoming mr (for the card) and the // allocated part of the region is non-empty. This implies that // we have actually allocated into this region. The code in // G1CollectedHeap.cpp that allocates a new region sets the // is_young tag on the region before allocating. Thus we // safely know if this region is young. if (is_young() && filter_young) { return NULL; } assert(!is_young(), "check value of filter_young"); // We can only clean the card here, after we make the decision that // the card is not young. And we only clean the card if we have been // asked to (i.e., card_ptr != NULL). if (card_ptr != NULL) { *card_ptr = CardTableModRefBS::clean_card_val(); // We must complete this write before we do any of the reads below. OrderAccess::storeload(); } // Cache the boundaries of the memory region in some const locals HeapWord* const start = mr.start(); HeapWord* const end = mr.end(); // We used to use "block_start_careful" here. But we're actually happy // to update the BOT while we do this... HeapWord* cur = block_start(start); assert(cur <= start, "Postcondition"); oop obj; HeapWord* next = cur; do { cur = next; obj = oop(cur); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; } // Otherwise... next = cur + block_size(cur); } while (next <= start); // If we finish the above loop...We have a parseable object that // begins on or before the start of the memory region, and ends // inside or spans the entire region. assert(cur <= start, "Loop postcondition"); assert(obj->klass_or_null() != NULL, "Loop postcondition"); do { obj = oop(cur); assert((cur + block_size(cur)) > (HeapWord*)obj, "Loop invariant"); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; } // Advance the current pointer. "obj" still points to the object to iterate. cur = cur + block_size(cur); if (!g1h->is_obj_dead(obj)) { // Non-objArrays are sometimes marked imprecise at the object start. We // always need to iterate over them in full. // We only iterate over object arrays in full if they are completely contained // in the memory region. if (!obj->is_objArray() || (((HeapWord*)obj) >= start && cur <= end)) { obj->oop_iterate(cl); } else { obj->oop_iterate(cl, mr); } } } while (cur < end); return NULL; }