void CardTableRS::verify() { // At present, we only know how to verify the card table RS for // generational heaps. VerifyCTGenClosure blk(this); CollectedHeap* ch = Universe::heap(); if (ch->kind() == CollectedHeap::GenCollectedHeap) { GenCollectedHeap::heap()->generation_iterate(&blk, false); _ct_bs->verify(); } }
inline void update_barrier_set(oop *p, oop v) { assert(oopDesc::bs() != NULL, "Uninitialized bs in oop!"); oopDesc::bs()->write_ref_field(p, v); if (UseTrainGC) { // Each generation has a chance to examine the oop. CollectedHeap* gch = Universe::heap(); // This is even more bogus. if (gch->kind() == CollectedHeap::GenCollectedHeap) { ((GenCollectedHeap*)gch)->examine_modified_oop(p); } } }
void CardTableRS::verify() { // At present, we only know how to verify the card table RS for // generational heaps. VerifyCTGenClosure blk(this); CollectedHeap* ch = Universe::heap(); // We will do the perm-gen portion of the card table, too. Generation* pg = SharedHeap::heap()->perm_gen(); HeapWord* pg_boundary = pg->reserved().start(); if (ch->kind() == CollectedHeap::GenCollectedHeap) { GenCollectedHeap::heap()->generation_iterate(&blk, false); _ct_bs->verify(); // If the old gen collections also collect perm, then we are only // interested in perm-to-young pointers, not perm-to-old pointers. GenCollectedHeap* gch = GenCollectedHeap::heap(); CollectorPolicy* cp = gch->collector_policy(); if (cp->is_mark_sweep_policy() || cp->is_concurrent_mark_sweep_policy()) { pg_boundary = gch->get_gen(1)->reserved().start(); } } VerifyCTSpaceClosure perm_space_blk(this, pg_boundary); SharedHeap::heap()->perm_gen()->space_iterate(&perm_space_blk, true); }
ParallelScavengeHeap* ParallelScavengeHeap::heap() { CollectedHeap* heap = Universe::heap(); assert(heap != NULL, "Uninitialized access to ParallelScavengeHeap::heap()"); assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Not a ParallelScavengeHeap"); return (ParallelScavengeHeap*)heap; }
void HeapInspection::heap_inspection(outputStream* st, bool need_prologue) { ResourceMark rm; HeapWord* ref; CollectedHeap* heap = Universe::heap(); bool is_shared_heap = false; switch (heap->kind()) { case CollectedHeap::G1CollectedHeap: case CollectedHeap::GenCollectedHeap: { is_shared_heap = true; SharedHeap* sh = (SharedHeap*)heap; if (need_prologue) { sh->gc_prologue(false /* !full */); // get any necessary locks, etc. } ref = sh->perm_gen()->used_region().start(); break; } #ifndef SERIALGC case CollectedHeap::ParallelScavengeHeap: { ParallelScavengeHeap* psh = (ParallelScavengeHeap*)heap; ref = psh->perm_gen()->object_space()->used_region().start(); break; } #endif // SERIALGC default: ShouldNotReachHere(); // Unexpected heap kind for this op } // Collect klass instance info KlassInfoTable cit(KlassInfoTable::cit_size, ref); if (!cit.allocation_failed()) { // Iterate over objects in the heap RecordInstanceClosure ric(&cit); // If this operation encounters a bad object when using CMS, // consider using safe_object_iterate() which avoids perm gen // objects that may contain bad references. Universe::heap()->object_iterate(&ric); // Report if certain classes are not counted because of // running out of C-heap for the histogram. size_t missed_count = ric.missed_count(); if (missed_count != 0) { st->print_cr("WARNING: Ran out of C-heap; undercounted " SIZE_FORMAT " total instances in data below", missed_count); } // Sort and print klass instance info KlassInfoHisto histo("\n" " num #instances #bytes class name\n" "----------------------------------------------", KlassInfoHisto::histo_initial_size); HistoClosure hc(&histo); cit.iterate(&hc); histo.sort(); histo.print_on(st); } else { st->print_cr("WARNING: Ran out of C-heap; histogram not generated"); } st->flush(); if (need_prologue && is_shared_heap) { SharedHeap* sh = (SharedHeap*)heap; sh->gc_epilogue(false /* !full */); // release all acquired locks, etc. } }
bool HeapInspection::is_shared_heap() { CollectedHeap* heap = Universe::heap(); return heap->kind() == CollectedHeap::G1CollectedHeap || heap->kind() == CollectedHeap::GenCollectedHeap; }
void ASParNewGeneration::resize_spaces(size_t requested_eden_size, size_t requested_survivor_size) { assert(UseAdaptiveSizePolicy, "sanity check"); assert(requested_eden_size > 0 && requested_survivor_size > 0, "just checking"); CollectedHeap* heap = Universe::heap(); assert(heap->kind() == CollectedHeap::GenCollectedHeap, "Sanity"); // We require eden and to space to be empty if ((!eden()->is_empty()) || (!to()->is_empty())) { return; } size_t cur_eden_size = eden()->capacity(); if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr("ASParNew::resize_spaces(requested_eden_size: " SIZE_FORMAT ", requested_survivor_size: " SIZE_FORMAT ")", requested_eden_size, requested_survivor_size); gclog_or_tty->print_cr(" eden: [" PTR_FORMAT ".." PTR_FORMAT ") " SIZE_FORMAT, eden()->bottom(), eden()->end(), pointer_delta(eden()->end(), eden()->bottom(), sizeof(char))); gclog_or_tty->print_cr(" from: [" PTR_FORMAT ".." PTR_FORMAT ") " SIZE_FORMAT, from()->bottom(), from()->end(), pointer_delta(from()->end(), from()->bottom(), sizeof(char))); gclog_or_tty->print_cr(" to: [" PTR_FORMAT ".." PTR_FORMAT ") " SIZE_FORMAT, to()->bottom(), to()->end(), pointer_delta( to()->end(), to()->bottom(), sizeof(char))); } // There's nothing to do if the new sizes are the same as the current if (requested_survivor_size == to()->capacity() && requested_survivor_size == from()->capacity() && requested_eden_size == eden()->capacity()) { if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" capacities are the right sizes, returning"); } return; } char* eden_start = (char*)eden()->bottom(); char* eden_end = (char*)eden()->end(); char* from_start = (char*)from()->bottom(); char* from_end = (char*)from()->end(); char* to_start = (char*)to()->bottom(); char* to_end = (char*)to()->end(); const size_t alignment = os::vm_page_size(); const bool maintain_minimum = (requested_eden_size + 2 * requested_survivor_size) <= min_gen_size(); // Check whether from space is below to space if (from_start < to_start) { // Eden, from, to if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" Eden, from, to:"); } // Set eden // "requested_eden_size" is a goal for the size of eden // and may not be attainable. "eden_size" below is // calculated based on the location of from-space and // the goal for the size of eden. from-space is // fixed in place because it contains live data. // The calculation is done this way to avoid 32bit // overflow (i.e., eden_start + requested_eden_size // may too large for representation in 32bits). size_t eden_size; if (maintain_minimum) { // Only make eden larger than the requested size if // the minimum size of the generation has to be maintained. // This could be done in general but policy at a higher // level is determining a requested size for eden and that // should be honored unless there is a fundamental reason. eden_size = pointer_delta(from_start, eden_start, sizeof(char)); } else { eden_size = MIN2(requested_eden_size, pointer_delta(from_start, eden_start, sizeof(char))); } eden_size = align_size_down(eden_size, alignment); eden_end = eden_start + eden_size; assert(eden_end >= eden_start, "addition overflowed") // To may resize into from space as long as it is clear of live data. // From space must remain page aligned, though, so we need to do some // extra calculations. // First calculate an optimal to-space to_end = (char*)virtual_space()->high(); to_start = (char*)pointer_delta(to_end, (char*)requested_survivor_size, sizeof(char)); // Does the optimal to-space overlap from-space? if (to_start < (char*)from()->end()) { // Calculate the minimum offset possible for from_end size_t from_size = pointer_delta(from()->top(), from_start, sizeof(char)); // Should we be in this method if from_space is empty? Why not the set_space method? FIX ME! if (from_size == 0) { from_size = alignment; } else { from_size = align_size_up(from_size, alignment); } from_end = from_start + from_size; assert(from_end > from_start, "addition overflow or from_size problem"); guarantee(from_end <= (char*)from()->end(), "from_end moved to the right"); // Now update to_start with the new from_end to_start = MAX2(from_end, to_start); } else { // If shrinking, move to-space down to abut the end of from-space // so that shrinking will move to-space down. If not shrinking // to-space is moving up to allow for growth on the next expansion. if (requested_eden_size <= cur_eden_size) { to_start = from_end; if (to_start + requested_survivor_size > to_start) { to_end = to_start + requested_survivor_size; } } // else leave to_end pointing to the high end of the virtual space. } guarantee(to_start != to_end, "to space is zero sized"); if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" [eden_start .. eden_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, eden_start, eden_end, pointer_delta(eden_end, eden_start, sizeof(char))); gclog_or_tty->print_cr(" [from_start .. from_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, from_start, from_end, pointer_delta(from_end, from_start, sizeof(char))); gclog_or_tty->print_cr(" [ to_start .. to_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, to_start, to_end, pointer_delta( to_end, to_start, sizeof(char))); } } else { // Eden, to, from if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" Eden, to, from:"); } // Calculate the to-space boundaries based on // the start of from-space. to_end = from_start; to_start = (char*)pointer_delta(from_start, (char*)requested_survivor_size, sizeof(char)); // Calculate the ideal eden boundaries. // eden_end is already at the bottom of the generation assert(eden_start == virtual_space()->low(), "Eden is not starting at the low end of the virtual space"); if (eden_start + requested_eden_size >= eden_start) { eden_end = eden_start + requested_eden_size; } else { eden_end = to_start; } // Does eden intrude into to-space? to-space // gets priority but eden is not allowed to shrink // to 0. if (eden_end > to_start) { eden_end = to_start; } // Don't let eden shrink down to 0 or less. eden_end = MAX2(eden_end, eden_start + alignment); assert(eden_start + alignment >= eden_start, "Overflow"); size_t eden_size; if (maintain_minimum) { // Use all the space available. eden_end = MAX2(eden_end, to_start); eden_size = pointer_delta(eden_end, eden_start, sizeof(char)); eden_size = MIN2(eden_size, cur_eden_size); } else { eden_size = pointer_delta(eden_end, eden_start, sizeof(char)); } eden_size = align_size_down(eden_size, alignment); assert(maintain_minimum || eden_size <= requested_eden_size, "Eden size is too large"); assert(eden_size >= alignment, "Eden size is too small"); eden_end = eden_start + eden_size; // Move to-space down to eden. if (requested_eden_size < cur_eden_size) { to_start = eden_end; if (to_start + requested_survivor_size > to_start) { to_end = MIN2(from_start, to_start + requested_survivor_size); } else { to_end = from_start; } } // eden_end may have moved so again make sure // the to-space and eden don't overlap. to_start = MAX2(eden_end, to_start); // from-space size_t from_used = from()->used(); if (requested_survivor_size > from_used) { if (from_start + requested_survivor_size >= from_start) { from_end = from_start + requested_survivor_size; } if (from_end > virtual_space()->high()) { from_end = virtual_space()->high(); } } assert(to_start >= eden_end, "to-space should be above eden"); if (PrintAdaptiveSizePolicy && Verbose) { gclog_or_tty->print_cr(" [eden_start .. eden_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, eden_start, eden_end, pointer_delta(eden_end, eden_start, sizeof(char))); gclog_or_tty->print_cr(" [ to_start .. to_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, to_start, to_end, pointer_delta( to_end, to_start, sizeof(char))); gclog_or_tty->print_cr(" [from_start .. from_end): " "[" PTR_FORMAT " .. " PTR_FORMAT ") " SIZE_FORMAT, from_start, from_end, pointer_delta(from_end, from_start, sizeof(char))); } } guarantee((HeapWord*)from_start <= from()->bottom(), "from start moved to the right"); guarantee((HeapWord*)from_end >= from()->top(), "from end moved into live data"); assert(is_object_aligned((intptr_t)eden_start), "checking alignment"); assert(is_object_aligned((intptr_t)from_start), "checking alignment"); assert(is_object_aligned((intptr_t)to_start), "checking alignment"); MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)eden_end); MemRegion toMR ((HeapWord*)to_start, (HeapWord*)to_end); MemRegion fromMR((HeapWord*)from_start, (HeapWord*)from_end); // Let's make sure the call to initialize doesn't reset "top"! HeapWord* old_from_top = from()->top(); // For PrintAdaptiveSizePolicy block below size_t old_from = from()->capacity(); size_t old_to = to()->capacity(); // If not clearing the spaces, do some checking to verify that // the spaces are already mangled. // Must check mangling before the spaces are reshaped. Otherwise, // the bottom or end of one space may have moved into another // a failure of the check may not correctly indicate which space // is not properly mangled. if (ZapUnusedHeapArea) { HeapWord* limit = (HeapWord*) virtual_space()->high(); eden()->check_mangled_unused_area(limit); from()->check_mangled_unused_area(limit); to()->check_mangled_unused_area(limit); } // The call to initialize NULL's the next compaction space eden()->initialize(edenMR, SpaceDecorator::Clear, SpaceDecorator::DontMangle); eden()->set_next_compaction_space(from()); to()->initialize(toMR , SpaceDecorator::Clear, SpaceDecorator::DontMangle); from()->initialize(fromMR, SpaceDecorator::DontClear, SpaceDecorator::DontMangle); assert(from()->top() == old_from_top, "from top changed!"); if (PrintAdaptiveSizePolicy) { GenCollectedHeap* gch = GenCollectedHeap::heap(); assert(gch->kind() == CollectedHeap::GenCollectedHeap, "Sanity"); gclog_or_tty->print("AdaptiveSizePolicy::survivor space sizes: " "collection: %d " "(" SIZE_FORMAT ", " SIZE_FORMAT ") -> " "(" SIZE_FORMAT ", " SIZE_FORMAT ") ", gch->total_collections(), old_from, old_to, from()->capacity(), to()->capacity()); gclog_or_tty->cr(); } }
void SharedUserData::task(){ #ifdef AZ_PROXIED // Static variables store peak values seen during the life of the run. static volatile sud_jvm_heap_rev1_t peak_jvm_heap; static sud_io_rev1_t io_stats; static volatile bool initialized = false; if (!initialized) { memset ((void*)(&peak_jvm_heap), 0, sizeof(peak_jvm_heap)); initialized = true; } if (SafepointSynchronize::is_at_safepoint()) return; CollectedHeap *heap = Universe::heap(); if (!heap) return; size_t l = heap->last_gc_live_bytes(); size_t u=heap->used(); size_t c = heap->capacity(); size_t m = heap->max_capacity(); size_t pu = heap->permanent_used(); size_t pc = heap->permanent_capacity(); // Make sure that the numbers make sense when graphing. c = (u > c) ? u : c; m = (c > m) ? c : m; pc = (pu > pc) ? pu : pc; sud_jvm_heap_rev1_t jvm_heap; memset(&jvm_heap, 0, sizeof(jvm_heap)); jvm_heap.revision = SUD_JVM_HEAP_REVISION; switch (heap->kind()) { case CollectedHeap::GenCollectedHeap: strcpy(jvm_heap.name, "GenCollectedHeap"); break; case CollectedHeap::ParallelScavengeHeap: strcpy(jvm_heap.name, "ParallelScavengeHeap"); break; case CollectedHeap::PauselessHeap: strcpy(jvm_heap.name, "PauselessHeap"); break; default: strcpy(jvm_heap.name, ""); } if (heap->supports_tlab_allocation()) jvm_heap.flags |= SUD_JVM_HEAP_FLAG_TLAB_ALLOCATION; if (heap->supports_inline_contig_alloc()) jvm_heap.flags |= SUD_JVM_HEAP_FLAG_INLINE_CONTIG_ALLOC; uint64_t now = (uint64_t) os::javaTimeMillis(); jvm_heap.timestamp_ms = now; jvm_heap.live_bytes = l; jvm_heap.used_bytes = u; jvm_heap.capacity_bytes = c; jvm_heap.max_capacity_bytes = m; jvm_heap.permanent_used_bytes = pu; jvm_heap.permanent_capacity_bytes = pc; jvm_heap.total_collections = heap->total_collections(); libos::AccountInfo ai; az_allocid_t allocid = process_get_allocationid(); sys_return_t ret = ai.inspectProcess (allocid); if (ret == SYSERR_NONE) { // Copy memory_accounting information into the sud structure. // Take care not to overflow the accounts past the maximum storable. const account_info_t *account_info = ai.getAccountInfo(); uint64_t count = (account_info->ac_count < SUD_MAX_ACCOUNTS) ? account_info->ac_count : SUD_MAX_ACCOUNTS; jvm_heap.account_info.ac_count = count; for (uint64_t i = 0; i < count; i++) { jvm_heap.account_info.ac_array[i] = account_info->ac_array[i]; } } else { warning("Failed to inspect memory accounting info (%d)",ret); } #define UPDATE_PEAK(struct_member,value) \ if (peak_jvm_heap.peak_ ## struct_member ## _bytes < value) { \ peak_jvm_heap.peak_ ## struct_member ## _bytes = value; \ peak_jvm_heap.peak_ ## struct_member ## _timestamp_ms = now; \ } \ jvm_heap.peak_ ## struct_member ## _bytes = peak_jvm_heap.peak_ ## struct_member ## _bytes; \ jvm_heap.peak_ ## struct_member ## _timestamp_ms = peak_jvm_heap.peak_ ## struct_member ## _timestamp_ms; UPDATE_PEAK (live,l); UPDATE_PEAK (used,u); UPDATE_PEAK (capacity,c); UPDATE_PEAK (max_capacity,m); UPDATE_PEAK (permanent_used,pu); UPDATE_PEAK (permanent_capacity,pc); UPDATE_PEAK (allocated,ai.getAllocatedBytes()); UPDATE_PEAK (funded,ai.getFundedBytes()); UPDATE_PEAK (overdraft,ai.getOverdraftBytes()); UPDATE_PEAK (footprint,ai.getFootprintBytes()); UPDATE_PEAK (committed,ai.getCommittedBytes()); UPDATE_PEAK (grant,ai.getGrantBytes()); UPDATE_PEAK (allocated_from_committed,ai.getAllocatedFromCommittedBytes()); UPDATE_PEAK (default_allocated,ai.getDefaultAllocatedBytes()); UPDATE_PEAK (default_committed,ai.getDefaultCommittedBytes()); UPDATE_PEAK (default_footprint,ai.getDefaultFootprintBytes()); UPDATE_PEAK (default_grant,ai.getDefaultGrantBytes()); UPDATE_PEAK (heap_allocated,ai.getHeapAllocatedBytes()); UPDATE_PEAK (heap_committed,ai.getHeapCommittedBytes()); UPDATE_PEAK (heap_footprint,ai.getHeapFootprintBytes()); UPDATE_PEAK (heap_grant,ai.getHeapGrantBytes()); ret = shared_user_data_set_jvm_heap_rev1 (allocid, &jvm_heap); if (ret != SYSERR_NONE) warning("Failed to set jvm_heap shared user data (%d)", ret); memset ((void*)(&io_stats), 0, sizeof(io_stats)); io_stats.revision = SUD_IO_REVISION; atcpn_stats_get_io_rev1(&io_stats); ret = shared_user_data_set_io_rev1 (allocid, &io_stats); if (ret != SYSERR_NONE) warning("Failed to set io_stats shared user data (%d)", ret); #endif // AZ_PROXIED }