Path: blob/master/runtime/compiler/env/J9SegmentAllocator.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 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 <new>23#include "env/J9SegmentAllocator.hpp"24#include "infra/Assert.hpp"25#include "control/Options.hpp"26#include "control/Options_inlines.hpp"27#include "control/CompilationRuntime.hpp"28#include "env/VerboseLog.hpp"29#include "OMR/Bytes.hpp"30#include "j9.h"31#undef min32#undef max3334namespace J9 {3536SegmentAllocator::SegmentAllocator(37int32_t segmentType,38J9JavaVM &javaVM39) throw() :40_segmentType(segmentType),41_javaVM(javaVM)42{43TR_ASSERT(((pageSize() & (pageSize()-1)) == 0), "Page size is not a power of 2, %llu", static_cast<unsigned long long>(pageSize()) );44}4546SegmentAllocator::~SegmentAllocator() throw()47{48}4950J9MemorySegment *51SegmentAllocator::allocate(const size_t segmentSize, const std::nothrow_t &tag) throw()52{53size_t const alignedSize = pageAlign(segmentSize);5455// If low on physical memory we may want to return NULL when allocating scratch segments56if (_segmentType & MEMORY_TYPE_JIT_SCRATCH_SPACE)57{58bool incomplete;59TR::CompilationInfo *compInfo = TR::CompilationInfo::get(_javaVM.jitConfig);60uint64_t freePhysicalMemory = compInfo->computeAndCacheFreePhysicalMemory(incomplete, 20);61if (freePhysicalMemory != OMRPORT_MEMINFO_NOT_AVAILABLE && !incomplete)62{63if (freePhysicalMemory < (TR::Options::getSafeReservePhysicalMemoryValue() + segmentSize))64{65// Set a flag that will determine one compilation thread to suspend itself66// Even if multiple threads enter his path we still want to suspend only67// one thread, not several. This is why we use a flag and not a counter.68//69// We allow a small race condition: it is possible that between the test70// for available physical memory and setting of the flag below, another71// compilation thread has suspended itself and reset the flag. The code72// below is going to set the flag again, possibly resulting into two73// compilation threads being suspended. This is still fine, because, if74// needed, a new compilation thread will be activated when a compilation75// request is queued76compInfo->setSuspendThreadDueToLowPhysicalMemory(true);77return NULL;78}79}80}81J9MemorySegment * newSegment =82_javaVM.internalVMFunctions->allocateMemorySegment(83&_javaVM,84alignedSize,85_segmentType,86J9MEM_CATEGORY_JIT87);88TR_ASSERT(89!newSegment || (newSegment->heapAlloc == newSegment->heapBase),90"Segment @ %p { heapBase: %p, heapAlloc: %p, heapTop: %p } is stale",91newSegment,92newSegment->heapBase,93newSegment->heapAlloc,94newSegment->heapTop95);96preventAllocationOfBTLMemory(newSegment, &_javaVM, _segmentType);97return newSegment;98}99100J9MemorySegment &101SegmentAllocator::allocate(size_t const segmentSize)102{103J9MemorySegment * newSegment = allocate(segmentSize, std::nothrow);104if (!newSegment) throw std::bad_alloc();105return *newSegment;106}107108void109SegmentAllocator::deallocate(J9MemorySegment &unusedSegment) throw()110{111_javaVM.internalVMFunctions->freeMemorySegment(&_javaVM, &unusedSegment, TRUE);112}113114J9MemorySegment &115SegmentAllocator::request(size_t segmentSize)116{117return allocate(segmentSize);118}119120void121SegmentAllocator::release(J9MemorySegment &unusedSegment) throw()122{123deallocate(unusedSegment);124}125126size_t127SegmentAllocator::pageSize() throw()128{129PORT_ACCESS_FROM_JAVAVM(&_javaVM);130static const size_t pageSize = j9vmem_supported_page_sizes()[0];131return pageSize;132}133134size_t135SegmentAllocator::pageAlign(const size_t requestedSize) throw()136{137size_t const pageSize = this->pageSize();138size_t alignedSize = OMR::align(requestedSize, pageSize);139return alignedSize;140}141142143void144SegmentAllocator::preventAllocationOfBTLMemory(J9MemorySegment * &segment, J9JavaVM * javaVM, int32_t segmentType)145{146#if defined(J9ZOS390)147// Special code for zOS. If we allocated BTL memory (first 16MB), then we must148// release this segment, failing the compilation and forcing to use only one compilation thread149if (TR::Options::getCmdLineOptions()->getOption(TR_DontAllocateScratchBTL) &&150segment && ((uintptr_t)(segment->heapBase) < (uintptr_t)(1 << 24)))151{152// If applicable, reduce the number of compilation threads to 1153TR::CompilationInfo * compInfo = TR::CompilationInfo::get();154if (compInfo)155{156if (!compInfo->getRampDownMCT())157{158compInfo->setRampDownMCT();159if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))160{161TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%u setRampDownMCT because JIT allocated BTL memory", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime());162}163}164else165{166// Perhaps we should consider lowering the compilation aggressiveness167if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoOptServer))168{169TR::Options::getAOTCmdLineOptions()->setOption(TR_NoOptServer);170}171if (!TR::Options::getJITCmdLineOptions()->getOption(TR_NoOptServer))172{173TR::Options::getJITCmdLineOptions()->setOption(TR_NoOptServer);174}175}176177// For scratch memory refuse to return memory below the line. Free the segment and let the compilation fail178// Compilation will be retried at lower opt level. However, We should not reject requests coming from hooks.179if (segmentType & MEMORY_TYPE_JIT_SCRATCH_SPACE)180{181J9VMThread *crtVMThread = javaVM->internalVMFunctions->currentVMThread(javaVM);182if (compInfo->getCompInfoForThread(crtVMThread))183{184javaVM->internalVMFunctions->freeMemorySegment(javaVM, segment, TRUE);185segment = NULL;186}187}188}189}190#endif // defined(J9ZOS390)191}192193}194195196