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); }
void HeapRegion::migrate_strong_code_roots() { assert(in_collection_set(), "only collection set regions"); assert(!isHumongous(), err_msg("humongous region "HR_FORMAT" should not have been added to collection set", HR_FORMAT_PARAMS(this))); HeapRegionRemSet* hrrs = rem_set(); hrrs->migrate_strong_code_roots(); }
void HeapRegion::set_continuesHumongous(HeapRegion* first_hr) { assert(!isHumongous(), "sanity / pre-condition"); assert(end() == _orig_end, "Should be normal before the humongous object allocation"); assert(top() == bottom(), "should be empty"); assert(first_hr->startsHumongous(), "pre-condition"); _humongous_type = ContinuesHumongous; _humongous_start_region = first_hr; }
inline HeapWord* G1CollectedHeap::old_attempt_allocation(size_t word_size) { assert(!isHumongous(word_size), "we should not be seeing humongous-size allocations in this path"); HeapWord* result = _old_gc_alloc_region.attempt_allocation(word_size, true /* bot_updates */); if (result == NULL) { MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag); result = _old_gc_alloc_region.attempt_allocation_locked(word_size, true /* bot_updates */); } return result; }
void HeapRegion::set_startsHumongous(HeapWord* new_top, HeapWord* new_end) { assert(!isHumongous(), "sanity / pre-condition"); assert(end() == _orig_end, "Should be normal before the humongous object allocation"); assert(top() == bottom(), "should be empty"); assert(bottom() <= new_top && new_top <= new_end, "pre-condition"); _humongous_type = StartsHumongous; _humongous_start_region = this; set_end(new_end); _offsets.set_for_starts_humongous(new_top); }
inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size, unsigned int* gc_count_before_ret) { assert_heap_not_locked_and_not_at_safepoint(); assert(!isHumongous(word_size), "attempt_allocation() should not " "be called for humongous allocation requests"); HeapWord* result = _mutator_alloc_region.attempt_allocation(word_size, false /* bot_updates */); if (result == NULL) { result = attempt_allocation_slow(word_size, gc_count_before_ret); } assert_heap_not_locked(); if (result != NULL) { dirty_young_block(result, word_size); } return result; }
void HeapRegion::clear_humongous() { assert(isHumongous(), "pre-condition"); if (startsHumongous()) { assert(top() <= end(), "pre-condition"); set_end(_orig_end); if (top() > end()) { // at least one "continues humongous" region after it set_top(end()); } } else { // continues humongous assert(end() == _orig_end, "sanity"); } assert(capacity() == HeapRegion::GrainBytes, "pre-condition"); _humongous_start_region = NULL; }
void HeapRegion::verify(bool allow_dirty, bool use_prev_marking, bool* failures) const { G1CollectedHeap* g1 = G1CollectedHeap::heap(); *failures = false; HeapWord* p = bottom(); HeapWord* prev_p = NULL; int objs = 0; int blocks = 0; VerifyLiveClosure vl_cl(g1, use_prev_marking); bool is_humongous = isHumongous(); size_t object_num = 0; while (p < top()) { size_t size = oop(p)->size(); if (is_humongous != g1->isHumongous(size)) { gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size (" SIZE_FORMAT" words) in a %shumongous region", p, g1->isHumongous(size) ? "" : "non-", size, is_humongous ? "" : "non-"); *failures = true; } object_num += 1; if (blocks == BLOCK_SAMPLE_INTERVAL) { HeapWord* res = block_start_const(p + (size/2)); if (p != res) { gclog_or_tty->print_cr("offset computation 1 for "PTR_FORMAT" and " SIZE_FORMAT" returned "PTR_FORMAT, p, size, res); *failures = true; return; } blocks = 0; } else { blocks++; } if (objs == OBJ_SAMPLE_INTERVAL) { oop obj = oop(p); if (!g1->is_obj_dead_cond(obj, this, use_prev_marking)) { if (obj->is_oop()) { klassOop klass = obj->klass(); if (!klass->is_perm()) { gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" " "not in perm", klass, 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, obj); *failures = true; return; } else { vl_cl.set_containing_obj(obj); obj->oop_iterate(&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", obj); *failures = true; return; } } objs = 0; } else { objs++; } prev_p = p; p += size; } HeapWord* rend = end(); HeapWord* rtop = top(); if (rtop < rend) { HeapWord* res = block_start_const(rtop + (rend - rtop) / 2); if (res != rtop) { gclog_or_tty->print_cr("offset computation 2 for "PTR_FORMAT" and " PTR_FORMAT" returned "PTR_FORMAT, rtop, rend, res); *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; } 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; } }
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); }