Path: blob/master/runtime/gc_vlhgc/CopyScanCacheListVLHGC.cpp
5986 views
/*******************************************************************************1* Copyright (c) 1991, 2020 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*******************************************************************************/2122#include "j9.h"23#include "j9cfg.h"24#include "j9port.h"2526#include "CopyScanCacheListVLHGC.hpp"27#include "CopyScanCacheChunkVLHGC.hpp"28#include "CopyScanCacheChunkVLHGCInHeap.hpp"29#include "CopyScanCacheVLHGC.hpp"30#include "EnvironmentVLHGC.hpp"31#include "GCExtensions.hpp"32#include "ParallelDispatcher.hpp"3334MM_CopyScanCacheListVLHGC::MM_CopyScanCacheListVLHGC()35: MM_BaseVirtual()36, _sublists(NULL)37, _sublistCount(0)38, _chunkHead(NULL)39, _totalEntryCount(0)40, _containsHeapAllocatedChunks(false)41{42_typeId = __FUNCTION__;43}4445bool46MM_CopyScanCacheListVLHGC::initialize(MM_EnvironmentVLHGC *env)47{48MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);49_sublistCount = extensions->packetListSplit;50Assert_MM_true(0 < _sublistCount);5152UDATA sublistBytes = sizeof(CopyScanCacheSublist) * _sublistCount;53_sublists = (CopyScanCacheSublist *)extensions->getForge()->allocate(sublistBytes, MM_AllocationCategory::FIXED, J9_GET_CALLSITE());54if (NULL == _sublists) {55_sublistCount = 0;56return false;57}5859memset((void *)_sublists, 0, sublistBytes);60for (UDATA i = 0; i < _sublistCount; i++) {61if (!_sublists[i]._cacheLock.initialize(env, &extensions->lnrlOptions, "MM_CopyScanCacheListVLHGC:_sublists[]._cacheLock")) {62return false;63}64}6566return true;67}6869void70MM_CopyScanCacheListVLHGC::tearDown(MM_EnvironmentVLHGC *env)71{72/* Free the memory allocated for the caches */73while (NULL != _chunkHead) {74MM_CopyScanCacheChunkVLHGC *_next = _chunkHead->getNext();75_chunkHead->kill(env);76_chunkHead = _next;77}7879if (NULL != _sublists) {80for (UDATA i = 0; i < _sublistCount; i++) {81_sublists[i]._cacheLock.tearDown();82}83env->getForge()->free(_sublists);84_sublists = NULL;85_sublistCount = 0;86}87}8889bool90MM_CopyScanCacheListVLHGC::appendCacheEntries(MM_EnvironmentVLHGC *env, UDATA cacheEntryCount)91{92CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];93MM_CopyScanCacheChunkVLHGC *chunk = MM_CopyScanCacheChunkVLHGC::newInstance(env, cacheEntryCount, &cacheList->_cacheHead, _chunkHead);94if(NULL != chunk) {95_chunkHead = chunk;96_totalEntryCount += cacheEntryCount;97}9899return NULL != chunk;100}101102bool103MM_CopyScanCacheListVLHGC::resizeCacheEntries(MM_EnvironmentVLHGC *env, UDATA totalCacheEntryCount)104{105MM_GCExtensions *ext = MM_GCExtensions::getExtensions(env);106107/* If -Xgc:fvtest=scanCacheCount has been specified, then restrict the number of scan caches to n.108* Stop all future resizes from having any effect. */109if (0 != ext->fvtest_scanCacheCount) {110if (0 == _totalEntryCount) {111totalCacheEntryCount = ext->fvtest_scanCacheCount;112return appendCacheEntries(env, totalCacheEntryCount);113} else {114return true;115}116}117118if (totalCacheEntryCount > _totalEntryCount) {119/* TODO: consider appending at least by some minimum entry count120* or having total entry count a multiple of let say 16 or so */121return appendCacheEntries(env, totalCacheEntryCount - _totalEntryCount);122}123124/* downsizing is non-trivial with current list/chunk implementation since125* the free caches are scattered across the chunks and cross reference themselves */126127return true;128}129130void131MM_CopyScanCacheListVLHGC::removeAllHeapAllocatedChunks(MM_EnvironmentVLHGC *env)132{133if (_containsHeapAllocatedChunks) {134/* execute if allocation in heap occur this Local GC */135/*136* Walk caches list first to remove all references to heap allocated caches137*/138for (UDATA i = 0; i < _sublistCount; i++) {139CopyScanCacheSublist *cacheList = &_sublists[i];140141MM_CopyScanCacheVLHGC *previousCache = NULL;142MM_CopyScanCacheVLHGC *cache = cacheList->_cacheHead;143144while(cache != NULL) {145if (0 != (cache->flags & J9VM_MODRON_SCAVENGER_CACHE_TYPE_HEAP)) {146/* this cache is heap allocated - remove it from list */147if (NULL == previousCache) {148/* remove first element */149cacheList->_cacheHead = (MM_CopyScanCacheVLHGC *)cache->next;150} else {151/* remove middle element */152previousCache->next = cache->next;153}154} else {155/* not heap allocated - just skip */156previousCache = cache;157}158cache = (MM_CopyScanCacheVLHGC *)cache->next;159}160}161162/*163* Walk caches chunks list and release all heap allocated164*/165MM_CopyScanCacheChunkVLHGC *previousChunk = NULL;166MM_CopyScanCacheChunkVLHGC *chunk = _chunkHead;167168while(chunk != NULL) {169MM_CopyScanCacheChunkVLHGC *nextChunk = chunk->getNext();170171if (0 != (chunk->getBase()->flags & J9VM_MODRON_SCAVENGER_CACHE_TYPE_HEAP)) {172/* this chunk is heap allocated - remove it from list */173if (NULL == previousChunk) {174/* still be a first element */175_chunkHead = nextChunk;176} else {177/* remove middle element */178previousChunk->setNext(nextChunk);179}180181/* release heap allocated chunk */182chunk->kill(env);183184} else {185/* not heap allocated - just skip */186previousChunk = chunk;187}188chunk = nextChunk;189}190191/* clear flag - no more heap allocated caches */192_containsHeapAllocatedChunks = false;193}194}195196MM_CopyScanCacheVLHGC *197MM_CopyScanCacheListVLHGC::allocateCacheEntriesInExistingMemory(MM_EnvironmentVLHGC *env, void *buffer, UDATA bufferLengthInBytes)198{199CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];200MM_CopyScanCacheVLHGC * result = NULL;201MM_CopyScanCacheChunkVLHGCInHeap *chunk = MM_CopyScanCacheChunkVLHGCInHeap::newInstance(env, buffer, bufferLengthInBytes, &cacheList->_cacheHead, _chunkHead);202if (NULL != chunk) {203_chunkHead = chunk;204_containsHeapAllocatedChunks = true;205206result = popCacheInternal(env, cacheList);207Assert_MM_true(NULL != result);208}209return result;210}211212void213MM_CopyScanCacheListVLHGC::lock()214{215for (UDATA i = 0; i < _sublistCount; ++i) {216_sublists[i]._cacheLock.acquire();217}218}219220void221MM_CopyScanCacheListVLHGC::unlock()222{223for (UDATA i = 0; i < _sublistCount; ++i) {224_sublists[i]._cacheLock.release();225}226}227228void229MM_CopyScanCacheListVLHGC::pushCacheInternal(MM_EnvironmentVLHGC *env, MM_CopyScanCacheVLHGC *cacheEntry, CopyScanCacheSublist* sublist)230{231Assert_MM_true(NULL != cacheEntry);232Assert_MM_true(NULL == cacheEntry->next);233234MM_CopyScanCacheVLHGC *oldCacheEntry = sublist->_cacheHead;235cacheEntry->next = oldCacheEntry;236sublist->_cacheHead = cacheEntry;237}238239MM_CopyScanCacheVLHGC *240MM_CopyScanCacheListVLHGC::popCacheInternal(MM_EnvironmentVLHGC *env, CopyScanCacheSublist* sublist)241{242MM_CopyScanCacheVLHGC *cache = sublist->_cacheHead;243if (NULL != cache) {244sublist->_cacheHead = (MM_CopyScanCacheVLHGC *)cache->next;245cache->next = NULL;246}247return cache;248}249250251void252MM_CopyScanCacheListVLHGC::pushCacheNoLock(MM_EnvironmentVLHGC *env, MM_CopyScanCacheVLHGC *cacheEntry)253{254CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];255pushCacheInternal(env, cacheEntry, cacheList);256}257258void259MM_CopyScanCacheListVLHGC::pushCache(MM_EnvironmentVLHGC *env, MM_CopyScanCacheVLHGC *cacheEntry)260{261CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];262cacheList->_cacheLock.acquire();263pushCacheInternal(env, cacheEntry, cacheList);264cacheList->_cacheLock.release();265}266267MM_CopyScanCacheVLHGC *268MM_CopyScanCacheListVLHGC::popCacheNoLock(MM_EnvironmentVLHGC *env)269{270UDATA indexStart = getSublistIndex(env);271MM_CopyScanCacheVLHGC *cache = NULL;272273for (UDATA i = 0; (i < _sublistCount) && (NULL == cache); ++i) {274UDATA index = (i + indexStart) % _sublistCount;275CopyScanCacheSublist *cacheList = &_sublists[index];276cache = popCacheInternal(env, cacheList);277}278279return cache;280}281282MM_CopyScanCacheVLHGC *283MM_CopyScanCacheListVLHGC::popCache(MM_EnvironmentVLHGC *env)284{285UDATA indexStart = getSublistIndex(env);286MM_CopyScanCacheVLHGC *cache = NULL;287for (UDATA i = 0; (i < _sublistCount) && (NULL == cache); ++i) {288UDATA index = (i + indexStart) % _sublistCount;289CopyScanCacheSublist *cacheList = &_sublists[index];290if (NULL != cacheList->_cacheHead) {291cacheList->_cacheLock.acquire();292cache = popCacheInternal(env, cacheList);293cacheList->_cacheLock.release();294}295}296return cache;297}298299bool300MM_CopyScanCacheListVLHGC::isEmpty()301{302MM_CopyScanCacheVLHGC *cache = NULL;303for (UDATA i = 0; (i < _sublistCount) && (NULL == cache); ++i) {304cache = _sublists[i]._cacheHead;305}306return NULL == cache;307}308309UDATA310MM_CopyScanCacheListVLHGC::countCaches()311{312UDATA count = 0;313for (UDATA i = 0; i < _sublistCount; ++i) {314MM_CopyScanCacheVLHGC *cache = _sublists[i]._cacheHead;315while (NULL != cache) {316count++;317cache = (MM_CopyScanCacheVLHGC *)cache->next;318}319}320return count;321}322323324