-
Notifications
You must be signed in to change notification settings - Fork 748
/
Copy pathEnvironmentDelegate.hpp
319 lines (269 loc) · 11.6 KB
/
EnvironmentDelegate.hpp
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/*******************************************************************************
* Copyright IBM Corp. and others 2017
*
* 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] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#ifndef ENVIRONMENTDELEGATE_HPP_
#define ENVIRONMENTDELEGATE_HPP_
#include "objectdescription.h"
#include "MarkJavaStats.hpp"
#include "ScavengerJavaStats.hpp"
#include "ContinuationStats.hpp"
#include "GCExtensionsBase.hpp"
#include "ObjectModel.hpp"
struct OMR_VMThread;
typedef struct GCmovedObjectHashCode {
uint32_t originalHashCode;
bool hasBeenMoved;
bool hasBeenHashed;
} GCmovedObjectHashCode;
class MM_EnvironmentBase;
class MM_OwnableSynchronizerObjectBuffer;
class MM_ContinuationObjectBuffer;
class MM_ReferenceObjectBuffer;
class MM_UnfinalizedObjectBuffer;
class GC_Environment
{
/* Data members */
private:
protected:
public:
MM_MarkJavaStats _markJavaStats;
#if defined(OMR_GC_MODRON_SCAVENGER)
MM_ScavengerJavaStats _scavengerJavaStats;
#endif /* OMR_GC_MODRON_SCAVENGER */
MM_ContinuationStats _continuationStats;
MM_ReferenceObjectBuffer *_referenceObjectBuffer; /**< The thread-specific buffer of recently discovered reference objects */
MM_UnfinalizedObjectBuffer *_unfinalizedObjectBuffer; /**< The thread-specific buffer of recently allocated unfinalized objects */
MM_OwnableSynchronizerObjectBuffer *_ownableSynchronizerObjectBuffer; /**< The thread-specific buffer of recently allocated ownable synchronizer objects */
MM_ContinuationObjectBuffer *_continuationObjectBuffer; /**< The thread-specific buffer of recently allocated continuation objects */
struct GCmovedObjectHashCode movedObjectHashCodeCache; /**< Structure to aid on object movement and hashing */
#if defined(J9VM_ENV_DATA64)
bool _shouldFixupDataAddrForContiguous; /**< Boolean to check if dataAddr fixup is needed on contiguous indexable object movement */
#endif /* defined(J9VM_ENV_DATA64) */
/* Function members */
private:
protected:
public:
GC_Environment()
:_referenceObjectBuffer(NULL)
,_unfinalizedObjectBuffer(NULL)
,_ownableSynchronizerObjectBuffer(NULL)
,_continuationObjectBuffer(NULL)
#if defined(J9VM_ENV_DATA64)
,_shouldFixupDataAddrForContiguous(false)
#endif /* defined(J9VM_ENV_DATA64) */
{}
};
class MM_EnvironmentDelegate
{
/* Data members */
private:
MM_EnvironmentBase *_env;
MM_GCExtensionsBase *_extensions;
J9VMThread *_vmThread;
GC_Environment _gcEnv;
protected:
public:
/* Function members */
private:
protected:
public:
static OMR_VMThread *attachVMThread(OMR_VM *omrVM, const char *threadName, uintptr_t reason);
static void detachVMThread(OMR_VM *omrVM, OMR_VMThread *omrVMThread, uintptr_t reason);
/**
* Initialize the delegate's internal structures and values.
* @return true if initialization completed, false otherwise
*/
bool initialize(MM_EnvironmentBase *env);
/**
* Free any internal structures associated to the receiver.
*/
void tearDown();
GC_Environment * getGCEnvironment() { return &_gcEnv; }
void flushNonAllocationCaches();
void setGCMainThread(bool isMainThread);
/**
* This will be called for every allocated object. Note this is not necessarily done when the object is allocated. You are however
* guaranteed by the start of the next gc, you will be notified for all objects allocated since the last gc.
* hooktool is actually functionality better for this but is probably too heavy-weight for what we want for performant code.
*/
bool objectAllocationNotify(omrobjectptr_t omrObject) { return true; }
/**
* Acquire shared VM access. Threads must acquire VM access before accessing any OMR internal
* structures such as the heap. Requests for VM access will be blocked if any other thread is
* requesting or has obtained exclusive VM access until exclusive VM access is released.
*
* This implementation is not preemptive. Threads that have obtained shared VM access must
* check frequently whether any other thread is requesting exclusive VM access and release
* shared VM access as quickly as possible in that event.
*/
void acquireVMAccess();
/**
* Release shared VM access.
*/
void releaseVMAccess();
/**
* Returns true if a mutator threads entered native code without releasing VM access
*/
bool inNative();
/**
* Check whether another thread is requesting exclusive VM access. This method must be
* called frequently by all threads that are holding shared VM access if the VM access framework
* is not preemptive. If this method returns true, the calling thread should release shared
* VM access as quickly as possible and reacquire it if necessary.
*
* @return true if another thread is waiting to acquire exclusive VM access
*/
bool isExclusiveAccessRequestWaiting();
/**
* Acquire exclusive VM access. This method should only be called by the OMR runtime to
* perform stop-the-world operations such as garbage collection. Calling thread will be
* blocked until all other threads holding shared VM access have release VM access.
*/
void acquireExclusiveVMAccess();
/**
* Release exclusive VM access. If no other thread is waiting for exclusive VM access
* this method will notify all threads waiting for shared VM access to continue and
* acquire shared VM access.
*/
void releaseExclusiveVMAccess();
uintptr_t relinquishExclusiveVMAccess();
void assumeExclusiveVMAccess(uintptr_t exclusiveCount);
void releaseCriticalHeapAccess(uintptr_t *data);
void reacquireCriticalHeapAccess(uintptr_t data);
void forceOutOfLineVMAccess();
/**
* This method is responsible for remembering object information before object is moved. Differently than
* evacuation, we're sliding the object; therefore, we need to remember object's original information
* before object moves and could potentially grow
*
* @param[in] objectPtr points to the object that is about to be moved
* @see postObjectMoveForCompact(omrobjectptr_t)
*/
MMINLINE void
preObjectMoveForCompact(omrobjectptr_t objectPtr)
{
GC_ObjectModel *objectModel = &_extensions->objectModel;
bool hashed = objectModel->hasBeenHashed(objectPtr);
bool moved = objectModel->hasBeenMoved(objectPtr);
_gcEnv.movedObjectHashCodeCache.hasBeenHashed = hashed;
_gcEnv.movedObjectHashCodeCache.hasBeenMoved = moved;
if (hashed && !moved) {
/* calculate this BEFORE we (potentially) destroy the object */
_gcEnv.movedObjectHashCodeCache.originalHashCode = computeObjectAddressToHash((J9JavaVM *)_extensions->getOmrVM()->_language_vm, objectPtr);
}
#if defined(J9VM_ENV_DATA64)
if (objectModel->isIndexable(objectPtr)) {
GC_ArrayObjectModel *indexableObjectModel = &_extensions->indexableObjectModel;
if (indexableObjectModel->isVirtualLargeObjectHeapEnabled() && indexableObjectModel->isInlineContiguousArraylet((J9IndexableObject *)objectPtr)) {
_gcEnv._shouldFixupDataAddrForContiguous = indexableObjectModel->shouldFixupDataAddrForContiguous((J9IndexableObject *)objectPtr);
} else {
_gcEnv._shouldFixupDataAddrForContiguous = false;
}
}
#endif /* defined(J9VM_ENV_DATA64) */
}
/**
* This method may be called during heap compaction, after the object has been moved to a new location.
* The implementation may apply any information extracted and cached in the calling thread at this point.
* It also updates indexable dataAddr field through fixupDataAddr.
*
* @param[in] destinationObjectPtr points to the object that has just been moved (new location)
* @param[in] sourceObjectPtr points to the old object that has just been moved (old location)
* @see preObjectMoveForCompact(omrobjectptr_t)
*/
MMINLINE void
postObjectMoveForCompact(omrobjectptr_t destinationObjectPtr, omrobjectptr_t sourceObjectPtr)
{
GC_ObjectModel *objectModel = &_extensions->objectModel;
GC_ArrayObjectModel *indexableObjectModel = &_extensions->indexableObjectModel;
if (_gcEnv.movedObjectHashCodeCache.hasBeenHashed && !_gcEnv.movedObjectHashCodeCache.hasBeenMoved) {
*(uint32_t *)((uintptr_t)destinationObjectPtr + objectModel->getHashcodeOffset(destinationObjectPtr)) = _gcEnv.movedObjectHashCodeCache.originalHashCode;
objectModel->setObjectHasBeenMoved(destinationObjectPtr);
}
if (objectModel->isIndexable(destinationObjectPtr)) {
#if defined(J9VM_ENV_DATA64)
if (_gcEnv._shouldFixupDataAddrForContiguous) {
/**
* Update the dataAddr internal field of the indexable object. The field being updated
* points to the array data. In the case of contiguous data, it will point to the data
* itself, and in case of discontiguous data, it will be NULL. How to
* update dataAddr is up to the target language that must override fixupDataAddr.
*/
indexableObjectModel->setDataAddrForContiguous((J9IndexableObject *)destinationObjectPtr);
}
#endif /* defined(J9VM_ENV_DATA64) */
if (UDATA_MAX != _extensions->getOmrVM()->_arrayletLeafSize) {
indexableObjectModel->fixupInternalLeafPointersAfterCopy((J9IndexableObject *)destinationObjectPtr, (J9IndexableObject *)sourceObjectPtr);
}
}
}
#if defined (OMR_GC_THREAD_LOCAL_HEAP)
/**
* Disable inline TLH allocates by hiding the real heap top address from
* JIT/Interpreter in realHeapTop and setting HeapTop == heapALloc so TLH
* looks full.
*
*/
void disableInlineTLHAllocate();
/**
* Re-enable inline TLH allocate by restoring heapTop from realHeapTop
*/
void enableInlineTLHAllocate();
/**
* Determine if inline TLH allocate is enabled; its enabled if realheapTop is NULL.
* @return TRUE if inline TLH allocates currently enabled for this thread; FALSE otherwise
*/
bool isInlineTLHAllocateEnabled();
/**
* Set TLH Sampling Top by hiding the real heap top address from
* JIT/Interpreter in realHeapTop and setting HeapTop = (HeapAlloc + size) if size < (HeapTop - HeapAlloc)
* so out of line allocate would happen at TLH Sampling Top.
* If size >= (HeapTop - HeapAlloc) resetTLHSamplingTop()
*
* @param size the number of bytes to next sampling point
*/
void setTLHSamplingTop(uintptr_t size);
/**
* Restore heapTop from realHeapTop if realHeapTop != NULL
*/
void resetTLHSamplingTop();
/**
* Retrieve allocation size inside TLH Cache.
* @return (heapAlloc - heapBase)
*/
uintptr_t getAllocatedSizeInsideTLH();
#endif /* OMR_GC_THREAD_LOCAL_HEAP */
#if defined(J9VM_OPT_CRIU_SUPPORT)
/**
* Reinitialize the Env Delegate by updating the thread local obj buffers.
*
* @param[in] env the current environment.
* @return boolean indicating whether the Env Delegate was successfully updated.
*/
virtual bool reinitializeForRestore(MM_EnvironmentBase* env);
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
MM_EnvironmentDelegate()
: _env(NULL)
, _extensions(NULL)
, _vmThread(NULL)
{ }
};
#endif /* ENVIRONMENTDELEGATE_HPP_ */