Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/ArrayletObjectModel.hpp
5990 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
/**
24
* @file
25
* @ingroup GC_Base
26
*/
27
#if !defined(ARRAYLETOBJECTMODEL_)
28
#define ARRAYLETOBJECTMODEL_
29
30
#include "j9.h"
31
#include "j9cfg.h"
32
#include "j9consts.h"
33
#include "modron.h"
34
#include "modronopt.h"
35
36
#include "ArrayletObjectModelBase.hpp"
37
#include "Bits.hpp"
38
#include "ForwardedHeader.hpp"
39
#include "Math.hpp"
40
#include "SlotObject.hpp"
41
42
class GC_ArrayletObjectModel : public GC_ArrayletObjectModelBase
43
{
44
/*
45
* Data members
46
*/
47
private:
48
protected:
49
public:
50
51
/*
52
* Function members
53
*/
54
private:
55
void AssertBadElementSize();
56
protected:
57
/* forward declare methods from parent class to avoid namespace issues */
58
MMINLINE uintptr_t
59
getSpineSizeWithoutHeader(ArrayLayout layout, uintptr_t numberArraylets, uintptr_t dataSize, bool alignData)
60
{
61
return GC_ArrayletObjectModelBase::getSpineSizeWithoutHeader(layout, numberArraylets, dataSize, alignData);
62
}
63
public:
64
/* forward declare methods from parent class to avoid namespace issues */
65
MMINLINE uintptr_t
66
arrayletSize(J9IndexableObject *objPtr, uintptr_t index, uintptr_t dataSizeInBytes, uintptr_t numberOfArraylets)
67
{
68
return GC_ArrayletObjectModelBase::arrayletSize(objPtr, index, dataSizeInBytes, numberOfArraylets);
69
}
70
MMINLINE uintptr_t
71
numArraylets(uintptr_t unadjustedDataSizeInBytes)
72
{
73
return GC_ArrayletObjectModelBase::numArraylets(unadjustedDataSizeInBytes);
74
}
75
76
/**
77
* Get the header size for contiguous arrays
78
* @return header size
79
*/
80
MMINLINE uintptr_t
81
contiguousHeaderSize()
82
{
83
return compressObjectReferences() ? sizeof(J9IndexableObjectContiguousCompressed) : sizeof(J9IndexableObjectContiguousFull);
84
}
85
86
/**
87
* Get the header size for discontiguous arrays
88
* @return header size
89
*/
90
MMINLINE uintptr_t
91
discontiguousHeaderSize()
92
{
93
return compressObjectReferences() ? sizeof(J9IndexableObjectDiscontiguousCompressed) : sizeof(J9IndexableObjectDiscontiguousFull);
94
}
95
96
/**
97
* Get the spine size for the given indexable object
98
* @param objPtr Pointer to an array object
99
* @return The total size in bytes of objPtr's array spine;
100
* includes header, arraylet ptrs, and (if present) padding & inline data
101
*/
102
MMINLINE uintptr_t
103
getSpineSize(J9IndexableObject* objPtr)
104
{
105
ArrayLayout layout = getArrayLayout(objPtr);
106
return getSpineSize(objPtr, layout);
107
}
108
109
/**
110
* Get the spine size for an arraylet with these properties
111
* @param J9Class The class of the array.
112
* @param layout The layout of the indexable object
113
* @param numberArraylets Number of arraylets for this indexable object
114
* @param dataSize How many elements are in the indexable object
115
* @param alignData Should the data section be aligned
116
* @return spineSize The actual size in byte of the spine
117
*/
118
MMINLINE uintptr_t
119
getSpineSize(J9Class *clazzPtr, ArrayLayout layout, uintptr_t numberArraylets, uintptr_t dataSize, bool alignData)
120
{
121
uintptr_t result = getHeaderSize(clazzPtr, layout) + getSpineSizeWithoutHeader(layout, numberArraylets, dataSize, alignData);
122
return result;
123
}
124
125
/**
126
* Return the total number of arraylets for the given indexable object
127
* @param objPtr Pointer to an array object
128
* @return the number of arraylets used for an array of dataSizeInBytes bytes
129
*/
130
MMINLINE uintptr_t
131
numArraylets(J9IndexableObject *objPtr)
132
{
133
return numArraylets(getDataSizeInBytes(objPtr));
134
}
135
136
/**
137
* Check the given indexable object is inline contiguous
138
* @param objPtr Pointer to an array object
139
* @return true of array is inline contiguous
140
*/
141
MMINLINE bool
142
isInlineContiguousArraylet(J9IndexableObject *objPtr)
143
{
144
return (getArrayLayout(objPtr) == InlineContiguous);
145
}
146
147
/**
148
* Get the number of discontiguous arraylets for the given indexable object
149
* @param objPtr Pointer to an array object
150
* @return the number of arraylets stored external to the spine.
151
*/
152
MMINLINE uintptr_t
153
numExternalArraylets(J9IndexableObject *objPtr)
154
{
155
ArrayLayout layout = getArrayLayout(objPtr);
156
if (layout == InlineContiguous) {
157
return 0;
158
}
159
160
uintptr_t numberArraylets = numArraylets(objPtr);
161
if (layout == Hybrid) {
162
/* last arrayoid pointer points into spine (remainder data is contiguous with header) */
163
numberArraylets -= 1;
164
} else if (layout == Discontiguous) {
165
/* Data fits exactly within a whole number of arraylets */
166
AssertArrayletIsDiscontiguous(objPtr);
167
}
168
169
return numberArraylets;
170
}
171
172
/**
173
* Get the total number of bytes consumed by arraylets external to the
174
* given indexable object.
175
* @param objPtr Pointer to an array object
176
* @return the number of bytes consumed external to the spine
177
*/
178
MMINLINE uintptr_t
179
externalArrayletsSize(J9IndexableObject *objPtr)
180
{
181
uintptr_t numberArraylets = numExternalArraylets(objPtr);
182
183
return numberArraylets * _omrVM->_arrayletLeafSize;
184
}
185
186
/**
187
* Determine if the specified array object includes any arraylet leaf pointers.
188
* @param objPtr[in] the object to test
189
* @return true if the array has any internal or external leaf pointers, false otherwise
190
*/
191
MMINLINE bool
192
hasArrayletLeafPointers(J9IndexableObject *objPtr)
193
{
194
/* Contiguous arraylet has no implicit leaf pointer */
195
return !isInlineContiguousArraylet(objPtr);
196
}
197
198
199
/**
200
* Get the size in bytes for the arraylet at index in indexable object objPtr
201
* @param objPtr Pointer to an array object
202
* @param index the index in question. 0<=index<numArraylets(objPtr)
203
* @return the size of the indexth arraylet
204
*/
205
MMINLINE uintptr_t
206
arrayletSize(J9IndexableObject *objPtr, uintptr_t index)
207
{
208
uintptr_t dataSizeInBytes = getDataSizeInBytes(objPtr);
209
uintptr_t numberOfArraylets = numArraylets(dataSizeInBytes);
210
return arrayletSize(objPtr, index, dataSizeInBytes, numberOfArraylets);
211
}
212
213
/**
214
* Get the spine size for the given indexable object
215
* @param objPtr Pointer to an array object
216
* @param layout layout for array object
217
* @return The total size in bytes of objPtr's array spine;
218
* includes header, arraylet ptrs, and (if present) padding & inline data
219
*/
220
MMINLINE uintptr_t
221
getSpineSize(J9IndexableObject* objPtr, ArrayLayout layout)
222
{
223
return getSpineSize(J9GC_J9OBJECT_CLAZZ(objPtr, this), layout, getSizeInElements(objPtr));
224
}
225
226
/**
227
* Get the spine size for the given indexable object
228
* @param clazzPtr Pointer to the preserved J9Class, used in scavenger
229
* @param layout layout for array object
230
* @param size Size of indexable object
231
* @return The total size in bytes of objPtr's array spine;
232
* includes header, arraylet ptrs, and (if present) padding & inline data
233
*/
234
MMINLINE uintptr_t
235
getSpineSize(J9Class *clazzPtr, ArrayLayout layout, uintptr_t size)
236
{
237
return getHeaderSize(clazzPtr, layout) + getSpineSizeWithoutHeader(clazzPtr, layout, size);
238
}
239
240
/**
241
* Get the spine size without header for the given indexable object
242
* @param clazzPtr Pointer to the preserved J9Class, used in scavenger
243
* @param layout layout for array object
244
* @param size Size of indexable object
245
* @return The size in bytes of objPtr's array spine without header;
246
* includes arraylet ptrs, padding and inline data (if any is present)
247
*/
248
MMINLINE uintptr_t
249
getSpineSizeWithoutHeader(J9Class *clazzPtr, ArrayLayout layout, uintptr_t size)
250
{
251
uintptr_t dataSize = getDataSizeInBytes(clazzPtr, size);
252
uintptr_t numberArraylets = numArraylets(dataSize);
253
bool alignData = shouldAlignSpineDataSection(clazzPtr);
254
return getSpineSizeWithoutHeader(layout, numberArraylets, dataSize, alignData);
255
}
256
257
#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)
258
/**
259
* Checks if arraylet falls into corner case of discontigous data
260
* Arraylet possible cases:
261
* 0: Empty arraylets, in this case the array is represented as
262
* an arraylet however it does not contain any data, but it
263
* does contain an arrayoid (leaf pointer) that points to NULL.
264
* Even though this case is represented as a discontiguous arraylet
265
* internally due to its implementation, it is actually a contiguous
266
* array with length zero.
267
* 1: The total data size in arraylet is between 0 and region
268
* size. Small enough to make the arraylet layout contiguous,
269
* in which case this function is unreachable.
270
* 2: The total data size in arraylet is exacly the same size
271
* of a region. In this case we do not need to double
272
* map since we already have a contiguous representation of the
273
* data at first leaf.
274
* 3: Similar to first case, the data portion is slightly smaller than
275
* a region size, however not small enough to include header and data
276
* at the same region to make it contiguous. In which case we would
277
* have one leaf, where we also do not need to double map.
278
* 4: The total data size in arraylet is stricly greater than one region;
279
* however, not multiple of region size. Since with enabled double map
280
* layout is always discontiguous, we would have 2 or more arraylet leaves
281
* therefore we always double map.
282
* 5: The total data size in arraylet is stricly greater than one region and
283
* multiple of region size. Here we would have 2 or more arraylet leaves
284
* containing data. We always double map in this case.
285
*
286
* @param spine Pointer to an array indexable object spine
287
* @return false in case corner cases 0, 2 or 3 are valid. On the other hand,
288
* if cases 4 or 5 are true, the function returns true.
289
*/
290
MMINLINE bool
291
isArrayletDataDiscontiguous(J9IndexableObject *spine)
292
{
293
return numArraylets(spine) > 1;
294
}
295
296
/**
297
* Checks if arraylet falls into corner case of contiguous data
298
*
299
* @param spine Pointer to an array indexable object spine
300
* @return true in case corner cases 2 or 3 are valid. On the other hand,
301
* if cases 0, 4 or 5 are true, the function returns false.
302
*/
303
MMINLINE bool
304
isArrayletDataContiguous(J9IndexableObject *spine)
305
{
306
return (1 == numArraylets(spine)) && (getSizeInElements(spine) > 0);
307
}
308
#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */
309
310
/**
311
* We can't use memcpy because it may be not atomic for pointers, use this function instead
312
* Copy data in uintptr_t words
313
* If length is not times of uintptr_t one more word is copied
314
* @param destAddr address copy to
315
* @param sourceAddr address copy from
316
* @param lengthInBytes requested size in bytes
317
*/
318
MMINLINE void
319
copyInWords (uintptr_t *destAddr, uintptr_t *sourceAddr, uintptr_t lengthInBytes)
320
{
321
uintptr_t lengthInWords = lengthInBytes / sizeof(uintptr_t);
322
while (lengthInWords--) {
323
*destAddr++ = *sourceAddr++;
324
}
325
}
326
327
/**
328
* Returns the header size of an arraylet for a given layout.
329
* This method is actually private, but since ArrayLayout is public,
330
* it cannot be declared in private section.
331
* @param layout Layout of the arraylet
332
* @return Size of header in bytes
333
*/
334
MMINLINE uintptr_t
335
getHeaderSize(J9Class *clazzPtr, ArrayLayout layout)
336
{
337
uintptr_t headerSize = contiguousHeaderSize();
338
if (layout != InlineContiguous) {
339
headerSize = discontiguousHeaderSize();
340
}
341
return headerSize;
342
}
343
344
/**
345
* Returns the size of data in an indexable object, in bytes, including leaves and alignment
346
* padding, excluding the header, or UDATA_MAX if an overflow occurs.
347
* @param arrayPtr Pointer to the indexable object whose size is required
348
* @return Aligned size in bytes excluding the header, or UDATA_MAX if an overflow occurs
349
*/
350
MMINLINE uintptr_t
351
getDataSizeInBytes(J9IndexableObject *arrayPtr)
352
{
353
return getDataSizeInBytes(J9GC_J9OBJECT_CLAZZ(arrayPtr, this), getSizeInElements(arrayPtr));
354
}
355
356
/**
357
* Returns the size of data in an indexable object, in bytes, including leaves and alignment
358
* padding, excluding the header, or UDATA_MAX if an overflow occurs.
359
* @param clazzPtr Pointer to the class of the object
360
* @param numberOfElements size from indexable object
361
* @return Aligned size in bytes excluding the header, or UDATA_MAX if an overflow occurs
362
*/
363
MMINLINE uintptr_t
364
getDataSizeInBytes(J9Class *clazzPtr, uintptr_t numberOfElements)
365
{
366
uintptr_t stride = J9ARRAYCLASS_GET_STRIDE(clazzPtr);
367
uintptr_t size = numberOfElements * stride;
368
uintptr_t alignedSize = UDATA_MAX;
369
if ((size / stride) == numberOfElements) {
370
alignedSize = MM_Math::roundToSizeofUDATA(size);
371
if (alignedSize < size) {
372
alignedSize = UDATA_MAX;
373
}
374
}
375
return alignedSize;
376
}
377
378
/**
379
* Get the size from the header for the given indexable object
380
* @param objPtr Pointer to an array object
381
* @return the size
382
*/
383
MMINLINE uintptr_t
384
getArraySize(J9IndexableObject *objPtr)
385
{
386
return compressObjectReferences()
387
? ((J9IndexableObjectContiguousCompressed*)objPtr)->size
388
: ((J9IndexableObjectContiguousFull*)objPtr)->size;
389
}
390
391
/**
392
* Get the layout for the given indexable object
393
* @param objPtr Pointer to an array object
394
* @return the ArrayLayout for objectPtr
395
*/
396
MMINLINE ArrayLayout
397
getArrayLayout(J9IndexableObject *objPtr)
398
{
399
GC_ArrayletObjectModel::ArrayLayout layout = GC_ArrayletObjectModel::InlineContiguous;
400
/* Trivial check for InlineContiguous. */
401
if (0 != getArraySize(objPtr)) {
402
return GC_ArrayletObjectModel::InlineContiguous;
403
}
404
405
/* Check if the objPtr is in the allowed arraylet range. */
406
if (((uintptr_t)objPtr >= (uintptr_t)_arrayletRangeBase) && ((uintptr_t)objPtr < (uintptr_t)_arrayletRangeTop)) {
407
uintptr_t dataSizeInBytes = getDataSizeInBytes(objPtr);
408
J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objPtr, this);
409
layout = getArrayletLayout(clazz, dataSizeInBytes);
410
}
411
return layout;
412
}
413
414
MMINLINE ArrayLayout
415
getArrayletLayout(J9Class* clazz, uintptr_t dataSizeInBytes)
416
{
417
return getArrayletLayout(clazz, dataSizeInBytes, _largestDesirableArraySpineSize);
418
}
419
420
/**
421
* Get the layout of an indexable object given it's class, data size in bytes and the subspace's largestDesirableSpine.
422
* @param clazz The class of the object stored in the array.
423
* @param dataSizeInBytes the size in bytes of the data of the array.
424
* @param largestDesirableSpine The largest desirable spine of the arraylet.
425
*/
426
ArrayLayout getArrayletLayout(J9Class* clazz, uintptr_t dataSizeInBytes, uintptr_t largestDesirableSpine);
427
428
/**
429
* Perform a safe memcpy of one array to another.
430
* Assumes that destObject and srcObject have the same shape and size.
431
*/
432
MMINLINE void
433
memcpyArray(J9IndexableObject *destObject, J9IndexableObject *srcObject)
434
{
435
if (InlineContiguous == getArrayLayout(srcObject)) {
436
/* assume that destObject must have the same shape! */
437
uintptr_t sizeInBytes = getSizeInBytesWithoutHeader(srcObject);
438
uintptr_t* srcData = (uintptr_t*)getDataPointerForContiguous(srcObject);
439
uintptr_t* destData = (uintptr_t*)getDataPointerForContiguous(destObject);
440
copyInWords(destData, srcData, sizeInBytes);
441
} else {
442
bool const compressed = compressObjectReferences();
443
uintptr_t arrayletCount = numArraylets(srcObject);
444
fj9object_t *srcArraylets = getArrayoidPointer(srcObject);
445
fj9object_t *destArraylets = getArrayoidPointer(destObject);
446
for (uintptr_t i = 0; i < arrayletCount; i++) {
447
GC_SlotObject srcSlotObject(_omrVM, GC_SlotObject::addToSlotAddress(srcArraylets, i, compressed));
448
GC_SlotObject destSlotObject(_omrVM, GC_SlotObject::addToSlotAddress(destArraylets, i, compressed));
449
void* srcLeafAddress = srcSlotObject.readReferenceFromSlot();
450
void* destLeafAddress = destSlotObject.readReferenceFromSlot();
451
452
453
uintptr_t copySize = _omrVM->_arrayletLeafSize;
454
455
if (i == arrayletCount - 1) {
456
copySize = arrayletSize(srcObject, i);
457
}
458
copyInWords((uintptr_t *)destLeafAddress, (uintptr_t *)srcLeafAddress, copySize);
459
}
460
}
461
}
462
463
/**
464
* Perform a memcpy from a primitive array to native memory.
465
* Assumes that the destination is large enough.
466
*
467
* @param destData the native memory buffer to copy into
468
* @param srcObject the array to copy from
469
* @param elementIndex the start index (element-relative) to copy from
470
* @param elementCount the number of elements of data to copy
471
*/
472
/*MMINLINE*/ void
473
memcpyFromArray(void *destData, J9IndexableObject *srcObject, int32_t elementIndex, int32_t elementCount)
474
{
475
uintptr_t elementSize = J9ARRAYCLASS_GET_STRIDE(J9GC_J9OBJECT_CLAZZ(srcObject, this));
476
if (isInlineContiguousArraylet(srcObject)) {
477
// If the data is stored contiguously, then a simple copy is sufficient.
478
void* srcData = getDataPointerForContiguous(srcObject);
479
switch(elementSize)
480
{
481
case 1:
482
// byte/boolean
483
{
484
uint8_t* srcCursor = ((uint8_t*)srcData) + elementIndex;
485
uint8_t* destCursor = (uint8_t*)destData;
486
int32_t count = elementCount;
487
while(count--) {
488
*destCursor++ = *srcCursor++;
489
}
490
}
491
break;
492
493
case 2:
494
// short/char
495
{
496
uint16_t* srcCursor = ((uint16_t*)srcData) + elementIndex;
497
uint16_t* destCursor = (uint16_t*)destData;
498
int32_t count = elementCount;
499
while(count--) {
500
*destCursor++ = *srcCursor++;
501
}
502
}
503
break;
504
505
case 4:
506
// int/float
507
{
508
uint32_t* srcCursor = ((uint32_t*)srcData) + elementIndex;
509
uint32_t* destCursor = (uint32_t*)destData;
510
uint32_t count = elementCount;
511
while(count--) {
512
*destCursor++ = *srcCursor++;
513
}
514
}
515
break;
516
517
case 8:
518
// long/double
519
{
520
U_64* srcCursor = ((U_64*)srcData) + elementIndex;
521
U_64* destCursor = (U_64*)destData;
522
uint32_t count = elementCount;
523
while(count--) {
524
*destCursor++ = *srcCursor++;
525
}
526
}
527
break;
528
529
default :
530
// unreachable since we currently do not expect anything other than primitive arrays to be using them.
531
{
532
AssertBadElementSize();
533
}
534
break;
535
}
536
} else {
537
bool const compressed = compressObjectReferences();
538
fj9object_t *srcArraylets = getArrayoidPointer(srcObject);
539
void *outerDestCursor = destData;
540
uint32_t outerCount = elementCount;
541
uintptr_t arrayletLeafElements = _omrVM->_arrayletLeafSize / elementSize;
542
uintptr_t arrayletIndex = elementIndex / arrayletLeafElements;
543
uintptr_t arrayletElementOffset = elementIndex % arrayletLeafElements;
544
while(outerCount > 0) {
545
GC_SlotObject srcSlotObject(_omrVM, GC_SlotObject::addToSlotAddress(srcArraylets, arrayletIndex++, compressed));
546
void* srcLeafAddress = srcSlotObject.readReferenceFromSlot();
547
uint32_t innerCount = outerCount;
548
// Can we fulfill the remainder of the copy from this page?
549
if (innerCount + arrayletElementOffset > arrayletLeafElements) {
550
// Copy as much as we can
551
innerCount = (uint32_t)(arrayletLeafElements - arrayletElementOffset);
552
}
553
switch(elementSize)
554
{
555
case 1:
556
// byte/boolean
557
{
558
uint8_t* srcCursor = ((uint8_t*)srcLeafAddress) + arrayletElementOffset;
559
uint8_t* destCursor = (uint8_t*)outerDestCursor;
560
outerCount -= innerCount; // Decrement the outer count before looping
561
while(innerCount--) {
562
*destCursor++ = *srcCursor++;
563
}
564
outerDestCursor = (void*)destCursor;
565
arrayletElementOffset = 0; // Consumed
566
}
567
break;
568
569
case 2:
570
// short/char
571
{
572
uint16_t* srcCursor = ((uint16_t*)srcLeafAddress) + arrayletElementOffset;
573
uint16_t* destCursor = (uint16_t*)outerDestCursor;
574
outerCount -= innerCount; // Decrement the outer count before looping
575
while(innerCount--) {
576
*destCursor++ = *srcCursor++;
577
}
578
outerDestCursor = (void*)destCursor;
579
arrayletElementOffset = 0;
580
}
581
break;
582
583
case 4:
584
// int/float
585
{
586
uint32_t* srcCursor = ((uint32_t*)srcLeafAddress) + arrayletElementOffset;
587
uint32_t* destCursor = (uint32_t*)outerDestCursor;
588
outerCount -= innerCount; // Decrement the outer count before looping
589
while(innerCount--) {
590
*destCursor++ = *srcCursor++;
591
}
592
outerDestCursor = (void*)destCursor;
593
arrayletElementOffset = 0;
594
}
595
break;
596
597
case 8:
598
// long/double
599
{
600
U_64* srcCursor = ((U_64*)srcLeafAddress) + arrayletElementOffset;
601
U_64* destCursor = (U_64*)outerDestCursor;
602
outerCount -= innerCount; // Decrement the outer count before looping
603
while(innerCount--) {
604
*destCursor++ = *srcCursor++;
605
}
606
outerDestCursor = (void*)destCursor;
607
arrayletElementOffset = 0;
608
}
609
break;
610
611
default :
612
// unreachable since we currently do not expect anything other than primitive arrays to be using them.
613
{
614
AssertBadElementSize();
615
}
616
break;
617
}
618
}
619
}
620
}
621
622
/**
623
* Perform a memcpy from native memory to a primitive array.
624
* Assumes that the destination is large enough.
625
*
626
* @param destObject the array to copy to
627
* @param elementIndex the start index (element-relative) to copy from
628
* @param elementCount the number of elements of data to copy
629
* @param srcData the native memory buffer to copy from
630
*/
631
MMINLINE void
632
memcpyToArray(J9IndexableObject *destObject, int32_t elementIndex, int32_t elementCount, void *srcData)
633
{
634
uintptr_t elementSize = J9ARRAYCLASS_GET_STRIDE(J9GC_J9OBJECT_CLAZZ(destObject, this));
635
if (isInlineContiguousArraylet(destObject)) {
636
// If the data is stored contiguously, then a simple copy is sufficient.
637
void* destData = getDataPointerForContiguous(destObject);
638
switch(elementSize)
639
{
640
case 1:
641
// byte/boolean
642
{
643
uint8_t* srcCursor = (uint8_t*)srcData;
644
uint8_t* destCursor = ((uint8_t*)destData) + elementIndex;
645
int32_t count = elementCount;
646
while(count--) {
647
*destCursor++ = *srcCursor++;
648
}
649
}
650
break;
651
652
case 2:
653
// short/char
654
{
655
uint16_t* srcCursor = (uint16_t*)srcData;
656
uint16_t* destCursor = ((uint16_t*)destData) + elementIndex;
657
int32_t count = elementCount;
658
while(count--) {
659
*destCursor++ = *srcCursor++;
660
}
661
}
662
break;
663
664
case 4:
665
// int/float
666
{
667
uint32_t* srcCursor = (uint32_t*)srcData;
668
uint32_t* destCursor = ((uint32_t*)destData) + elementIndex;
669
uint32_t count = elementCount;
670
while(count--) {
671
*destCursor++ = *srcCursor++;
672
}
673
}
674
break;
675
676
case 8:
677
// long/double
678
{
679
U_64* srcCursor = (U_64*)srcData;
680
U_64* destCursor = ((U_64*)destData) + elementIndex;
681
uint32_t count = elementCount;
682
while(count--) {
683
*destCursor++ = *srcCursor++;
684
}
685
}
686
break;
687
688
default :
689
// unreachable since we currently do not expect anything other than primitive arrays to be using them.
690
{
691
AssertBadElementSize();
692
}
693
break;
694
}
695
} else {
696
bool const compressed = compressObjectReferences();
697
fj9object_t *destArraylets = getArrayoidPointer(destObject);
698
void *outerSrcCursor = srcData;
699
uint32_t outerCount = elementCount;
700
uintptr_t arrayletLeafElements = _omrVM->_arrayletLeafSize / elementSize;
701
uintptr_t arrayletIndex = elementIndex / arrayletLeafElements;
702
uintptr_t arrayletElementOffset = elementIndex % arrayletLeafElements;
703
while(outerCount > 0) {
704
GC_SlotObject destSlotObject(_omrVM, GC_SlotObject::addToSlotAddress(destArraylets, arrayletIndex++, compressed));
705
void* destLeafAddress = destSlotObject.readReferenceFromSlot();
706
uint32_t innerCount = outerCount;
707
// Can we fulfill the remainder of the copy from this page?
708
if (innerCount + arrayletElementOffset > arrayletLeafElements) {
709
// Copy as much as we can
710
innerCount = (uint32_t)(arrayletLeafElements - arrayletElementOffset);
711
}
712
switch(elementSize)
713
{
714
case 1:
715
// byte/boolean
716
{
717
uint8_t* srcCursor = (uint8_t*)outerSrcCursor;
718
uint8_t* destCursor = ((uint8_t*)destLeafAddress) + arrayletElementOffset;
719
outerCount -= innerCount; // Decrement the outer count before looping
720
while(innerCount--) {
721
*destCursor++ = *srcCursor++;
722
}
723
outerSrcCursor = (void*)srcCursor;
724
arrayletElementOffset = 0; // Consumed
725
}
726
break;
727
728
case 2:
729
// short/char
730
{
731
uint16_t* srcCursor = (uint16_t*)outerSrcCursor;
732
uint16_t* destCursor = ((uint16_t*)destLeafAddress) + arrayletElementOffset;
733
outerCount -= innerCount; // Decrement the outer count before looping
734
while(innerCount--) {
735
*destCursor++ = *srcCursor++;
736
}
737
outerSrcCursor = (void*)srcCursor;
738
arrayletElementOffset = 0;
739
}
740
break;
741
742
case 4:
743
// int/float
744
{
745
uint32_t* srcCursor = (uint32_t*)outerSrcCursor;
746
uint32_t* destCursor = ((uint32_t*)destLeafAddress) + arrayletElementOffset;
747
outerCount -= innerCount; // Decrement the outer count before looping
748
while(innerCount--) {
749
*destCursor++ = *srcCursor++;
750
}
751
outerSrcCursor = (void*)srcCursor;
752
arrayletElementOffset = 0;
753
}
754
break;
755
756
case 8:
757
// long/double
758
{
759
U_64* srcCursor = (U_64*)outerSrcCursor;
760
U_64* destCursor = ((U_64*)destLeafAddress) + arrayletElementOffset;
761
outerCount -= innerCount; // Decrement the outer count before looping
762
while(innerCount--) {
763
*destCursor++ = *srcCursor++;
764
}
765
outerSrcCursor = (void*)srcCursor;
766
arrayletElementOffset = 0;
767
}
768
break;
769
770
default :
771
// unreachable since we currently do not expect anything other than primitive arrays to be using them.
772
{
773
AssertBadElementSize();
774
}
775
break;
776
}
777
}
778
}
779
}
780
781
/**
782
* Returns the size of an indexable object, in bytes, excluding the header.
783
* @param arrayPtr Pointer to the indexable object whose size is required
784
* @return Size of object in bytes excluding the header
785
*/
786
MMINLINE uintptr_t
787
getSizeInBytesWithoutHeader(J9IndexableObject *arrayPtr)
788
{
789
ArrayLayout layout = getArrayLayout(arrayPtr);
790
return getSpineSizeWithoutHeader(J9GC_J9OBJECT_CLAZZ(arrayPtr, this), layout, getSizeInElements(arrayPtr));
791
}
792
793
/**
794
* Returns the size of an indexable object, in bytes, including the header.
795
* WARNING: This implementation assumes the arraylet layout is InlineContiguous.
796
* @param clazz Pointer to the preserved indexable object class which may not be intact
797
* @param numberOfElements size from indexable object
798
* @return Size of object in bytes including the header
799
*/
800
MMINLINE uintptr_t
801
getSizeInBytesWithHeader(J9Class *clazz, uintptr_t numberOfElements)
802
{
803
ArrayLayout layout = InlineContiguous;
804
if(0 == numberOfElements) {
805
layout = Discontiguous;
806
}
807
return getSizeInBytesWithHeader(clazz, layout, numberOfElements);
808
}
809
810
/**
811
* Returns the size of an indexable object, in bytes, including the header.
812
* @param clazz Pointer to the preserved indexable object class which may not be intact
813
* @param flags Indexable object flags
814
* @param numberOfElements size from indexable object
815
* @return Size of object in bytes including the header
816
*/
817
MMINLINE uintptr_t
818
getSizeInBytesWithHeader(J9Class *clazz, ArrayLayout layout, uintptr_t numberOfElements)
819
{
820
return getSpineSize(clazz, layout, numberOfElements);
821
}
822
823
/**
824
* Returns the size of an indexable object, in bytes, including the header.
825
* @param arrayPtr Pointer to the indexable object whose size is required
826
* @return Size of object in bytes including the header
827
*/
828
MMINLINE uintptr_t
829
getSizeInBytesWithHeader(J9IndexableObject *arrayPtr)
830
{
831
ArrayLayout layout = getArrayLayout(arrayPtr);
832
return getSpineSize(J9GC_J9OBJECT_CLAZZ(arrayPtr, this), layout, getSizeInElements(arrayPtr));
833
}
834
835
#if defined(J9VM_ENV_DATA64)
836
837
/**
838
* Gets data pointer of a contiguous indexable object.
839
* Helper to get dataAddr field of contiguous indexable objects.
840
*
841
* @return Pointer which points to indexable object data
842
*/
843
MMINLINE void **
844
dataAddrSlotForContiguous(J9IndexableObject *arrayPtr)
845
{
846
AssertContiguousArrayletLayout(arrayPtr);
847
bool const compressed = compressObjectReferences();
848
void **dataAddrPtr = NULL;
849
if (compressed) {
850
dataAddrPtr = &((J9IndexableObjectContiguousCompressed *)arrayPtr)->dataAddr;
851
} else {
852
dataAddrPtr = &((J9IndexableObjectContiguousFull *)arrayPtr)->dataAddr;
853
}
854
return dataAddrPtr;
855
}
856
857
/**
858
* Gets data pointer of a discontiguous indexable object.
859
* Helper to get dataAddr field of discontiguous indexable objects.
860
*
861
* @return Pointer which points to discontiguous indexable object data
862
*/
863
MMINLINE void **
864
dataAddrSlotForDiscontiguous(J9IndexableObject *arrayPtr)
865
{
866
/* If double mapping is enabled only, arraylet will have a discontiguous layout.
867
* If sparse-heap is enabled, arraylet will have a contiguous layout. For now
868
* we can't simply Assert only the discontiguous case because there could also
869
* exist hybrid arraylets (which will be dicontinued in the future) */
870
bool const compressed = compressObjectReferences();
871
void **dataAddrPtr = NULL;
872
if (compressed) {
873
dataAddrPtr = &((J9IndexableObjectDiscontiguousCompressed *)arrayPtr)->dataAddr;
874
} else {
875
dataAddrPtr = &((J9IndexableObjectDiscontiguousFull *)arrayPtr)->dataAddr;
876
}
877
return dataAddrPtr;
878
}
879
880
/**
881
* Sets data pointer of a contiguous indexable object.
882
* Sets the data pointer of a contiguous indexable object; in this case
883
* dataAddr will point directly into the data right after dataAddr field
884
* (data resides in heap).
885
*
886
* @param arrayPtr Pointer to the indexable object whose size is required
887
*/
888
MMINLINE void
889
setDataAddrForContiguous(J9IndexableObject *arrayPtr)
890
{
891
void **dataAddrPtr = dataAddrSlotForContiguous(arrayPtr);
892
void *dataAddr = (void *)((uintptr_t)arrayPtr + contiguousHeaderSize());
893
*dataAddrPtr = dataAddr;
894
}
895
896
/**
897
* Sets data pointer of a discontiguous indexable object.
898
* Sets the data pointer of a discontiguous indexable object; in this case
899
* dataAddr will point to the contiguous representation of the data
900
* which resides outside the heap (assuming double map/sparse-heap is enabled).
901
* In case double map is disabled, the dataAddr will point to the first arrayoid
902
* of the discontiguous indexable object, which also resides right after dataAddr
903
* field.
904
*
905
* @param arrayPtr Pointer to the indexable object whose size is required
906
* @param address Pointer which points to indexable object data
907
*/
908
MMINLINE void
909
setDataAddrForDiscontiguous(J9IndexableObject *arrayPtr, void *address)
910
{
911
/* If double mapping is enabled only, arraylet will have a discontiguous layout.
912
* If sparse-heap is enabled, arraylet will have a contiguous layout. For now
913
* we can't simply Assert only the discontiguous case because there could also
914
* exist hybrid arraylets (which will be dicontinued in the future) */
915
void *calculatedDataAddr = address;
916
void **dataAddrPtr = dataAddrSlotForDiscontiguous(arrayPtr);
917
918
/* If calculatedDataAddr is NULL then we make dataAddr point to the first arrayoid */
919
/* Later on, when sparse-heap is enabled by default, we must assert dataAddr is not NULL */
920
if (NULL == calculatedDataAddr) {
921
calculatedDataAddr = (void *)((uintptr_t)arrayPtr + discontiguousHeaderSize());
922
}
923
924
*dataAddrPtr = calculatedDataAddr;
925
}
926
927
/**
928
* Asserts that an indexable object pointer is indeed an indexable object
929
*
930
* @param arrayPtr Pointer to the indexable object
931
*/
932
void AssertArrayPtrIsIndexable(J9IndexableObject *arrayPtr);
933
934
/**
935
* Asserts that the dataAddr field of the indexable object is correct.
936
*
937
* @param arrayPtr Pointer to the indexable object
938
* @param dataAddr Pointer to indexable object data address
939
*/
940
MMINLINE bool
941
isCorrectDataAddrContiguous(J9IndexableObject *arrayPtr, void *dataAddr)
942
{
943
return dataAddr == (void *)((uintptr_t)arrayPtr + contiguousHeaderSize());
944
}
945
946
/**
947
* Asserts that an indexable object pointer is indeed an indexable object
948
*
949
* @param arrayPtr Pointer to the indexable object
950
* @param dataAddr Pointer to indexable object data address
951
*/
952
MMINLINE bool
953
isCorrectDataAddrDiscontiguous(J9IndexableObject *arrayPtr, void *dataAddr)
954
{
955
return dataAddr == (void *)((uintptr_t)arrayPtr + discontiguousHeaderSize());
956
}
957
958
/**
959
* Returns data pointer associated with a contiguous Indexable object.
960
* Data pointer will always be pointing at the arraylet data. In this
961
* case the data pointer will be pointing to address immediately after
962
* the header.
963
*
964
* @param arrayPtr Pointer to the indexable object whose size is required
965
* @return data address associated with the Indexable object
966
*/
967
MMINLINE void *
968
getDataAddrForContiguous(J9IndexableObject *arrayPtr)
969
{
970
void *dataAddr = *dataAddrSlotForContiguous(arrayPtr);
971
return dataAddr;
972
}
973
974
/**
975
* Returns data pointer associated with a discontiguous Indexable object.
976
* Data pointer will always be pointing at the arraylet data. In this
977
* case the data pointer will be pointing to address immediately after
978
* the header (the arrayoid), except when double mapping or sparse-heap
979
* is enabled. In these cases, the data pointer will point to the
980
* contiguous representation of the data; hence returning that pointer.
981
*
982
* @param arrayPtr Pointer to the indexable object whose size is required
983
* @return data address associated with the Indexable object
984
*/
985
MMINLINE void *
986
getDataAddrForDiscontiguous(J9IndexableObject *arrayPtr)
987
{
988
/* If double mapping is enabled only, arraylet will have a discontiguous layout.
989
* If sparse-heap is enabled, arraylet will have a contiguous layout. For now we
990
* Assert only the discontiguous case until sparse-heap is introduced. */
991
AssertDiscontiguousArrayletLayout(arrayPtr);
992
void *dataAddr = *dataAddrSlotForDiscontiguous(arrayPtr);
993
return dataAddr;
994
}
995
996
/**
997
* Returns data pointer associated with the Indexable object.
998
* Data pointer will always be pointing at the arraylet data. In all
999
* cases the data pointer will be pointing to address immediately after
1000
* the header, except when double mapping is enabled. In this case,
1001
* if double mapping is enabled and arraylet was double mapped
1002
* successfully the data pointer will point to the contiguous
1003
* representation of the data; hence returning that pointer.
1004
*
1005
* @param arrayPtr Pointer to the indexable object whose size is required
1006
* @return data address associated with the Indexable object
1007
*/
1008
MMINLINE void *
1009
getDataAddrForIndexableObject(J9IndexableObject *arrayPtr)
1010
{
1011
return (InlineContiguous == getArrayLayout(arrayPtr))
1012
? getDataAddrForContiguous(arrayPtr)
1013
: getDataAddrForDiscontiguous(arrayPtr);
1014
}
1015
1016
/**
1017
* Asserts that the dataAddr field of the indexable object is correct.
1018
*
1019
* @param arrayPtr Pointer to the indexable object
1020
*/
1021
MMINLINE bool
1022
isCorrectDataAddr(J9IndexableObject *arrayPtr)
1023
{
1024
1025
return (InlineContiguous == getArrayLayout(arrayPtr))
1026
? isCorrectDataAddrForContiguousArraylet(arrayPtr)
1027
: isCorrectDataAddrForDiscontiguousArraylet(arrayPtr);
1028
}
1029
1030
/**
1031
* Asserts that the dataAddr field of the contiguous arraylet is correct.
1032
*
1033
* @param arrayPtr Pointer to the indexable object
1034
*/
1035
MMINLINE bool
1036
isCorrectDataAddrForContiguousArraylet(J9IndexableObject *arrayPtr)
1037
{
1038
void *dataAddr = getDataAddrForContiguous(arrayPtr);
1039
return isCorrectDataAddrContiguous(arrayPtr, dataAddr);
1040
}
1041
1042
/**
1043
* Asserts that the dataAddr field of the indexable object is correct.
1044
*
1045
* @param arrayPtr Pointer to the indexable object
1046
*/
1047
MMINLINE bool
1048
isCorrectDataAddrForDiscontiguousArraylet(J9IndexableObject *arrayPtr)
1049
{
1050
void *dataAddr = getDataAddrForDiscontiguous(arrayPtr);
1051
return isCorrectDataAddrDiscontiguous(arrayPtr, dataAddr);
1052
}
1053
#endif /* J9VM_ENV_DATA64 */
1054
1055
/**
1056
* External fixup dataAddr API to update pointer of indexable objects.
1057
* Used in concurrent GCs in case of mutator and GC thread races.
1058
* Sets the dataAddr of either a contiguous or discomtiguous indexable
1059
* object.
1060
*
1061
* @param forwardedHeader Forwarded header of arrayPtr
1062
* @param arrayPtr Pointer to the indexable object whose size is required
1063
*/
1064
MMINLINE void
1065
fixupDataAddr(MM_ForwardedHeader *forwardedHeader, omrobjectptr_t arrayPtr)
1066
{
1067
#if defined(J9VM_ENV_DATA64)
1068
J9IndexableObject *j9ArrayPtr = (J9IndexableObject *)arrayPtr;
1069
1070
if (InlineContiguous == getPreservedArrayLayout(forwardedHeader)) {
1071
setDataAddrForContiguous(j9ArrayPtr);
1072
} else {
1073
setDataAddrForDiscontiguous(j9ArrayPtr, NULL);
1074
}
1075
#endif /* J9VM_ENV_DATA64 */
1076
}
1077
/**
1078
* External fixup dataAddr API to update pointer of indexable objects.
1079
* Sets the dataAddr of either a contiguous or discomtiguous indexable
1080
* object.
1081
*
1082
* @param arrayPtr Pointer to the indexable object whose size is required
1083
*/
1084
MMINLINE void
1085
fixupDataAddr(omrobjectptr_t arrayPtr)
1086
{
1087
#if defined(J9VM_ENV_DATA64)
1088
J9IndexableObject *j9ArrayPtr = (J9IndexableObject *)arrayPtr;
1089
AssertArrayPtrIsIndexable(j9ArrayPtr);
1090
1091
if (InlineContiguous == getArrayLayout(j9ArrayPtr)) {
1092
setDataAddrForContiguous(j9ArrayPtr);
1093
} else {
1094
setDataAddrForDiscontiguous(j9ArrayPtr, NULL);
1095
}
1096
#endif /* J9VM_ENV_DATA64 */
1097
}
1098
1099
/**
1100
* Extract the class pointer from an unforwarded object.
1101
*
1102
* This method will assert if the object has been marked as forwarded.
1103
*
1104
* @param[in] pointer to forwardedHeader the MM_ForwardedHeader instance encapsulating the object
1105
* @return pointer to the J9Class from the object encapsulated by forwardedHeader
1106
* @see MM_ForwardingHeader::isForwardedObject()
1107
*/
1108
MMINLINE J9Class *
1109
getPreservedClass(MM_ForwardedHeader *forwardedHeader)
1110
{
1111
return (J9Class *)((uintptr_t)(forwardedHeader->getPreservedSlot()) & J9GC_J9OBJECT_CLAZZ_ADDRESS_MASK);
1112
}
1113
1114
/**
1115
* Get the preserved hashcode offset of forwarded header.
1116
*
1117
* @param[in] Pointer to forwardedHeader the MM_ForwardedHeader instance encapsulating the object
1118
*/
1119
MMINLINE uintptr_t
1120
getPreservedHashcodeOffset(MM_ForwardedHeader *forwardedHeader)
1121
{
1122
J9Class *clazz = getPreservedClass(forwardedHeader);
1123
return getHashcodeOffset(clazz, getPreservedArrayLayout(forwardedHeader), getPreservedIndexableSize(forwardedHeader));
1124
}
1125
1126
/**
1127
* Extract the size (as getSizeInElements()) from an unforwarded object
1128
*
1129
* This method will assert if the object is not indexable or has been marked as forwarded.
1130
*
1131
* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
1132
* @return the size (#elements) of the array encapsulated by forwardedHeader
1133
* @see MM_ForwardingHeader::isForwardedObject()
1134
*/
1135
MMINLINE uint32_t
1136
getPreservedIndexableSize(MM_ForwardedHeader *forwardedHeader)
1137
{
1138
/* Asserts if object is indeed indexable */
1139
ForwardedHeaderAssert(J9GC_CLASS_IS_ARRAY(getPreservedClass(forwardedHeader)));
1140
1141
/* in compressed headers, the size of the object is stored in the low-order half of the uintptr_t read when we read clazz
1142
* so read it from there instead of the heap (since the heap copy would have been over-written by the forwarding
1143
* pointer if another thread copied the object underneath us). In non-compressed, this field should still be readable
1144
* out of the heap.
1145
*/
1146
uint32_t size = 0;
1147
#if defined (OMR_GC_COMPRESSED_POINTERS)
1148
if (compressObjectReferences()) {
1149
size = forwardedHeader->getPreservedOverlap();
1150
} else
1151
#endif /* defined (OMR_GC_COMPRESSED_POINTERS) */
1152
{
1153
size = ((J9IndexableObjectContiguousFull *)forwardedHeader->getObject())->size;
1154
}
1155
1156
if (0 == size) {
1157
/* Discontiguous */
1158
if (compressObjectReferences()) {
1159
size = ((J9IndexableObjectDiscontiguousCompressed *)forwardedHeader->getObject())->size;
1160
} else {
1161
size = ((J9IndexableObjectDiscontiguousFull *)forwardedHeader->getObject())->size;
1162
}
1163
}
1164
1165
return size;
1166
}
1167
1168
/**
1169
* Extract the array layout from preserved info in Forwarded header
1170
* (this mimics getArrayLayout())
1171
*
1172
* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
1173
* @return the ArrayLayout for the forwarded object
1174
*/
1175
MMINLINE ArrayLayout
1176
getPreservedArrayLayout(MM_ForwardedHeader *forwardedHeader)
1177
{
1178
J9Class *clazz = getPreservedClass(forwardedHeader);
1179
/* Asserts if object is indeed indexable */
1180
ForwardedHeaderAssert(J9GC_CLASS_IS_ARRAY(clazz));
1181
1182
ArrayLayout layout = InlineContiguous;
1183
uint32_t size = 0;
1184
#if defined (OMR_GC_COMPRESSED_POINTERS)
1185
if (compressObjectReferences()) {
1186
size = forwardedHeader->getPreservedOverlap();
1187
} else
1188
#endif /* defined (OMR_GC_COMPRESSED_POINTERS) */
1189
{
1190
size = ((J9IndexableObjectContiguousFull *)forwardedHeader->getObject())->size;
1191
}
1192
1193
if (0 == size) {
1194
/* we know we are dealing with heap object, so we don't need to check against _arrayletRangeBase/Top, like getArrayLayout does */
1195
uintptr_t dataSizeInBytes = getDataSizeInBytes(clazz, getPreservedIndexableSize(forwardedHeader));
1196
layout = getArrayletLayout(clazz, dataSizeInBytes);
1197
}
1198
1199
return layout;
1200
}
1201
1202
/**
1203
* Calculates object size in bytes with header and object's hashcode offset
1204
*
1205
* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
1206
* @param[out] hashcodeOffset hashcode offset of object being moved
1207
*
1208
* @return object size in bytes with header
1209
*/
1210
MMINLINE uintptr_t
1211
calculateObjectSizeAndHashcode(MM_ForwardedHeader *forwardedHeader, uintptr_t *hashcodeOffset)
1212
{
1213
J9Class* clazz = getPreservedClass(forwardedHeader);
1214
uintptr_t numberOfElements = (uintptr_t)getPreservedIndexableSize(forwardedHeader);
1215
uintptr_t dataSizeInBytes = getDataSizeInBytes(clazz, numberOfElements);
1216
ArrayLayout layout = getArrayletLayout(clazz, dataSizeInBytes);
1217
*hashcodeOffset = getHashcodeOffset(clazz, layout, numberOfElements);
1218
return getSizeInBytesWithHeader(clazz, layout, numberOfElements);
1219
}
1220
1221
/**
1222
* Returns the header size of a given indexable object. The arraylet layout is determined base on "small" size.
1223
* @param arrayPtr Ptr to an array for which header size will be returned
1224
* @return Size of header in bytes
1225
*/
1226
MMINLINE uintptr_t
1227
getHeaderSize(J9IndexableObject *arrayPtr)
1228
{
1229
uintptr_t headerSize = 0;
1230
if (compressObjectReferences()) {
1231
uintptr_t size = ((J9IndexableObjectContiguousCompressed *)arrayPtr)->size;
1232
headerSize = sizeof(J9IndexableObjectContiguousCompressed);
1233
if (0 == size) {
1234
headerSize = sizeof(J9IndexableObjectDiscontiguousCompressed);
1235
}
1236
} else {
1237
uintptr_t size = ((J9IndexableObjectContiguousFull *)arrayPtr)->size;
1238
headerSize = sizeof(J9IndexableObjectContiguousFull);
1239
if (0 == size) {
1240
headerSize = sizeof(J9IndexableObjectDiscontiguousFull);
1241
}
1242
}
1243
return headerSize;
1244
}
1245
1246
/**
1247
* Returns the address of first arraylet leaf slot in the spine
1248
* @param arrayPtr Ptr to an array
1249
* @return Arrayoid ptr
1250
*/
1251
MMINLINE fj9object_t *
1252
getArrayoidPointer(J9IndexableObject *arrayPtr)
1253
{
1254
return (fj9object_t *)((uintptr_t)arrayPtr + (compressObjectReferences() ? sizeof(J9IndexableObjectDiscontiguousCompressed) : sizeof(J9IndexableObjectDiscontiguousFull)));
1255
}
1256
1257
/**
1258
* Returns the address of first data slot in the array
1259
* @param arrayPtr Ptr to an array
1260
* @return Address of first data slot in the array
1261
*/
1262
MMINLINE void *
1263
getDataPointerForContiguous(J9IndexableObject *arrayPtr)
1264
{
1265
return (void *)((uintptr_t)arrayPtr + contiguousHeaderSize());
1266
}
1267
1268
1269
/**
1270
* Returns the offset of the hashcode slot, in bytes, from the beginning of the header.
1271
* WARNING: This implementation assumes the arraylet layout is InlineContiguous.
1272
* @param clazzPtr Pointer to the class of the object
1273
* @param numberOfElements size from indexable object
1274
* @return offset of the hashcode slot
1275
*/
1276
MMINLINE uintptr_t
1277
getHashcodeOffset(J9Class *clazzPtr, uintptr_t numberOfElements)
1278
{
1279
ArrayLayout layout = InlineContiguous;
1280
if(0 == numberOfElements) {
1281
layout = Discontiguous;
1282
}
1283
return getHashcodeOffset(clazzPtr, layout, numberOfElements);
1284
}
1285
1286
/**
1287
* Returns the offset of the hashcode slot, in bytes, from the beginning of the header.
1288
* @param clazzPtr Pointer to the class of the object
1289
* @param layout The layout of the indexable object
1290
* @param numberOfElements size from indexable object
1291
* @return offset of the hashcode slot
1292
*/
1293
MMINLINE uintptr_t
1294
getHashcodeOffset(J9Class *clazzPtr, ArrayLayout layout, uintptr_t numberOfElements)
1295
{
1296
/* Don't call getDataSizeInBytes() since that rounds up to uintptr_t. */
1297
uintptr_t dataSize = numberOfElements * J9ARRAYCLASS_GET_STRIDE(clazzPtr);
1298
uintptr_t numberOfArraylets = numArraylets(dataSize);
1299
bool alignData = shouldAlignSpineDataSection(clazzPtr);
1300
uintptr_t spineSize = getSpineSize(clazzPtr, layout, numberOfArraylets, dataSize, alignData);
1301
return MM_Math::roundToSizeofU32(spineSize);
1302
}
1303
1304
/**
1305
* Returns the offset of the hashcode slot, in bytes, from the beginning of the header.
1306
* @param arrayPtr Pointer to the array
1307
* @return offset of the hashcode slot
1308
*/
1309
MMINLINE uintptr_t
1310
getHashcodeOffset(J9IndexableObject *arrayPtr)
1311
{
1312
ArrayLayout layout = getArrayLayout(arrayPtr);
1313
return getHashcodeOffset(J9GC_J9OBJECT_CLAZZ(arrayPtr, this), layout, getSizeInElements(arrayPtr));
1314
}
1315
1316
MMINLINE void
1317
expandArrayletSubSpaceRange(MM_MemorySubSpace * subSpace, void * rangeBase, void * rangeTop, uintptr_t largestDesirableArraySpineSize)
1318
{
1319
GC_ArrayletObjectModelBase::expandArrayletSubSpaceRange(subSpace, rangeBase, rangeTop, largestDesirableArraySpineSize);
1320
}
1321
1322
/**
1323
* Updates leaf pointers that point to an address located within the indexable object. For example,
1324
* when the array layout is either inline continuous or hybrid, there will be leaf pointers that point
1325
* to data that is contained within the indexable object. These internal leaf pointers are updated by
1326
* calculating their offset within the source arraylet, then updating the destination arraylet pointers
1327
* to use the same offset.
1328
*
1329
* @param destinationPtr Pointer to the new indexable object
1330
* @param sourcePtr Pointer to the original indexable object that was copied
1331
*/
1332
void fixupInternalLeafPointersAfterCopy(J9IndexableObject *destinationPtr, J9IndexableObject *sourcePtr);
1333
1334
/**
1335
* Initialize the receiver, a new instance of GC_ObjectModel
1336
*
1337
* @return true on success, false on failure
1338
*/
1339
bool initialize(MM_GCExtensionsBase *extensions);
1340
1341
/**
1342
* Tear down the receiver
1343
*/
1344
void tearDown(MM_GCExtensionsBase *extensions);
1345
1346
/**
1347
* Asserts that an Arraylet has indeed discontiguous layout
1348
*/
1349
void AssertArrayletIsDiscontiguous(J9IndexableObject *objPtr);
1350
1351
/**
1352
* Asserts that an Arraylet has true contiguous layout
1353
*/
1354
void AssertContiguousArrayletLayout(J9IndexableObject *objPtr);
1355
1356
/**
1357
* Asserts that an Arraylet has true discontiguous layout
1358
*/
1359
void AssertDiscontiguousArrayletLayout(J9IndexableObject *objPtr);
1360
};
1361
#endif /* ARRAYLETOBJECTMODEL_ */
1362
1363