/* * Copyright (c) 2021, 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. *
*/
class G1CardSetAllocOptions; class G1CardSetHashTable; class G1CardSetHashTableValue; class G1CardSetMemoryManager; class Mutex;
// The result of an attempt to add a card to that card set. enum G1AddCardResult {
Overflow, // The card set is more than full. The entry may have been added. Need // Coarsen and retry.
Found, // The card is already in the set.
Added // The card has been added to the set by this attempt.
};
class G1CardSetConfiguration { // Holds the number of bits required to cover the maximum card index for the // regions covered by this card set.
uint _inline_ptr_bits_per_card;
// Array of Cards configuration // Maximum number of cards in "Array of Cards" set; 0 to disable. // Always coarsen to next level if full, so no specific threshold.
uint max_cards_in_array() const { return _max_cards_in_array; }
// Bitmap within Howl card set container configuration
uint max_cards_in_howl_bitmap() const { return _max_cards_in_howl_bitmap; } // (Approximate) Number of cards in bitmap to coarsen Howl Bitmap to Howl Full.
uint cards_in_howl_bitmap_threshold() const { return _cards_in_howl_bitmap_threshold; }
uint log2_max_cards_in_howl_bitmap() const {return _log2_max_cards_in_howl_bitmap;}
// Howl card set container configuration
uint num_buckets_in_howl() const { return _num_buckets_in_howl; } // Threshold at which to turn howling arrays into Full.
uint cards_in_howl_threshold() const { return _cards_in_howl_threshold; }
uint howl_bitmap_offset(uint card_idx) const { return card_idx & _bitmap_hash_mask; } // Given a card index, return the bucket in the array of card sets.
uint howl_bucket_index(uint card_idx) { return card_idx >> _log2_max_cards_in_howl_bitmap; }
// Full card configuration // Maximum number of cards in a non-full card set for a single card region. Card sets // with more entries per region are coarsened to Full.
uint max_cards_in_region() const { return _max_cards_in_card_set; }
// Heap region virtualization: there are some limitations to how many cards the // containers can cover to save memory for the common case. Heap region virtualization // allows to use multiple entries in the G1CardSet hash table per area covered // by the remembered set (e.g. heap region); each such entry is called "card_region". // // The next two members give information about how many card regions are there // per area (heap region) and how many cards each card region has.
// The log2 of the number of card regions per heap region configured.
uint log2_card_regions_per_heap_region() const { return _log2_card_regions_per_heap_region; } // The log2 of the number of cards per card region. This is calculated from max_cards_in_region() // and above.
uint log2_cards_per_card_region() const { return _log2_cards_per_card_region; }
// Memory object types configuration // Number of distinctly sized memory objects on the card set heap. // Currently contains CHT-Nodes, ArrayOfCards, BitMaps, Howl static constexpr uint num_mem_object_types() { return 4; } // Returns the memory allocation options for the memory objects on the card set heap. const G1CardSetAllocOptions* mem_object_alloc_options(uint idx);
// For a given memory object, get a descriptive name. staticconstchar* mem_object_type_name_str(uint index);
};
// Collects coarsening statistics: how many attempts of each kind and how many // failed due to a competing thread doing the coarsening first. class G1CardSetCoarsenStats { public: // Number of entries in the statistics tables: since we index with the source // container of the coarsening, this is the total number of combinations of // card set containers - 1. static constexpr size_t NumCoarsenCategories = 7; // Coarsening statistics for the possible ContainerPtr in the Howl card set // start from this offset. static constexpr size_t CoarsenHowlOffset = 4;
private: // Indices are "from" indices.
size_t _coarsen_from[NumCoarsenCategories];
size_t _coarsen_collision[NumCoarsenCategories];
public:
G1CardSetCoarsenStats() { reset(); }
void reset();
void set(G1CardSetCoarsenStats& other);
void subtract_from(G1CardSetCoarsenStats& other);
// Record a coarsening for the given tag/category. Collision should be true if // this coarsening lost the race to do the coarsening of that category. void record_coarsening(uint tag, bool collision);
void print_on(outputStream* out);
};
// Set of card indexes comprising a remembered set on the Java heap. Card // size is assumed to be card table card size. // // Technically it is implemented using a ConcurrentHashTable that stores a card // set container for every region containing at least one card. // // There are in total five different containers, encoded in the ConcurrentHashTable // node as ContainerPtr. A ContainerPtr may cover the whole region or just a part of // it. // See its description below for more information. class G1CardSet : public CHeapObj<mtGCCardSet> { friendclass G1CardSetTest; friendclass G1CardSetMtTestTask; friendclass G1CheckCardClosure;
friendclass G1TransferCard;
friendclass G1ReleaseCardsets;
// When splitting addresses into region and card within that region, the logical // shift value to get the region. static uint _split_card_shift; // When splitting addresses into region and card within that region, the mask // to get the offset within the region. static size_t _split_card_mask;
static G1CardSetCoarsenStats _coarsen_stats; // Coarsening statistics since VM start. static G1CardSetCoarsenStats _last_coarsen_stats; // Coarsening statistics before last GC. public: // Two lower bits are used to encode the card set container types staticconst uintptr_t ContainerPtrHeaderSize = 2;
// ContainerPtr represents the card set container type of a given covered area. // It encodes a type in the LSBs, in addition to having a few significant values. // // Possible encodings: // // 0...00000 free (Empty, should never happen on a top-level ContainerPtr) // 1...11111 full All card indexes in the whole area this ContainerPtr covers are part of this container. // X...XXX00 inline-ptr-cards A handful of card indexes covered by this ContainerPtr are encoded within the ContainerPtr. // X...XXX01 array of cards The container is a contiguous array of card indexes. // X...XXX10 bitmap The container uses a bitmap to determine whether a given index is part of this set. // X...XXX11 howl This is a card set container containing an array of ContainerPtr, with each ContainerPtr // limited to a sub-range of the original range. Currently only one level of this // container is supported. // // The container's pointer starts off with an inline container and is then subsequently // coarsened as more cards are added. // // Coarsening happens in the order below: // ContainerInlinePtr -> ContainerArrayOfCards -> ContainerHowl -> Full // // There is intentionally no bitmap based container that covers a full region; first, // a whole region is covered very well (and more flexibly) using the howl container and // even then the overhead of the ContainerPtr array with all-bitmaps vs. a single bitmap // is negligible, and most importantly transferring such a Howl container to a // "Full Region Bitmap" is fairly hard without missing entries that are added by // concurrent threads. // // Howl containers are basically arrays of containers. An entry starts off with // Free. Further corsening of containers inside the ContainerHowl happens in the order: // // Free -> ContainerInlinePtr -> ContainerArrayOfCards -> ContainerBitMap -> Full // // Throughout the code it is assumed (and checked) that the last two bits of the encoding // for Howl (0b11) is assumed to be the same as the last two bits for "FullCardSet"; this // has been done in various places to not be required to check for a "FullCardSet" first // all the time in iteration code (only if there is a Howl card set container, that is // fairly uncommon). using ContainerPtr = void*; staticconst uintptr_t ContainerInlinePtr = 0x0; staticconst uintptr_t ContainerArrayOfCards = 0x1; staticconst uintptr_t ContainerBitMap = 0x2; staticconst uintptr_t ContainerHowl = 0x3;
// The special sentinel values static constexpr ContainerPtr FreeCardSet = nullptr; // Unfortunately we can't make (G1CardSet::ContainerPtr)-1 constexpr because // reinterpret_casts are forbidden in constexprs. Use a regular static instead. static ContainerPtr FullCardSet;
// Total number of cards in this card set. This is a best-effort value, i.e. there may // be (slightly) more cards in the card set than this value in reality.
size_t _num_occupied;
ContainerPtr acquire_container(ContainerPtr volatile* container_addr); // Returns true if the card set container should be released bool release_container(ContainerPtr container); // Release card set and free if needed. void release_and_maybe_free_container(ContainerPtr container); // Release card set and free (and it must be freeable). void release_and_must_free_container(ContainerPtr container);
// Coarsens the card set container cur_container to the next level; tries to replace the // previous ContainerPtr with a new one which includes the given card_in_region. // coarsen_container does not transfer cards from cur_container // to the new container. Transfer is achieved by transfer_cards. // Returns true if this was the thread that coarsened the container (and added the card). bool coarsen_container(ContainerPtr volatile* container_addr,
ContainerPtr cur_container,
uint card_in_region, bool within_howl = false);
// Transfer entries from source_card_set to a recently installed coarser storage type // We only need to transfer anything finer than ContainerBitMap. "Full" contains // all elements anyway. void transfer_cards(G1CardSetHashTableValue* table_entry, ContainerPtr source_container, uint card_region); void transfer_cards_in_howl(ContainerPtr parent_container, ContainerPtr source_container, uint card_region);
// Iterate over cards of a card set container during transfer of the cards from // one container to another. Executes // // void operator ()(uint card_idx) // // on the given class. template <class CardVisitor> void iterate_cards_during_transfer(ContainerPtr const container, CardVisitor& vl);
// Create a new remembered set for a particular heap region.
G1CardSet(G1CardSetConfiguration* config, G1CardSetMemoryManager* mm); virtual ~G1CardSet();
staticvoid initialize(MemRegion reserved);
// Adds the given card to this set, returning an appropriate result. // If incremental_count is true and the card has been added, updates the total count.
G1AddCardResult add_card(uintptr_t card);
// Returns whether this remembered set (and all sub-sets) have an occupancy // that is less or equal to the given occupancy. bool occupancy_less_or_equal_to(size_t limit) const;
// Returns whether this remembered set (and all sub-sets) does not contain any entry. bool is_empty() const;
// Returns the number of cards contained in this remembered set.
size_t occupied() const;
// Returns size of the actual remembered set containers in bytes.
size_t mem_size() const;
size_t unused_mem_size() const; // Returns the size of static data in bytes. static size_t static_mem_size();
// Clear the entire contents of this remembered set. void clear();
void reset_table_scanner();
// Iterate over the container, calling a method on every card or card range contained // in the card container. // For every container, first calls // // void start_iterate(uint tag, uint region_idx); // // Then for every card or card range it calls // // void do_card(uint card_idx); // void do_card_range(uint card_idx, uint length); // // where card_idx is the card index within that region_idx passed before in // start_iterate(). // template <class CardOrRangeVisitor> void iterate_cards_or_ranges_in_container(ContainerPtr const container, CardOrRangeVisitor& cl);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.