Path: blob/master/runtime/gc_glue_java/EnvironmentDelegate.cpp
5985 views
/*******************************************************************************1* Copyright (c) 2017, 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*******************************************************************************/21#include "j9protos.h"22#include "ModronAssertions.h"2324#include "EnvironmentBase.hpp"25#include "EnvironmentDelegate.hpp"26#include "GCExtensions.hpp"27#include "JNICriticalRegion.hpp"28#include "OMRVMInterface.hpp"29#include "OwnableSynchronizerObjectBufferRealtime.hpp"30#include "OwnableSynchronizerObjectBufferStandard.hpp"31#include "OwnableSynchronizerObjectBufferVLHGC.hpp"32#include "ReferenceObjectBufferRealtime.hpp"33#include "ReferenceObjectBufferStandard.hpp"34#include "ReferenceObjectBufferVLHGC.hpp"35#include "SublistFragment.hpp"36#include "UnfinalizedObjectBufferRealtime.hpp"37#include "UnfinalizedObjectBufferStandard.hpp"38#include "UnfinalizedObjectBufferVLHGC.hpp"39#include "VMAccess.hpp"40#include "omrlinkedlist.h"4142/**43* Initialize the delegate's internal structures and values.44*/45bool46MM_EnvironmentDelegate::initialize(MM_EnvironmentBase *env)47{48_env = env;49_extensions = _env->getExtensions();50_vmThread = (J9VMThread *)_env->getOmrVMThread()->_language_vmthread;5152MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);53if (extensions->isStandardGC()) {54#if defined(OMR_GC_MODRON_STANDARD)55_gcEnv._referenceObjectBuffer = MM_ReferenceObjectBufferStandard::newInstance(env);56_gcEnv._unfinalizedObjectBuffer = MM_UnfinalizedObjectBufferStandard::newInstance(env);57_gcEnv._ownableSynchronizerObjectBuffer = MM_OwnableSynchronizerObjectBufferStandard::newInstance(env);58#endif /* defined(OMR_GC_MODRON_STANDARD) */59} else if (extensions->isMetronomeGC()) {60#if defined(OMR_GC_REALTIME)61_gcEnv._referenceObjectBuffer = MM_ReferenceObjectBufferRealtime::newInstance(env);62_gcEnv._unfinalizedObjectBuffer = MM_UnfinalizedObjectBufferRealtime::newInstance(env);63_gcEnv._ownableSynchronizerObjectBuffer = MM_OwnableSynchronizerObjectBufferRealtime::newInstance(env);64#endif /* defined(OMR_GC_REALTIME) */65} else if (extensions->isVLHGC()) {66#if defined(OMR_GC_VLHGC)67_gcEnv._referenceObjectBuffer = MM_ReferenceObjectBufferVLHGC::newInstance(env);68_gcEnv._unfinalizedObjectBuffer = MM_UnfinalizedObjectBufferVLHGC::newInstance(env);69_gcEnv._ownableSynchronizerObjectBuffer = MM_OwnableSynchronizerObjectBufferVLHGC::newInstance(env);70#endif /* defined(OMR_GC_VLHGC) */71} else {72Assert_MM_unreachable();73}7475if ((NULL == _gcEnv._referenceObjectBuffer) ||76(NULL == _gcEnv._unfinalizedObjectBuffer) ||77(NULL == _gcEnv._ownableSynchronizerObjectBuffer)) {78return false;79}8081return true;82}8384/**85* Free any internal structures associated to the receiver.86*/87void88MM_EnvironmentDelegate::tearDown()89{90if (NULL != _gcEnv._referenceObjectBuffer) {91_gcEnv._referenceObjectBuffer->kill(_env);92_gcEnv._referenceObjectBuffer = NULL;93}9495if (NULL != _gcEnv._unfinalizedObjectBuffer) {96_gcEnv._unfinalizedObjectBuffer->kill(_env);97_gcEnv._unfinalizedObjectBuffer = NULL;98}99100if (NULL != _gcEnv._ownableSynchronizerObjectBuffer) {101_gcEnv._ownableSynchronizerObjectBuffer->kill(_env);102_gcEnv._ownableSynchronizerObjectBuffer = NULL;103}104}105106OMR_VMThread *107MM_EnvironmentDelegate::attachVMThread(OMR_VM *omrVM, const char *threadName, uintptr_t reason)108{109J9JavaVM *javaVM = (J9JavaVM *)omrVM->_language_vm;110J9VMThread *vmThread = NULL;111if (JNI_OK != javaVM->internalVMFunctions->attachSystemDaemonThread(javaVM, &vmThread, threadName)) {112return NULL;113}114115#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)116if ((MM_EnvironmentBase::ATTACH_THREAD != reason) && (NULL != javaVM->javaOffloadSwitchOnWithReasonFunc)) {117(*javaVM->javaOffloadSwitchOnWithReasonFunc)(vmThread, J9_JNI_OFFLOAD_SWITCH_FINALIZE_WORKER_THREAD + reason);118vmThread->javaOffloadState = 1;119}120#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */121122return vmThread->omrVMThread;123}124125void126MM_EnvironmentDelegate::detachVMThread(OMR_VM *omrVM, OMR_VMThread *omrThread, uintptr_t reason)127{128J9JavaVM *javaVM = (J9JavaVM *)omrVM->_language_vm;129130#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)131if ((MM_EnvironmentBase::ATTACH_THREAD != reason) && (NULL != javaVM->javaOffloadSwitchOnWithReasonFunc)) {132(*javaVM->javaOffloadSwitchOffWithReasonFunc)((J9VMThread *)omrThread->_language_vmthread, reason);133}134#endif135136javaVM->internalVMFunctions->DetachCurrentThread((JavaVM *)javaVM);137}138139void140MM_EnvironmentDelegate::flushNonAllocationCaches()141{142#if defined(J9VM_GC_GENERATIONAL)143if (_env->getExtensions()->isStandardGC()) {144MM_SublistFragment::flush((J9VMGC_SublistFragment*)&_vmThread->gcRememberedSet);145}146#endif /* J9VM_GC_GENERATIONAL */147148#if defined(J9VM_GC_FINALIZATION)149_gcEnv._unfinalizedObjectBuffer->flush(_env);150#endif /* J9VM_GC_FINALIZATION */151152_gcEnv._ownableSynchronizerObjectBuffer->flush(_env);153}154155void156MM_EnvironmentDelegate::setGCMainThread(bool isMainThread)157{158if (isMainThread) {159_vmThread->privateFlags |= J9_PRIVATE_FLAGS_GC_MAIN_THREAD;160} else {161_vmThread->privateFlags &= ~J9_PRIVATE_FLAGS_GC_MAIN_THREAD;162}163}164165void166MM_EnvironmentDelegate::acquireVMAccess()167{168_vmThread->javaVM->internalVMFunctions->internalAcquireVMAccess(_vmThread);169}170171void172MM_EnvironmentDelegate::releaseVMAccess()173{174_vmThread->javaVM->internalVMFunctions->internalReleaseVMAccess(_vmThread);175}176177bool178MM_EnvironmentDelegate::inNative()179{180return (FALSE != _vmThread->inNative);181}182183bool184MM_EnvironmentDelegate::isExclusiveAccessRequestWaiting()185{186return (J9_PUBLIC_FLAGS_HALT_THREAD_EXCLUSIVE == (_vmThread->publicFlags & J9_PUBLIC_FLAGS_HALT_THREAD_EXCLUSIVE));187}188189/**190* Acquires exclusive VM access191*/192void193MM_EnvironmentDelegate::acquireExclusiveVMAccess()194{195_vmThread->javaVM->internalVMFunctions->acquireExclusiveVMAccess(_vmThread);196}197198/**199* Releases exclusive VM access.200*/201void202MM_EnvironmentDelegate::releaseExclusiveVMAccess()203{204_vmThread->javaVM->internalVMFunctions->releaseExclusiveVMAccess(_vmThread);205}206207208uintptr_t209MM_EnvironmentDelegate::relinquishExclusiveVMAccess()210{211uintptr_t savedExclusiveCount = _vmThread->omrVMThread->exclusiveCount;212213Assert_MM_true(J9_PUBLIC_FLAGS_VM_ACCESS == (_vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS));214Assert_MM_true(0 < savedExclusiveCount);215216_vmThread->omrVMThread->exclusiveCount = 0;217VM_VMAccess::clearPublicFlags(_vmThread, J9_PUBLIC_FLAGS_VM_ACCESS);218219return savedExclusiveCount;220}221222void223MM_EnvironmentDelegate::assumeExclusiveVMAccess(uintptr_t exclusiveCount)224{225Assert_MM_true(exclusiveCount >= 1);226Assert_MM_true(0 == (_vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS));227Assert_MM_true(0 == _vmThread->omrVMThread->exclusiveCount);228229_vmThread->omrVMThread->exclusiveCount = exclusiveCount;230VM_VMAccess::setPublicFlags(_vmThread, J9_PUBLIC_FLAGS_VM_ACCESS);231}232233void234MM_EnvironmentDelegate::releaseCriticalHeapAccess(uintptr_t *data)235{236VM_VMAccess::setPublicFlags(_vmThread, J9_PUBLIC_FLAGS_NOT_AT_SAFE_POINT);237MM_JNICriticalRegion::releaseAccess(_vmThread, data);238}239240void241MM_EnvironmentDelegate::reacquireCriticalHeapAccess(uintptr_t data)242{243MM_JNICriticalRegion::reacquireAccess(_vmThread, data);244VM_VMAccess::clearPublicFlags(_vmThread, J9_PUBLIC_FLAGS_NOT_AT_SAFE_POINT);245}246247void248MM_EnvironmentDelegate::forceOutOfLineVMAccess()249{250VM_VMAccess::setPublicFlags(_vmThread, J9_PUBLIC_FLAGS_DISABLE_INLINE_VM_ACCESS);251}252253#if defined (J9VM_GC_THREAD_LOCAL_HEAP)254/**255* Disable inline TLH allocates by hiding the real heap top address from256* JIT/Interpreter in realHeapTop and setting HeapTop == heapALloc so TLH257* looks full.258*259*/260void261MM_EnvironmentDelegate::disableInlineTLHAllocate()262{263J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;264if (NULL == tlh->realHeapTop) {265tlh->realHeapTop = _vmThread->heapTop;266}267_vmThread->heapTop = _vmThread->heapAlloc;268269#if defined(J9VM_GC_NON_ZERO_TLH)270tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;271if (NULL == tlh->realHeapTop) {272tlh->realHeapTop = _vmThread->nonZeroHeapTop;273}274_vmThread->nonZeroHeapTop = _vmThread->nonZeroHeapAlloc;275#endif /* defined(J9VM_GC_NON_ZERO_TLH) */276}277278/**279* Re-enable inline TLH allocate by restoring heapTop from realHeapTop280*/281void282MM_EnvironmentDelegate::enableInlineTLHAllocate()283{284J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;285if (NULL != tlh->realHeapTop) {286_vmThread->heapTop = tlh->realHeapTop;287tlh->realHeapTop = NULL;288}289290#if defined(J9VM_GC_NON_ZERO_TLH)291tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;292if (NULL != tlh->realHeapTop) {293_vmThread->nonZeroHeapTop = tlh->realHeapTop;294tlh->realHeapTop = NULL;295}296#endif /* defined(J9VM_GC_NON_ZERO_TLH) */297}298299/**300* Determine if inline TLH allocate is enabled; its enabled if realheapTop is NULL.301* @return TRUE if inline TLH allocates currently enabled for this thread; FALSE otherwise302*/303bool304MM_EnvironmentDelegate::isInlineTLHAllocateEnabled()305{306J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;307bool result = (NULL == tlh->realHeapTop);308309#if defined(J9VM_GC_NON_ZERO_TLH)310tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;311result = result && (NULL == tlh->realHeapTop);312#endif /* defined(J9VM_GC_NON_ZERO_TLH) */313314return result;315}316317318void319MM_EnvironmentDelegate::setTLHSamplingTop(uintptr_t size)320{321uintptr_t max = 0;322J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;323if (NULL != tlh->realHeapTop) {324max = tlh->realHeapTop - _vmThread->heapAlloc;325} else {326max = _vmThread->heapTop - _vmThread->heapAlloc;327}328329if (max > size) {330if (NULL == tlh->realHeapTop) {331tlh->realHeapTop = _vmThread->heapTop;332}333_vmThread->heapTop = _vmThread->heapAlloc + size;334} else {335if (NULL != tlh->realHeapTop) {336_vmThread->heapTop = tlh->realHeapTop;337tlh->realHeapTop = NULL;338}339}340341#if defined(J9VM_GC_NON_ZERO_TLH)342/* TODO: need to find better way set TLH sampling Top for NON ZERO case */343tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;344if (NULL != tlh->realHeapTop) {345max = tlh->realHeapTop - _vmThread->nonZeroHeapAlloc;346} else {347max = _vmThread->nonZeroHeapTop - _vmThread->nonZeroHeapAlloc;348}349350if (max > size) {351if (NULL == tlh->realHeapTop) {352tlh->realHeapTop = _vmThread->nonZeroHeapTop;353}354_vmThread->nonZeroHeapTop = _vmThread->nonZeroHeapAlloc + size;355} else {356if (NULL != tlh->realHeapTop) {357_vmThread->nonZeroHeapTop = tlh->realHeapTop;358tlh->realHeapTop = NULL;359}360}361362#endif /* defined(J9VM_GC_NON_ZERO_TLH) */363}364365void366MM_EnvironmentDelegate::resetTLHSamplingTop()367{368enableInlineTLHAllocate();369}370371uintptr_t372MM_EnvironmentDelegate::getAllocatedSizeInsideTLH()373{374uintptr_t ret = 0;375J9ModronThreadLocalHeap *tlh = (J9ModronThreadLocalHeap *)&_vmThread->allocateThreadLocalHeap;376ret += _vmThread->heapAlloc - tlh->heapBase;377#if defined(J9VM_GC_NON_ZERO_TLH)378tlh = (J9ModronThreadLocalHeap *)&_vmThread->nonZeroAllocateThreadLocalHeap;379ret += _vmThread->nonZeroHeapAlloc - tlh->heapBase;380#endif /* defined(J9VM_GC_NON_ZERO_TLH) */381return ret;382}383384#endif /* J9VM_GC_THREAD_LOCAL_HEAP */385386387388