--- old/src/share/vm/gc_implementation/g1/g1Allocator.cpp 2014-12-15 12:59:10.887718694 +0100 +++ new/src/share/vm/gc_implementation/g1/g1Allocator.cpp 2014-12-15 12:59:10.829716955 +0100 @@ -150,11 +150,11 @@ } void G1DefaultParGCAllocator::retire_alloc_buffers() { - for (uint i = 0; i < InCSetState::Num; i += 1) { - G1ParGCAllocBuffer* const buf = _alloc_buffers[i]; + for (uint state = 0; state < InCSetState::Num; state += 1) { + G1ParGCAllocBuffer* const buf = _alloc_buffers[state]; if (buf != NULL) { add_to_alloc_buffer_waste(buf->words_remaining()); - buf->flush_stats_and_retire(_g1h->alloc_buffer_stats(i), + buf->flush_stats_and_retire(_g1h->alloc_buffer_stats(state), true /* end_of_gc */, false /* retain */); } --- old/src/share/vm/gc_implementation/g1/g1Allocator.hpp 2014-12-15 12:59:11.232729040 +0100 +++ new/src/share/vm/gc_implementation/g1/g1Allocator.hpp 2014-12-15 12:59:11.173727271 +0100 @@ -27,29 +27,9 @@ #include "gc_implementation/g1/g1AllocationContext.hpp" #include "gc_implementation/g1/g1AllocRegion.hpp" +#include "gc_implementation/g1/g1InCSetState.hpp" #include "gc_implementation/shared/parGCAllocBuffer.hpp" -typedef int8_t in_cset_state_t; - -// Helper class used to examine in_cset_t values. -class InCSetState : AllStatic { -public: - enum { - // Values <0 mean the region is a humongous region. - NotInCSet = 0, // The region is not in the collection set. - Young = 1, // The region is in the collection set and a young region. - Old = 2, // The region is in the collection set and an old region. - Num - }; - - static in_cset_state_t humongous() { return -1; } - - static bool is_not_in_cset(in_cset_state_t state) { return state == NotInCSet; } - static bool is_in_cset_or_humongous(in_cset_state_t state) { return state != NotInCSet; } - static bool is_in_cset(in_cset_state_t state) { return state > NotInCSet; } - static bool is_humongous(in_cset_state_t state) { return state < NotInCSet; } -}; - // Base class for G1 allocators. class G1Allocator : public CHeapObj { friend class VMStructs; --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2014-12-15 12:59:11.586739656 +0100 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp 2014-12-15 12:59:11.520737677 +0100 @@ -2763,7 +2763,7 @@ default: ShouldNotReachHere(); } - return false; // keep some compilers happy + return false; // Keep some compilers happy } HeapWord* G1CollectedHeap::top_at_mark_start(HeapRegion* hr, VerifyOption vo) { @@ -5769,9 +5769,7 @@ } }; -#ifdef PRODUCT -bool G1CollectedHeap::check_cset_fast_test() { return true; } -#else +#ifndef PRODUCT class G1VerifyCardTableCleanup: public HeapRegionClosure { G1CollectedHeap* _g1h; G1SATBCardTableModRefBS* _ct_bs; --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2014-12-15 12:59:12.006752251 +0100 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp 2014-12-15 12:59:11.941750302 +0100 @@ -32,6 +32,7 @@ #include "gc_implementation/g1/g1AllocRegion.hpp" #include "gc_implementation/g1/g1BiasedArray.hpp" #include "gc_implementation/g1/g1HRPrinter.hpp" +#include "gc_implementation/g1/g1InCSetState.hpp" #include "gc_implementation/g1/g1MonitoringSupport.hpp" #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp" #include "gc_implementation/g1/g1YCTypes.hpp" @@ -547,22 +548,9 @@ // allocation region, either by picking one or expanding the // heap, and then allocate a block of the given size. The block // may not be a humongous - it must fit into a single heap region. - HeapWord* par_allocate_during_gc(in_cset_state_t dest, - size_t word_size, - AllocationContext_t context) { - switch (dest) { - case InCSetState::Young: - return survivor_attempt_allocation(word_size, context); - case InCSetState::Old: - return old_attempt_allocation(word_size, context); - default: - assert(false, err_msg("Unknown dest: %d", dest)); - break; - } - // keep some compilers happy - return NULL; - } - + inline HeapWord* par_allocate_during_gc(in_cset_state_t dest, + size_t word_size, + AllocationContext_t context); // Ensure that no further allocations can happen in "r", bearing in mind // that parallel threads might be attempting allocations. void par_allocate_remaining_space(HeapRegion* r); @@ -648,41 +636,10 @@ bool expand(size_t expand_bytes); // Returns the PLAB statistics for a given destination. - PLABStats* alloc_buffer_stats(in_cset_state_t dest) { - switch (dest) { - case InCSetState::Young: - return &_survivor_plab_stats; - case InCSetState::Old: - return &_old_plab_stats; - default: - assert(false, err_msg("unknown dest: %d", dest)); - break; - } - // keep some compilers happy - return NULL; - } + inline PLABStats* alloc_buffer_stats(in_cset_state_t dest); // Determines PLAB size for a given destination. - size_t desired_plab_sz(in_cset_state_t dest) { - size_t gclab_word_size = 0; - switch (dest) { - case InCSetState::Young: - gclab_word_size = _survivor_plab_stats.desired_plab_sz(); - break; - case InCSetState::Old: - gclab_word_size = _old_plab_stats.desired_plab_sz(); - break; - default: - assert(false, err_msg("Unknown dest: %d", dest)); - break; - } - - // Prevent humongous PLAB sizes for two reasons: - // * PLABs are allocated using a similar paths as oops, but should - // never be in a humongous region - // * Allowing humongous PLABs needlessly churns the region free lists - return MIN2(_humongous_object_threshold_in_words, gclab_word_size); - } + inline size_t desired_plab_sz(in_cset_state_t dest); inline AllocationContextStats& allocation_context_stats(); @@ -1208,7 +1165,7 @@ void check_bitmaps(const char* caller) PRODUCT_RETURN; // Do sanity check on the contents of the in-cset fast test table. - bool check_cset_fast_test(); + bool check_cset_fast_test() PRODUCT_RETURN_( return true; ); // verify_region_sets() performs verification over the region // lists. It will be compiled in the product code to be used when @@ -1306,46 +1263,6 @@ inline bool is_in_cset_or_humongous(const oop obj); private: - // Instances of this class are used for quick tests on whether a reference points - // into the collection set and into which generation or is a humongous object - // - // Each of the array's elements indicates whether the corresponding region is in - // the collection set and if so in which generation, or a humongous region. - // - // We use this to speed up reference processing during young collection and - // quickly reclaim humongous objects. For the latter, by making a humongous region - // succeed this test, we sort-of add it to the collection set. During the reference - // iteration closures, when we see a humongous region, we then simply mark it as - // referenced, i.e. live. - class G1InCSetStateFastTestBiasedMappedArray : public G1BiasedMappedArray { - protected: - in_cset_state_t default_value() const { return InCSetState::NotInCSet; } - public: - void set_humongous(uintptr_t index) { - assert(get_by_index(index) == default_value(), "should be default"); - set_by_index(index, InCSetState::humongous()); - } - - void clear_humongous(uintptr_t index) { - set_by_index(index, InCSetState::NotInCSet); - } - - void set_in_young(uintptr_t index) { - assert(get_by_index(index) == default_value(), "should be default"); - set_by_index(index, InCSetState::Young); - } - - void set_in_old(uintptr_t index) { - assert(get_by_index(index) == default_value(), "should be default"); - set_by_index(index, InCSetState::Old); - } - - bool is_in_cset_or_humongous(HeapWord* addr) const { return InCSetState::is_in_cset_or_humongous(at(addr)); } - bool is_in_cset(HeapWord* addr) const { return InCSetState::is_in_cset(at(addr)); } - in_cset_state_t at(HeapWord* addr) const { return (in_cset_state_t) get_by_address(addr); } - void clear() { G1BiasedMappedArray::clear(); } - }; - // This array is used for a quick test on whether a reference points into // the collection set or not. Each of the array's elements denotes whether the // corresponding region is in the collection set or not. --- old/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp 2014-12-15 12:59:12.415764516 +0100 +++ new/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp 2014-12-15 12:59:12.347762477 +0100 @@ -35,6 +35,41 @@ #include "runtime/orderAccess.inline.hpp" #include "utilities/taskqueue.hpp" +PLABStats* G1CollectedHeap::alloc_buffer_stats(in_cset_state_t dest) { + switch (dest) { + case InCSetState::Young: + return &_survivor_plab_stats; + case InCSetState::Old: + return &_old_plab_stats; + default: + ShouldNotReachHere(); + return NULL; // Keep some compilers happy + } +} + +size_t G1CollectedHeap::desired_plab_sz(in_cset_state_t dest) { + size_t gclab_word_size = alloc_buffer_stats(dest)->desired_plab_sz(); + // Prevent humongous PLAB sizes for two reasons: + // * PLABs are allocated using a similar paths as oops, but should + // never be in a humongous region + // * Allowing humongous PLABs needlessly churns the region free lists + return MIN2(_humongous_object_threshold_in_words, gclab_word_size); +} + +HeapWord* G1CollectedHeap::par_allocate_during_gc(in_cset_state_t dest, + size_t word_size, + AllocationContext_t context) { + switch (dest) { + case InCSetState::Young: + return survivor_attempt_allocation(word_size, context); + case InCSetState::Old: + return old_attempt_allocation(word_size, context); + default: + ShouldNotReachHere(); + return NULL; // Keep some compilers happy + } +} + // Inline functions for G1CollectedHeap inline AllocationContextStats& G1CollectedHeap::allocation_context_stats() { --- old/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp 2014-12-15 12:59:12.810776361 +0100 +++ new/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp 2014-12-15 12:59:12.744774382 +0100 @@ -32,7 +32,6 @@ #include "gc_implementation/g1/g1OopClosures.inline.hpp" #include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/heapRegionRemSet.hpp" -#include "oops/markOop.inline.hpp" #include "utilities/workgroup.hpp" // Closures and tasks associated with any self-forwarding pointers @@ -121,9 +120,7 @@ _last_gap_threshold = _hr->cross_threshold(_end_of_last_gap, obj_addr); } - markOop m = obj->mark(); - if (m->is_marked() && ((oop)m->decode_pointer() == obj)) { - + if (obj->is_forwarded() && obj->forwardee() == obj) { // The object failed to move. // We consider all objects that we find self-forwarded to be --- /dev/null 2014-12-12 17:10:47.511674808 +0100 +++ new/src/share/vm/gc_implementation/g1/g1InCSetState.hpp 2014-12-15 12:59:13.113785448 +0100 @@ -0,0 +1,100 @@ +/* + * 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. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP + +#include "gc_implementation/g1/g1BiasedArray.hpp" +#include "memory/allocation.hpp" + +typedef int8_t in_cset_state_t; + +// Helper class used to examine in_cset_t values. +class InCSetState : AllStatic { +public: + enum { + // Selection of the values were driven to micro-optimize the encoding and + // frequency of the checks. + // The most common check is whether the region is in the collection set or not. + // This encoding allows us to use an != 0 check which in some architectures + // (x86*) can be encoded slightly more efficently than a normal comparison + // against zero. + // The same situation occurs when checking whether the region is humongous + // or not, which is encoded by values < 0. + // The other values are simply encoded in increasing generation order, which + // makes getting the next generation fast by a simple increment. + Humongous = -1, // The region is humongous - note that actually any value < 0 would be possible here. + NotInCSet = 0, // The region is not in the collection set. + Young = 1, // The region is in the collection set and a young region. + Old = 2, // The region is in the collection set and an old region. + Num + }; + + static bool is_not_in_cset(in_cset_state_t state) { return state == NotInCSet; } + static bool is_in_cset_or_humongous(in_cset_state_t state) { return state != NotInCSet; } + static bool is_in_cset(in_cset_state_t state) { return state > NotInCSet; } + static bool is_humongous(in_cset_state_t state) { return state < NotInCSet; } +}; + +// Instances of this class are used for quick tests on whether a reference points +// into the collection set and into which generation or is a humongous object +// +// Each of the array's elements indicates whether the corresponding region is in +// the collection set and if so in which generation, or a humongous region. +// +// We use this to speed up reference processing during young collection and +// quickly reclaim humongous objects. For the latter, by making a humongous region +// succeed this test, we sort-of add it to the collection set. During the reference +// iteration closures, when we see a humongous region, we then simply mark it as +// referenced, i.e. live. +class G1InCSetStateFastTestBiasedMappedArray : public G1BiasedMappedArray { + protected: + in_cset_state_t default_value() const { return InCSetState::NotInCSet; } + public: + void set_humongous(uintptr_t index) { + assert(get_by_index(index) == default_value(), "should be default"); + set_by_index(index, InCSetState::Humongous); + } + + void clear_humongous(uintptr_t index) { + set_by_index(index, InCSetState::NotInCSet); + } + + void set_in_young(uintptr_t index) { + assert(get_by_index(index) == default_value(), "should be default"); + set_by_index(index, InCSetState::Young); + } + + void set_in_old(uintptr_t index) { + assert(get_by_index(index) == default_value(), "should be default"); + set_by_index(index, InCSetState::Old); + } + + bool is_in_cset_or_humongous(HeapWord* addr) const { return InCSetState::is_in_cset_or_humongous(at(addr)); } + bool is_in_cset(HeapWord* addr) const { return InCSetState::is_in_cset(at(addr)); } + in_cset_state_t at(HeapWord* addr) const { return (in_cset_state_t) get_by_address(addr); } + void clear() { G1BiasedMappedArray::clear(); } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1INCSETSTATE_HPP