Path: blob/master/runtime/gc_glue_java/ArrayletObjectModel.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#include "ArrayletLeafIterator.hpp"23#include "ArrayletObjectModel.hpp"24#include "GCExtensionsBase.hpp"25#include "ModronAssertions.h"26#include "ObjectModel.hpp"2728bool29GC_ArrayletObjectModel::initialize(MM_GCExtensionsBase *extensions)30{31return GC_ArrayletObjectModelBase::initialize(extensions);32}3334void35GC_ArrayletObjectModel::tearDown(MM_GCExtensionsBase *extensions)36{37GC_ArrayletObjectModelBase::tearDown(extensions);38}3940void41GC_ArrayletObjectModel::AssertBadElementSize()42{43Assert_MM_unreachable();44}4546void47GC_ArrayletObjectModel::AssertArrayletIsDiscontiguous(J9IndexableObject *objPtr)48{49#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)50if (!isDoubleMappingEnabled())51#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */52{53MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(_omrVM);54UDATA arrayletLeafSize = _omrVM->_arrayletLeafSize;55UDATA remainderBytes = getDataSizeInBytes(objPtr) % arrayletLeafSize;56if (0 != remainderBytes) {57Assert_MM_true((getSpineSize(objPtr) + remainderBytes + extensions->getObjectAlignmentInBytes()) > arrayletLeafSize);58}59}60}6162void63GC_ArrayletObjectModel::AssertContiguousArrayletLayout(J9IndexableObject *objPtr)64{65Assert_MM_true(InlineContiguous == getArrayLayout(objPtr));66}6768void69GC_ArrayletObjectModel::AssertDiscontiguousArrayletLayout(J9IndexableObject *objPtr)70{71ArrayLayout layout = getArrayLayout(objPtr);72Assert_MM_true((Discontiguous == layout) || (Hybrid == layout));73}7475GC_ArrayletObjectModel::ArrayLayout76GC_ArrayletObjectModel::getArrayletLayout(J9Class* clazz, UDATA dataSizeInBytes, UDATA largestDesirableSpine)77{78ArrayLayout layout = Illegal;79MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(_omrVM);80UDATA objectAlignmentInBytes = extensions->getObjectAlignmentInBytes();8182/* the spine need not contain a pointer to the data */83const UDATA minimumSpineSize = 0;84UDATA minimumSpineSizeAfterGrowing = minimumSpineSize;85if (extensions->isVLHGC()) {86/* 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 grows87* (easier to handle this case in the allocator than to special-case the collectors to know how to avoid this case)88* (currently, we only grow by a hashcode slot which is 4-bytes but will increase our size by the granule of alignment)89*/90minimumSpineSizeAfterGrowing += objectAlignmentInBytes;91}9293/* CMVC 135307 : when checking for InlineContiguous layout, perform subtraction as adding to dataSizeInBytes could trigger overflow. */94if ((largestDesirableSpine == UDATA_MAX) || (dataSizeInBytes <= (largestDesirableSpine - minimumSpineSizeAfterGrowing - contiguousHeaderSize()))) {95layout = InlineContiguous;96if(0 == dataSizeInBytes) {97/* Zero sized NUA uses the discontiguous shape */98layout = Discontiguous;99}100} else {101UDATA arrayletLeafSize = _omrVM->_arrayletLeafSize;102UDATA lastArrayletBytes = dataSizeInBytes & (arrayletLeafSize - 1);103104if (lastArrayletBytes > 0) {105/* determine how large the spine would be if this were a hybrid array */106UDATA numberArraylets = numArraylets(dataSizeInBytes);107bool align = shouldAlignSpineDataSection(clazz);108UDATA hybridSpineBytes = getSpineSize(clazz, Hybrid, numberArraylets, dataSizeInBytes, align);109UDATA adjustedHybridSpineBytes = extensions->objectModel.adjustSizeInBytes(hybridSpineBytes);110UDATA adjustedHybridSpineBytesAfterMove = adjustedHybridSpineBytes;111if (extensions->isVLHGC()) {112adjustedHybridSpineBytesAfterMove += objectAlignmentInBytes;113}114#if defined(J9VM_GC_ENABLE_DOUBLE_MAP)115if (extensions->indexableObjectModel.isDoubleMappingEnabled()) {116layout = Discontiguous;117} else118#endif /* J9VM_GC_ENABLE_DOUBLE_MAP */119/* if remainder data can fit in spine, make it hybrid */120if (adjustedHybridSpineBytesAfterMove <= largestDesirableSpine) {121/* remainder data can fit in spine, last arrayoid pointer points to empty data section in spine */122layout = Hybrid;123} else {124/* remainder data will go into an arraylet, last arrayoid pointer points to it */125layout = Discontiguous;126}127} else {128/* remainder is empty, so no arraylet allocated; last arrayoid pointer is set to MULL */129layout = Discontiguous;130}131}132return layout;133}134135void136GC_ArrayletObjectModel::fixupInternalLeafPointersAfterCopy(J9IndexableObject *destinationPtr, J9IndexableObject *sourcePtr)137{138if (hasArrayletLeafPointers(destinationPtr)) {139GC_ArrayletLeafIterator leafIterator((J9JavaVM*)_omrVM->_language_vm, destinationPtr);140GC_SlotObject *leafSlotObject = NULL;141UDATA sourceStartAddress = (UDATA) sourcePtr;142UDATA sourceEndAddress = sourceStartAddress + getSizeInBytesWithHeader(destinationPtr);143144while (NULL != (leafSlotObject = leafIterator.nextLeafPointer())) {145UDATA leafAddress = (UDATA)leafSlotObject->readReferenceFromSlot();146147if ((sourceStartAddress < leafAddress) && (leafAddress < sourceEndAddress)) {148leafSlotObject->writeReferenceToSlot((J9Object*)((UDATA)destinationPtr + (leafAddress - sourceStartAddress)));149}150}151}152}153154#if defined(J9VM_ENV_DATA64)155void156GC_ArrayletObjectModel::AssertArrayPtrIsIndexable(J9IndexableObject *arrayPtr)157{158MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(_omrVM);159Assert_MM_true(extensions->objectModel.isIndexable(J9GC_J9OBJECT_CLAZZ(arrayPtr, this)));160}161#endif /* defined(J9VM_ENV_DATA64) */162163164