Path: blob/master/runtime/gc_vlhgc/AllocationContextBalanced.hpp
5986 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/212223/**24* @file25* @ingroup GC_Modron_Base26*/2728#if !defined(ALLOCATIONCONTEXTBALANCED_HPP_)29#define ALLOCATIONCONTEXTBALANCED_HPP_3031#include "j9.h"32#include "j9cfg.h"33#include "j9protos.h"34#include "modronopt.h"3536#include "AllocationContextTarok.hpp"37#include "LightweightNonReentrantLock.hpp"38#include "RegionListTarok.hpp"3940class MM_AllocateDescription;41class MM_AllocationContextMultiTenant;42class MM_EnvironmentBase;43class MM_MemorySubSpaceTarok;444546class MM_AllocationContextBalanced : public MM_AllocationContextTarok47{48/* Data members / Types */49public:50protected:51private:52MM_LightweightNonReentrantLock _contextLock; /**< protects updates to the context's region cache */53MM_LightweightNonReentrantLock _freeListLock; /**< protects updates to the context's free list (managed distinctly from the rest of the context to support region stealing */54MM_MemorySubSpaceTarok *_subspace; /**< the subspace from which this context allocates and refreshes itself */55MM_HeapRegionDescriptorVLHGC *_allocationRegion; /**< The region currently satisfying allocations within this context - also the most recently replenished/stolen region in this context */56MM_RegionListTarok _nonFullRegions; /**< Regions which failed to satisfy a large object allocation but which are not yet full. The _allocationRegion is added to this list when it fails to satisfy an object allocation but this list will quickly be consumed by TLH allocation requests which can soak up all remaining space. This list is consulted after _allocationRegion but before replenishment or theft. */57MM_RegionListTarok _discardRegionList; /**< The list of MPAOL regions currently privately owned by this context but either too full or too fragmented to be used to satisfy allocations. These regions must be flushed back to the subspace before a collection */58MM_RegionListTarok _flushedRegions; /**< The list of MPAOL regions which have been flushed from active use, for a GC, and have unknown stats (at any point after the GC, however, these regions could all be migrated to _ownedRegions) */59MM_RegionListTarok _freeRegions; /**< The list regions which are owned by this context but currently marked as FREE */60MM_RegionListTarok _idleMPRegions; /**< The list regions which are owned by this context, currently marked as ADDRESS_ORDERED_IDLE, but contain no objects (this also implies that they can migrate to other contexts on this node, for free, since the receiver isn't using them) */61UDATA _freeMemorySize; /**< The amount of free memory currently managed by the context in the _ownedRegions list only (note that dark matter and small holes are not considered free memory). This value is always accurate (that is, there is no time when it becomes out of sync with the actual amount of free memory managed by the context). */62UDATA _regionCount[MM_HeapRegionDescriptor::LAST_REGION_TYPE]; /**< Count of regions that are owned by this AC (accurate only for TGC purposes) */63UDATA _threadCount;/**< Count of mutator threads that allocate from this AC (accurate only for TGC purposes) */64UDATA _numaNode; /**< the NUMA node this context is associated with, or 0 if none */65MM_AllocationContextBalanced *_nextSibling; /**< Instances of the receiver are built into a circular linked-list. This points to the next adjacent downstream neighbour in this list (may be pointing to this if there is only one context in the node) */66MM_AllocationContextBalanced *_cachedReplenishPoint; /**< The sibling context which most recently replenished the receiver */67MM_AllocationContextBalanced *_stealingCousin; /**< A context in the "next" node which the receiver will use for spilling memory requests across NUMA nodes. Points back at the receiver if this is non-NUMA */68MM_AllocationContextBalanced *_nextToSteal; /**< A pointer to the next context we will try to steal from (we steal in a round-robin to try to distribute the heap's asymmetry). Points back at the receiver if this is non-NUMA */69MM_HeapRegionManager *_heapRegionManager; /**< A cached pointer to the HeapRegionManager */70UDATA *_freeProcessorNodes; /**< The array listing all the NUMA node numbers which account for the nodes with processors but no memory plus an empty slot for each context to use (element 0 is used by this context) - this is used when setting affinity */71UDATA _freeProcessorNodeCount; /**< The length, in elements, of the _freeProcessorNodes array (always at least 1 after startup) */7273/* Methods */74public:75static MM_AllocationContextBalanced *newInstance(MM_EnvironmentBase *env, MM_MemorySubSpaceTarok *subspace, UDATA numaNode, UDATA allocationContextNumber);76virtual void flush(MM_EnvironmentBase *env);77virtual void flushForShutdown(MM_EnvironmentBase *env);7879/**80* Ideally, this would only be understood by sub-classes which know about TLH allocation but we will use runtime assertions to ensure this is safe, for now81*/82virtual void *allocateTLH(MM_EnvironmentBase *env, MM_AllocateDescription *allocateDescription, MM_ObjectAllocationInterface *objectAllocationInterface, bool shouldCollectOnFailure);83virtual void *allocateObject(MM_EnvironmentBase *env, MM_AllocateDescription *allocateDescription, bool shouldCollectOnFailure);84virtual void *allocateArrayletLeaf(MM_EnvironmentBase *env, MM_AllocateDescription *allocateDescription, bool shouldCollectOnFailure);8586/**87* Acquire a new region to be placed in the active set of regions from which to allocate.88* @param env GC thread.89* @return A region descriptor that has been acquired and put into the active to be consumed from rotation.90* @note This will immediately move the acquired region from _ownedRegions to _flushedRegions91*/92virtual MM_HeapRegionDescriptorVLHGC *collectorAcquireRegion(MM_EnvironmentBase *env);9394/**95* @See MM_AllocationContext::allocate96*/97virtual void *allocate(MM_EnvironmentBase *env, MM_ObjectAllocationInterface *objectAllocationInterface, MM_AllocateDescription *allocateDescription, MM_MemorySubSpace::AllocationType allocationType);9899/**100* Perform an allocate of the given allocationType and return it. Note that the receiver can assume that either the context is locked or the calling thread has exclusive.101*102* @param[in] env The calling thread103* @param[in] objectAllocationInterface The allocation interface through which the original allocation call was initiated (only used by TLH allocations, can be NULL in other cases)104* @param[in] allocateDescription The description of the requested allocation105* @param[in] allocationType The type of allocation to perform106*107* @return The result of the allocation (NULL on failure)108*/109virtual void *lockedAllocate(MM_EnvironmentBase *env, MM_ObjectAllocationInterface *objectAllocationInterface, MM_AllocateDescription *allocateDescription, MM_MemorySubSpace::AllocationType allocationType);110111/**112* Called when the given region has been deemed empty, but is not a FREE region. The receiver is responsible for changing the region type and ensuring that it is appropriately stored.113* @param env[in] The calling thread (typically the main GC thread)114* @param region[in] The region to recycle115*/116virtual void recycleRegion(MM_EnvironmentVLHGC *env, MM_HeapRegionDescriptorVLHGC *region);117118/**119* Called during tear down of a subspace to discard any regions which comprise the subspace.120* The region should be FREE (not IDLE!) on completion of this call.121* @param env[in] The calling thread (typically the main GC thread)122* @param region[in] The region to tear down123*/124virtual void tearDownRegion(MM_EnvironmentBase *env, MM_HeapRegionDescriptorVLHGC *region);125126/**127* Called during both expansion and during region recycling (if the region was owned by this context, it will come through this path when128* recycled). This method can only accept FREE regions.129* @param env[in] The thread which expanded the region or recycled it130* @param region[in] The region which should be added to our free list131*/132virtual void addRegionToFreeList(MM_EnvironmentBase *env, MM_HeapRegionDescriptorVLHGC *region);133134/**135* Reset region count, used by TGC136* @param regionType type of the region that we reset the count for137*/138virtual void resetRegionCount(MM_HeapRegionDescriptor::RegionType regionType) { _regionCount[regionType] = 0; }139/**140* Increment region count, used by TGC141* @param regionType type of the region that we update the count for142*/143virtual void incRegionCount(MM_HeapRegionDescriptor::RegionType regionType) { _regionCount[regionType] += 1; }144145/**146* Return the region count associated with this AC, used by TGC147* @param regionType type of the region that we get the count for148* @return region count149*/150virtual UDATA getRegionCount(MM_HeapRegionDescriptor::RegionType regionType) { return _regionCount[regionType]; }151/**152* Reset mutator count, used by TGC153*/154virtual void resetThreadCount() { _threadCount = 0; }155156/**157* Increment mutator count, used by TGC158*/159virtual void incThreadCount() { _threadCount += 1; }160161/**162* Return the mutator count associated with this AC, used by TGC163*164* @return mutator count165*/166virtual UDATA getThreadCount() { return _threadCount; }167168/**169* Return the NUMA node with which this AC is associated, or 0 if none170*171* @return associated NUMA node172*/173virtual UDATA getNumaNode() { return _numaNode; }174175/**176* Return the amount of free memory currently managed by the context. This value is always accurate (that is, there is no time when it becomes177* out of sync with the actual amount of free memory managed by the context).178*179* @return The free memory managed by the receiver, in bytes.180*/181virtual UDATA getFreeMemorySize();182183/**184* Return the number of free (empty) regions currently managed by the context. This value is always accurate (that is, there is no time when it becomes185* out of sync with the actual number of regions managed by the context).186*187* @return The count of free regions managed by the receiver.188*/189virtual UDATA getFreeRegionCount();190191/**192* Sets the downstream sibling in the circularly linked-list of contexts on a given node.193* @param sibling[in] The next downstream neighbour in the list (might be this if there is only one context on the node)194*/195void setNextSibling(MM_AllocationContextBalanced *sibling);196197/**198* @return The next region in the circular linked list of contexts on this node (could be this if there is only one context on the node)199*/200MM_AllocationContextBalanced *getNextSibling() { return _nextSibling; }201202/**203* Sets the _stealingCousin instance variable (can only be called once!).204* @param cousin[in] The context onto which the receiver will spill failed allocates within its node (must not be NULL)205*/206void setStealingCousin(MM_AllocationContextBalanced *cousin);207208/**209* @return The first context onto which the receiver will spill allocation failures within its own node210*/211MM_AllocationContextBalanced *getStealingCousin() { return _stealingCousin; }212213/**214* Called to reset the largest free entry in all the MemoryPoolBumpPointer instances in the regions managed by the receiver.215*/216virtual void resetLargestFreeEntry();217218/**219* @return The largest free entry out of all the pools managed by the receiver.220*/221virtual UDATA getLargestFreeEntry();222223/**224* Called to move the given region directly from the receiver and into the target context instance. Note that this method can only225* be called in one thread on any instance since it directly manipulates lists across contexts. The caller is responsible for226* ensuring that these threading semantics are preserved.227* @param region[in] The region to migrate from the receiver228* @param newOwner[in] The context to which the given region is being migrated229*/230virtual void migrateRegionToAllocationContext(MM_HeapRegionDescriptorVLHGC *region, MM_AllocationContextTarok *newOwner);231232/**233* Called by migrateRegionToAllocationContext on the target context receiving the migrated region.234* The receiver will insert the migrated context in its list.235*236* @param region[in] The region to accept237*/238virtual void acceptMigratingRegion(MM_HeapRegionDescriptorVLHGC *region);239240/**241* This helper merely forwards the resetHeapStatistics call on to all the memory pools owned by the receiver.242* @param globalCollect[in] True if this was a global collect (blindly passed through)243*/244virtual void resetHeapStatistics(bool globalCollect);245246/**247* This helper merely forwards the mergeHeapStats call on to all the memory pools owned by the receiver.248* @param heapStats[in/out] The stats structure to receive the merged data (blindly passed through)249* @param includeMemoryType[in] The memory space type to use in the merge (blindly passed through)250*/251virtual void mergeHeapStats(MM_HeapStats *heapStats, UDATA includeMemoryType);252253/**254* Used by TGC to get the count of regions owned by this context. Differentiates between regions node-local to the context and node-foreign.255* @param localCount[out] The number of regions owned by the receiver which are bound to the node in which the receiver logically operates256* @param foreignCount[out] The number of regions owned by the receiver which are NOT bound to the node in which the receiver logically operates257*/258virtual void getRegionCount(UDATA *localCount, UDATA *foreignCount);259260/**261* Remove the specified region from the flushed regions list.262*263* @param region[in] The region to remove from the list264*/265virtual void removeRegionFromFlushedList(MM_HeapRegionDescriptorVLHGC *region);266267/**268* @See MM_AllocationContextTarok::setNumaAffinityForThread269*/270virtual bool setNumaAffinityForThread(MM_EnvironmentBase *env);271272273protected:274virtual void tearDown(MM_EnvironmentBase *env);275bool initialize(MM_EnvironmentBase *env);276MM_AllocationContextBalanced(MM_MemorySubSpaceTarok *subspace, UDATA numaNode, UDATA allocationContextNumber)277: MM_AllocationContextTarok(allocationContextNumber, MM_AllocationContextTarok::BALANCED)278, _subspace(subspace)279, _allocationRegion(NULL)280, _nonFullRegions()281, _discardRegionList()282, _flushedRegions()283, _freeRegions()284, _idleMPRegions()285, _freeMemorySize(0)286, _threadCount(0)287, _numaNode(numaNode)288, _nextSibling(NULL)289, _cachedReplenishPoint(NULL)290, _stealingCousin(NULL)291, _nextToSteal(NULL)292, _heapRegionManager(NULL)293, _freeProcessorNodes(NULL)294, _freeProcessorNodeCount(0)295{296_typeId = __FUNCTION__;297}298299virtual void *lockedReplenishAndAllocate(MM_EnvironmentBase *env, MM_ObjectAllocationInterface *objectAllocationInterface, MM_AllocateDescription *allocateDescription, MM_MemorySubSpace::AllocationType allocationType);300virtual MM_HeapRegionDescriptorVLHGC * selectRegionForContraction(MM_EnvironmentBase *env);301302private:303304/**305* Locks the "common" _contextLock (as opposed to the _freeListLock).306*/307void lockCommon();308/**309* Locks the "common" _contextLock (as opposed to the _freeListLock).310*/311void unlockCommon();312313/**314* Tries to acquire an MPAOL region from the receiver (either from an existing, but idle, ADDRESS_ORDERED or by converting a free region).315* If the receiver does not have a valid candidate it will check its siblings and cousins for one.316* The region that this method returns will have been removed from the receiver's management and its owning context is set to requestingContext.317*318* @note Caller must hold this context's @ref _contextLock319*320* @param env[in] The thread attempting the allocation321* @param subspace[in] The subSpace to which the allocated pool must be attached322* @param requestingContext[in] The context requesting a region from the receiver323* @return The region or NULL if there were none available in the heap324*/325MM_HeapRegionDescriptorVLHGC *acquireMPRegionFromHeap(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, MM_AllocationContextTarok *requestingContext);326327/**328* Tries to acquire a FREE region from the receiver (either from an existing FREE region or by converting an idle region).329* If the receiver does not have a valid candidate it will check its siblings and cousins for one.330* The region that this method returns will have been removed from the receiver's management and its owning context is set to requestingContext.331*332* @note Caller must hold this context's @ref _contextLock333*334* @param env[in] The thread attempting the allocation335* @return The region or NULL if there were none available in the heap336*/337MM_HeapRegionDescriptorVLHGC *acquireFreeRegionFromHeap(MM_EnvironmentBase *env);338339/**340* Returns a region descriptor of ADDRESS_ORDERED type on the node where the receiver is resident. The region may not have been found341* in the receiver (it may have been managed by a sibling) but it will be placed under the management of the given requestingContext342* before this call returns.343* @note The caller must own the receiver's _contextLock344* @param env[in] The thread requesting the region345* @param subSpace[in] The subSpace to which the allocated pool must be attached346* @param requestingContext[in] The context which is requesting the region and asking this context to search its node347* @return A region of type ADDRESS_ORDERED (or NULL if no ADDRESS_ORDERED regions could be found or created on the receiver's node)348*/349MM_HeapRegionDescriptorVLHGC *acquireMPRegionFromNode(MM_EnvironmentBase *env, MM_MemorySubSpace *subSpace, MM_AllocationContextTarok *requestingContext);350351/**352* Returns a region descriptor of FREE type on the node where the receiver is resident. The region may not have been found in the353* receiver (it may have been managed by a sibling) but it will not be under any context's management, when it is returned and the354* caller accepts responsibility for managing it.355* @note The caller must own the receiver's _contextLock356* @param env[in] The thread requesting the free region357* @return A region of type FREE (or NULL if no FREE regions could be found or created on the receiver's node)358*/359MM_HeapRegionDescriptorVLHGC *acquireFreeRegionFromNode(MM_EnvironmentBase *env);360361/**362* Tries to acquire an MPAOL region from the receiver (either from an existing, but idle, ADDRESS_ORDERED or by converting a free region).363* The region that this method returns will have been removed from the receiver's management and its owning context is set to requestingContext.364*365* @param env[in] The thread attempting the allocation366* @param subSpace[in] The subSpace to which the allocated pool must be attached367* @param requestingContext[in] The context requesting a region from the receiver368* @return The region or NULL if there were none available in the receiver369*/370MM_HeapRegionDescriptorVLHGC *acquireMPRegionFromContext(MM_EnvironmentBase *env, MM_MemorySubSpace *subSpace, MM_AllocationContextTarok *requestingContext);371372/**373* Tries to acquire a FREE region from the receiver (either from an existing FREE region or by converting an idle region).374* The region that this method returns will have been removed from the receiver's management and its owning context is set to requestingContext.375*376* @param env[in] The thread attempting the allocation377* @return The region or NULL if there were none available in the receiver378*/379MM_HeapRegionDescriptorVLHGC *acquireFreeRegionFromContext(MM_EnvironmentBase *env);380381/**382* Perform a TLH allocation. Note that the receiver can assume that either the context is locked or the calling thread has exclusive.383*384* @param[in] env The calling thread385* @param[in] allocateDescription The allocation to perform386* @param[in] objectAllocationInterface The interface through which the allocation request was initiated (required to initialize the TLH)387*388* @return The base pointer of the allocated TLH (or NULL, if the allocation failed)389*/390void *lockedAllocateTLH(MM_EnvironmentBase *env, MM_AllocateDescription *allocateDescription, MM_ObjectAllocationInterface *objectAllocationInterface);391/**392* Allocate an object. Note that the receiver can assume that either the context is locked or the calling thread has exclusive.393*394* @param[in] env The calling thread395* @param[in] allocateDescription The allocation to perform396*397* @return The address of the allocated object (or NULL, if the allocation failed)398*/399void *lockedAllocateObject(MM_EnvironmentBase *env, MM_AllocateDescription *allocateDescription);400401/**402* Allocate an arraylet leaf. Note that the receiver can assume that either the context is locked or the calling thread has exclusive.403* NOTE: The returned arraylet leaf is UNINITIALIZED MEMORY (since it can't be zeroed under lock) so the caller must zero it before it404* can be seen by the collector or user code.405*406* @param[in] env The calling thread407* @param[in] allocateDescription The allocation to perform408* @param[in] freeRegionForArrayletLeaf The region to use for the allocation409*410* @return The address of the leaf411*/412void *lockedAllocateArrayletLeaf(MM_EnvironmentBase *env, MM_AllocateDescription *allocateDescription, MM_HeapRegionDescriptorVLHGC *freeRegionForArrayletLeaf);413414/**415* Common implementation for flush() and flushForShutdown()416*/417void flushInternal(MM_EnvironmentBase *env);418419/**420* Replenishes the receiver's active region list. Called by lockedReplenishAndAllocate in the cases where we aren't allocating a leaf.421* @note The calling env must own the receiver's _contextLock or have exclusive VM access422*423* @param env[in] A GC thread (must own either _contextLock or have exclusive access)424* @param payTax Flag indicating whether taxation restrictions should apply425* @return region descriptor that was used to replenish the active region, or NULL if no descriptor was found.426*/427MM_HeapRegionDescriptorVLHGC *internalReplenishActiveRegion(MM_EnvironmentBase *env, bool payTax);428429/**430* A helper which increments the given count of local and foreign regions based on the location of the given region.431* A region is considered "local" if it is bound to the node managed by the receiver.432* @param region[in] A region to check433* @param localCount[in/out] The number of regions owned by the receiver which are bound to the node in which the receiver logically operates434* @param foreignCount[in/out] The number of regions owned by the receiver which are NOT bound to the node in which the receiver logically operates435*/436void accountForRegionLocation(MM_HeapRegionDescriptorVLHGC *region, UDATA *localCount, UDATA *foreignCount);437438/**439* A helper counts the regions in a specific region list and differentiates between node-local and node-foreign regions440* @param localCount[out] The number of regions owned by the receiver which are bound to the node in which the receiver logically operates441* @param foreignCount[out] The number of regions owned by the receiver which are NOT bound to the node in which the receiver logically operates442*/443void countRegionsInList(MM_RegionListTarok *list, UDATA *localCount, UDATA *foreignCount);444445/**446* Helper for collectorAcquireRegion447* @param env The current GC thread.448* @return A region descriptor that has been acquired and put into the active to be consumed from rotation.449*/450MM_HeapRegionDescriptorVLHGC *internalCollectorAcquireRegion(MM_EnvironmentBase *env);451452};453454#endif /* ALLOCATIONCONTEXTBALANCED_HPP_ */455456457