HeapWord* HeapRegion::object_iterate_mem_careful(MemRegion mr, ObjectClosure* cl) { G1CollectedHeap* g1h = G1CollectedHeap::heap(); // 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()); mr = mr.intersection(used_region()); if (mr.is_empty()) return NULL; // Otherwise, find the obj that extends onto mr.start(). assert(cur <= mr.start() && (oop(cur)->klass_or_null() == NULL || cur + oop(cur)->size() > mr.start()), "postcondition of block_start"); oop obj; while (cur < mr.end()) { obj = oop(cur); if (obj->klass_or_null() == NULL) { // Ran into an unparseable point. return cur; } else if (!g1h->is_obj_dead(obj)) { cl->do_object(obj); } if (cl->abort()) return cur; // The check above must occur before the operation below, since an // abort might invalidate the "size" operation. cur += obj->size(); } return NULL; }
void ContiguousSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) { assert(!mr.is_empty(), "Should be non-empty"); assert(used_region().contains(mr), "Should be within used space"); HeapWord* prev = cl->previous(); // max address from last time if (prev >= mr.end()) { // nothing to do return; } // See comment above (in more general method above) in case you // happen to use this method. assert(prev == NULL || is_in_reserved(prev), "Should be within space"); bool last_was_obj_array = false; HeapWord *obj_start_addr, *region_start_addr; if (prev > mr.start()) { region_start_addr = prev; obj_start_addr = prev; assert(obj_start_addr == block_start(region_start_addr), "invariant"); } else { region_start_addr = mr.start(); obj_start_addr = block_start(region_start_addr); } HeapWord* region_end_addr = mr.end(); MemRegion derived_mr(region_start_addr, region_end_addr); while (obj_start_addr < region_end_addr) { oop obj = oop(obj_start_addr); const size_t size = obj->size(); last_was_obj_array = cl->do_object_bm(obj, derived_mr); obj_start_addr += size; } if (!last_was_obj_array) { assert((bottom() <= obj_start_addr) && (obj_start_addr <= end()), "Should be within (closed) used space"); assert(obj_start_addr > prev, "Invariant"); cl->set_previous(obj_start_addr); // min address for next time } }
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; }
// Objects in this generation may have moved, invalidate this // generation's cards. void CardGeneration::invalidate_remembered_set() { _rs->invalidate(used_region()); }
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; }
// Returns true iff the given the space contains the // given address as part of an allocated object. For // certain kinds of spaces, this might be a potentially // expensive operation. To prevent performance problems // on account of its inadvertent use in product jvm's, // we restrict its use to assertion checks only. bool is_in(const void* p) const { return used_region().contains(p); }