Mercurial > hg > graal-jvmci-8
changeset 22896:5743a702da65
Merge
author | tschatzl |
---|---|
date | Tue, 24 Mar 2015 10:04:10 +0000 |
parents | f2e3f0e1f97d (diff) 695017a614d5 (current diff) |
children | 80ac3ee51955 |
files | |
diffstat | 6 files changed, 177 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Mar 19 08:55:50 2015 -0400 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Mar 24 10:04:10 2015 +0000 @@ -3720,7 +3720,7 @@ cl.candidate_humongous()); _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0; - if (_has_humongous_reclaim_candidates) { + if (_has_humongous_reclaim_candidates || G1TraceReclaimDeadHumongousObjectsAtYoungGC) { clear_humongous_is_live_table(); } } @@ -4479,10 +4479,11 @@ if (state == G1CollectedHeap::InCSet) { oop forwardee; - if (obj->is_forwarded()) { - forwardee = obj->forwardee(); + markOop m = obj->mark(); + if (m->is_marked()) { + forwardee = (oop) m->decode_pointer(); } else { - forwardee = _par_scan_state->copy_to_survivor_space(obj); + forwardee = _par_scan_state->copy_to_survivor_space(obj, m); } assert(forwardee != NULL, "forwardee should not be NULL"); oopDesc::encode_store_heap_oop(p, forwardee); @@ -6420,9 +6421,10 @@ g1h->humongous_region_is_always_live(region_idx)) { if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { - gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", + gclog_or_tty->print_cr("Live humongous %d region %d size "SIZE_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", r->isHumongous(), region_idx, + obj->size()*HeapWordSize, r->rem_set()->occupied(), r->rem_set()->strong_code_roots_list_length(), next_bitmap->isMarked(r->bottom()), @@ -6439,8 +6441,9 @@ r->bottom())); if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) { - gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d", + gclog_or_tty->print_cr("Reclaim humongous region %d size "SIZE_FORMAT" start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other ", r->isHumongous(), + obj->size()*HeapWordSize, r->bottom(), region_idx, r->region_num(), @@ -6479,7 +6482,8 @@ void G1CollectedHeap::eagerly_reclaim_humongous_regions() { assert_at_safepoint(true); - if (!G1ReclaimDeadHumongousObjectsAtYoungGC || !_has_humongous_reclaim_candidates) { + if (!G1ReclaimDeadHumongousObjectsAtYoungGC || + (!_has_humongous_reclaim_candidates && !G1TraceReclaimDeadHumongousObjectsAtYoungGC)) { g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0); return; }
--- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Thu Mar 19 08:55:50 2015 -0400 +++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp Tue Mar 24 10:04:10 2015 +0000 @@ -150,7 +150,8 @@ } while (!_refs->is_empty()); } -oop G1ParScanThreadState::copy_to_survivor_space(oop const old) { +oop G1ParScanThreadState::copy_to_survivor_space(oop const old, + markOop const old_mark) { size_t word_sz = old->size(); HeapRegion* from_region = _g1h->heap_region_containing_raw(old); // +1 to make the -1 indexes valid... @@ -158,9 +159,8 @@ assert( (from_region->is_young() && young_index > 0) || (!from_region->is_young() && young_index == 0), "invariant" ); G1CollectorPolicy* g1p = _g1h->g1_policy(); - markOop m = old->mark(); - int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age() - : m->age(); + uint age = old_mark->has_displaced_mark_helper() ? old_mark->displaced_mark_helper()->age() + : old_mark->age(); GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age, word_sz); AllocationContext_t context = from_region->allocation_context(); @@ -196,30 +196,22 @@ alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured; if (g1p->track_object_age(alloc_purpose)) { - // We could simply do obj->incr_age(). However, this causes a - // performance issue. obj->incr_age() will first check whether - // the object has a displaced mark by checking its mark word; - // getting the mark word from the new location of the object - // stalls. So, given that we already have the mark word and we - // are about to install it anyway, it's better to increase the - // age on the mark word, when the object does not have a - // displaced mark word. We're not expecting many objects to have - // a displaced marked word, so that case is not optimized - // further (it could be...) and we simply call obj->incr_age(). - - if (m->has_displaced_mark_helper()) { - // in this case, we have to install the mark word first, + if (age < markOopDesc::max_age) { + age++; + } + if (old_mark->has_displaced_mark_helper()) { + // In this case, we have to install the mark word first, // otherwise obj looks to be forwarded (the old mark word, // which contains the forward pointer, was copied) - obj->set_mark(m); - obj->incr_age(); + obj->set_mark(old_mark); + markOop new_mark = old_mark->displaced_mark_helper()->set_age(age); + old_mark->set_displaced_mark_helper(new_mark); } else { - m = m->incr_age(); - obj->set_mark(m); + obj->set_mark(old_mark->set_age(age)); } - age_table()->add(obj, word_sz); + age_table()->add(age, word_sz); } else { - obj->set_mark(m); + obj->set_mark(old_mark); } if (G1StringDedup::is_enabled()) {
--- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Thu Mar 19 08:55:50 2015 -0400 +++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp Tue Mar 24 10:04:10 2015 +0000 @@ -195,7 +195,7 @@ inline void dispatch_reference(StarTask ref); public: - oop copy_to_survivor_space(oop const obj); + oop copy_to_survivor_space(oop const obj, markOop const old_mark); void trim_queue();
--- a/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Thu Mar 19 08:55:50 2015 -0400 +++ b/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp Tue Mar 24 10:04:10 2015 +0000 @@ -41,10 +41,11 @@ G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj); if (in_cset_state == G1CollectedHeap::InCSet) { oop forwardee; - if (obj->is_forwarded()) { - forwardee = obj->forwardee(); + markOop m = obj->mark(); + if (m->is_marked()) { + forwardee = (oop) m->decode_pointer(); } else { - forwardee = copy_to_survivor_space(obj); + forwardee = copy_to_survivor_space(obj, m); } oopDesc::encode_store_heap_oop(p, forwardee); } else if (in_cset_state == G1CollectedHeap::IsHumongous) {
--- a/src/share/vm/gc_implementation/shared/ageTable.hpp Thu Mar 19 08:55:50 2015 -0400 +++ b/src/share/vm/gc_implementation/shared/ageTable.hpp Tue Mar 24 10:04:10 2015 +0000 @@ -55,7 +55,10 @@ // add entry void add(oop p, size_t oop_size) { - uint age = p->age(); + add(p->age(), oop_size); + } + + void add(uint age, size_t oop_size) { assert(age > 0 && age < table_size, "invalid age of object"); sizes[age] += oop_size; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/gc/g1/TestG1TraceReclaimDeadHumongousObjectsAtYoungGC.java Tue Mar 24 10:04:10 2015 +0000 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test TestG1TraceReclaimDeadHumongousObjectsAtYoungGC + * @bug 8058801 + * @summary Ensure that the output for a G1TraceReclaimDeadHumongousObjectsAtYoungGC + * includes the expected necessary messages. + * @key gc + * @library /testlibrary + */ + +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.OutputAnalyzer; +import java.util.LinkedList; + +public class TestG1TraceReclaimDeadHumongousObjectsAtYoungGC { + public static void main(String[] args) throws Exception { + testGCLogs(); + testHumongousObjectGCLogs(); + } + + private static void testGCLogs() throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", + "-Xms128M", + "-Xmx128M", + "-Xmn16M", + "-XX:G1HeapRegionSize=1M", + "-XX:+PrintGC", + "-XX:+UnlockExperimentalVMOptions", + "-XX:G1LogLevel=finest", + "-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC", + GCTest.class.getName()); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed. + // And GCTest doesn't have humongous objects, so values should be zero. + output.shouldContain("[Humongous Reclaim"); + output.shouldContain("[Humongous Total: 0]"); + output.shouldContain("[Humongous Candidate: 0]"); + output.shouldContain("[Humongous Reclaimed: 0]"); + + output.shouldHaveExitValue(0); + } + + private static void testHumongousObjectGCLogs() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC", + "-Xms128M", + "-Xmx128M", + "-Xmn16M", + "-XX:G1HeapRegionSize=1M", + "-XX:+PrintGC", + "-XX:+UnlockExperimentalVMOptions", + "-XX:G1LogLevel=finest", + "-XX:+G1TraceReclaimDeadHumongousObjectsAtYoungGC", + GCWithHumongousObjectTest.class.getName()); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // As G1ReclaimDeadHumongousObjectsAtYoungGC is set(default), below logs should be displayed. + output.shouldContain("[Humongous Reclaim"); + output.shouldContain("[Humongous Total"); + output.shouldContain("[Humongous Candidate"); + output.shouldContain("[Humongous Reclaimed"); + + // As G1TraceReclaimDeadHumongousObjectsAtYoungGC is set and GCWithHumongousObjectTest has humongous objects, + // these logs should be displayed. + output.shouldContain("Live humongous"); + output.shouldContain("Reclaim humongous region"); + output.shouldHaveExitValue(0); + } + + static class GCTest { + private static byte[] garbage; + + public static void main(String [] args) { + System.out.println("Creating garbage"); + // create 128MB of garbage. This should result in at least one GC + for (int i = 0; i < 1024; i++) { + garbage = new byte[128 * 1024]; + } + System.out.println("Done"); + } + } + + static class GCWithHumongousObjectTest { + + public static final int M = 1024*1024; + public static LinkedList<Object> garbageList = new LinkedList<Object>(); + // A large object referenced by a static. + static int[] filler = new int[10 * M]; + + public static void genGarbage() { + for (int i = 0; i < 32*1024; i++) { + garbageList.add(new int[100]); + } + garbageList.clear(); + } + + public static void main(String[] args) { + + int[] large = new int[M]; + Object ref = large; + + System.out.println("Creating garbage"); + for (int i = 0; i < 100; i++) { + // A large object that will be reclaimed eagerly. + large = new int[6*M]; + genGarbage(); + // Make sure that the compiler cannot completely remove + // the allocation of the large object until here. + System.out.println(large); + } + + // Keep the reference to the first object alive. + System.out.println(ref); + System.out.println("Done"); + } + } +}