Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_realtime/MemorySubSpaceMetronome.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2019 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 "omr.h"
24
#include "omrcfg.h"
25
26
#include "AllocateDescription.hpp"
27
#include "Collector.hpp"
28
#include "EnvironmentRealtime.hpp"
29
#include "GCCode.hpp"
30
#include "MemoryPool.hpp"
31
#include "MemorySubSpace.hpp"
32
#include "MetronomeDelegate.hpp"
33
#include "Scheduler.hpp"
34
#include "RealtimeGC.hpp"
35
36
#include "MemorySubSpaceMetronome.hpp"
37
38
/**
39
* Allocation.
40
* @todo Provide class documentation
41
*/
42
void *
43
MM_MemorySubSpaceMetronome::allocateObject(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription, MM_MemorySubSpace *baseSubSpace, MM_MemorySubSpace *previousSubSpace, bool shouldCollectOnFailure)
44
{
45
void *result = NULL;
46
47
if (shouldCollectOnFailure) {
48
result = allocateMixedObjectOrArraylet((MM_EnvironmentRealtime *)env, allocDescription, mixedObject);
49
} else {
50
/* not setting these object flags causes a failure working with empty arrays but where this is set should probably be hoisted into the caller */
51
allocDescription->setObjectFlags(getObjectFlags());
52
result = _memoryPoolSegregated->allocateObject(env, allocDescription);
53
}
54
return result;
55
}
56
57
/**
58
* Allocate an arraylet leaf.
59
*/
60
void *
61
MM_MemorySubSpaceMetronome::allocateArrayletLeaf(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription, MM_MemorySubSpace *baseSubSpace, MM_MemorySubSpace *previousSubSpace, bool shouldCollectOnFailure)
62
{
63
omrarrayptr_t spine = allocDescription->getSpine();
64
/* spine object refers to the barrier-safe "object" reference, as opposed to the internal "heap address" represented by the spine variable */
65
omrobjectptr_t spineObject = (omrobjectptr_t)spine;
66
void *leaf = NULL;
67
if(env->saveObjects(spineObject)) {
68
leaf = allocateMixedObjectOrArraylet(env, allocDescription, arrayletLeaf);
69
env->restoreObjects(&spineObject);
70
spine = (omrarrayptr_t)spineObject;
71
allocDescription->setSpine(spine);
72
}
73
return leaf;
74
}
75
76
void
77
MM_MemorySubSpaceMetronome::collectOnOOM(MM_EnvironmentBase *env, MM_GCCode gcCode, MM_AllocateDescription *allocDescription)
78
{
79
MM_EnvironmentRealtime *envRealtime = MM_EnvironmentRealtime::getEnvironment(env);
80
MM_GCExtensionsBase *ext = envRealtime->getExtensions();
81
MM_Scheduler *sched = (MM_Scheduler *)ext->dispatcher;
82
83
if (sched->isInitialized()) {
84
sched->startGC(envRealtime);
85
sched->setGCCode(gcCode);
86
sched->continueGC(envRealtime, OUT_OF_MEMORY_TRIGGER, allocDescription->getBytesRequested(), env->getOmrVMThread(), true);
87
}
88
/* TODO CRGTMP remove call to yieldWhenRequested since continueGC blocks */
89
ext->realtimeGC->getRealtimeDelegate()->yieldWhenRequested(envRealtime);
90
}
91
92
/**
93
* TODO: this is temporary as a way to avoid duplication of (badly written) code in MemorySubSpaceMetronome::allocate.
94
* We will specifically fix this allocate method in a separate design.
95
*/
96
void *
97
MM_MemorySubSpaceMetronome::allocateMixedObjectOrArraylet(MM_EnvironmentBase *env, MM_AllocateDescription *allocDescription, AllocateType allocType)
98
{
99
MM_EnvironmentRealtime *envRealtime = MM_EnvironmentRealtime::getEnvironment(env);
100
void *result;
101
102
allocDescription->setObjectFlags(getObjectFlags());
103
104
result = allocate(envRealtime, allocDescription, allocType);
105
if (NULL != result) {
106
return result;
107
}
108
109
/* We failed to allocate the object so do a synchronous GC. This may complete the current GC */
110
collectOnOOM(envRealtime, MM_GCCode(J9MMCONSTANT_IMPLICIT_GC_DEFAULT), allocDescription);
111
112
/* We completed a GC so try the allocate again */
113
result = allocate(envRealtime, allocDescription, allocType);
114
if (NULL != result) {
115
return result;
116
}
117
118
/* Still failed to allocate so try another synchronous GC */
119
collectOnOOM(envRealtime, MM_GCCode(J9MMCONSTANT_IMPLICIT_GC_DEFAULT), allocDescription);
120
121
/* We completed a GC so try the allocate again */
122
result = allocate(envRealtime, allocDescription, allocType);
123
if (NULL != result) {
124
return result;
125
}
126
127
/* Still failed to allocate so try an aggressive synchronous GC */
128
collectOnOOM(envRealtime, MM_GCCode(J9MMCONSTANT_IMPLICIT_GC_AGGRESSIVE), allocDescription);
129
130
result = allocate(envRealtime, allocDescription, allocType);
131
if (NULL != result) {
132
return result;
133
}
134
135
return NULL;
136
}
137
138
/**
139
* On a request for systemGC metronome will initiate a GC,
140
* but doesn't wait for it to complete.
141
*/
142
void
143
MM_MemorySubSpaceMetronome::systemGarbageCollect(MM_EnvironmentBase *env, U_32 gcCode) {
144
MM_EnvironmentRealtime *envRealtime = MM_EnvironmentRealtime::getEnvironment(env);
145
MM_Scheduler *sched = (MM_Scheduler *)envRealtime->getExtensions()->dispatcher;
146
147
if (sched->isInitialized()) {
148
MM_GCExtensionsBase *ext = env->getExtensions();
149
ext->realtimeGC->setFixHeapForWalk(true);
150
sched->startGC(envRealtime);
151
sched->setGCCode(MM_GCCode(gcCode));
152
/* if we were triggered by rasdump, then the caller has already acquired exclusive VM access */
153
sched->continueGC(envRealtime, SYSTEM_GC_TRIGGER, 0, envRealtime->getOmrVMThread(), J9MMCONSTANT_EXPLICIT_GC_RASDUMP_COMPACT != gcCode);
154
/* TODO CRGTMP remove this call since continueGC blocks */
155
ext->realtimeGC->getRealtimeDelegate()->yieldWhenRequested(envRealtime);
156
}
157
}
158
159
/**
160
* @todo Provide class documentation
161
* @ingroup GC_Metronome methodGroup
162
*/
163
void
164
MM_MemorySubSpaceMetronome::collect(MM_EnvironmentBase *env, MM_GCCode gcCode)
165
{
166
_collector->garbageCollect(env, this, NULL, gcCode.getCode(), NULL, NULL, NULL);
167
}
168
169
/**
170
* Initialization.
171
* @todo Provide class documentation
172
*/
173
MM_MemorySubSpaceMetronome *
174
MM_MemorySubSpaceMetronome::newInstance(
175
MM_EnvironmentBase *env, MM_PhysicalSubArena *physicalSubArena, MM_MemoryPool *memoryPool,
176
bool usesGlobalCollector, UDATA minimumSize, UDATA initialSize, UDATA maximumSize)
177
{
178
MM_MemorySubSpaceMetronome *memorySubSpace;
179
180
memorySubSpace = (MM_MemorySubSpaceMetronome *)env->getForge()->allocate(sizeof(MM_MemorySubSpaceMetronome), MM_AllocationCategory::FIXED, OMR_GET_CALLSITE());
181
if (NULL != memorySubSpace) {
182
new(memorySubSpace) MM_MemorySubSpaceMetronome(env, physicalSubArena, memoryPool, usesGlobalCollector, minimumSize, initialSize, maximumSize);
183
if (!memorySubSpace->initialize(env)) {
184
memorySubSpace->kill(env);
185
memorySubSpace = NULL;
186
}
187
}
188
return memorySubSpace;
189
}
190
191
/**
192
* Initialization.
193
* @todo Provide class documentation
194
*/
195
bool
196
MM_MemorySubSpaceMetronome::initialize(MM_EnvironmentBase *env)
197
{
198
if(!MM_MemorySubSpaceSegregated::initialize(env)) {
199
return false;
200
}
201
202
/* TODO: Not valid for multiple memory spaces */
203
MM_RealtimeGC *realtimeGC = (MM_RealtimeGC *)_collector;
204
realtimeGC->setMemoryPool(_memoryPoolSegregated);
205
realtimeGC->setMemorySubSpace(this);
206
207
return true;
208
}
209
210