-
Notifications
You must be signed in to change notification settings - Fork 750
/
Copy pathGenerationalAccessBarrierComponent.cpp
168 lines (151 loc) · 7.06 KB
/
GenerationalAccessBarrierComponent.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
/*******************************************************************************
* Copyright IBM Corp. and others 1991
*
* 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
*******************************************************************************/
/**
* @file
* @ingroup GC_Base
*/
#include "j9.h"
#include "j9cfg.h"
#include "j9consts.h"
#include "j9protos.h"
#include "ModronAssertions.h"
#include "j9nongenerated.h"
#if defined(J9VM_GC_GENERATIONAL)
#include "GenerationalAccessBarrierComponent.hpp"
#include "AtomicOperations.hpp"
#include "Debug.hpp"
#include "EnvironmentBase.hpp"
#include "mmhook_internal.h"
#include "GCExtensions.hpp"
#include "ObjectModel.hpp"
#include "SublistFragment.hpp"
extern "C" {
/**
* Inform consumers of RememberedSet overflow.
*/
static void
reportRememberedSetOverflow(J9VMThread *vmThread)
{
Trc_MM_RememberedSetOverflow(vmThread);
TRIGGER_J9HOOK_MM_PRIVATE_REMEMBEREDSET_OVERFLOW(MM_GCExtensions::getExtensions(vmThread->javaVM)->privateHookInterface, (OMR_VMThread *)vmThread->omrVMThread);
}
} /* extern "C" */
bool
MM_GenerationalAccessBarrierComponent::initialize(MM_EnvironmentBase *env)
{
return true;
}
void
MM_GenerationalAccessBarrierComponent::tearDown(MM_EnvironmentBase *env)
{
}
/**
* Generational write barrier call when a single object is stored into another.
* The remembered set system consists of a physical list of objects in the OLD area that
* may contain references to the new area. The mutator is responsible for adding these old
* area objects to the remembered set; the collectors are responsible for removing these objects
* from the list when they no longer contain references. Objects that are to be remembered have their
* REMEMBERED bit set in the flags field. For performance reasons, sublists are used to maintain the
* remembered set.
*
* @param vmThread The current thread that has performed the store.
* @param dstObject The object which is being stored into.
* @param srcObject The object being stored.
*
* @note The write barrier can be called with minimal, all, or no validation checking.
* @note Any object that contains a new reference MUST have its REMEMBERED bit set.
*/
void
MM_GenerationalAccessBarrierComponent::postObjectStore(J9VMThread *vmThread, J9Object *dstObject, J9Object *srcObject)
{
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
/* If the source object is NULL, there is no need for a write barrier. */
/* If scavenger not enabled then no need to add to remembered set */
if ((NULL != srcObject) && extensions->scavengerEnabled) {
if (extensions->isOld(dstObject) && !extensions->isOld(srcObject)) {
if (extensions->objectModel.atomicSetRememberedState(dstObject, STATE_REMEMBERED)) {
/* Successfully set the remembered bit in the object. Now allocate an entry from the
* remembered set fragment of the current thread and store the destination object into
* the remembered set.
*/
MM_SublistFragment fragment((J9VMGC_SublistFragment*)&vmThread->gcRememberedSet);
if (!fragment.add(env, (UDATA)dstObject )) {
/* No slot was available from any fragment. Set the remembered set overflow flag.
* The REMEMBERED bit is kept in the object for optimization purposes (only scan objects
* whose REMEMBERED bit is set in an overflow scan)
*/
extensions->setScavengerRememberedSetOverflowState();
reportRememberedSetOverflow(vmThread);
}
}
}
}
}
/**
* Generational write barrier call when a group of objects are stored into a single object.
* The remembered set system consists of a physical list of objects in the OLD area that
* may contain references to the new area. The mutator is responsible for adding these old
* area objects to the remembered set; the collectors are responsible for removing these objects
* from the list when they no longer contain references. Objects that are to be remembered have their
* REMEMBERED bit set in the flags field. For performance reasons, sublists are used to maintain the
* remembered set.
*
* @param vmThread The current thread that has performed the store.
* @param dstObject The object which is being stored into.
*
* @note The write barrier can be called with minimal, all, or no validation checking.
* @note Any object that contains a new reference MUST have its REMEMBERED bit set.
* @note This call is typically used by array copies, when it may be more efficient
* to optimistically add an object to the remembered set without checking too hard.
*/
void
MM_GenerationalAccessBarrierComponent::postBatchObjectStore(J9VMThread *vmThread, J9Object *dstObject)
{
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
/* If scavenger not enabled then no need to add to remembered set */
if (extensions->scavengerEnabled) {
/* Since we don't know what the references stored into dstObject were, we have to pessimistically
* assume they included old->new references, and the object should be added to the remembered set */
if (extensions->isOld(dstObject)) {
if (extensions->objectModel.atomicSetRememberedState(dstObject, STATE_REMEMBERED)) {
/* Successfully set the remembered bit in the object. Now allocate an entry from the
* remembered set fragment of the current thread and store the destination object into
* the remembered set. */
UDATA *rememberedSlot;
MM_SublistFragment fragment((J9VMGC_SublistFragment*)&vmThread->gcRememberedSet);
if (NULL == (rememberedSlot = (UDATA *)fragment.allocate(env))) {
/* No slot was available from any fragment. Set the remembered set overflow flag.
* The REMEMBERED bit is kept in the object for optimization purposes (only scan objects
* whose REMEMBERED bit is set in an overflow scan) */
extensions->setScavengerRememberedSetOverflowState();
reportRememberedSetOverflow(vmThread);
} else {
/* Successfully allocated a slot from the remembered set. Record the object. */
*rememberedSlot = (UDATA)dstObject;
}
}
}
}
}
#endif /* J9VM_GC_GENERATIONAL */