Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_modron_startup/arrayCopy.cpp
5986 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
24
/**
25
* @file
26
* @ingroup GC_Modron_Base
27
*/
28
29
#include "j9.h"
30
#include "j9protos.h"
31
#include "j9consts.h"
32
#include "j9cfg.h"
33
#include "modronopt.h"
34
#include "j9modron.h"
35
#include "arrayCopyInterface.h"
36
#include "ModronAssertions.h"
37
38
#include <string.h>
39
40
#include "EnvironmentBase.hpp"
41
#include "GCExtensions.hpp"
42
#include "ObjectAccessBarrier.hpp"
43
#include "ObjectModel.hpp"
44
#include "SlotObject.hpp"
45
46
extern "C" {
47
48
/**
49
* Called from JIT to determine how reference array copy should be handled.
50
* @return true if jitted code should always call the C helper for a reference array copy
51
* @return false otherwise
52
*/
53
UDATA
54
alwaysCallReferenceArrayCopyHelper(J9JavaVM *javaVM)
55
{
56
return MM_GCExtensions::getExtensions(javaVM)->isMetronomeGC() ? 1 : 0;
57
}
58
59
/**
60
* Internal helper for performing a type check before an array store.
61
* @return true if the store is legal, false otherwise
62
* @note Translated from builder: J9VM>>typeCheckArrayStoreOf:into:ifFail:nullCheck:
63
*/
64
static bool
65
typeCheckArrayStore(J9VMThread *vmThread, J9Object *object, J9IndexableObject *arrayObj)
66
{
67
if (object) {
68
J9Class *componentType = ((J9ArrayClass *)J9OBJECT_CLAZZ(vmThread, arrayObj))->componentType;
69
/* Check if we are storing the object into an array of the same type */
70
J9Class *storedClazz = J9OBJECT_CLAZZ(vmThread, object);
71
if (storedClazz != componentType) {
72
/* Check if we are storing the object into an array of Object[] */
73
UDATA classDepth = J9CLASS_DEPTH(componentType);
74
if (classDepth != 0) {
75
return (0 != instanceOfOrCheckCast(storedClazz, componentType));
76
}
77
}
78
}
79
return true;
80
}
81
82
/**
83
* Internal helper to see whether any type checks need to be performed during arraycopy.
84
* @return true if type checks should be performed, false otherwise.
85
*/
86
static MMINLINE bool
87
arrayStoreCheckRequired(J9VMThread *vmThread, J9IndexableObject *destObject, J9IndexableObject *srcObject)
88
{
89
J9Class *srcClazz = J9OBJECT_CLAZZ(vmThread, srcObject);
90
J9Class *destClazz = J9OBJECT_CLAZZ(vmThread, destObject);
91
92
/* Type checks are not required only if both classes are the same, or
93
* the source class is a subclass of the dest class
94
*/
95
if (srcClazz != destClazz) {
96
UDATA srcDepth = J9CLASS_DEPTH(srcClazz);
97
UDATA destDepth = J9CLASS_DEPTH(destClazz);
98
if ((srcDepth <= destDepth) || (destClazz->superclasses[srcDepth] != srcClazz)) {
99
return true;
100
}
101
}
102
103
return false;
104
}
105
106
/**
107
* VM helper for performing a reference array copy.
108
* This function corresponds to the function of the same name in the memory manager
109
* function table. This helper is called by the System.arraycopy native when performing
110
* a reference array copy, after bounds checks have been made.
111
* This specific API takes starting positions in a form of address of a slot. It would just calculate
112
* corresponding starting indices and pass the request to referenceArrayCopyIndex() API.
113
* This API must be used only with contiguous arrays.
114
* @return -1 if the copy succeeded
115
* @return the index where the ArrayStoreException occurred, if the copy failed
116
*/
117
I_32
118
referenceArrayCopy(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, fj9object_t *srcAddress, fj9object_t *destAddress, I_32 lengthInSlots)
119
{
120
if (lengthInSlots > 0) {
121
MM_GCExtensions *ext = MM_GCExtensions::getExtensions(vmThread->javaVM);
122
123
Assert_MM_true(ext->indexableObjectModel.isInlineContiguousArraylet(srcObject) && ext->indexableObjectModel.isInlineContiguousArraylet(destObject));
124
125
uintptr_t srcHeaderSize = ext->indexableObjectModel.getHeaderSize(srcObject);
126
uintptr_t destHeaderSize = ext->indexableObjectModel.getHeaderSize(destObject);
127
uintptr_t const referenceSize = J9VMTHREAD_REFERENCE_SIZE(vmThread);
128
I_32 srcIndex = (I_32)(((uintptr_t)srcAddress - (srcHeaderSize + (uintptr_t)srcObject)) / referenceSize);
129
I_32 destIndex = (I_32)(((uintptr_t)destAddress - (destHeaderSize + (uintptr_t)destObject)) / referenceSize);
130
131
return referenceArrayCopyIndex(vmThread, srcObject, destObject, srcIndex, destIndex, lengthInSlots);
132
}
133
return -1;
134
135
}
136
137
/**
138
* VM helper for performing a reference array copy.
139
* This function corresponds to the function of the same name in the memory manager
140
* function table. This helper is called by the System.arraycopy native when performing
141
* a reference array copy, after bounds checks have been made.
142
* @return -1 if the copy succeeded
143
* @return if the copy failed, return the index where the exception occurred. It
144
* may be an ArrayStoreException
145
*/
146
I_32
147
referenceArrayCopyIndex(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, I_32 srcIndex, I_32 destIndex, I_32 lengthInSlots)
148
{
149
if (lengthInSlots > 0) {
150
151
J9WriteBarrierType wrtbarType = (J9WriteBarrierType)j9gc_modron_getWriteBarrierType(vmThread->javaVM);
152
J9ReferenceArrayCopyTable *table = &MM_GCExtensions::getExtensions(vmThread->javaVM)->referenceArrayCopyTable;
153
154
if ((srcObject == destObject) && (srcIndex < destIndex) && ((srcIndex + lengthInSlots) > destIndex)) {
155
return table->backwardReferenceArrayCopyIndex[wrtbarType](vmThread, srcObject, destObject, srcIndex, destIndex, lengthInSlots);
156
}
157
if (arrayStoreCheckRequired(vmThread, destObject, srcObject)) {
158
return table->forwardReferenceArrayCopyWithCheckIndex[wrtbarType](vmThread, srcObject, destObject, srcIndex, destIndex, lengthInSlots);
159
}
160
return table->forwardReferenceArrayCopyWithoutCheckIndex[wrtbarType](vmThread, srcObject, destObject, srcIndex, destIndex, lengthInSlots);
161
}
162
return -1;
163
}
164
165
I_32
166
backwardReferenceArrayCopyAndAlwaysWrtbarIndex(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, I_32 srcIndex, I_32 destIndex, I_32 lengthInSlots)
167
{
168
MM_ObjectAccessBarrier *barrier = MM_GCExtensions::getExtensions(vmThread->javaVM)->accessBarrier;
169
I_32 result;
170
171
/* Let access barrier specific code try doing an optimized version of the copy (if such exists) */
172
/* -1 copy successful, -2 no copy done, >=0 copy was attempted but and exception was raised (index returned) */
173
if (-1 <= (result = barrier->backwardReferenceArrayCopyIndex(vmThread, srcObject, destObject, srcIndex, destIndex, lengthInSlots))) {
174
return result;
175
}
176
177
I_32 endSrcIndex = srcIndex;
178
J9Object *copyObject = NULL;
179
180
srcIndex += lengthInSlots;
181
destIndex += lengthInSlots;
182
while(srcIndex > endSrcIndex) {
183
srcIndex--;
184
destIndex--;
185
copyObject = J9JAVAARRAYOFOBJECT_LOAD(vmThread, srcObject, srcIndex);
186
J9JAVAARRAYOFOBJECT_STORE(vmThread, destObject, destIndex, copyObject);
187
}
188
189
return -1;
190
}
191
192
I_32
193
forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, I_32 srcIndex, I_32 destIndex, I_32 lengthInSlots)
194
{
195
I_32 srcEndIndex = srcIndex + lengthInSlots;
196
197
while (srcIndex < srcEndIndex) {
198
J9Object *copyObject = J9JAVAARRAYOFOBJECT_LOAD(vmThread, srcObject, srcIndex);
199
if (!typeCheckArrayStore(vmThread, copyObject, destObject)) {
200
goto error;
201
}
202
J9JAVAARRAYOFOBJECT_STORE(vmThread, destObject, destIndex, copyObject);
203
srcIndex++;
204
destIndex++;
205
}
206
207
return -1;
208
209
error:
210
return srcIndex;
211
}
212
213
I_32
214
forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, I_32 srcIndex, I_32 destIndex, I_32 lengthInSlots)
215
{
216
MM_ObjectAccessBarrier *barrier = MM_GCExtensions::getExtensions(vmThread->javaVM)->accessBarrier;
217
I_32 result;
218
219
/* Let access barrier specific code try doing an optimized version of the copy (if such exists) */
220
/* -1 copy successful, -2 no copy done, >=0 copy was attempted but and exception was raised (index returned) */
221
if (-1 <= (result = barrier->forwardReferenceArrayCopyIndex(vmThread, srcObject, destObject, srcIndex, destIndex, lengthInSlots))) {
222
return result;
223
}
224
225
I_32 srcEndIndex = srcIndex + lengthInSlots;
226
227
while (srcIndex < srcEndIndex) {
228
J9Object *copyObject = J9JAVAARRAYOFOBJECT_LOAD(vmThread, srcObject, srcIndex);
229
J9JAVAARRAYOFOBJECT_STORE(vmThread, destObject, destIndex, copyObject);
230
srcIndex++;
231
destIndex++;
232
}
233
234
return -1;
235
}
236
237
/**
238
* Error stub for function table entries that aren't needed by Metronome.
239
*/
240
I_32
241
copyVariantUndefinedIndex(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, I_32 srcIndex, I_32 destIndex, I_32 lengthInSlots)
242
{
243
Assert_MM_unreachable();
244
return srcIndex;
245
}
246
247
/**
248
* Initialize the reference array copy function table with the appropriate function pointers
249
* @note This table must be updated if @ref J9WriteBarrierType is changed
250
*/
251
void
252
initializeReferenceArrayCopyTable(J9ReferenceArrayCopyTable *table)
253
{
254
/* The generic reference array copy */
255
table->referenceArrayCopyIndex = referenceArrayCopyIndex;
256
257
/* Backward copy doesn't require a type check, but source and dest object are the same */
258
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_illegal] = copyVariantUndefinedIndex;
259
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_none] = backwardReferenceArrayCopyAndAlwaysWrtbarIndex;
260
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_always] = backwardReferenceArrayCopyAndAlwaysWrtbarIndex;
261
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_oldcheck] = backwardReferenceArrayCopyAndAlwaysWrtbarIndex;
262
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_cardmark] = backwardReferenceArrayCopyAndAlwaysWrtbarIndex;
263
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_cardmark_incremental] = backwardReferenceArrayCopyAndAlwaysWrtbarIndex;
264
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_cardmark_and_oldcheck] = backwardReferenceArrayCopyAndAlwaysWrtbarIndex;
265
table->backwardReferenceArrayCopyIndex[j9gc_modron_wrtbar_satb] = backwardReferenceArrayCopyAndAlwaysWrtbarIndex;
266
267
/* Forward copies with type check on each element (check for ArrayStoreException) */
268
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_illegal] = copyVariantUndefinedIndex;
269
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_none] = forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex;
270
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_always] = forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex;
271
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_oldcheck] = forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex;
272
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_cardmark] = forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex;
273
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_cardmark_incremental] = forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex;
274
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_cardmark_and_oldcheck] = forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex;
275
table->forwardReferenceArrayCopyWithCheckIndex[j9gc_modron_wrtbar_satb] = forwardReferenceArrayCopyWithCheckAndAlwaysWrtbarIndex;
276
277
/* Forward copies with no type check */
278
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_illegal] = copyVariantUndefinedIndex;
279
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_none] = forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex;
280
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_always] = forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex;
281
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_oldcheck] = forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex;
282
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_cardmark] = forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex;
283
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_cardmark_incremental] = forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex;
284
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_cardmark_and_oldcheck] = forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex;
285
table->forwardReferenceArrayCopyWithoutCheckIndex[j9gc_modron_wrtbar_satb] = forwardReferenceArrayCopyWithoutCheckAndAlwaysWrtbarIndex;
286
}
287
288
} /* extern "C" */
289
290