Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/ArrayletObjectModel.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 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 "ArrayletLeafIterator.hpp"
24
#include "ArrayletObjectModel.hpp"
25
#include "GCExtensionsBase.hpp"
26
#include "ModronAssertions.h"
27
#include "ObjectModel.hpp"
28
29
bool
30
GC_ArrayletObjectModel::initialize(MM_GCExtensionsBase *extensions)
31
{
32
return GC_ArrayletObjectModelBase::initialize(extensions);
33
}
34
35
void
36
GC_ArrayletObjectModel::tearDown(MM_GCExtensionsBase *extensions)
37
{
38
GC_ArrayletObjectModelBase::tearDown(extensions);
39
}
40
41
void
42
GC_ArrayletObjectModel::AssertBadElementSize()
43
{
44
Assert_MM_unreachable();
45
}
46
47
void
48
GC_ArrayletObjectModel::AssertArrayletIsDiscontiguous(J9IndexableObject *objPtr)
49
{
50
#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)
51
if (!isDoubleMappingEnabled())
52
#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */
53
{
54
MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(_omrVM);
55
UDATA arrayletLeafSize = _omrVM->_arrayletLeafSize;
56
UDATA remainderBytes = getDataSizeInBytes(objPtr) % arrayletLeafSize;
57
if (0 != remainderBytes) {
58
Assert_MM_true((getSpineSize(objPtr) + remainderBytes + extensions->getObjectAlignmentInBytes()) > arrayletLeafSize);
59
}
60
}
61
}
62
63
void
64
GC_ArrayletObjectModel::AssertContiguousArrayletLayout(J9IndexableObject *objPtr)
65
{
66
Assert_MM_true(InlineContiguous == getArrayLayout(objPtr));
67
}
68
69
void
70
GC_ArrayletObjectModel::AssertDiscontiguousArrayletLayout(J9IndexableObject *objPtr)
71
{
72
ArrayLayout layout = getArrayLayout(objPtr);
73
Assert_MM_true((Discontiguous == layout) || (Hybrid == layout));
74
}
75
76
GC_ArrayletObjectModel::ArrayLayout
77
GC_ArrayletObjectModel::getArrayletLayout(J9Class* clazz, UDATA dataSizeInBytes, UDATA largestDesirableSpine)
78
{
79
ArrayLayout layout = Illegal;
80
MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(_omrVM);
81
UDATA objectAlignmentInBytes = extensions->getObjectAlignmentInBytes();
82
83
/* the spine need not contain a pointer to the data */
84
const UDATA minimumSpineSize = 0;
85
UDATA minimumSpineSizeAfterGrowing = minimumSpineSize;
86
if (extensions->isVLHGC()) {
87
/* CMVC 170688: Ensure that we don't try to allocate an inline contiguous array of a size which will overflow the region if it ever grows
88
* (easier to handle this case in the allocator than to special-case the collectors to know how to avoid this case)
89
* (currently, we only grow by a hashcode slot which is 4-bytes but will increase our size by the granule of alignment)
90
*/
91
minimumSpineSizeAfterGrowing += objectAlignmentInBytes;
92
}
93
94
/* CMVC 135307 : when checking for InlineContiguous layout, perform subtraction as adding to dataSizeInBytes could trigger overflow. */
95
if ((largestDesirableSpine == UDATA_MAX) || (dataSizeInBytes <= (largestDesirableSpine - minimumSpineSizeAfterGrowing - contiguousHeaderSize()))) {
96
layout = InlineContiguous;
97
if(0 == dataSizeInBytes) {
98
/* Zero sized NUA uses the discontiguous shape */
99
layout = Discontiguous;
100
}
101
} else {
102
UDATA arrayletLeafSize = _omrVM->_arrayletLeafSize;
103
UDATA lastArrayletBytes = dataSizeInBytes & (arrayletLeafSize - 1);
104
105
if (lastArrayletBytes > 0) {
106
/* determine how large the spine would be if this were a hybrid array */
107
UDATA numberArraylets = numArraylets(dataSizeInBytes);
108
bool align = shouldAlignSpineDataSection(clazz);
109
UDATA hybridSpineBytes = getSpineSize(clazz, Hybrid, numberArraylets, dataSizeInBytes, align);
110
UDATA adjustedHybridSpineBytes = extensions->objectModel.adjustSizeInBytes(hybridSpineBytes);
111
UDATA adjustedHybridSpineBytesAfterMove = adjustedHybridSpineBytes;
112
if (extensions->isVLHGC()) {
113
adjustedHybridSpineBytesAfterMove += objectAlignmentInBytes;
114
}
115
#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)
116
if (extensions->indexableObjectModel.isDoubleMappingEnabled()) {
117
layout = Discontiguous;
118
} else
119
#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */
120
/* if remainder data can fit in spine, make it hybrid */
121
if (adjustedHybridSpineBytesAfterMove <= largestDesirableSpine) {
122
/* remainder data can fit in spine, last arrayoid pointer points to empty data section in spine */
123
layout = Hybrid;
124
} else {
125
/* remainder data will go into an arraylet, last arrayoid pointer points to it */
126
layout = Discontiguous;
127
}
128
} else {
129
/* remainder is empty, so no arraylet allocated; last arrayoid pointer is set to MULL */
130
layout = Discontiguous;
131
}
132
}
133
return layout;
134
}
135
136
void
137
GC_ArrayletObjectModel::fixupInternalLeafPointersAfterCopy(J9IndexableObject *destinationPtr, J9IndexableObject *sourcePtr)
138
{
139
if (hasArrayletLeafPointers(destinationPtr)) {
140
GC_ArrayletLeafIterator leafIterator((J9JavaVM*)_omrVM->_language_vm, destinationPtr);
141
GC_SlotObject *leafSlotObject = NULL;
142
UDATA sourceStartAddress = (UDATA) sourcePtr;
143
UDATA sourceEndAddress = sourceStartAddress + getSizeInBytesWithHeader(destinationPtr);
144
145
while (NULL != (leafSlotObject = leafIterator.nextLeafPointer())) {
146
UDATA leafAddress = (UDATA)leafSlotObject->readReferenceFromSlot();
147
148
if ((sourceStartAddress < leafAddress) && (leafAddress < sourceEndAddress)) {
149
leafSlotObject->writeReferenceToSlot((J9Object*)((UDATA)destinationPtr + (leafAddress - sourceStartAddress)));
150
}
151
}
152
}
153
}
154
155
#if defined(J9VM_ENV_DATA64)
156
void
157
GC_ArrayletObjectModel::AssertArrayPtrIsIndexable(J9IndexableObject *arrayPtr)
158
{
159
MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(_omrVM);
160
Assert_MM_true(extensions->objectModel.isIndexable(J9GC_J9OBJECT_CLAZZ(arrayPtr, this)));
161
}
162
#endif /* defined(J9VM_ENV_DATA64) */
163
164