Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/codegen/MonitorState.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2019 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#include <stdint.h>
24
#include "codegen/CodeGenerator.hpp"
25
#include "codegen/MonitorState.hpp"
26
#include "il/Block.hpp"
27
#include "il/Node_inlines.hpp"
28
#include "il/RegisterMappedSymbol.hpp"
29
#include "il/SymbolReference.hpp"
30
#include "infra/Array.hpp"
31
#include "infra/Cfg.hpp"
32
#include "infra/List.hpp"
33
#include "infra/TRCfgEdge.hpp"
34
#include "infra/TRCfgNode.hpp"
35
#include "infra/Stack.hpp"
36
37
38
39
int32_t
40
J9::SetMonitorStateOnBlockEntry::addSuccessors(
41
TR::CFGNode * cfgNode,
42
TR_Stack<TR::SymbolReference *> * monitorStack,
43
bool traceIt,
44
bool dontPropagateMonitor,
45
MonitorInBlock monitorType,
46
int32_t callerIndex,
47
bool walkOnlyExceptionSuccs)
48
{
49
if (traceIt)
50
traceMsg(comp(),
51
"\tIn SMSOBE::addSuccessors for cfgNode %d, monitorStack %p dontPropagateMonitor %d monitorType = %d callerIndex %d walkOlyExceptionSuccs %d\n"
52
, cfgNode->getNumber(),monitorStack,dontPropagateMonitor,monitorType,callerIndex,walkOnlyExceptionSuccs);
53
54
bool firstSuccessor = true;
55
56
// to reiterate:
57
// 3 cases to consider when propagating the monitorStack
58
// 1. MonitorEnter
59
// Normal Edge -> propagate
60
// Exception Edge ->
61
// if syncMethodMonitor from callerIndex=-1
62
// -> propagate
63
// else -> do not propagate
64
//
65
// 2. MonitorExit (at this stage the monitor has been temporarily pushed on the monitorStack)
66
// Normal Edge -> pop before propagate
67
// Exception Edge ->
68
// check if the exception successor of the current block has the same caller index or not
69
// if same caller index, then:
70
// a) in a synchronized method, the catch block will eventually unlock the monitor. so we assume
71
// that if the blocks are in the same method, then the monitor will be unlocked by the catch block
72
// b) for a synchronized block, all blocks within the region (including the block with the monexit)
73
// will always branch to the "catch-all" block inserted by the JIT and not to a user catch block.
74
// the catch-all block will unlock the monitor and rethrow the exception.
75
// so in both these cases, we want to push the monitor along the exception successor because the monitor
76
// will be unlocked eventually.
77
//
78
// if not the same caller index, then:
79
// a) the monexit block and the exception successor are in different methods (ie. the monexit - regardless of
80
// sync method or sync block, came from an inlined method and the successor is in the caller).
81
// in this case, we dont want to push the monitor along the exception successor because the exception successor
82
// has no idea that it needs to unlock the monitor.
83
//
84
// -> pop before propagate / push before propagate in the case described above
85
// else -> propagate the monitorStack (with the monitor pushed on it temporarily) ie. do not pop
86
//
87
// 3. NoMonitor -> propagate the monitorStack as is
88
//
89
// return value
90
// -1 : default value
91
// 1 : if the monitorStack was propagated with the monitor pushed temporarily
92
// 0 : otherwise
93
//
94
int32_t returnValue = -1;
95
96
TR_SuccessorIterator succs(cfgNode);
97
for (TR::CFGEdge *edge = succs.getFirst(); edge; edge = succs.getNext())
98
{
99
TR::Block * succBlock = toBlock(edge->getTo());
100
// skip the exception successors for now in this walk
101
// they will be processed later
102
//
103
if (walkOnlyExceptionSuccs && !succBlock->isCatchBlock())
104
continue;
105
106
if (succBlock->getEntry())
107
{
108
bool addInfo = true;
109
if (monitorType == MonitorEnter)
110
{
111
if (traceIt)
112
traceMsg(comp(), "\tIn J9::SetMonitorStateOnBlockEntry::addSuccessors monitorType = MonitorEnter block %d\n", succBlock->getNumber());
113
if (succBlock->isCatchBlock() && dontPropagateMonitor)
114
{
115
returnValue = 0;
116
addInfo = false;
117
}
118
}
119
120
if (monitorType == MonitorExit)
121
{
122
if (walkOnlyExceptionSuccs)
123
{
124
if (callerIndex != succBlock->getEntry()->getNode()->getByteCodeInfo().getCallerIndex())
125
{
126
returnValue = 0;
127
addInfo = false;
128
}
129
else
130
returnValue = 1; // push the monitor along this exception edge
131
}
132
else if (succBlock->isCatchBlock()) // already processed during exception successors walk
133
continue;
134
}
135
136
if (traceIt)
137
traceMsg(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());
138
139
bool popMonitor = false;
140
if (monitorStack)
141
{
142
// pop the last element of the stack if dontPropagateMonitor is true
143
//
144
if (!addInfo &&
145
!monitorStack->isEmpty())
146
{
147
popMonitor = true;
148
}
149
150
if (succBlock->getVisitCount() != _visitCount)
151
{
152
TR_Stack<TR::SymbolReference *> *newMonitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);
153
154
if (traceIt)
155
traceMsg(comp(), "\tIn SMSOnBE::addSuccesors created newMonitorStack %p and monitorStack %p\n", newMonitorStack,monitorStack);
156
157
if (popMonitor)
158
{
159
if (traceIt)
160
traceMsg(comp(), "popping monitor symRef=%d before propagation\n", newMonitorStack->top()->getReferenceNumber());
161
newMonitorStack->pop();
162
}
163
164
if (_liveMonitorStacks->find(succBlock->getNumber()) != _liveMonitorStacks->end())
165
{
166
_liveMonitorStacks->erase(succBlock->getNumber());
167
}
168
(*_liveMonitorStacks)[succBlock->getNumber()] = newMonitorStack;
169
if (traceIt)
170
traceMsg(comp(), "adding monitorstack to successor %d (%p size %d)\n", succBlock->getNumber(), newMonitorStack, newMonitorStack->size());
171
}
172
else
173
{
174
// the block has been propagated already but we want to verify the monitor state is consistent
175
// skip osr blocks here because the monitor state of osrBlocks don't have to be consistent
176
if (!succBlock->isOSRCatchBlock() && !succBlock->isOSRCodeBlock())
177
{
178
if (!isMonitorStateConsistentForBlock(succBlock, monitorStack, popMonitor))
179
comp()->cg()->setLmmdFailed();
180
else
181
{
182
if (traceIt)
183
traceMsg(comp(), "verified block_%d monitorState is consistent\n", succBlock->getNumber());
184
}
185
}
186
continue;
187
}
188
}
189
else if (succBlock->getVisitCount() == _visitCount)
190
{
191
if(!succBlock->isOSRCatchBlock() && !succBlock->isOSRCodeBlock())
192
{
193
if (!isMonitorStateConsistentForBlock(succBlock, monitorStack, popMonitor))
194
comp()->cg()->setLmmdFailed();
195
else if (traceIt)
196
traceMsg(comp(), "verified block_%d monitorState is consistent\n", succBlock->getNumber());
197
}
198
continue;
199
}
200
201
if (traceIt)
202
traceMsg(comp(), "\tIn SMSOnBE::addSuccessors adding block %d to blocksToVisit\n", succBlock->getNumber());
203
_blocksToVisit.push(succBlock);
204
}
205
}
206
207
return returnValue;
208
}
209
210
bool
211
J9::SetMonitorStateOnBlockEntry::isMonitorStateConsistentForBlock(
212
TR::Block *block,
213
TR_Stack<TR::SymbolReference *> *newMonitorStack,
214
bool popMonitor)
215
{
216
TR_Stack<TR::SymbolReference *> *oldMonitorStack = _liveMonitorStacks->find(block->getNumber()) != _liveMonitorStacks->end() ?
217
(*_liveMonitorStacks)[block->getNumber()] : NULL;
218
static const bool traceItEnv = feGetEnv("TR_traceLiveMonitors") ? true : false;
219
bool traceIt = traceItEnv || comp()->getOption(TR_TraceLiveMonitorMetadata);
220
221
if (traceIt)
222
traceMsg(comp(), "MonitorState block_%d: oldMonitorStack %p newMonitorStack %p popMonitor %d\n", block->getNumber(), oldMonitorStack, newMonitorStack, popMonitor);
223
224
// first step: check if both monitor stacks are empty
225
bool oldMonitorStackEmpty = false;
226
bool newMonitorStackEmpty = false;
227
228
if (!oldMonitorStack || oldMonitorStack->isEmpty())
229
oldMonitorStackEmpty = true;
230
if (!newMonitorStack || newMonitorStack->isEmpty()
231
|| (newMonitorStack->size() == 1 && popMonitor))
232
newMonitorStackEmpty = true;
233
if (oldMonitorStackEmpty != newMonitorStackEmpty)
234
{
235
if (traceIt)
236
traceMsg(comp(), "MonitorState inconsistent for block_%d: oldMonitorStack isEmpty %d, newMonitorStack isEmpty %d\n", block->getNumber(), oldMonitorStackEmpty, newMonitorStackEmpty);
237
return false;
238
}
239
else if (oldMonitorStackEmpty)
240
return true;
241
242
// second step: check if the monitor stacks are the same size
243
int32_t oldSize = oldMonitorStack->size();
244
int32_t newSize = newMonitorStack->size();
245
if (popMonitor)
246
newSize--;
247
if (newSize != oldSize)
248
{
249
if (traceIt)
250
traceMsg(comp(), "MonitorState inconsistent for block_%d: oldMonitorStack size %d, newMonitorStack size %d\n",block->getNumber(), oldSize, newSize);
251
return false;
252
}
253
254
// third step: check if all the monitors in both stacks are the same
255
for (int i = oldMonitorStack->topIndex(); i>= 0; i--)
256
{
257
if (newMonitorStack->element(i)->getReferenceNumber() != oldMonitorStack->element(i)->getReferenceNumber())
258
{
259
if (traceIt)
260
traceMsg(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());
261
return false;
262
}
263
}
264
return true;
265
}
266
267
// this routine is used to decide if the monitorStack needs to be popped
268
// the analysis needs to be careful in particular for DLT compiles as there are
269
// several scenarios as the DLT control could land into the middle of a
270
// nested (several levels deep) synchronized region
271
// a) if the monexit is at callerIndex=-1,
272
// this means that the monitorStack could be imbalanced
273
// i) if synchronized method then the syncObjectTemp would have been used to
274
// initialize the hidden slot in the DLT entry (monitorStack size is 1) and
275
// then control could branch into the middle of a synchronized region (without
276
// ever seeing any monents). At the monexit, the analysis would then try to pop
277
// the lone monitor on the stack so prevent this by checking if the stack size is 1.
278
// This is done because the special slot needs to be live across the entire method
279
//
280
// ii) an improvement to i) is done at blocks that exit the method. in these cases,
281
// the analysis would have encountered the monexits corresponding to the synchronized
282
// 'this' so it needs to empty the stack
283
//
284
// iii) an exception to i) is when the method is a static synchronized method. in this
285
// case, the syncObjectTemp is not used to initialize the monitor slot in the DLT entry
286
// (so the monitorStack size is 0). so the analysis should avoid any special checks
287
//
288
// in case i) or iii) fails, this means that the DLT control landed straight into the sync
289
// region (with no monitorStack), in this case the analysis needs to ensure that an empty
290
// monitorStack is not popped
291
//
292
//
293
// b) if the monexit is not at callerIndex=-1, then this means that the monexit was
294
// part of a monent-monexit region that would have normally appeared in the method. an imbalance
295
// in the monitorStack indicates an error, but return the default answer as "yes", the stack
296
// can be popped.
297
//
298
// c) if not DLT, then return the default answer as "yes"
299
//
300
//
301
static bool canPopMonitorStack(
302
TR::Compilation *comp,
303
TR_Stack<TR::SymbolReference *> * monitorStack,
304
TR::Node *node,
305
bool blockExitsMethod,
306
bool traceIt)
307
{
308
int32_t callerIndex = node->getByteCodeInfo().getCallerIndex();
309
if (comp->isDLT())
310
{
311
if (callerIndex == -1)
312
{
313
if (comp->getJittedMethodSymbol()->isSynchronised())
314
{
315
// We have the special slot set up at DLT entry. Let us avoid resetting
316
// the bit for this special slot so that we do not have any wrong GC maps
317
// TODO : if we need to empty the monitor stack at the end of the method
318
// then pop it off the stack only when we reach a block whose successor is
319
// the dummy exit block
320
//
321
if (monitorStack->size() == 1 &&
322
!comp->getJittedMethodSymbol()->isStatic() &&
323
!blockExitsMethod)
324
{
325
if (traceIt)
326
traceMsg(comp, "monitorStack is empty (except for special DLT sync object slot) for DLT compile at monexit %p\n", node);
327
return false;
328
}
329
else if (monitorStack->isEmpty())
330
{
331
if (traceIt)
332
traceMsg(comp, "monitorStack is empty for DLT compile at monexit %p\n", node);
333
return false;
334
}
335
}
336
else
337
{
338
if (monitorStack->isEmpty())
339
{
340
if (traceIt)
341
traceMsg(comp, "monitorStack is empty for non-synchronized DLT compile at monexit %p\n", node);
342
return false;
343
}
344
}
345
}
346
else
347
{
348
// TODO : could add an assert error here : check if the elem to be popped off
349
// from the monitor stack for your caller index and assert if there is not
350
/*
351
if (!monitorStack->isEmpty() &&
352
monitorStack->top())
353
{
354
if (monitorStack->top()->getOwningMethodIndex() != callerIndex)
355
traceMsg(comp(), "unbalanced monitorStack, trying to pop %d but top is %d symRef: %d\n", callerIndex, monitorStack->top()->getOwningMethodIndex(), monitorStack->top()->getReferenceNumber());
356
TR_ASSERT(monitorStack->top()->getOwningMethodIndex() == callerIndex, "unbalanced monitorStack, trying to pop %d but top is %d\n", callerIndex, monitorStack->top()->getOwningMethodIndex());
357
}
358
*/
359
return true;
360
}
361
}
362
363
return true;
364
}
365
366
static bool needToPushMonitor(TR::Compilation *comp, TR::Block *block, bool traceIt)
367
{
368
// this routine is needed to decide if the monitor needs to be temporarily
369
// pushed back onto the stack for the successor
370
// for a sequence such as this for a synchronized block:
371
// synchronized {
372
// ...
373
// }
374
// return
375
// BBEnd
376
//
377
// older javac includes the return in the exception range (for the catch-all block)
378
// when MethodEnter/MethodExit hooks are enabled, we split the blocks as follows:
379
// synchronized {
380
// ...
381
// }
382
// check the hook bit
383
// BBEnd
384
// BBStart <-- new block after split
385
// return
386
// BBEnd
387
// ...
388
// since the return is included in the exception range, the new blocks (after the split)
389
// also have exception successors to the catch-all block. this results in unbalanced
390
// monitors because we would have popped the monitorStack at the block containing the monexit
391
// new javac seem to correctly exclude the return from the exception range
392
// To support this case, walk the successors of the current block and check if the successor
393
// has identical exception successors.
394
//
395
// A new case. When a transaction exists, the monexitfence is in a separate block from the
396
// monexit and the tfinish. So the two blocks will generally have an exception edge with the same destination block
397
// So for this case don't return true. *Shudder*
398
399
bool retval = false;
400
for (auto e = block->getSuccessors().begin(); e != block->getSuccessors().end(); ++e)
401
{
402
TR::Block *succ = (*e)->getTo()->asBlock();
403
if (comp->getFlowGraph()->compareExceptionSuccessors(block, succ) == 0)
404
{
405
if (traceIt)
406
traceMsg(comp, "found identical exception successors for block %d and succ %d\n", block->getNumber(), succ->getNumber());
407
408
retval = true;
409
for (TR::TreeTop *tt = succ->getEntry(); tt != succ->getExit() ; tt = tt->getNextTreeTop())
410
{
411
TR::Node *aNode = tt->getNode();
412
413
if (aNode && (aNode->getOpCodeValue() == TR::tfinish || aNode->getOpCodeValue() == TR::monexit ||
414
((aNode->getOpCodeValue() == TR::treetop|| aNode->getOpCodeValue() == TR::NULLCHK) && aNode->getFirstChild()->getOpCodeValue() == TR::monexit )
415
))
416
{
417
if(traceIt)
418
traceMsg(comp, "overriding identical exception decision because node %p in block %d is either monexit or tfinish",aNode,succ->getNumber());
419
retval = false;
420
break;
421
}
422
}
423
break;
424
}
425
}
426
return retval;
427
}
428
429
void J9::SetMonitorStateOnBlockEntry::set(bool& lmmdFailed, bool traceIt)
430
{
431
addSuccessors(comp()->getFlowGraph()->getStart(), 0, traceIt);
432
static bool traceInitMonitorsForExceptionAfterMonexit = feGetEnv("TR_traceInitMonitorsForExceptionAfterMonexit")? true: false;
433
434
while (!_blocksToVisit.isEmpty())
435
{
436
TR::Block * block = _blocksToVisit.pop();
437
if (block->getVisitCount() == _visitCount)
438
continue;
439
block->setVisitCount(_visitCount);
440
441
if (traceIt)
442
traceMsg(comp(), "block to process: %d\n", block->getNumber());
443
444
TR_Stack<TR::SymbolReference *> *monitorStack =
445
(_liveMonitorStacks->find(block->getNumber()) != _liveMonitorStacks->end()) ?
446
(*_liveMonitorStacks)[block->getNumber()] :
447
NULL;
448
449
if (traceIt && monitorStack && !monitorStack->isEmpty())
450
traceMsg(comp(), "top of the stack symRef=%d, and size=%d\n", monitorStack->top()->getReferenceNumber(), monitorStack->size());
451
else if (traceIt)
452
traceMsg(comp(), "monitor stack is empty\n");
453
454
bool blockHasMonent = false;
455
bool blockHasMonexit = false;
456
457
bool blockExitsMethod = false;
458
TR_SuccessorIterator succs(block);
459
for (TR::CFGEdge *edge = succs.getFirst(); edge; edge = succs.getNext())
460
{
461
if (edge->getTo()->getNumber() == comp()->getFlowGraph()->getEnd()->getNumber())
462
blockExitsMethod = true;
463
}
464
465
bool isSyncMethodMonent = false;
466
bool isSyncMethodMonexit = false;
467
TR::SymbolReference *monitorStackTop = NULL;
468
int32_t callerIndex = -1;
469
int32_t monitorPoppedForExceptionSucc = 1;
470
int32_t monitorEnterStore = 0;
471
int32_t monitorExitFence= 0;
472
for (TR::TreeTop * tt = block->getEntry(); ; tt = tt->getNextTreeTop())
473
{
474
TR::Node * node = tt->getNode();
475
if (node->getOpCodeValue() == TR::treetop || node->getOpCodeValue() == TR::NULLCHK)
476
node = node->getFirstChild();
477
478
TR::ILOpCodes opCode = node->getOpCodeValue();
479
480
if ((node->getOpCode().isStore() && //only monents are represented by this store now
481
node->getSymbol()->holdsMonitoredObject() &&
482
!node->isLiveMonitorInitStore()))
483
{
484
//problem with lmmd only occurs when the exception successor is not 0
485
if(!block->getExceptionSuccessors().empty())
486
monitorEnterStore++;
487
488
callerIndex = node->getByteCodeInfo().getCallerIndex();
489
if (monitorStack)
490
{
491
monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);
492
if (traceIt)
493
traceMsg(comp(), "adding monitor to stack symbol=%p symRef=%d (size=%d) (node %p)\n", node->getSymbol(), node->getSymbolReference()->getReferenceNumber(), monitorStack->size()+1,node);
494
}
495
else
496
{
497
monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(trMemory());
498
if (traceIt)
499
traceMsg(comp(), "adding monitor to fresh stack symbol=%p symRef=%d (size=%d) (node %p)\n", node->getSymbol(), node->getSymbolReference()->getReferenceNumber(), monitorStack->size()+1,node);
500
}
501
502
monitorStack->push(node->getSymbolReference());
503
blockHasMonent = true;
504
505
// if the callerIndex of the node is *not* -1, then this node
506
// came from a synchronized method that was inlined. in this case,
507
// don't push the monitor info along exception successors for this block.
508
// the typical pattern should be:
509
// ...
510
// astore <holdsMonitoredObject>
511
// monent
512
// BBEnd // exception successor of this block will not unlock the object (it
513
// // actually belongs to the caller
514
// BBStart //start of inlined method, these blocks will have the catchall block
515
// //that unlocks the monitor
516
//
517
if (node->getSymbolReference()->holdsMonitoredObjectForSyncMethod() &&
518
(callerIndex == -1))
519
isSyncMethodMonent = true;
520
}
521
else if ( (node->getOpCode().getOpCodeValue() == TR::monexitfence) &&
522
monitorStack && !monitorStack->isEmpty() &&
523
canPopMonitorStack(comp(), monitorStack, node, blockExitsMethod, traceIt))
524
{
525
if(!block->getExceptionSuccessors().empty())
526
monitorExitFence++;
527
528
// The check for this assume was moved in the if statement above.
529
// JCK has tests for unbalanced monitor exits and we would crash during compilation
530
// if we tried to pop a non-existent monitor off the stack.
531
// TR_ASSERT(!monitorStack->isEmpty(), "monitor stack is empty at block %d node %p\n",
532
// block->getNumber(), node);
533
//
534
monitorStackTop = monitorStack->top();
535
if (monitorStackTop && monitorStackTop->holdsMonitoredObjectForSyncMethod())
536
isSyncMethodMonexit = true;
537
blockHasMonexit = true;
538
callerIndex = node->getByteCodeInfo().getCallerIndex();
539
540
///traceMsg(comp(), "blockHasMonexit = %d isSyncMethodMonitor = %d\n", blockHasMonexit, isSyncMethodMonitor);
541
// process all the exception successors at this point
542
// the normal successors will be processed at the end of the block
543
//
544
monitorPoppedForExceptionSucc = addSuccessors(block, monitorStack, traceIt, false /*not used*/, MonitorExit, callerIndex, true /*walkOnlyExceptionSuccs*/);
545
// monexit
546
if (monitorStack->topIndex() == 0)
547
{
548
monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);
549
if (traceIt)
550
traceMsg(comp(), "popping monitor off stack symRef=%d, BEFORE pop size=%d, ", monitorStack->top()->getReferenceNumber(), monitorStack->size());
551
monitorStack->pop();
552
if (traceIt)
553
traceMsg(comp(), "AFTER size=%d\n", monitorStack->size());
554
}
555
556
else
557
{
558
monitorStack = new (trHeapMemory()) TR_Stack<TR::SymbolReference *>(*monitorStack);
559
if (traceIt)
560
traceMsg(comp(), "popping monitor off stack symRef=%d, BEFORE pop size=%d, ", monitorStack->top()->getReferenceNumber(), monitorStack->size());
561
monitorStack->pop();
562
if (traceIt)
563
traceMsg(comp(), "AFTER size=%d\n", monitorStack->size());
564
}
565
}
566
else if(node->getOpCode().getOpCodeValue() != TR::monexit && node->exceptionsRaised())
567
{
568
if (monitorExitFence > 0)
569
{
570
auto edge = block->getExceptionSuccessors().begin();
571
for (; edge != block->getExceptionSuccessors().end(); ++edge)
572
{
573
TR::Block * succBlock = toBlock((*edge)->getTo());
574
if (node->getByteCodeInfo().getCallerIndex() ==
575
succBlock->getEntry()->getNode()->getByteCodeInfo().getCallerIndex())
576
{
577
if (traceInitMonitorsForExceptionAfterMonexit)
578
traceMsg(comp(), "block_%d has exceptions after monexit with catch block in the same method %s\n", block->getNumber(), comp()->signature());
579
lmmdFailed = true;
580
break;
581
}
582
}
583
}
584
}
585
586
if (tt == block->getExit())
587
{
588
bool dontPropagateMonitor = false; // so propagate it by default!
589
MonitorInBlock monitorType = NoMonitor;
590
if ((monitorExitFence+monitorEnterStore)>= 2)
591
{
592
if (traceIt)
593
traceMsg(comp(), "block_%d has monitorEnterStore=%d monitorExitFence=%d\n", block->getNumber(), monitorEnterStore, monitorExitFence);
594
lmmdFailed = true;
595
}
596
597
if (blockHasMonent)
598
{
599
// the monitorStack will contain the monitor to be pushed
600
// along the successors at this point
601
// a) if the edge is a normal edge, then just propagate the stack
602
// b) if the edge is an exception edge, then only push the monitor on
603
// the stack if it is a syncMethodMonitor. otherwise don't propagate
604
// the monitor to the exception successors (this is because if there is
605
// an exception successor of a block containing the monent and control to
606
// the exception is reached, this means that the monitor is not locked, ie
607
// there is no monexit to pop the stack)
608
//
609
monitorType = MonitorEnter;
610
dontPropagateMonitor = !isSyncMethodMonent;
611
}
612
613
if (blockHasMonexit)
614
{
615
// the monitorStack will be popped under 2 conditions:
616
// a) if the successor is a normal edge (ie. not an exception edge)
617
// b) if the successor is an exception edge, then pop the stack *only* if the
618
// monexit came from a synchronized method (check the callerIndex on the catch block
619
// and the monexit)
620
//
621
// isSyncMethodMonexit will control b)
622
//
623
monitorType = MonitorExit;
624
dontPropagateMonitor = isSyncMethodMonexit;
625
626
if ((monitorPoppedForExceptionSucc > 0) &&
627
monitorStackTop &&
628
needToPushMonitor(comp(), block, traceIt))
629
{
630
if (traceIt)
631
traceMsg(comp(), "pushing monexit symRef=%d back temporarily\n", monitorStackTop->getReferenceNumber());
632
monitorStack->push(monitorStackTop);
633
}
634
}
635
636
if (traceIt)
637
traceMsg(comp(), "blockHasMonent=%d blockHasMonexit=%d dontPropagateMonitor=%d callerIndex=%d monitorPoppedForExceptionSucc=%d\n", blockHasMonent, blockHasMonexit, dontPropagateMonitor, callerIndex, monitorPoppedForExceptionSucc);
638
639
addSuccessors(block, monitorStack, traceIt, dontPropagateMonitor, monitorType, callerIndex);
640
break;
641
}
642
}
643
}
644
645
static bool disableCountingMonitors = feGetEnv("TR_disableCountingMonitors")? true: false;
646
if (lmmdFailed && !disableCountingMonitors)
647
{
648
TR_Array<List<TR::RegisterMappedSymbol> *> & monitorAutos = comp()->getMonitorAutos();
649
for (int32_t i=0; i<monitorAutos.size(); i++)
650
{
651
List<TR::RegisterMappedSymbol> *autos = monitorAutos[i];
652
if (autos)
653
{
654
ListIterator<TR::RegisterMappedSymbol> iterator(autos);
655
for (TR::RegisterMappedSymbol * a = iterator.getFirst(); a; a = iterator.getNext())
656
{
657
TR::DebugCounter::incStaticDebugCounter(comp(), TR::DebugCounter::debugCounterName(comp(), "lmmdFailed/(%s)", comp()->signature()));
658
a->setUninitializedReference();
659
}
660
}
661
}
662
}
663
}
664
665
666