Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/optimizer/InterProceduralAnalyzer.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2021 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 "optimizer/InterProceduralAnalyzer.hpp"
24
25
#include <stdint.h>
26
#include <string.h>
27
#include "env/FrontEnd.hpp"
28
#include "compile/Compilation.hpp"
29
#include "compile/Method.hpp"
30
#include "compile/ResolvedMethod.hpp"
31
#include "compile/SymbolReferenceTable.hpp"
32
#include "control/Options.hpp"
33
#include "control/Options_inlines.hpp"
34
#include "env/CHTable.hpp"
35
#include "env/CompilerEnv.hpp"
36
#include "env/PersistentCHTable.hpp"
37
#include "env/PersistentInfo.hpp"
38
#include "env/TRMemory.hpp"
39
#include "env/jittypes.h"
40
#include "env/ClassTableCriticalSection.hpp"
41
#include "il/Block.hpp"
42
#include "il/DataTypes.hpp"
43
#include "il/ILOpCodes.hpp"
44
#include "il/ILOps.hpp"
45
#include "il/MethodSymbol.hpp"
46
#include "il/Node.hpp"
47
#include "il/Node_inlines.hpp"
48
#include "il/ResolvedMethodSymbol.hpp"
49
#include "il/Symbol.hpp"
50
#include "il/SymbolReference.hpp"
51
#include "il/TreeTop.hpp"
52
#include "il/TreeTop_inlines.hpp"
53
#include "infra/Link.hpp"
54
#include "infra/List.hpp"
55
#include "infra/Stack.hpp"
56
#include "ras/Debug.hpp"
57
#include "runtime/RuntimeAssumptions.hpp"
58
59
#define MAX_SNIFF_BYTECODE_SIZE 1000
60
#define MAX_SNIFF_DEPTH 10
61
#define MAX_SUB_METHODS 5
62
63
class TR_OpaqueClassBlock;
64
class TR_OpaqueMethodBlock;
65
66
TR::InterProceduralAnalyzer::InterProceduralAnalyzer(TR::Compilation * c, bool trace)
67
:
68
_compilation(c),
69
_trMemory(c->trMemory()),
70
_maxSniffDepth(MAX_SNIFF_DEPTH),
71
_sniffDepth(0),
72
_maxSniffDepthExceeded(false),
73
_totalPeekedBytecodeSize(0),
74
_maxPeekedBytecodeSize(c->getMaxPeekedBytecodeSize()),
75
_trace(trace),
76
_fe(c->fe()),
77
_successfullyPeekedMethods(trMemory()),
78
_unsuccessfullyPeekedMethods(trMemory()),
79
_classesThatShouldNotBeLoadedInCurrentPeek(trMemory()),
80
_classesThatShouldNotBeNewlyExtendedInCurrentPeek(trMemory()),
81
_globalsWrittenInCurrentPeek(trMemory())
82
{
83
//TR_ScratchList<TR_ClassExtendCheck> _classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[1+ CLASSHASHTABLE_SIZE];
84
_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT =
85
(TR_ScratchList<TR_ClassExtendCheck> *)
86
trMemory()->allocateHeapMemory(sizeof(TR_ScratchList<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));
87
88
memset(_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT, 0, sizeof(TR_ScratchList<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));
89
for (int32_t i = 0; i < CLASSHASHTABLE_SIZE + 1; ++i)
90
_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[i].setRegion(trMemory()->currentStackRegion());
91
92
_classesThatShouldNotBeNewlyExtendedHT =
93
(TR_LinkHead<TR_ClassExtendCheck> *)
94
trMemory()->allocateHeapMemory(sizeof(TR_LinkHead<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));
95
memset(_classesThatShouldNotBeNewlyExtendedHT, 0, sizeof(TR_LinkHead<TR_ClassExtendCheck>) * (CLASSHASHTABLE_SIZE + 1));
96
97
}
98
99
100
int32_t
101
TR::InterProceduralAnalyzer::perform()
102
{
103
return 2;
104
}
105
106
107
108
bool TR::InterProceduralAnalyzer::capableOfPeekingVirtualCalls()
109
{
110
if (comp()->performVirtualGuardNOPing() &&
111
!comp()->getOption(TR_DisableIPA))
112
return true;
113
return false;
114
}
115
116
117
118
List<OMR::RuntimeAssumption> *TR::InterProceduralAnalyzer::analyzeCall(TR::Node *callNode)
119
{
120
if (comp()->isProfilingCompilation() ||
121
!capableOfPeekingVirtualCalls())
122
return 0;
123
124
comp()->incVisitCount();
125
bool success = true;
126
_maxSniffDepthExceeded = false;
127
_sniffDepth = 0;
128
_prevCec = NULL;
129
_prevClc = NULL;
130
_classesThatShouldNotBeLoaded.setFirst(NULL);
131
_classesThatShouldNotBeNewlyExtended.setFirst(NULL);
132
int32_t i;
133
134
for (i=0;i<CLASSHASHTABLE_SIZE;i++)
135
_classesThatShouldNotBeNewlyExtendedHT[i].setFirst(NULL);
136
137
_globalsWritten.setFirst(NULL);
138
139
List<OMR::RuntimeAssumption> *runtimeAssumptions = analyzeCallGraph(callNode, &success);
140
if (trace())
141
{
142
if (success)
143
{
144
traceMsg(comp(), "Ended peek which was successful\n");
145
traceMsg(comp(), "Number of unloaded classes are %d\n", _classesThatShouldNotBeLoaded.getSize());
146
traceMsg(comp(), "Number of classes that should not be newly extended are %d\n", _classesThatShouldNotBeNewlyExtended.getSize());
147
}
148
else
149
traceMsg(comp(), "Ended peek which was unsuccessful\n");
150
}
151
152
ListElement<TR_ClassExtendCheck> *currCec = _classesThatShouldNotBeNewlyExtendedInCurrentPeek.getListHead();
153
while (currCec)
154
{
155
TR_PersistentClassInfo * cl = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(currCec->getData()->_clazz, comp());
156
cl->resetShouldNotBeNewlyExtended(comp()->getCompThreadID());
157
currCec = currCec->getNextElement();
158
}
159
_classesThatShouldNotBeLoadedInCurrentPeek.deleteAll();
160
_classesThatShouldNotBeNewlyExtendedInCurrentPeek.deleteAll();
161
for (i=0;i<CLASSHASHTABLE_SIZE;i++)
162
_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[i].deleteAll();
163
_globalsWrittenInCurrentPeek.deleteAll();
164
165
if (success)
166
return new (trStackMemory()) TR_ScratchList<OMR::RuntimeAssumption>(trMemory());
167
else
168
return NULL;
169
170
//return runtimeAssumptions;
171
}
172
173
List<OMR::RuntimeAssumption> *TR::InterProceduralAnalyzer::analyzeCallGraph(TR::Node *callNode, bool *success)
174
{
175
if (_sniffDepth >= _maxSniffDepth)
176
{
177
_maxSniffDepthExceeded = true;
178
*success = false;
179
180
if (trace())
181
{
182
traceMsg(comp(), "High sniff depth made peek unsuccessful\n");
183
}
184
185
return 0;
186
}
187
188
TR::SymbolReference *symRef = callNode->getSymbolReference();
189
TR::MethodSymbol *methodSymbol = symRef->getSymbol()->castToMethodSymbol();
190
TR::ResolvedMethodSymbol * resolvedMethodSymbol = methodSymbol->getResolvedMethodSymbol();
191
TR_ResolvedMethod *owningMethod = symRef->getOwningMethod(comp());
192
193
if (!resolvedMethodSymbol &&
194
!methodSymbol->isInterface())
195
{
196
*success = false;
197
if (trace())
198
{
199
traceMsg(comp(), "Unresolved non-interface call node %p made peek unsuccessful\n", callNode);
200
}
201
202
return 0;
203
}
204
205
if ((*success) &&
206
callNode->getOpCode().isIndirect() &&
207
!capableOfPeekingVirtualCalls())
208
{
209
*success = false;
210
return 0;
211
}
212
213
TR_OpaqueClassBlock *clazz = NULL;
214
if (!resolvedMethodSymbol) // as per current logic, it is an interface method
215
{
216
int32_t cpIndex = symRef->getCPIndex();
217
TR::Method * originalMethod = methodSymbol->getMethod();
218
int32_t len = originalMethod->classNameLength();
219
char *s = TR::Compiler->cls.classNameToSignature(originalMethod->classNameChars(), len, comp());
220
clazz = fe()->getClassFromSignature(s, len, owningMethod);
221
if (!clazz)
222
{
223
// Add assumption here
224
//
225
if (!s)
226
{
227
*success = false;
228
if (trace())
229
{
230
traceMsg(comp(), "Found unresolved method call node %p while peeking whose class is unresolved and unable to add assumption -- peek unsuccessful\n", callNode);
231
}
232
}
233
else
234
{
235
addClassThatShouldNotBeLoaded(s, len);
236
237
if (trace())
238
{
239
traceMsg(comp(), "Found unresolved method call node %p while peeking -- add assumption\n", callNode);
240
}
241
}
242
return 0;
243
}
244
}
245
else
246
{
247
TR_ResolvedMethod *method = resolvedMethodSymbol->getResolvedMethod();
248
if (!method)
249
{
250
*success = false;
251
return 0;
252
}
253
254
analyzeMethod(callNode, method, success);
255
clazz = method->containingClass();
256
}
257
258
259
if ((*success) &&
260
callNode->getOpCode().isIndirect())
261
{
262
TR::Node *thisChild = callNode->getChild(callNode->getFirstArgumentIndex());
263
int32_t len;
264
const char *s = thisChild->getTypeSignature(len);
265
if (!s)
266
{
267
if (thisChild->getOpCodeValue() == TR::New)
268
s = thisChild->getFirstChild()->getTypeSignature(len);
269
}
270
271
//traceMsg(comp(), "callNode %p thisChild %p\n", callNode, thisChild);
272
//if (s)
273
// traceMsg(comp(), "sig %s\n", s);
274
//else
275
// traceMsg(comp(), "sig is NULL\n");
276
277
if (s)
278
{
279
TR_OpaqueClassBlock *thisClazz = fe()->getClassFromSignature(s, len, owningMethod);
280
if (thisClazz && (clazz != thisClazz))
281
{
282
TR_YesNoMaybe isInstance = fe()->isInstanceOf(thisClazz, clazz, true);
283
if (isInstance == TR_yes)
284
clazz = thisClazz;
285
}
286
}
287
288
if (clazz)
289
{
290
if (!addClassThatShouldNotBeNewlyExtended(clazz))
291
{
292
if(trace())
293
traceMsg(comp(), "Could not add Class That should not be newly extended to assumptions list.\n");
294
295
*success = false;
296
return 0;
297
}
298
299
if (trace())
300
{
301
traceMsg(comp(), "Found class for this object -- add assumption that the class should not be newly extended\n");
302
}
303
}
304
305
bool allowForAOT = comp()->getOption(TR_UseSymbolValidationManager);
306
TR_PersistentClassInfo *classInfo = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp(), allowForAOT);
307
if (classInfo)
308
{
309
TR_ScratchList<TR_PersistentClassInfo> subClasses(trMemory());
310
TR_ClassQueries::getSubClasses(classInfo, subClasses, fe());
311
if (trace())
312
traceMsg(comp(), "Number of subclasses = %d\n", subClasses.getSize());
313
TR_ScratchList<TR_ResolvedMethod> subMethods(trMemory());
314
int32_t numSubMethods = 0;
315
ListIterator<TR_PersistentClassInfo> subClassesIt(&subClasses);
316
for (TR_PersistentClassInfo *subClassInfo = subClassesIt.getFirst(); subClassInfo; subClassInfo = subClassesIt.getNext())
317
{
318
TR_OpaqueClassBlock *subClass = (TR_OpaqueClassBlock *) subClassInfo->getClassId();
319
if (TR::Compiler->cls.isInterfaceClass(comp(), subClass))
320
continue;
321
TR_ResolvedMethod *subClassMethod;
322
if (methodSymbol->isInterface())
323
subClassMethod = owningMethod->getResolvedInterfaceMethod(comp(), subClass, symRef->getCPIndex());
324
else
325
subClassMethod = owningMethod->getResolvedVirtualMethod(comp(), subClass, symRef->getOffset());
326
int32_t length;
327
if (trace())
328
traceMsg(comp(), "Class name %s\n", TR::Compiler->cls.classNameChars(comp(), subClass, length));
329
if (subClassMethod && !subMethods.find(subClassMethod))
330
{
331
subMethods.add(subClassMethod);
332
numSubMethods++;
333
analyzeMethod(callNode, subClassMethod, success);
334
}
335
336
if (numSubMethods > MAX_SUB_METHODS)
337
*success = false;
338
339
if (!(*success))
340
break;
341
}
342
}
343
return 0;
344
}
345
346
return 0;
347
}
348
349
350
List<OMR::RuntimeAssumption> *TR::InterProceduralAnalyzer::analyzeMethod(TR::Node *callNode, TR_ResolvedMethod *method, bool *success)
351
{
352
if (trace())
353
{
354
traceMsg(comp(), "Consider method %s for peek\n", method->signature(trMemory()));
355
}
356
357
if (!method->isCompilable(trMemory()) || method->isJNINative())
358
{
359
*success = false;
360
return 0;
361
}
362
363
bool successfulPriorPeek = true;
364
TR::PriorPeekInfo *priorPeek = NULL;
365
if (0 && alreadyPeekedMethod(method, &successfulPriorPeek, &priorPeek))
366
{
367
if (!successfulPriorPeek)
368
{
369
*success = false;
370
if (trace())
371
{
372
traceMsg(comp(), "Prior peek failure for method %s caused current peek to be unsuccessful\n", method->signature(trMemory()));
373
}
374
}
375
else
376
{
377
if (trace())
378
{
379
traceMsg(comp(), "Prior peek success for method %s caused current peek to be successful -- prior assumptions added\n", method->signature(trMemory()));
380
}
381
382
for (TR_ClassLoadCheck * clc = priorPeek->_classesThatShouldNotBeLoaded.getFirst(); clc; clc = clc->getNext())
383
addClassThatShouldNotBeLoaded(clc->_name, clc->_length);
384
385
for (TR_ClassExtendCheck * cec = priorPeek->_classesThatShouldNotBeNewlyExtended.getFirst(); cec; cec = cec->getNext())
386
addClassThatShouldNotBeNewlyExtended(cec->_clazz);
387
}
388
return 0;
389
}
390
391
uint32_t bytecodeSize = method->maxBytecodeIndex();
392
if (bytecodeSize > MAX_SNIFF_BYTECODE_SIZE)
393
{
394
*success = false;
395
if (trace())
396
{
397
traceMsg(comp(), "Large bytecode size %d made peek unsuccessful\n", bytecodeSize);
398
}
399
400
return 0;
401
}
402
403
if (isOnPeekingStack(method))
404
return 0;
405
406
if (trace())
407
traceMsg(comp(), "\nDepth %d sniffing into call at [%p] to %s\n", _sniffDepth, callNode, method->signature(trMemory()));
408
409
TR::SymbolReference * symRef = callNode->getSymbolReference();
410
int32_t offset = symRef->getOffset();
411
TR::SymbolReference * newSymRef = NULL;
412
413
if (method->isStatic())
414
newSymRef = comp()->getSymRefTab()->findOrCreateMethodSymbol(symRef->getOwningMethodIndex(), -1, method, TR::MethodSymbol::Static);
415
else
416
newSymRef = comp()->getSymRefTab()->findOrCreateMethodSymbol(symRef->getOwningMethodIndex(), -1, method, TR::MethodSymbol::Interface);
417
418
newSymRef->copyAliasSets(symRef, comp()->getSymRefTab());
419
newSymRef->setOffset(offset);
420
TR::MethodSymbol *methodSymbol = newSymRef->getSymbol()->castToMethodSymbol();
421
TR::ResolvedMethodSymbol * resolvedMethodSymbol = methodSymbol->getResolvedMethodSymbol();
422
423
vcount_t visitCount = comp()->getVisitCount();
424
if (!resolvedMethodSymbol->getFirstTreeTop())
425
{
426
int32_t firstArgIndex = callNode->getFirstArgumentIndex();
427
int32_t numRealArgs = callNode->getNumChildren() - firstArgIndex;
428
const char **argInfo = (const char **)trMemory()->allocateHeapMemory(numRealArgs*sizeof(char *)); // can stack allocate in some cases
429
memset(argInfo, 0, numRealArgs*sizeof(char *));
430
int32_t *lenInfo = (int32_t *) trMemory()->allocateHeapMemory(numRealArgs*sizeof(int32_t)); // can stack allocate in some cases
431
memset(lenInfo, 0xFF, numRealArgs*sizeof(int32_t));
432
433
for (int32_t c = callNode->getNumChildren() - 1 ; c >= firstArgIndex; --c)
434
{
435
TR::Node *argument = callNode->getChild(c);
436
if (argument->getDataType() == TR::Address)
437
{
438
int32_t len;
439
const char *s = argument->getTypeSignature(len);
440
if (!s)
441
{
442
if (argument->getOpCodeValue() == TR::New)
443
s = argument->getFirstChild()->getTypeSignature(len);
444
}
445
446
if (trace())
447
{
448
traceMsg(comp(), "callNode %p arg %p\n", callNode, argument);
449
if (s)
450
traceMsg(comp(), "sig %s\n", s);
451
else
452
traceMsg(comp(), "sig is NULL\n");
453
}
454
455
if (s && (c == firstArgIndex))
456
{
457
TR_OpaqueClassBlock *argClazz = fe()->getClassFromSignature(s, len, symRef->getOwningMethod(comp()));
458
TR_OpaqueClassBlock *thisClazz = method->containingClass();
459
460
if (!argClazz || !thisClazz)
461
{
462
*success = false;
463
if (trace())
464
{
465
traceMsg(comp(), "The call argument class is NULL, bailing out. (probably because of different class loaders)\n");
466
}
467
468
return 0;
469
}
470
471
if (argClazz != thisClazz)
472
{
473
TR_YesNoMaybe isInstance = fe()->isInstanceOf(thisClazz, argClazz, true);
474
if (isInstance == TR_yes)
475
{
476
s = TR::Compiler->cls.classSignature_DEPRECATED(comp(), thisClazz, len, trMemory());
477
}
478
}
479
}
480
481
argInfo[c-firstArgIndex] = s;
482
lenInfo[c-firstArgIndex] = len;
483
}
484
}
485
486
_totalPeekedBytecodeSize = _totalPeekedBytecodeSize + bytecodeSize;
487
if (_totalPeekedBytecodeSize > _maxPeekedBytecodeSize)
488
{
489
*success = false;
490
if (trace())
491
{
492
traceMsg(comp(), "Large bytecode size %d made peek unsuccessful\n", bytecodeSize);
493
}
494
495
return 0;
496
}
497
498
if (!performTransformation(comp(), "O^O INTERPROCEDURAL ANALYZER: Peeking into the IL for doing a limited form of interprocedural analysis \n"))
499
return 0;
500
501
TR_PeekingArgInfo *peekInfo = (TR_PeekingArgInfo *) trMemory()->allocateStackMemory(sizeof(TR_PeekingArgInfo)); // can stack allocate in some cases
502
peekInfo->_args = argInfo;
503
peekInfo->_lengths = lenInfo;
504
peekInfo->_method = resolvedMethodSymbol->getResolvedMethod();
505
comp()->addPeekingArgInfo(peekInfo);
506
//comp()->setVisitCount(1);
507
508
_currentPeekingSymRefTab = resolvedMethodSymbol->getResolvedMethod()->genMethodILForPeeking(resolvedMethodSymbol, comp());
509
//comp()->setVisitCount(visitCount);
510
comp()->removePeekingArgInfo();
511
512
if (!_currentPeekingSymRefTab)
513
{
514
*success = false;
515
if (trace())
516
traceMsg(comp(), " (IL generation failed)\n");
517
return 0;
518
}
519
520
if (trace())
521
{
522
//comp()->setVisitCount(1);
523
for (TR::TreeTop *tt = resolvedMethodSymbol->getFirstTreeTop(); tt; tt = tt->getNextTreeTop())
524
comp()->getDebug()->print(comp()->getOutFile(), tt);
525
//comp()->setVisitCount(visitCount);
526
}
527
}
528
else
529
{
530
if (trace())
531
traceMsg(comp(), " (trees already dumped)\n");
532
}
533
534
++_sniffDepth;
535
536
537
ListElement<TR_ClassLoadCheck> *prevClc = NULL; //_classesThatShouldNotBeLoadedInCurrentPeek.getListHead();
538
ListElement<TR_ClassExtendCheck> *prevCec = NULL; //_classesThatShouldNotBeNewlyExtendedInCurrentPeek.getListHead();
539
ListElement<TR::GlobalSymbol> *prevSymRef = NULL; //_globalsWrittenInCurrentPeek.getListHead();
540
_prevClc = prevClc;
541
_prevCec = prevCec;
542
_prevSymRef = prevSymRef;
543
544
545
TR::TreeTop *treeTop = NULL;
546
TR::Node *node = NULL;
547
TR::Block *block = NULL;
548
for (treeTop = resolvedMethodSymbol->getFirstTreeTop(); treeTop; treeTop = treeTop->getNextTreeTop())
549
{
550
node = treeTop->getNode();
551
552
if (node->getOpCodeValue() == TR::BBStart)
553
{
554
block = node->getBlock();
555
}
556
557
if (node->getOpCode().isCheck() || node->getOpCodeValue() == TR::treetop)
558
node = node->getFirstChild();
559
560
if (node->getOpCode().isCall() && node->getVisitCount() != visitCount)
561
{
562
_prevClc = prevClc;
563
_prevCec = prevCec;
564
_prevSymRef = prevSymRef;
565
566
//node->setVisitCount(visitCount);
567
analyzeCallGraph(node, success);
568
}
569
570
if (!*success)
571
{
572
if (trace())
573
{
574
traceMsg(comp(), "Node %p made peek unsuccessful\n", node);
575
}
576
break;
577
}
578
579
if (analyzeNode(node, visitCount, success))
580
treeTop = block->getExit();
581
582
if (!*success)
583
{
584
if (trace())
585
{
586
traceMsg(comp(), "Node %p made peek unsuccessful\n", node);
587
}
588
break;
589
}
590
}
591
592
--_sniffDepth;
593
594
if (0 && *success)
595
{
596
TR::PriorPeekInfo *priorPeek = (TR::PriorPeekInfo *) trMemory()->allocateHeapMemory(sizeof(TR::PriorPeekInfo));
597
priorPeek->_method = resolvedMethodSymbol->getResolvedMethod();
598
priorPeek->_classesThatShouldNotBeLoaded.setFirst(NULL);
599
priorPeek->_classesThatShouldNotBeNewlyExtended.setFirst(NULL);
600
priorPeek->_globalsWritten.setFirst(NULL);
601
ListElement<TR_ClassLoadCheck> *currClc = _classesThatShouldNotBeLoadedInCurrentPeek.getListHead();
602
ListElement<TR_ClassExtendCheck> *currCec = _classesThatShouldNotBeNewlyExtendedInCurrentPeek.getListHead();
603
ListElement<TR::GlobalSymbol> *currSymRef = _globalsWrittenInCurrentPeek.getListHead();
604
while (currClc != prevClc)
605
{
606
priorPeek->_classesThatShouldNotBeLoaded.add(new (trHeapMemory()) TR_ClassLoadCheck(currClc->getData()->_name, currClc->getData()->_length));
607
currClc = currClc->getNextElement();
608
}
609
610
while (currCec != prevCec)
611
{
612
priorPeek->_classesThatShouldNotBeNewlyExtended.add(new (trHeapMemory()) TR_ClassExtendCheck(currCec->getData()->_clazz));
613
currCec = currCec->getNextElement();
614
}
615
616
while (currSymRef != prevSymRef)
617
{
618
priorPeek->_globalsWritten.add(new (trHeapMemory()) TR::GlobalSymbol(currSymRef->getData()->_symRef));
619
currSymRef = currSymRef->getNextElement();
620
}
621
622
_successfullyPeekedMethods.add(priorPeek);
623
if (trace())
624
{
625
traceMsg(comp(), "Method %s is successfully peeked\n", resolvedMethodSymbol->getResolvedMethod()->signature(trMemory()));
626
}
627
}
628
else
629
{
630
if (_sniffDepth == 0)
631
{
632
if (trace())
633
{
634
traceMsg(comp(), "1Method %s is unsuccessfully peeked\n", resolvedMethodSymbol->getResolvedMethod()->signature(trMemory()));
635
}
636
637
_unsuccessfullyPeekedMethods.add(resolvedMethodSymbol->getResolvedMethod());
638
_maxSniffDepthExceeded = false;
639
}
640
else
641
{
642
if (!_maxSniffDepthExceeded)
643
{
644
if (trace())
645
{
646
traceMsg(comp(), "2Method %s is unsuccessfully peeked\n", resolvedMethodSymbol->getResolvedMethod()->signature(trMemory()));
647
}
648
_unsuccessfullyPeekedMethods.add(resolvedMethodSymbol->getResolvedMethod());
649
}
650
}
651
}
652
653
654
return 0;
655
}
656
657
658
bool TR::InterProceduralAnalyzer::isOnPeekingStack(TR_ResolvedMethod *method)
659
{
660
TR_Stack<TR_PeekingArgInfo *> *peekingStackInfo = comp()->getPeekingArgInfo();
661
int32_t topOfStack = peekingStackInfo->topIndex();
662
int32_t i;
663
for (i=0;i<=topOfStack;i++)
664
{
665
TR_PeekingArgInfo *peekInfo = peekingStackInfo->element(i);
666
if (peekInfo)
667
{
668
if (peekInfo->_method->isSameMethod(method))
669
return true;
670
/*
671
if ((nameLength(peekInfo->_method) == nameLength(method)) &&
672
!strncmp(nameChars(peekInfo->_method), nameChars(method), nameLength(method)) &&
673
(signatureLength(peekInfo->_method) == signatureLength(method)) &&
674
!strncmp(signatureChars(peekInfo->_method), signatureChars(method), signatureLength(method)))
675
{
676
TR_OpaqueClassBlock *peekedClazz = peekInfo->_method->containingClass();
677
TR_OpaqueClassBlock *clazz = method->containingClass();
678
TR_PersistentClassInfo *classInfo = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp());
679
if (classInfo)
680
{
681
TR_ScratchList<TR_PersistentClassInfo> subClasses;
682
classInfo->getSubClasses(subClasses, comp());
683
if (trace())
684
traceMsg(comp(), "Number of subclasses = %d\n", subClasses.getSize());
685
ListIterator<TR_PersistentClassInfo> subClassesIt(&subClasses);
686
for (TR_PersistentClassInfo *subClassInfo = subClassesIt.getFirst(); subClassInfo; subClassInfo = subClassesIt.getNext())
687
{
688
TR_OpaqueClassBlock *subClass = subClassInfo->getClassId();
689
if (subClass == peekedClazz)
690
return true;
691
}
692
}
693
}
694
*/
695
}
696
}
697
698
return false;
699
}
700
701
702
703
bool TR::InterProceduralAnalyzer::alreadyPeekedMethod(TR_ResolvedMethod *method, bool *success, TR::PriorPeekInfo **priorPeek)
704
{
705
ListIterator<TR::PriorPeekInfo> priorPeekedMethodsIt(&_successfullyPeekedMethods);
706
TR::PriorPeekInfo *priorPeekedMethod = NULL;
707
for (priorPeekedMethod = priorPeekedMethodsIt.getFirst(); priorPeekedMethod; priorPeekedMethod = priorPeekedMethodsIt.getNext())
708
{
709
if (priorPeekedMethod->_method->isSameMethod(method))
710
{
711
*priorPeek = priorPeekedMethod;
712
//*success = true;
713
return true;
714
}
715
}
716
717
//peekedMethodsIt.set(&_unsuccessfullyPeekedMethods);
718
ListIterator<TR_ResolvedMethod> peekedMethodsIt(&_unsuccessfullyPeekedMethods);
719
TR_ResolvedMethod *peekedMethod;
720
for (peekedMethod = peekedMethodsIt.getFirst(); peekedMethod; peekedMethod = peekedMethodsIt.getNext())
721
{
722
if (peekedMethod->isSameMethod(method))
723
{
724
*success = false;
725
return true;
726
}
727
}
728
729
return false;
730
}
731
732
733
734
bool
735
TR::InterProceduralAnalyzer::addClassThatShouldNotBeLoaded(char *name, int32_t len)
736
{
737
bool found = false;
738
739
for (ListElement<TR_ClassLoadCheck> *currClc = _classesThatShouldNotBeLoadedInCurrentPeek.getListHead(); currClc != _prevClc; currClc = currClc->getNextElement())
740
{
741
if (currClc->getData()->_length == len && !strncmp(currClc->getData()->_name, name, len))
742
{
743
found = true;
744
break;
745
}
746
}
747
748
if (!found)
749
_classesThatShouldNotBeLoadedInCurrentPeek.add(new (trStackMemory()) TR_ClassLoadCheck(name, len));
750
751
for (TR_ClassLoadCheck * clc = _classesThatShouldNotBeLoaded.getFirst(); clc; clc = clc->getNext())
752
if (clc->_length == len && !strncmp(clc->_name, name, len))
753
return false;
754
755
_classesThatShouldNotBeLoaded.add(new (trHeapMemory()) TR_ClassLoadCheck(name, len));
756
757
return true;
758
}
759
760
761
762
763
764
bool
765
TR::InterProceduralAnalyzer::addClassThatShouldNotBeNewlyExtended(TR_OpaqueClassBlock *clazz)
766
{
767
TR::ClassTableCriticalSection addClassThatShouldNotBeNewlyExtended(comp()->fe());
768
769
TR_PersistentClassInfo * cl = comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp());
770
if(!cl)
771
return false;
772
773
if (!cl->shouldNotBeNewlyExtended(comp()->getCompThreadID()))
774
addSingleClassThatShouldNotBeNewlyExtended(clazz);
775
776
777
cl->setShouldNotBeNewlyExtended(comp()->getCompThreadID());
778
TR_ScratchList<TR_PersistentClassInfo> subClasses(trMemory());
779
780
TR_ClassQueries::collectAllSubClasses(cl, &subClasses, comp());
781
782
ListIterator<TR_PersistentClassInfo> it(&subClasses);
783
TR_PersistentClassInfo *info = NULL;
784
for (info = it.getFirst(); info; info = it.getNext())
785
{
786
if (!info->shouldNotBeNewlyExtended(comp()->getCompThreadID()))
787
{
788
info->setShouldNotBeNewlyExtended(comp()->getCompThreadID());
789
TR_OpaqueClassBlock *subClass = info->getClassId();
790
addSingleClassThatShouldNotBeNewlyExtended(subClass);
791
}
792
}
793
794
return true;
795
}
796
797
798
uint32_t TR::InterProceduralAnalyzer::hash(void * h, uint32_t size)
799
{
800
// 2654435761 is the golden ratio of 2^32.
801
//
802
return (((uint32_t)(uintptr_t)h >> 2) * 2654435761u) % size;
803
}
804
805
806
bool TR::InterProceduralAnalyzer::addSingleClassThatShouldNotBeNewlyExtended(TR_OpaqueClassBlock *clazz)
807
{
808
bool found = false;
809
uint32_t hashNum = hash(clazz, CLASSHASHTABLE_SIZE);
810
for (ListElement<TR_ClassExtendCheck> *currCec = _classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[hashNum].getListHead(); currCec != _prevCec; currCec = currCec->getNextElement())
811
{
812
if (currCec->getData()->_clazz == clazz)
813
{
814
found = true;
815
break;
816
}
817
}
818
819
if (!found)
820
{
821
_classesThatShouldNotBeNewlyExtendedInCurrentPeek.add(new (trStackMemory()) TR_ClassExtendCheck(clazz));
822
_classesThatShouldNotBeNewlyExtendedInCurrentPeekHT[hashNum].add(new (trStackMemory()) TR_ClassExtendCheck(clazz));
823
}
824
825
found = false;
826
for (TR_ClassExtendCheck *clc = _classesThatShouldNotBeNewlyExtendedHT[hashNum].getFirst(); clc; clc = clc->getNext())
827
if (clc->_clazz == clazz)
828
{
829
found = true;
830
break;
831
//return false;
832
}
833
834
if (!found)
835
{
836
_classesThatShouldNotBeNewlyExtended.add(new (trHeapMemory()) TR_ClassExtendCheck(clazz));
837
_classesThatShouldNotBeNewlyExtendedHT[hashNum].add(new (trHeapMemory()) TR_ClassExtendCheck(clazz));
838
}
839
return true;
840
}
841
842
843
844
845
bool
846
TR::InterProceduralAnalyzer::addWrittenGlobal(TR::SymbolReference *symRef)
847
{
848
char *sig = NULL;
849
int32_t length = 0;
850
if (symRef->getSymbol()->isStaticField())
851
sig = symRef->getOwningMethod(comp())->staticName(symRef->getCPIndex(), length, trMemory());
852
else if (symRef->getSymbol()->isShadow())
853
sig = symRef->getOwningMethod(comp())->fieldName(symRef->getCPIndex(), length, trMemory());
854
855
bool found = false;
856
for (ListElement<TR::GlobalSymbol> *currSymRef = _globalsWrittenInCurrentPeek.getListHead(); currSymRef != _prevSymRef; currSymRef = currSymRef->getNextElement())
857
{
858
TR::SymbolReference *currSymReference = currSymRef->getData()->_symRef;
859
char *currSig = NULL;
860
int32_t currLength = 0;
861
if (currSymReference->getSymbol()->isStaticField())
862
currSig = currSymReference->getOwningMethod(comp())->staticName(currSymReference->getCPIndex(), currLength, trMemory());
863
else if (currSymReference->getSymbol()->isShadow())
864
currSig = currSymReference->getOwningMethod(comp())->fieldName(currSymReference->getCPIndex(), currLength, trMemory());
865
866
if ((length == currLength) &&
867
(memcmp(sig, currSig, length) == 0))
868
{
869
found = true;
870
break;
871
}
872
}
873
874
if (!found)
875
_globalsWrittenInCurrentPeek.add(new (trStackMemory()) TR::GlobalSymbol(symRef));
876
877
for (TR::GlobalSymbol *currSym = _globalsWritten.getFirst(); currSym; currSym = currSym->getNext())
878
{
879
TR::SymbolReference *currSymReference = currSym->_symRef;
880
char *currSig = NULL;
881
int32_t currLength = 0;
882
if (currSymReference->getSymbol()->isStaticField())
883
currSig = currSymReference->getOwningMethod(comp())->staticName(currSymReference->getCPIndex(), currLength, trMemory());
884
else if (currSymReference->getSymbol()->isShadow())
885
currSig = currSymReference->getOwningMethod(comp())->fieldName(currSymReference->getCPIndex(), currLength, trMemory());
886
887
if ((length == currLength) &&
888
(memcmp(sig, currSig, length) == 0))
889
return false;
890
}
891
892
_globalsWritten.add(new (trHeapMemory()) TR::GlobalSymbol(symRef));
893
894
return true;
895
}
896
897
898
899
900
bool
901
TR::InterProceduralAnalyzer::addMethodThatShouldNotBeNewlyOverridden(TR_OpaqueMethodBlock *method)
902
{
903
//
904
// Should check if method is overridden in future causing peeked call graph to
905
// change
906
//
907
// This check will be more precise than class extension check but
908
// will also be moe expensive at run-time. Implement if really required in
909
// the future
910
//
911
return true;
912
}
913
914
915
916
917