Path: blob/master/runtime/compiler/codegen/MonitorState.cpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2019 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 <stdint.h>23#include "codegen/CodeGenerator.hpp"24#include "codegen/MonitorState.hpp"25#include "il/Block.hpp"26#include "il/Node_inlines.hpp"27#include "il/RegisterMappedSymbol.hpp"28#include "il/SymbolReference.hpp"29#include "infra/Array.hpp"30#include "infra/Cfg.hpp"31#include "infra/List.hpp"32#include "infra/TRCfgEdge.hpp"33#include "infra/TRCfgNode.hpp"34#include "infra/Stack.hpp"35363738int32_t39J9::SetMonitorStateOnBlockEntry::addSuccessors(40TR::CFGNode * cfgNode,41TR_Stack<TR::SymbolReference *> * monitorStack,42bool traceIt,43bool dontPropagateMonitor,44MonitorInBlock monitorType,45int32_t callerIndex,46bool walkOnlyExceptionSuccs)47{48if (traceIt)49traceMsg(comp(),50"\tIn SMSOBE::addSuccessors for cfgNode %d, monitorStack %p dontPropagateMonitor %d monitorType = %d callerIndex %d walkOlyExceptionSuccs %d\n"51, cfgNode->getNumber(),monitorStack,dontPropagateMonitor,monitorType,callerIndex,walkOnlyExceptionSuccs);5253bool firstSuccessor = true;5455// to reiterate:56// 3 cases to consider when propagating the monitorStack57// 1. MonitorEnter58// Normal Edge -> propagate59// Exception Edge ->60// if syncMethodMonitor from callerIndex=-161// -> propagate62// else -> do not propagate63//64// 2. MonitorExit (at this stage the monitor has been temporarily pushed on the monitorStack)65// Normal Edge -> pop before propagate66// Exception Edge ->67// check if the exception successor of the current block has the same caller index or not68// if same caller index, then:69// a) in a synchronized method, the catch block will eventually unlock the monitor. so we assume70// that if the blocks are in the same method, then the monitor will be unlocked by the catch block71// b) for a synchronized block, all blocks within the region (including the block with the monexit)72// will always branch to the "catch-all" block inserted by the JIT and not to a user catch block.73// the catch-all block will unlock the monitor and rethrow the exception.74// so in both these cases, we want to push the monitor along the exception successor because the monitor75// will be unlocked eventually.76//77// if not the same caller index, then:78// a) the monexit block and the exception successor are in different methods (ie. the monexit - regardless of79// sync method or sync block, came from an inlined method and the successor is in the caller).80// in this case, we dont want to push the monitor along the exception successor because the exception successor81// has no idea that it needs to unlock the monitor.82//83// -> pop before propagate / push before propagate in the case described above84// else -> propagate the monitorStack (with the monitor pushed on it temporarily) ie. do not pop85//86// 3. NoMonitor -> propagate the monitorStack as is87//88// return value89// -1 : default value90// 1 : if the monitorStack was propagated with the monitor pushed temporarily91// 0 : otherwise92//93int32_t returnValue = -1;9495TR_SuccessorIterator succs(cfgNode);96for (TR::CFGEdge *edge = succs.getFirst(); edge; edge = succs.getNext())97{98TR::Block * succBlock = toBlock(edge->getTo());99// skip the exception successors for now in this walk100// they will be processed later101//102if (walkOnlyExceptionSuccs && !succBlock->isCatchBlock())103continue;104105if (succBlock->getEntry())106{107bool addInfo = true;108if (monitorType == MonitorEnter)109{110if (traceIt)111traceMsg(comp(), "\tIn J9::SetMonitorStateOnBlockEntry::addSuccessors monitorType = MonitorEnter block %d\n", succBlock->getNumber());112if (succBlock->isCatchBlock() && dontPropagateMonitor)113{114returnValue = 0;115addInfo = false;116}117}118119if (monitorType == MonitorExit)120{121if (walkOnlyExceptionSuccs)122{123if (callerIndex != succBlock->getEntry()->getNode()->getByteCodeInfo().getCallerIndex())124{125returnValue = 0;126addInfo = false;127}128else129returnValue = 1; // push the monitor along this exception edge130}131else if (succBlock->isCatchBlock()) // already processed during exception successors walk132continue;133}134135if (traceIt)136traceMsg(comp(), "process succBlock %d propagate (t/f: %d) isCatchBlock=%d monitorType=%d callerIndex=%d entryCallerIndex=%d\n", succBlock->getNumber(), addInfo, succBlock->isCatchBlock(), monitorType, callerIndex, succBlock->getEntry()->getNode()->getByteCodeInfo().getCallerIndex());137138bool popMonitor = false;139if (monitorStack)140{141// pop the last element of the stack if dontPropagateMonitor is true142//143if (!addInfo &&144!monitorStack->isEmpty())145{146popMonitor = true;147}148149if (succBlock->getVisitCount() != _visitCount)150{151TR_Stack<TR::SymbolReference *> *newMonitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);152153if (traceIt)154traceMsg(comp(), "\tIn SMSOnBE::addSuccesors created newMonitorStack %p and monitorStack %p\n", newMonitorStack,monitorStack);155156if (popMonitor)157{158if (traceIt)159traceMsg(comp(), "popping monitor symRef=%d before propagation\n", newMonitorStack->top()->getReferenceNumber());160newMonitorStack->pop();161}162163if (_liveMonitorStacks->find(succBlock->getNumber()) != _liveMonitorStacks->end())164{165_liveMonitorStacks->erase(succBlock->getNumber());166}167(*_liveMonitorStacks)[succBlock->getNumber()] = newMonitorStack;168if (traceIt)169traceMsg(comp(), "adding monitorstack to successor %d (%p size %d)\n", succBlock->getNumber(), newMonitorStack, newMonitorStack->size());170}171else172{173// the block has been propagated already but we want to verify the monitor state is consistent174// skip osr blocks here because the monitor state of osrBlocks don't have to be consistent175if (!succBlock->isOSRCatchBlock() && !succBlock->isOSRCodeBlock())176{177if (!isMonitorStateConsistentForBlock(succBlock, monitorStack, popMonitor))178comp()->cg()->setLmmdFailed();179else180{181if (traceIt)182traceMsg(comp(), "verified block_%d monitorState is consistent\n", succBlock->getNumber());183}184}185continue;186}187}188else if (succBlock->getVisitCount() == _visitCount)189{190if(!succBlock->isOSRCatchBlock() && !succBlock->isOSRCodeBlock())191{192if (!isMonitorStateConsistentForBlock(succBlock, monitorStack, popMonitor))193comp()->cg()->setLmmdFailed();194else if (traceIt)195traceMsg(comp(), "verified block_%d monitorState is consistent\n", succBlock->getNumber());196}197continue;198}199200if (traceIt)201traceMsg(comp(), "\tIn SMSOnBE::addSuccessors adding block %d to blocksToVisit\n", succBlock->getNumber());202_blocksToVisit.push(succBlock);203}204}205206return returnValue;207}208209bool210J9::SetMonitorStateOnBlockEntry::isMonitorStateConsistentForBlock(211TR::Block *block,212TR_Stack<TR::SymbolReference *> *newMonitorStack,213bool popMonitor)214{215TR_Stack<TR::SymbolReference *> *oldMonitorStack = _liveMonitorStacks->find(block->getNumber()) != _liveMonitorStacks->end() ?216(*_liveMonitorStacks)[block->getNumber()] : NULL;217static const bool traceItEnv = feGetEnv("TR_traceLiveMonitors") ? true : false;218bool traceIt = traceItEnv || comp()->getOption(TR_TraceLiveMonitorMetadata);219220if (traceIt)221traceMsg(comp(), "MonitorState block_%d: oldMonitorStack %p newMonitorStack %p popMonitor %d\n", block->getNumber(), oldMonitorStack, newMonitorStack, popMonitor);222223// first step: check if both monitor stacks are empty224bool oldMonitorStackEmpty = false;225bool newMonitorStackEmpty = false;226227if (!oldMonitorStack || oldMonitorStack->isEmpty())228oldMonitorStackEmpty = true;229if (!newMonitorStack || newMonitorStack->isEmpty()230|| (newMonitorStack->size() == 1 && popMonitor))231newMonitorStackEmpty = true;232if (oldMonitorStackEmpty != newMonitorStackEmpty)233{234if (traceIt)235traceMsg(comp(), "MonitorState inconsistent for block_%d: oldMonitorStack isEmpty %d, newMonitorStack isEmpty %d\n", block->getNumber(), oldMonitorStackEmpty, newMonitorStackEmpty);236return false;237}238else if (oldMonitorStackEmpty)239return true;240241// second step: check if the monitor stacks are the same size242int32_t oldSize = oldMonitorStack->size();243int32_t newSize = newMonitorStack->size();244if (popMonitor)245newSize--;246if (newSize != oldSize)247{248if (traceIt)249traceMsg(comp(), "MonitorState inconsistent for block_%d: oldMonitorStack size %d, newMonitorStack size %d\n",block->getNumber(), oldSize, newSize);250return false;251}252253// third step: check if all the monitors in both stacks are the same254for (int i = oldMonitorStack->topIndex(); i>= 0; i--)255{256if (newMonitorStack->element(i)->getReferenceNumber() != oldMonitorStack->element(i)->getReferenceNumber())257{258if (traceIt)259traceMsg(comp(), "MonitorState inconsistent for block_%d: oldMonitorStack(%d) symRef=%d, newMonitorStack(%d) symRef=%d\n",block->getNumber(), i, oldMonitorStack->element(i)->getReferenceNumber(), i, newMonitorStack->element(i)->getReferenceNumber());260return false;261}262}263return true;264}265266// this routine is used to decide if the monitorStack needs to be popped267// the analysis needs to be careful in particular for DLT compiles as there are268// several scenarios as the DLT control could land into the middle of a269// nested (several levels deep) synchronized region270// a) if the monexit is at callerIndex=-1,271// this means that the monitorStack could be imbalanced272// i) if synchronized method then the syncObjectTemp would have been used to273// initialize the hidden slot in the DLT entry (monitorStack size is 1) and274// then control could branch into the middle of a synchronized region (without275// ever seeing any monents). At the monexit, the analysis would then try to pop276// the lone monitor on the stack so prevent this by checking if the stack size is 1.277// This is done because the special slot needs to be live across the entire method278//279// ii) an improvement to i) is done at blocks that exit the method. in these cases,280// the analysis would have encountered the monexits corresponding to the synchronized281// 'this' so it needs to empty the stack282//283// iii) an exception to i) is when the method is a static synchronized method. in this284// case, the syncObjectTemp is not used to initialize the monitor slot in the DLT entry285// (so the monitorStack size is 0). so the analysis should avoid any special checks286//287// in case i) or iii) fails, this means that the DLT control landed straight into the sync288// region (with no monitorStack), in this case the analysis needs to ensure that an empty289// monitorStack is not popped290//291//292// b) if the monexit is not at callerIndex=-1, then this means that the monexit was293// part of a monent-monexit region that would have normally appeared in the method. an imbalance294// in the monitorStack indicates an error, but return the default answer as "yes", the stack295// can be popped.296//297// c) if not DLT, then return the default answer as "yes"298//299//300static bool canPopMonitorStack(301TR::Compilation *comp,302TR_Stack<TR::SymbolReference *> * monitorStack,303TR::Node *node,304bool blockExitsMethod,305bool traceIt)306{307int32_t callerIndex = node->getByteCodeInfo().getCallerIndex();308if (comp->isDLT())309{310if (callerIndex == -1)311{312if (comp->getJittedMethodSymbol()->isSynchronised())313{314// We have the special slot set up at DLT entry. Let us avoid resetting315// the bit for this special slot so that we do not have any wrong GC maps316// TODO : if we need to empty the monitor stack at the end of the method317// then pop it off the stack only when we reach a block whose successor is318// the dummy exit block319//320if (monitorStack->size() == 1 &&321!comp->getJittedMethodSymbol()->isStatic() &&322!blockExitsMethod)323{324if (traceIt)325traceMsg(comp, "monitorStack is empty (except for special DLT sync object slot) for DLT compile at monexit %p\n", node);326return false;327}328else if (monitorStack->isEmpty())329{330if (traceIt)331traceMsg(comp, "monitorStack is empty for DLT compile at monexit %p\n", node);332return false;333}334}335else336{337if (monitorStack->isEmpty())338{339if (traceIt)340traceMsg(comp, "monitorStack is empty for non-synchronized DLT compile at monexit %p\n", node);341return false;342}343}344}345else346{347// TODO : could add an assert error here : check if the elem to be popped off348// from the monitor stack for your caller index and assert if there is not349/*350if (!monitorStack->isEmpty() &&351monitorStack->top())352{353if (monitorStack->top()->getOwningMethodIndex() != callerIndex)354traceMsg(comp(), "unbalanced monitorStack, trying to pop %d but top is %d symRef: %d\n", callerIndex, monitorStack->top()->getOwningMethodIndex(), monitorStack->top()->getReferenceNumber());355TR_ASSERT(monitorStack->top()->getOwningMethodIndex() == callerIndex, "unbalanced monitorStack, trying to pop %d but top is %d\n", callerIndex, monitorStack->top()->getOwningMethodIndex());356}357*/358return true;359}360}361362return true;363}364365static bool needToPushMonitor(TR::Compilation *comp, TR::Block *block, bool traceIt)366{367// this routine is needed to decide if the monitor needs to be temporarily368// pushed back onto the stack for the successor369// for a sequence such as this for a synchronized block:370// synchronized {371// ...372// }373// return374// BBEnd375//376// older javac includes the return in the exception range (for the catch-all block)377// when MethodEnter/MethodExit hooks are enabled, we split the blocks as follows:378// synchronized {379// ...380// }381// check the hook bit382// BBEnd383// BBStart <-- new block after split384// return385// BBEnd386// ...387// since the return is included in the exception range, the new blocks (after the split)388// also have exception successors to the catch-all block. this results in unbalanced389// monitors because we would have popped the monitorStack at the block containing the monexit390// new javac seem to correctly exclude the return from the exception range391// To support this case, walk the successors of the current block and check if the successor392// has identical exception successors.393//394// A new case. When a transaction exists, the monexitfence is in a separate block from the395// monexit and the tfinish. So the two blocks will generally have an exception edge with the same destination block396// So for this case don't return true. *Shudder*397398bool retval = false;399for (auto e = block->getSuccessors().begin(); e != block->getSuccessors().end(); ++e)400{401TR::Block *succ = (*e)->getTo()->asBlock();402if (comp->getFlowGraph()->compareExceptionSuccessors(block, succ) == 0)403{404if (traceIt)405traceMsg(comp, "found identical exception successors for block %d and succ %d\n", block->getNumber(), succ->getNumber());406407retval = true;408for (TR::TreeTop *tt = succ->getEntry(); tt != succ->getExit() ; tt = tt->getNextTreeTop())409{410TR::Node *aNode = tt->getNode();411412if (aNode && (aNode->getOpCodeValue() == TR::tfinish || aNode->getOpCodeValue() == TR::monexit ||413((aNode->getOpCodeValue() == TR::treetop|| aNode->getOpCodeValue() == TR::NULLCHK) && aNode->getFirstChild()->getOpCodeValue() == TR::monexit )414))415{416if(traceIt)417traceMsg(comp, "overriding identical exception decision because node %p in block %d is either monexit or tfinish",aNode,succ->getNumber());418retval = false;419break;420}421}422break;423}424}425return retval;426}427428void J9::SetMonitorStateOnBlockEntry::set(bool& lmmdFailed, bool traceIt)429{430addSuccessors(comp()->getFlowGraph()->getStart(), 0, traceIt);431static bool traceInitMonitorsForExceptionAfterMonexit = feGetEnv("TR_traceInitMonitorsForExceptionAfterMonexit")? true: false;432433while (!_blocksToVisit.isEmpty())434{435TR::Block * block = _blocksToVisit.pop();436if (block->getVisitCount() == _visitCount)437continue;438block->setVisitCount(_visitCount);439440if (traceIt)441traceMsg(comp(), "block to process: %d\n", block->getNumber());442443TR_Stack<TR::SymbolReference *> *monitorStack =444(_liveMonitorStacks->find(block->getNumber()) != _liveMonitorStacks->end()) ?445(*_liveMonitorStacks)[block->getNumber()] :446NULL;447448if (traceIt && monitorStack && !monitorStack->isEmpty())449traceMsg(comp(), "top of the stack symRef=%d, and size=%d\n", monitorStack->top()->getReferenceNumber(), monitorStack->size());450else if (traceIt)451traceMsg(comp(), "monitor stack is empty\n");452453bool blockHasMonent = false;454bool blockHasMonexit = false;455456bool blockExitsMethod = false;457TR_SuccessorIterator succs(block);458for (TR::CFGEdge *edge = succs.getFirst(); edge; edge = succs.getNext())459{460if (edge->getTo()->getNumber() == comp()->getFlowGraph()->getEnd()->getNumber())461blockExitsMethod = true;462}463464bool isSyncMethodMonent = false;465bool isSyncMethodMonexit = false;466TR::SymbolReference *monitorStackTop = NULL;467int32_t callerIndex = -1;468int32_t monitorPoppedForExceptionSucc = 1;469int32_t monitorEnterStore = 0;470int32_t monitorExitFence= 0;471for (TR::TreeTop * tt = block->getEntry(); ; tt = tt->getNextTreeTop())472{473TR::Node * node = tt->getNode();474if (node->getOpCodeValue() == TR::treetop || node->getOpCodeValue() == TR::NULLCHK)475node = node->getFirstChild();476477TR::ILOpCodes opCode = node->getOpCodeValue();478479if ((node->getOpCode().isStore() && //only monents are represented by this store now480node->getSymbol()->holdsMonitoredObject() &&481!node->isLiveMonitorInitStore()))482{483//problem with lmmd only occurs when the exception successor is not 0484if(!block->getExceptionSuccessors().empty())485monitorEnterStore++;486487callerIndex = node->getByteCodeInfo().getCallerIndex();488if (monitorStack)489{490monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);491if (traceIt)492traceMsg(comp(), "adding monitor to stack symbol=%p symRef=%d (size=%d) (node %p)\n", node->getSymbol(), node->getSymbolReference()->getReferenceNumber(), monitorStack->size()+1,node);493}494else495{496monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(trMemory());497if (traceIt)498traceMsg(comp(), "adding monitor to fresh stack symbol=%p symRef=%d (size=%d) (node %p)\n", node->getSymbol(), node->getSymbolReference()->getReferenceNumber(), monitorStack->size()+1,node);499}500501monitorStack->push(node->getSymbolReference());502blockHasMonent = true;503504// if the callerIndex of the node is *not* -1, then this node505// came from a synchronized method that was inlined. in this case,506// don't push the monitor info along exception successors for this block.507// the typical pattern should be:508// ...509// astore <holdsMonitoredObject>510// monent511// BBEnd // exception successor of this block will not unlock the object (it512// // actually belongs to the caller513// BBStart //start of inlined method, these blocks will have the catchall block514// //that unlocks the monitor515//516if (node->getSymbolReference()->holdsMonitoredObjectForSyncMethod() &&517(callerIndex == -1))518isSyncMethodMonent = true;519}520else if ( (node->getOpCode().getOpCodeValue() == TR::monexitfence) &&521monitorStack && !monitorStack->isEmpty() &&522canPopMonitorStack(comp(), monitorStack, node, blockExitsMethod, traceIt))523{524if(!block->getExceptionSuccessors().empty())525monitorExitFence++;526527// The check for this assume was moved in the if statement above.528// JCK has tests for unbalanced monitor exits and we would crash during compilation529// if we tried to pop a non-existent monitor off the stack.530// TR_ASSERT(!monitorStack->isEmpty(), "monitor stack is empty at block %d node %p\n",531// block->getNumber(), node);532//533monitorStackTop = monitorStack->top();534if (monitorStackTop && monitorStackTop->holdsMonitoredObjectForSyncMethod())535isSyncMethodMonexit = true;536blockHasMonexit = true;537callerIndex = node->getByteCodeInfo().getCallerIndex();538539///traceMsg(comp(), "blockHasMonexit = %d isSyncMethodMonitor = %d\n", blockHasMonexit, isSyncMethodMonitor);540// process all the exception successors at this point541// the normal successors will be processed at the end of the block542//543monitorPoppedForExceptionSucc = addSuccessors(block, monitorStack, traceIt, false /*not used*/, MonitorExit, callerIndex, true /*walkOnlyExceptionSuccs*/);544// monexit545if (monitorStack->topIndex() == 0)546{547monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);548if (traceIt)549traceMsg(comp(), "popping monitor off stack symRef=%d, BEFORE pop size=%d, ", monitorStack->top()->getReferenceNumber(), monitorStack->size());550monitorStack->pop();551if (traceIt)552traceMsg(comp(), "AFTER size=%d\n", monitorStack->size());553}554555else556{557monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);558if (traceIt)559traceMsg(comp(), "popping monitor off stack symRef=%d, BEFORE pop size=%d, ", monitorStack->top()->getReferenceNumber(), monitorStack->size());560monitorStack->pop();561if (traceIt)562traceMsg(comp(), "AFTER size=%d\n", monitorStack->size());563}564}565else if(node->getOpCode().getOpCodeValue() != TR::monexit && node->exceptionsRaised())566{567if (monitorExitFence > 0)568{569auto edge = block->getExceptionSuccessors().begin();570for (; edge != block->getExceptionSuccessors().end(); ++edge)571{572TR::Block * succBlock = toBlock((*edge)->getTo());573if (node->getByteCodeInfo().getCallerIndex() ==574succBlock->getEntry()->getNode()->getByteCodeInfo().getCallerIndex())575{576if (traceInitMonitorsForExceptionAfterMonexit)577traceMsg(comp(), "block_%d has exceptions after monexit with catch block in the same method %s\n", block->getNumber(), comp()->signature());578lmmdFailed = true;579break;580}581}582}583}584585if (tt == block->getExit())586{587bool dontPropagateMonitor = false; // so propagate it by default!588MonitorInBlock monitorType = NoMonitor;589if ((monitorExitFence+monitorEnterStore)>= 2)590{591if (traceIt)592traceMsg(comp(), "block_%d has monitorEnterStore=%d monitorExitFence=%d\n", block->getNumber(), monitorEnterStore, monitorExitFence);593lmmdFailed = true;594}595596if (blockHasMonent)597{598// the monitorStack will contain the monitor to be pushed599// along the successors at this point600// a) if the edge is a normal edge, then just propagate the stack601// b) if the edge is an exception edge, then only push the monitor on602// the stack if it is a syncMethodMonitor. otherwise don't propagate603// the monitor to the exception successors (this is because if there is604// an exception successor of a block containing the monent and control to605// the exception is reached, this means that the monitor is not locked, ie606// there is no monexit to pop the stack)607//608monitorType = MonitorEnter;609dontPropagateMonitor = !isSyncMethodMonent;610}611612if (blockHasMonexit)613{614// the monitorStack will be popped under 2 conditions:615// a) if the successor is a normal edge (ie. not an exception edge)616// b) if the successor is an exception edge, then pop the stack *only* if the617// monexit came from a synchronized method (check the callerIndex on the catch block618// and the monexit)619//620// isSyncMethodMonexit will control b)621//622monitorType = MonitorExit;623dontPropagateMonitor = isSyncMethodMonexit;624625if ((monitorPoppedForExceptionSucc > 0) &&626monitorStackTop &&627needToPushMonitor(comp(), block, traceIt))628{629if (traceIt)630traceMsg(comp(), "pushing monexit symRef=%d back temporarily\n", monitorStackTop->getReferenceNumber());631monitorStack->push(monitorStackTop);632}633}634635if (traceIt)636traceMsg(comp(), "blockHasMonent=%d blockHasMonexit=%d dontPropagateMonitor=%d callerIndex=%d monitorPoppedForExceptionSucc=%d\n", blockHasMonent, blockHasMonexit, dontPropagateMonitor, callerIndex, monitorPoppedForExceptionSucc);637638addSuccessors(block, monitorStack, traceIt, dontPropagateMonitor, monitorType, callerIndex);639break;640}641}642}643644static bool disableCountingMonitors = feGetEnv("TR_disableCountingMonitors")? true: false;645if (lmmdFailed && !disableCountingMonitors)646{647TR_Array<List<TR::RegisterMappedSymbol> *> & monitorAutos = comp()->getMonitorAutos();648for (int32_t i=0; i<monitorAutos.size(); i++)649{650List<TR::RegisterMappedSymbol> *autos = monitorAutos[i];651if (autos)652{653ListIterator<TR::RegisterMappedSymbol> iterator(autos);654for (TR::RegisterMappedSymbol * a = iterator.getFirst(); a; a = iterator.getNext())655{656TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "lmmdFailed/(%s)", comp()->signature()));657a->setUninitializedReference();658}659}660}661}662}663664665666