Path: blob/master/runtime/compiler/control/J9Recompilation.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2022 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 "AtomicSupport.hpp"23#include "codegen/CodeGenerator.hpp"24#include "control/CompilationRuntime.hpp"25#include "control/Recompilation.hpp"26#include "control/RecompilationInfo.hpp"27#include "compile/Compilation.hpp"28#include "control/Options.hpp"29#include "compile/SymbolReferenceTable.hpp"30#include "env/VMJ9.h"31#include "env/VerboseLog.hpp"32#include "runtime/J9Profiler.hpp"33#include "exceptions/RuntimeFailure.hpp"34#if defined(J9VM_OPT_JITSERVER)35#include "control/JITServerCompilationThread.hpp"36#endif /* defined(J9VM_OPT_JITSERVER) */3738bool J9::Recompilation::_countingSupported = false;39404142J9::Recompilation::Recompilation(TR::Compilation *comp) :43OMR::RecompilationConnector(comp),44_firstCompile(comp->getCurrentMethod()->isInterpreted()),45_useSampling(TR::Options::getSamplingFrequency() != 0 && !comp->getOption(TR_MimicInterpreterFrameShape)),46_doNotCompileAgain(comp->getOption(TR_NoRecompile) || !comp->allowRecompilation()),47_methodInfo(0),48_bodyInfo(0),49_nextLevel(warm),50_nextCounter(0)51{52_timer.initialize(0, comp->trMemory());53}545556void57J9::Recompilation::setupMethodInfo()58{59// FIXME: this code should move into the constructor60// the problem is - if someone gets the bodyinfo/method info before61// this method is done - there will be a bug.6263// NOTE: by the end of this method we must have determined whether or64// not this method is going to be recompiled using sampling or counting.65//66TR_OptimizationPlan * optimizationPlan = _compilation->getOptimizationPlan();6768#if defined(J9VM_OPT_JITSERVER)69// NOTE: cannot use _compilation->isOutOfProcessCompilation here, because this70// method is called from within OMR::Compilation() constructor, before71// _isOutOfProcessCompilation is set72if (comp()->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)73{74auto compInfoPT = static_cast<TR::CompilationInfoPerThreadRemote *>(TR::compInfoPT);75_methodInfo = compInfoPT->getRecompilationMethodInfo();76if (!_methodInfo)77{78_compilation->failCompilation<std::bad_alloc>("Unable to allocate method info");79}80}81else if (_firstCompile)82#else83if (_firstCompile)84#endif /* defined(J9VM_OPT_JITSERVER) */85{86// Create the persistent method information87// If the previous compiled version of the method is AOTed, then we need to create a new persistent method information88//89_methodInfo = new (PERSISTENT_NEW) TR_PersistentMethodInfo(_compilation);9091if (!_methodInfo)92{93_compilation->failCompilation<std::bad_alloc>("Unable to allocate method info");94}9596// During compilation methodInfo->nextOptLevel is the current optlevel97// ie. we pretend that the previous (nonexistent) compile has set this up98// for us. Mark this as a non-profiling compile. Only sampleMethod99// even enables profiling.100//101// During bootstrapping of TR::Options, _compilation->getMethodHotness102// will be setup properly from the count strings103//104_methodInfo->setNextCompileLevel(optimizationPlan->getOptLevel(),105(optimizationPlan->insertInstrumentation() != 0));106_methodInfo->setWasNeverInterpreted(!comp()->fej9()->methodMayHaveBeenInterpreted(comp()));107}108else // this is a recompilation109{110// There already is a persistent method info for this method which already111// has a compilation level set in it (by virtue of a previous compilation)112//113_methodInfo = getExistingMethodInfo(_compilation->getCurrentMethod());114#if defined(J9VM_OPT_JITSERVER)115if (comp()->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)116{117TR_ASSERT_FATAL(_methodInfo->profilingDisabled(), "Profiling is not supported in JITServer");118}119#endif /* defined(J9VM_OPT_JITSERVER) */120121if (!comp()->fej9()->canRecompileMethodWithMatchingPersistentMethodInfo(comp()) &&122!comp()->isGPUCompilation())123{124// TODO: Why does this assume sometimes fail in HCR mode?125TR_ASSERT(_compilation->getMethodHotness() == _methodInfo->getNextCompileLevel(),126"discrepancy in the method compile level %d %d while compiling %s",127_compilation->getMethodHotness(),128_methodInfo->getNextCompileLevel(),129_compilation->signature());130}131}132133// TR_Controller is being used and has provided a compilation plan. Use it to setup the compilation134//135_bodyInfo = TR_PersistentJittedBodyInfo::allocate(136_methodInfo,137_compilation->getMethodHotness(),138(optimizationPlan->insertInstrumentation() != 0),139_compilation);140141if (!_bodyInfo)142{143_compilation->failCompilation<std::bad_alloc>("Unable to allocate body info");144}145146if (!optimizationPlan->getUseSampling())147{148_bodyInfo->setDisableSampling(true);149}150151if (_compilation->getOption(TR_EnableFastHotRecompilation) ||152_compilation->getOption(TR_EnableFastScorchingRecompilation))153{154// The body must be able to receive samples and recompilation should be enabled155//156if (!_bodyInfo->getDisableSampling() && !_doNotCompileAgain)157{158if (_compilation->getOption(TR_EnableFastHotRecompilation) && _bodyInfo->getHotness() < hot)159{160_bodyInfo->setFastHotRecompilation(true);161}162163if (_compilation->getOption(TR_EnableFastScorchingRecompilation) && _bodyInfo->getHotness() < scorching)164{165_bodyInfo->setFastScorchingRecompilation(true);166}167}168}169}170171172int32_t173J9::Recompilation::getProfilingFrequency()174{175return self()->findOrCreateProfileInfo()->getProfilingFrequency();176}177178179int32_t180J9::Recompilation::getProfilingCount()181{182return self()->findOrCreateProfileInfo()->getProfilingCount();183}184185/**186* Find or create profiling information for the current jitted187* body. If creating information, this will update the recent188* profile information on the current method info.189*/190TR_PersistentProfileInfo *191J9::Recompilation::findOrCreateProfileInfo()192{193// Determine whether this bodyInfo already has profiling information194TR_PersistentProfileInfo *profileInfo = _bodyInfo->getProfileInfo();195if (!profileInfo)196{197// Create a new profiling info198profileInfo = new (PERSISTENT_NEW) TR_PersistentProfileInfo(DEFAULT_PROFILING_FREQUENCY, DEFAULT_PROFILING_COUNT);199_methodInfo->setRecentProfileInfo(profileInfo);200_bodyInfo->setProfileInfo(profileInfo);201202// If running with the profiling thread, add to its list203if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableJProfilerThread))204{205TR::CompilationInfo::get(NULL)->getJProfilerThread()->addProfileInfo(profileInfo);206}207}208return profileInfo;209}210211TR_PersistentProfileInfo *212J9::Recompilation::getProfileInfo()213{214return _bodyInfo->getProfileInfo();215}216217void218J9::Recompilation::startOfCompilation()219{220if (!_firstCompile && _compilation->getOption(TR_FailRecompile))221{222_compilation->failCompilation<TR::CompilationException>("failRecompile");223}224225if (!_compilation->fej9()->isAOT_DEPRECATED_DO_NOT_USE())226{227_timer.startTiming(_compilation);228}229}230231232void233J9::Recompilation::beforeOptimization()234{235// If the method is to be compiled with profiling info, force it to use236// counting and not sampling. Also make sure there is a persistent237// profile info block.238//239if (self()->isProfilingCompilation()) // this asks the bodyInfo240{241// JProfiling should not use either sampling or counting mechanism to trip recompilation.242// Even though _useSampling is set to true here, at the end of compilation we disable sampling243// causing us to rely only on the in-body recompilation test that relies on block frequency counter244// to trip recompilation making sure we have enough profiling data to use in recompilation.245_useSampling = _compilation->getProfilingMode() != JitProfiling;246self()->findOrCreateProfileInfo()->setProfilingCount (DEFAULT_PROFILING_COUNT);247self()->findOrCreateProfileInfo()->setProfilingFrequency (DEFAULT_PROFILING_FREQUENCY);248}249250// Create profilers251//252if (self()->couldBeCompiledAgain())253{254if (_compilation->getProfilingMode() == JProfiling)255self()->createProfilers();256else if (!self()->useSampling())257{258if (_compilation->getMethodHotness() == cold)259{260_profilers.add(new (_compilation->trHeapMemory()) TR_LocalRecompilationCounters(_compilation, self()));261}262else if (self()->isProfilingCompilation())263{264self()->createProfilers();265}266else if (!_compilation->getOption(TR_FullSpeedDebug))267{268_profilers.add(new (_compilation->trHeapMemory()) TR_GlobalRecompilationCounters(_compilation, self()));269}270}271else272{273if (!debug("disableCatchBlockProfiler"))274{275_profilers.add(new (_compilation->trHeapMemory()) TR_CatchBlockProfiler(_compilation, self(), true));276}277}278}279}280281282void283J9::Recompilation::beforeCodeGen()284{285// Set up the opt level and counter for the next compilation. This will286// also decide if there is going to be a next compilation.287TR::CompilationController::getCompilationStrategy()->beforeCodeGen(_compilation->getOptimizationPlan(), self());288}289290291void292J9::Recompilation::endOfCompilation()293{294// Perform any platform-dependant tasks if needed295//296self()->postCompilation();297298// We will free the optimizationPlan at the end of compilation,299// do we need to clear the corresponding field in300//301TR::CompilationController::getCompilationStrategy()->postCompilation(_compilation->getOptimizationPlan(), self());302303if (self()->couldBeCompiledAgain())304{305_bodyInfo->setCounter(_nextCounter);306307// set the start counter to the current timestamp308//309_bodyInfo->setStartCount(globalSampleCount);310_bodyInfo->setOldStartCountDelta(TR::Options::_sampleThreshold);311_bodyInfo->setHotStartCountDelta(0);312_bodyInfo->setSampleIntervalCount(0);313314// if the only possible next compilation of this method is315// unnatural, _nextLevel will not be set, recompile at the316// current level317//318if (!self()->shouldBeCompiledAgain())319{320_nextLevel = _compilation->getMethodHotness();321}322323_methodInfo->setNextCompileLevel(_nextLevel, false); // profiling can only be triggered from sampleMethod324325_bodyInfo->setHasLoops (_compilation->mayHaveLoops());326_bodyInfo->setUsesPreexistence(_compilation->usesPreexistence());327328// if the only future compilation can be a forced one (preexistence)329// do not sample this method. If this is a counting based compilation330// disable sampling as well331//332if (!self()->shouldBeCompiledAgain() || !_useSampling || _compilation->getProfilingMode() == JProfiling)333{334_bodyInfo->setDisableSampling(true);335}336}337338// If we disallow recompilation then disable sampling339if (!_compilation->allowRecompilation())340_bodyInfo->setDisableSampling(true);341}342343344/**345* @brief346* Switches the current compilation to a profiling mode in which profiling group optimizations will347* run and potentially insert profiling trees into the compiled body.348*349* @param f350* The profiling frequency for the persistent profiling info to use.351* @param c352* The profiling count for the persistent profiling info to use.353*354* @return355* True if the compilation was successfully switched to a profiling compilation; false otherwise.356*/357bool358J9::Recompilation::switchToProfiling(uint32_t f, uint32_t c)359{360if (_compilation->fej9()->isAOT_DEPRECATED_DO_NOT_USE())361{362return false;363}364365if (!_methodInfo)366{367return false;368}369370if (_methodInfo->profilingDisabled())371{372return false;373}374375if (!self()->countingSupported())376{377return false;378}379380if (self()->isProfilingCompilation())381{382return true;383}384385if (!TR::CompilationController::getCompilationStrategy()->enableSwitchToProfiling())386{387return false;388}389390if (comp()->getOptimizationPlan()->getDoNotSwitchToProfiling())391{392return false;393}394395if (_compilation->isOptServer() && !_compilation->getOption(TR_AggressiveSwitchingToProfiling))396{397return false;398}399400if (!_bodyInfo->getIsProfilingBody())401{402if (!performTransformation(comp(), "\nSwitching the compile to do profiling (isProfilingCompile=1)\n"))403return false;404}405406_bodyInfo->setIsProfilingBody(true);407408// If profiling will use JProfiling instrumentation and this is post JProfilingBlock opt pass, trigger restart409if (_compilation->getProfilingMode() == JProfiling && _compilation->getSkippedJProfilingBlock())410{411TR::DebugCounter::incStaticDebugCounter(_compilation, TR::DebugCounter::debugCounterName(_compilation,412"jprofiling.restartCompile/(%s)", _compilation->signature()));413if (TR::Options::getVerboseOption(TR_VerboseProfiling))414TR_VerboseLog::writeLineLocked(TR_Vlog_PROFILING, "Restarting compilation due to late switch to profiling");415comp()->failCompilation<J9::EnforceProfiling>("Enforcing profiling compilation");416}417418_useSampling = _compilation->getProfilingMode() != JitProfiling;419self()->findOrCreateProfileInfo()->setProfilingFrequency(f);420self()->findOrCreateProfileInfo()->setProfilingCount(c);421self()->createProfilers();422return true;423}424425426bool427J9::Recompilation::switchToProfiling()428{429return self()->switchToProfiling(DEFAULT_PROFILING_FREQUENCY, DEFAULT_PROFILING_COUNT);430}431432433void434J9::Recompilation::switchAwayFromProfiling()435{436_bodyInfo->setIsProfilingBody(false);437_useSampling = true;438}439440441void442J9::Recompilation::createProfilers()443{444if (!self()->getValueProfiler())445_profilers.add(new (_compilation->trHeapMemory()) TR_ValueProfiler(_compilation, self(),446_compilation->getProfilingMode() == JProfiling ? HashTableProfiler : LinkedListProfiler ));447448if (!self()->getBlockFrequencyProfiler() && _compilation->getProfilingMode() != JProfiling)449_profilers.add(new (_compilation->trHeapMemory()) TR_BlockFrequencyProfiler(_compilation, self()));450}451452453bool454J9::Recompilation::couldBeCompiledAgain()455{456return457self()->shouldBeCompiledAgain() ||458_compilation->usesPreexistence() ||459_compilation->getOption(TR_EnableHCR);460}461462463bool464J9::Recompilation::shouldBeCompiledAgain()465{466return TR::Options::canJITCompile() && !_doNotCompileAgain;467}468469470void471J9::Recompilation::preventRecompilation()472{473_nextCounter = 0;474_doNotCompileAgain = true;475476for (TR_RecompilationProfiler * rp = getFirstProfiler(); rp; rp = rp->getNext())477{478if (rp->getHasModifiedTrees())479{480rp->removeTrees();481rp->setHasModifiedTrees(false);482}483}484}485486487TR_PersistentMethodInfo *488J9::Recompilation::getExistingMethodInfo(TR_ResolvedMethod *method)489{490// Default (null) implementation491//492TR_ASSERT(0, "This method needs to be implemented");493return 0;494}495496/**497* This method can extract a value profiler from the current list of498* recompilation profilers.499*500* \return The first TR_ValueProfiler in the current list of profilers, NULL if there are none.501*/502TR_ValueProfiler *503J9::Recompilation::getValueProfiler()504{505for (TR_RecompilationProfiler * rp = getFirstProfiler(); rp; rp = rp->getNext())506{507TR_ValueProfiler *vp = rp->asValueProfiler();508if (vp)509return vp;510}511512return NULL;513}514515/**516* This method can extract a block profiler from the current list of517* recompilation profilers.518*519* \return The first TR_BlockFrequencyProfiler in the current list of profilers, NULL if there are none.520*/521TR_BlockFrequencyProfiler *522J9::Recompilation::getBlockFrequencyProfiler()523{524for (TR_RecompilationProfiler * rp = getFirstProfiler(); rp; rp = rp->getNext())525{526TR_BlockFrequencyProfiler *vp = rp->asBlockFrequencyProfiler();527if (vp)528return vp;529}530531return NULL;532}533534/**535* This method can remove a specified recompilation profiler from the536* current list. Useful when modifying the profiling strategy.537*538* \param rp The recompilation profiler to remove.539*/540void541J9::Recompilation::removeProfiler(TR_RecompilationProfiler *rp)542{543_profilers.remove(rp);544}545546TR_Hotness547J9::Recompilation::getNextCompileLevel(void *oldStartPC)548{549TR_PersistentMethodInfo *methodInfo = TR::Recompilation::getMethodInfoFromPC(oldStartPC);550return methodInfo->getNextCompileLevel();551}552553554TR::SymbolReference *555J9::Recompilation::getCounterSymRef()556{557return _compilation->getSymRefTab()->findOrCreateRecompilationCounterSymbolRef(_bodyInfo->getCounterAddress());558}559560561/////////////////////////562// DEBUG563//////////////////////////564565void566J9::Recompilation::shutdown()567{568static bool TR_RecompilationStats = feGetEnv("TR_RecompilationStats")?1:0;569if (TR_RecompilationStats)570{571TR_VerboseLog::writeLine(TR_Vlog_INFO,"Methods recompiled via count = %d", limitMethodsCompiled);572TR_VerboseLog::writeLine(TR_Vlog_INFO,"Methods recompiled via hot threshold = %d", hotThresholdMethodsCompiled);573TR_VerboseLog::writeLine(TR_Vlog_INFO,"Methods recompiled via scorching threshold = %d", scorchingThresholdMethodsCompiled);574}575}576577578579580TR_PersistentMethodInfo::TR_PersistentMethodInfo(TR::Compilation *comp) :581_methodInfo((TR_OpaqueMethodBlock *)comp->getCurrentMethod()->resolvedMethodAddress()),582_flags(0),583_nextHotness(unknownHotness),584_recentProfileInfo(0),585_bestProfileInfo(0),586_optimizationPlan(0),587_numberOfInvalidations(0),588_numberOfInlinedMethodRedefinition(0),589_numPrexAssumptions(0)590{591if (comp->getOption(TR_EnableHCR) && !comp->fej9()->isAOT_DEPRECATED_DO_NOT_USE())592{593// If the method gets replaced, we'll want _methodInfo to get updated594//595comp->cg()->jitAddPicToPatchOnClassRedefinition((void*)_methodInfo, (void*)&_methodInfo, false);596}597598if (comp->getOption(TR_DisableProfiling) || comp->fej9()->isAOT_DEPRECATED_DO_NOT_USE())599{600setDisableProfiling();601}602603// Start cpoSampleCounter at 1. Because the method sample count604// is stored in the compiled method info, we can't start counting605// until already compiled once, thus we missed the first sample.606// (not particularly clean solution. Should really attach the607// counter to the method, not the compiled-method)608//609_cpoSampleCounter = 1;610611uint64_t tempTimeStamp = comp->getPersistentInfo()->getElapsedTime();612if (tempTimeStamp < (uint64_t)0x0FFFF)613_timeStamp = (uint16_t)tempTimeStamp;614else615_timeStamp = (uint16_t)0xFFFF;616}617618TR_PersistentMethodInfo::TR_PersistentMethodInfo(TR_OpaqueMethodBlock *methodInfo) :619_methodInfo(methodInfo),620_flags(0),621_nextHotness(unknownHotness),622_recentProfileInfo(0),623_bestProfileInfo(0),624_optimizationPlan(0),625_numberOfInvalidations(0),626_numberOfInlinedMethodRedefinition(0),627_numPrexAssumptions(0)628{629}630631TR_PersistentMethodInfo *632TR_PersistentMethodInfo::get(TR::Compilation *comp)633{634TR::Recompilation * recomp = comp->getRecompilationInfo();635return recomp ? recomp->getMethodInfo() : 0;636}637638TR_PersistentMethodInfo *639TR_PersistentMethodInfo::get(TR_ResolvedMethod * feMethod)640{641if (feMethod->isInterpreted() || feMethod->isJITInternalNative())642return 0;643644TR_PersistentJittedBodyInfo *bodyInfo = ((TR_ResolvedJ9Method*) feMethod)->getExistingJittedBodyInfo();645return bodyInfo ? bodyInfo->getMethodInfo() : 0;646}647648TR_PersistentJittedBodyInfo::TR_PersistentJittedBodyInfo(649TR_PersistentMethodInfo *methodInfo,650TR_Hotness hotness,651bool profile,652TR::Compilation *comp) :653_methodInfo(methodInfo),654_counter(INT_MAX),655_mapTable(comp == 0 || comp->getOption(TR_DoNotUseFastStackwalk) ? 0 : (void *)-1),656_hotness(hotness),657_flags(0),658_sampleIntervalCount(0),659_startCount(0),660_isInvalidated(false),661_aggressiveRecompilationChances((uint8_t)TR::Options::_aggressiveRecompilationChances),662_startPCAfterPreviousCompile(0),663_longRunningInterpreted(false),664_numScorchingIntervals(0),665_profileInfo(0)666,_hwpInstructionStartCount(0),667_hwpInstructionCount(0),668_hwpInducedRecompilation(false),669_hwpReducedWarmCompileRequested(false),670_hwpReducedWarmCompileInQueue(false)671{672setIsProfilingBody(profile);673}674675TR_PersistentJittedBodyInfo *676TR_PersistentJittedBodyInfo::allocate(677TR_PersistentMethodInfo *methodInfo,678TR_Hotness hotness,679bool profile,680TR::Compilation *comp)681{682return new (PERSISTENT_NEW) TR_PersistentJittedBodyInfo(methodInfo, hotness, profile, comp);683}684685/**686* Increment reference count for shared profile info.687*688* This function and setForSharedInfo use the pointer's low bit as a lock,689* preventing other accesses to the persistent information through this pointer.690* This is necessary as the process of incrementing the reference count isn't691* atomic with the pointer updates.692*693* When locked, its able to safely dereference the pointer and increment694* its reference count. Without the lock, the information could have been695* deallocated in the interim.696*697* \param ptr Pointer shared across several threads.698*/699TR_PersistentProfileInfo *700TR_PersistentMethodInfo::getForSharedInfo(TR_PersistentProfileInfo** ptr)701{702uintptr_t locked;703uintptr_t unlocked;704705// Lock the ptr706do {707locked = ((uintptr_t) *ptr) | (1ULL);708unlocked = ((uintptr_t) *ptr) & ~(1ULL);709if (unlocked == 0)710return NULL;711}712while (unlocked != VM_AtomicSupport::lockCompareExchange((uintptr_t*)ptr, unlocked, locked));713714// Inc ref count715TR_PersistentProfileInfo::incRefCount((TR_PersistentProfileInfo*)unlocked);716717// Unlock the ptr718// Assumes no updates to the ptr whilst locked719VM_AtomicSupport::set((uintptr_t*)ptr, unlocked);720721return *ptr;722}723724/**725* Update a shared pointer to reference a new persistent profile info.726*727* This should be used with getForSharedInfo, to ensure a shared persistent profile info is728* updated correctly.729*730* \param ptr Pointer shared across several threads.731* \param newInfo New persistent profile info to use. Should have a non-zero reference count in caller.732*/733void734TR_PersistentMethodInfo::setForSharedInfo(TR_PersistentProfileInfo** ptr, TR_PersistentProfileInfo *newInfo)735{736uintptr_t oldPtr;737738// Before it can be accessed, inc ref count on new info739if (newInfo)740TR_PersistentProfileInfo::incRefCount(newInfo);741742// Update ptr as if it was unlocked743// Doesn't matter what the old info was, as long as it was unlocked744do {745oldPtr = ((uintptr_t) *ptr) & ~(1ULL);746}747while (oldPtr != VM_AtomicSupport::lockCompareExchange((uintptr_t*)ptr, oldPtr, (uintptr_t)newInfo));748749// Now that it can no longer be accessed, dec ref count on old info750if (oldPtr)751TR_PersistentProfileInfo::decRefCount((TR_PersistentProfileInfo*)oldPtr);752}753754#if defined(J9VM_OPT_JITSERVER)755TR_PersistentJittedBodyInfo *756J9::Recompilation::persistentJittedBodyInfoFromString(const std::string &bodyInfoStr, const std::string &methodInfoStr, TR_Memory *trMemory)757{758if (bodyInfoStr.empty())759return NULL;760TR_ASSERT_FATAL(!methodInfoStr.empty(), "If we have a persistentBodyInfo we must have a persistentMethodInfo too");761auto bodyInfo = (TR_PersistentJittedBodyInfo*) trMemory->allocateHeapMemory(sizeof(TR_PersistentJittedBodyInfo), TR_MemoryBase::Recompilation);762auto methodInfo = (TR_PersistentMethodInfo*) trMemory->allocateHeapMemory(sizeof(TR_PersistentMethodInfo), TR_MemoryBase::Recompilation);763764memcpy(bodyInfo, &bodyInfoStr[0], sizeof(TR_PersistentJittedBodyInfo));765memcpy(methodInfo, &methodInfoStr[0], sizeof(TR_PersistentMethodInfo));766767bodyInfo->setMethodInfo(methodInfo);768bodyInfo->setProfileInfo(NULL);769bodyInfo->setMapTable(NULL);770resetPersistentProfileInfo(methodInfo);771return bodyInfo;772}773774void775J9::Recompilation::resetPersistentProfileInfo(TR_PersistentMethodInfo *methodInfo)776{777methodInfo->setOptimizationPlan(NULL);778// Cannot use setter because it calls the destructor on the old profile data,779// which is a client pointer780methodInfo->_recentProfileInfo = NULL;781methodInfo->_bestProfileInfo = NULL;782}783#endif /* defined(J9VM_OPT_JITSERVER) */784785786