Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_vlhgc/CopyScanCacheListVLHGC.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2020 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#include "j9.h"
24
#include "j9cfg.h"
25
#include "j9port.h"
26
27
#include "CopyScanCacheListVLHGC.hpp"
28
#include "CopyScanCacheChunkVLHGC.hpp"
29
#include "CopyScanCacheChunkVLHGCInHeap.hpp"
30
#include "CopyScanCacheVLHGC.hpp"
31
#include "EnvironmentVLHGC.hpp"
32
#include "GCExtensions.hpp"
33
#include "ParallelDispatcher.hpp"
34
35
MM_CopyScanCacheListVLHGC::MM_CopyScanCacheListVLHGC()
36
: MM_BaseVirtual()
37
, _sublists(NULL)
38
, _sublistCount(0)
39
, _chunkHead(NULL)
40
, _totalEntryCount(0)
41
, _containsHeapAllocatedChunks(false)
42
{
43
_typeId = __FUNCTION__;
44
}
45
46
bool
47
MM_CopyScanCacheListVLHGC::initialize(MM_EnvironmentVLHGC *env)
48
{
49
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
50
_sublistCount = extensions->packetListSplit;
51
Assert_MM_true(0 < _sublistCount);
52
53
UDATA sublistBytes = sizeof(CopyScanCacheSublist) * _sublistCount;
54
_sublists = (CopyScanCacheSublist *)extensions->getForge()->allocate(sublistBytes, MM_AllocationCategory::FIXED, J9_GET_CALLSITE());
55
if (NULL == _sublists) {
56
_sublistCount = 0;
57
return false;
58
}
59
60
memset((void *)_sublists, 0, sublistBytes);
61
for (UDATA i = 0; i < _sublistCount; i++) {
62
if (!_sublists[i]._cacheLock.initialize(env, &extensions->lnrlOptions, "MM_CopyScanCacheListVLHGC:_sublists[]._cacheLock")) {
63
return false;
64
}
65
}
66
67
return true;
68
}
69
70
void
71
MM_CopyScanCacheListVLHGC::tearDown(MM_EnvironmentVLHGC *env)
72
{
73
/* Free the memory allocated for the caches */
74
while (NULL != _chunkHead) {
75
MM_CopyScanCacheChunkVLHGC *_next = _chunkHead->getNext();
76
_chunkHead->kill(env);
77
_chunkHead = _next;
78
}
79
80
if (NULL != _sublists) {
81
for (UDATA i = 0; i < _sublistCount; i++) {
82
_sublists[i]._cacheLock.tearDown();
83
}
84
env->getForge()->free(_sublists);
85
_sublists = NULL;
86
_sublistCount = 0;
87
}
88
}
89
90
bool
91
MM_CopyScanCacheListVLHGC::appendCacheEntries(MM_EnvironmentVLHGC *env, UDATA cacheEntryCount)
92
{
93
CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];
94
MM_CopyScanCacheChunkVLHGC *chunk = MM_CopyScanCacheChunkVLHGC::newInstance(env, cacheEntryCount, &cacheList->_cacheHead, _chunkHead);
95
if(NULL != chunk) {
96
_chunkHead = chunk;
97
_totalEntryCount += cacheEntryCount;
98
}
99
100
return NULL != chunk;
101
}
102
103
bool
104
MM_CopyScanCacheListVLHGC::resizeCacheEntries(MM_EnvironmentVLHGC *env, UDATA totalCacheEntryCount)
105
{
106
MM_GCExtensions *ext = MM_GCExtensions::getExtensions(env);
107
108
/* If -Xgc:fvtest=scanCacheCount has been specified, then restrict the number of scan caches to n.
109
* Stop all future resizes from having any effect. */
110
if (0 != ext->fvtest_scanCacheCount) {
111
if (0 == _totalEntryCount) {
112
totalCacheEntryCount = ext->fvtest_scanCacheCount;
113
return appendCacheEntries(env, totalCacheEntryCount);
114
} else {
115
return true;
116
}
117
}
118
119
if (totalCacheEntryCount > _totalEntryCount) {
120
/* TODO: consider appending at least by some minimum entry count
121
* or having total entry count a multiple of let say 16 or so */
122
return appendCacheEntries(env, totalCacheEntryCount - _totalEntryCount);
123
}
124
125
/* downsizing is non-trivial with current list/chunk implementation since
126
* the free caches are scattered across the chunks and cross reference themselves */
127
128
return true;
129
}
130
131
void
132
MM_CopyScanCacheListVLHGC::removeAllHeapAllocatedChunks(MM_EnvironmentVLHGC *env)
133
{
134
if (_containsHeapAllocatedChunks) {
135
/* execute if allocation in heap occur this Local GC */
136
/*
137
* Walk caches list first to remove all references to heap allocated caches
138
*/
139
for (UDATA i = 0; i < _sublistCount; i++) {
140
CopyScanCacheSublist *cacheList = &_sublists[i];
141
142
MM_CopyScanCacheVLHGC *previousCache = NULL;
143
MM_CopyScanCacheVLHGC *cache = cacheList->_cacheHead;
144
145
while(cache != NULL) {
146
if (0 != (cache->flags & J9VM_MODRON_SCAVENGER_CACHE_TYPE_HEAP)) {
147
/* this cache is heap allocated - remove it from list */
148
if (NULL == previousCache) {
149
/* remove first element */
150
cacheList->_cacheHead = (MM_CopyScanCacheVLHGC *)cache->next;
151
} else {
152
/* remove middle element */
153
previousCache->next = cache->next;
154
}
155
} else {
156
/* not heap allocated - just skip */
157
previousCache = cache;
158
}
159
cache = (MM_CopyScanCacheVLHGC *)cache->next;
160
}
161
}
162
163
/*
164
* Walk caches chunks list and release all heap allocated
165
*/
166
MM_CopyScanCacheChunkVLHGC *previousChunk = NULL;
167
MM_CopyScanCacheChunkVLHGC *chunk = _chunkHead;
168
169
while(chunk != NULL) {
170
MM_CopyScanCacheChunkVLHGC *nextChunk = chunk->getNext();
171
172
if (0 != (chunk->getBase()->flags & J9VM_MODRON_SCAVENGER_CACHE_TYPE_HEAP)) {
173
/* this chunk is heap allocated - remove it from list */
174
if (NULL == previousChunk) {
175
/* still be a first element */
176
_chunkHead = nextChunk;
177
} else {
178
/* remove middle element */
179
previousChunk->setNext(nextChunk);
180
}
181
182
/* release heap allocated chunk */
183
chunk->kill(env);
184
185
} else {
186
/* not heap allocated - just skip */
187
previousChunk = chunk;
188
}
189
chunk = nextChunk;
190
}
191
192
/* clear flag - no more heap allocated caches */
193
_containsHeapAllocatedChunks = false;
194
}
195
}
196
197
MM_CopyScanCacheVLHGC *
198
MM_CopyScanCacheListVLHGC::allocateCacheEntriesInExistingMemory(MM_EnvironmentVLHGC *env, void *buffer, UDATA bufferLengthInBytes)
199
{
200
CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];
201
MM_CopyScanCacheVLHGC * result = NULL;
202
MM_CopyScanCacheChunkVLHGCInHeap *chunk = MM_CopyScanCacheChunkVLHGCInHeap::newInstance(env, buffer, bufferLengthInBytes, &cacheList->_cacheHead, _chunkHead);
203
if (NULL != chunk) {
204
_chunkHead = chunk;
205
_containsHeapAllocatedChunks = true;
206
207
result = popCacheInternal(env, cacheList);
208
Assert_MM_true(NULL != result);
209
}
210
return result;
211
}
212
213
void
214
MM_CopyScanCacheListVLHGC::lock()
215
{
216
for (UDATA i = 0; i < _sublistCount; ++i) {
217
_sublists[i]._cacheLock.acquire();
218
}
219
}
220
221
void
222
MM_CopyScanCacheListVLHGC::unlock()
223
{
224
for (UDATA i = 0; i < _sublistCount; ++i) {
225
_sublists[i]._cacheLock.release();
226
}
227
}
228
229
void
230
MM_CopyScanCacheListVLHGC::pushCacheInternal(MM_EnvironmentVLHGC *env, MM_CopyScanCacheVLHGC *cacheEntry, CopyScanCacheSublist* sublist)
231
{
232
Assert_MM_true(NULL != cacheEntry);
233
Assert_MM_true(NULL == cacheEntry->next);
234
235
MM_CopyScanCacheVLHGC *oldCacheEntry = sublist->_cacheHead;
236
cacheEntry->next = oldCacheEntry;
237
sublist->_cacheHead = cacheEntry;
238
}
239
240
MM_CopyScanCacheVLHGC *
241
MM_CopyScanCacheListVLHGC::popCacheInternal(MM_EnvironmentVLHGC *env, CopyScanCacheSublist* sublist)
242
{
243
MM_CopyScanCacheVLHGC *cache = sublist->_cacheHead;
244
if (NULL != cache) {
245
sublist->_cacheHead = (MM_CopyScanCacheVLHGC *)cache->next;
246
cache->next = NULL;
247
}
248
return cache;
249
}
250
251
252
void
253
MM_CopyScanCacheListVLHGC::pushCacheNoLock(MM_EnvironmentVLHGC *env, MM_CopyScanCacheVLHGC *cacheEntry)
254
{
255
CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];
256
pushCacheInternal(env, cacheEntry, cacheList);
257
}
258
259
void
260
MM_CopyScanCacheListVLHGC::pushCache(MM_EnvironmentVLHGC *env, MM_CopyScanCacheVLHGC *cacheEntry)
261
{
262
CopyScanCacheSublist *cacheList = &_sublists[getSublistIndex(env)];
263
cacheList->_cacheLock.acquire();
264
pushCacheInternal(env, cacheEntry, cacheList);
265
cacheList->_cacheLock.release();
266
}
267
268
MM_CopyScanCacheVLHGC *
269
MM_CopyScanCacheListVLHGC::popCacheNoLock(MM_EnvironmentVLHGC *env)
270
{
271
UDATA indexStart = getSublistIndex(env);
272
MM_CopyScanCacheVLHGC *cache = NULL;
273
274
for (UDATA i = 0; (i < _sublistCount) && (NULL == cache); ++i) {
275
UDATA index = (i + indexStart) % _sublistCount;
276
CopyScanCacheSublist *cacheList = &_sublists[index];
277
cache = popCacheInternal(env, cacheList);
278
}
279
280
return cache;
281
}
282
283
MM_CopyScanCacheVLHGC *
284
MM_CopyScanCacheListVLHGC::popCache(MM_EnvironmentVLHGC *env)
285
{
286
UDATA indexStart = getSublistIndex(env);
287
MM_CopyScanCacheVLHGC *cache = NULL;
288
for (UDATA i = 0; (i < _sublistCount) && (NULL == cache); ++i) {
289
UDATA index = (i + indexStart) % _sublistCount;
290
CopyScanCacheSublist *cacheList = &_sublists[index];
291
if (NULL != cacheList->_cacheHead) {
292
cacheList->_cacheLock.acquire();
293
cache = popCacheInternal(env, cacheList);
294
cacheList->_cacheLock.release();
295
}
296
}
297
return cache;
298
}
299
300
bool
301
MM_CopyScanCacheListVLHGC::isEmpty()
302
{
303
MM_CopyScanCacheVLHGC *cache = NULL;
304
for (UDATA i = 0; (i < _sublistCount) && (NULL == cache); ++i) {
305
cache = _sublists[i]._cacheHead;
306
}
307
return NULL == cache;
308
}
309
310
UDATA
311
MM_CopyScanCacheListVLHGC::countCaches()
312
{
313
UDATA count = 0;
314
for (UDATA i = 0; i < _sublistCount; ++i) {
315
MM_CopyScanCacheVLHGC *cache = _sublists[i]._cacheHead;
316
while (NULL != cache) {
317
count++;
318
cache = (MM_CopyScanCacheVLHGC *)cache->next;
319
}
320
}
321
return count;
322
}
323
324