-
Notifications
You must be signed in to change notification settings - Fork 392
/
ConcurrentGCIncrementalUpdate.cpp
205 lines (169 loc) · 7.2 KB
/
ConcurrentGCIncrementalUpdate.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*******************************************************************************
* Copyright (c) 2018, 2018 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] http://openjdk.java.net/legal/assembly-exception.html
*
* 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
*******************************************************************************/
/**
* @file
* @ingroup GC_Modron_Standard
*/
#include "omrcfg.h"
#if defined(OMR_GC_MODRON_CONCURRENT_MARK)
#define J9_EXTERNAL_TO_VM
#include "mmprivatehook.h"
#include "modronbase.h"
#include "modronopt.h"
#include "ModronAssertions.h"
#include "omr.h"
#include <string.h>
#include "ConcurrentGCIncrementalUpdate.hpp"
#include "ConcurrentCardTableForWC.hpp"
/**
* Create new instance of ConcurrentGCIncrementalUpdate object.
*
* @return Reference to new MM_ConcurrentGCIncrementalUpdate object or NULL
*/
MM_ConcurrentGCIncrementalUpdate *
MM_ConcurrentGCIncrementalUpdate::newInstance(MM_EnvironmentBase *env)
{
MM_ConcurrentGCIncrementalUpdate *concurrentGC =
(MM_ConcurrentGCIncrementalUpdate *)env->getForge()->allocate(sizeof(MM_ConcurrentGCIncrementalUpdate),
OMR::GC::AllocationCategory::FIXED, OMR_GET_CALLSITE());
if (NULL != concurrentGC) {
new(concurrentGC) MM_ConcurrentGCIncrementalUpdate(env);
if (!concurrentGC->initialize(env)) {
concurrentGC->kill(env);
concurrentGC = NULL;
}
}
return concurrentGC;
}
/**
* Destroy instance of an ConcurrentGCIncrementalUpdate object.
*
*/
void
MM_ConcurrentGCIncrementalUpdate::kill(MM_EnvironmentBase *env)
{
tearDown(env);
env->getForge()->free(this);
}
/* Teardown a ConcurrentGCIncrementalUpdate object
* Destroy referenced objects and release
* all allocated storage before ConcurrentGCIncrementalUpdate object is freed.
*/
void
MM_ConcurrentGCIncrementalUpdate::tearDown(MM_EnvironmentBase *env)
{
/* ..and then tearDown our super class */
MM_ConcurrentGC::tearDown(env);
}
/**
* Initialize a new ConcurrentGCIncrementalUpdate object.
* Instantiate card table and concurrent RAS objects(if required) and initialize all
* monitors required by concurrent. Allocate and initialize the concurrent helper thread
* table.
*
* @return TRUE if initialization completed OK;FALSE otheriwse
*/
bool
MM_ConcurrentGCIncrementalUpdate::initialize(MM_EnvironmentBase *env)
{
J9HookInterface** mmPrivateHooks = J9_HOOK_INTERFACE(_extensions->privateHookInterface);
if (!MM_ConcurrentGC::initialize(env)) {
goto error_no_memory;
}
if (!createCardTable(env)) {
goto error_no_memory;
}
/* Register on any hook we are interested in */
(*mmPrivateHooks)->J9HookRegisterWithCallSite(mmPrivateHooks, J9HOOK_MM_PRIVATE_CARD_CLEANING_PASS_2_START, hookCardCleanPass2Start, OMR_GET_CALLSITE(), (void *)this);
return true;
error_no_memory:
return false;
}
bool
MM_ConcurrentGCIncrementalUpdate::heapAddRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress)
{
/* CS check is added to preemptively clean new cards during expansion when in the middle of a CS cycle, even if CM is off. CS cycle during
* expansion can be overlapped with KO, in which case we can miss to update the init table (or update it too late) when we KO after the cleanCards check.
* It it known that this will cause cards to be cleared unnecessarily during the expand given CM is off + CS. This is fine because cleaning cards
* (memset) is negligible, each 512 bytes of expanded heap will require to memset of 1 byte and CS shouldn't be expanding Tenure too frequently.
*/
bool clearCards = ((CONCURRENT_OFF < _stats.getExecutionMode()) || _extensions->isConcurrentScavengerInProgress()) && subspace->isConcurrentCollectable();
/* Expand any superclass structures including mark bits*/
bool result = MM_ConcurrentGC::heapAddRange(env, subspace, size, lowAddress, highAddress);
if (result) {
/* expand the card table */
result = ((MM_ConcurrentCardTable *)_cardTable)->heapAddRange(env, subspace, size, lowAddress, highAddress, clearCards);
if (!result) {
/* Expansion of Concurrent Card Table has failed
* ParallelGlobalGC expansion must be reversed
*/
MM_ParallelGlobalGC::heapRemoveRange(env, subspace, size, lowAddress, highAddress, NULL, NULL);
}
}
_heapAlloc = _extensions->heap->getHeapTop();
return result;
}
/**
* Hook function called when an the 2nd pass over card table to clean cards starts.
* This is a wrapper into the non-static MM_ConcurrentGCIncrementalUpdate::recordCardCleanPass2Start
*/
void
MM_ConcurrentGCIncrementalUpdate::hookCardCleanPass2Start(J9HookInterface** hook, uintptr_t eventNum, void* eventData, void* userData)
{
MM_CardCleanPass2StartEvent* event = (MM_CardCleanPass2StartEvent *)eventData;
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(event->currentThread);
((MM_ConcurrentGCIncrementalUpdate *)userData)->recordCardCleanPass2Start(env);
/* Boost the trace rate for the 2nd card cleaning pass */
}
void
MM_ConcurrentGCIncrementalUpdate::recordCardCleanPass2Start(MM_EnvironmentBase *env)
{
_pass2Started = true;
/* Record how mush work we did before pass 2 KO */
_totalTracedAtPass2KO = _stats.getTraceSizeCount() + _stats.getConHelperTraceSizeCount();
_totalCleanedAtPass2KO = _stats.getCardCleanCount() + _stats.getConHelperCardCleanCount();
/* ..and boost tracing rate from here to end of cycle so we complete pass 2 ASAP */
_allocToTraceRate *= _allocToTraceRateCardCleanPass2Boost;
}
bool
MM_ConcurrentGCIncrementalUpdate::createCardTable(MM_EnvironmentBase *env)
{
bool result = false;
Assert_MM_true(NULL == _cardTable);
Assert_MM_true(NULL == _extensions->cardTable);
#if defined(AIXPPC) || defined(LINUXPPC)
OMRPORT_ACCESS_FROM_OMRPORT(env->getPortLibrary());
if ((uintptr_t)omrsysinfo_get_number_CPUs_by_type(OMRPORT_CPU_ONLINE) > 1 ) {
_cardTable = MM_ConcurrentCardTableForWC::newInstance(env, _extensions->getHeap(), _markingScheme, this);
} else
#endif /* AIXPPC || LINUXPPC */
{
_cardTable = MM_ConcurrentCardTable::newInstance(env, _extensions->getHeap(), _markingScheme, this);
}
if(NULL != _cardTable) {
result = true;
/* Set card table address in GC Extensions */
_extensions->cardTable = _cardTable;
}
return result;
}
#endif /* OMR_GC_MODRON_CONCURRENT_MARK */