Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/ilgen/ClassLookahead.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 "ilgen/ClassLookahead.hpp"
24
#include "codegen/CodeGenerator.hpp"
25
#include "compile/Method.hpp"
26
#include "compile/ResolvedMethod.hpp"
27
#include "compiler/il/OMRTreeTop_inlines.hpp"
28
#include "env/ClassTableCriticalSection.hpp"
29
#include "env/IO.hpp"
30
#include "env/PersistentCHTable.hpp"
31
#include "il/Node.hpp"
32
#include "il/Node_inlines.hpp"
33
#include "il/TreeTop.hpp"
34
#include "ilgen/J9ByteCodeIlGenerator.hpp"
35
#include "ilgen/J9ByteCodeIterator.hpp"
36
#include "infra/Cfg.hpp"
37
38
TR_ClassLookahead::TR_ClassLookahead(
39
TR_PersistentClassInfo * classInfo, TR_FrontEnd * fe, TR::Compilation * comp,
40
TR::SymbolReferenceTable * symRefTab)
41
:
42
_classPointer((TR_OpaqueClassBlock *) classInfo->getClassId()),
43
_compilation(comp),
44
_symRefTab(symRefTab),
45
_fe(fe),
46
_currentMethodSymbol(NULL)
47
{
48
_classFieldInfo = new (PERSISTENT_NEW) TR_PersistentClassInfoForFields;
49
_classInfo = classInfo;
50
_classFieldInfo->setFirst(0);
51
_traceIt = comp->getOption(TR_TraceLookahead);
52
}
53
54
55
int32_t
56
TR_ClassLookahead::perform()
57
{
58
TR_J9VMBase *fej9 = (TR_J9VMBase *)fe();
59
60
if ((fej9->getNumInnerClasses(_classPointer) > 0) ||
61
_classInfo->cannotTrustStaticFinal())
62
return 0;
63
64
bool isClassInitialized = false;
65
bool seenFirstInitializerMethod = false;
66
bool allowForAOT = comp()->getOption(TR_UseSymbolValidationManager);
67
TR_PersistentClassInfo * classInfo =
68
comp()->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(_classPointer, comp(), allowForAOT);
69
if (classInfo && classInfo->isInitialized())
70
isClassInitialized = true;
71
72
if (!isClassInitialized)
73
return 0;
74
75
TR_ScratchList<TR_ResolvedMethod> resolvedMethodsInClass(comp()->trMemory());
76
fej9->getResolvedMethods(comp()->trMemory(), _classPointer, &resolvedMethodsInClass);
77
78
ListIterator<TR_ResolvedMethod> resolvedMethIt(&resolvedMethodsInClass);
79
TR_ResolvedMethod *resolvedMethod = NULL;
80
for (resolvedMethod = resolvedMethIt.getFirst(); resolvedMethod; resolvedMethod = resolvedMethIt.getNext())
81
{
82
if (resolvedMethod->isNative() ||
83
resolvedMethod->isJNINative() ||
84
resolvedMethod->isJITInternalNative())
85
{
86
_classInfo->setCannotTrustStaticFinal();
87
return 0;
88
}
89
}
90
91
bool b = comp()->getNeedsClassLookahead();
92
comp()->setNeedsClassLookahead(false);
93
94
int32_t len; char * name = fej9->getClassNameChars(_classPointer, len);
95
96
if (_traceIt)
97
printf("ATTN: Doing classlookahead for %.*s\n", len, name);
98
99
if (!performTransformation(comp(), "O^O CLASS LOOKAHEAD: Performing class lookahead for %s\n", name))
100
return 0;
101
102
TR_ScratchList<TR::ResolvedMethodSymbol> initializerMethodsInClass(comp()->trMemory());
103
TR_ScratchList<TR::ResolvedMethodSymbol> resolvedMethodSyms(comp()->trMemory());
104
TR::ResolvedMethodSymbol *classInitializer = NULL;
105
106
// check if peeking failed for any of the resolved methods
107
// if so, classLookahead cannot proceed
108
//
109
bool peekFailedForAnyMethod = false;
110
findInitializerMethods(&resolvedMethodsInClass, &initializerMethodsInClass, &resolvedMethodSyms, &classInitializer, &peekFailedForAnyMethod);
111
112
if (peekFailedForAnyMethod)
113
{
114
comp()->setNeedsClassLookahead(b);
115
_classInfo->setCannotTrustStaticFinal();
116
return 0;
117
}
118
119
_inClassInitializerMethod = false;
120
_inFirstInitializerMethod = false;
121
122
if (classInitializer)
123
{
124
_currentMethodSymbol = classInitializer;
125
_inClassInitializerMethod = true;
126
_inInitializerMethod = true;
127
_inFirstBlock = true;
128
///fprintf(stderr, "looking at method %s\n", classInitializer->getResolvedMethod()->nameChars()); fflush(stderr);
129
130
vcount_t visitCount = comp()->incVisitCount();
131
TR::TreeTop *tt;
132
comp()->resetVisitCounts(0, classInitializer->getFirstTreeTop());
133
for (tt = classInitializer->getFirstTreeTop(); tt; tt = tt->getNextTreeTop())
134
{
135
TR::Node *node = tt->getNode();
136
if (!examineNode(tt->getNextTreeTop(), NULL, NULL, -1, node, visitCount))
137
{
138
_classFieldInfo->setFirst(0);
139
_classInfo->setCannotTrustStaticFinal();
140
comp()->setNeedsClassLookahead(b);
141
return 2;
142
}
143
}
144
145
_inClassInitializerMethod = false;
146
}
147
148
149
ListIterator<TR::ResolvedMethodSymbol> resolvedIt(&initializerMethodsInClass);
150
TR::ResolvedMethodSymbol *resolvedMethodSymbol = NULL;
151
resolvedMethod = NULL;
152
for (resolvedMethodSymbol = resolvedIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedIt.getNext())
153
{
154
_currentMethodSymbol = resolvedMethodSymbol;
155
resolvedMethod = resolvedMethodSymbol->getResolvedMethod();
156
if (strncmp(resolvedMethod->nameChars(), "<clinit>", 8))
157
{
158
//_inInitializerMethod = false;
159
//if (findMethod(&initializerMethodsInClass, resolvedMethodSymbol))
160
{
161
if (!seenFirstInitializerMethod)
162
{
163
_inFirstInitializerMethod = true;
164
seenFirstInitializerMethod = true;
165
}
166
167
_inInitializerMethod = true;
168
if (!_inFirstInitializerMethod)
169
initializeFieldInfo();
170
}
171
172
/////fprintf(stderr, "looking at method %s\n", resolvedMethod->nameChars()); fflush(stderr);
173
TR::TreeTop *startTree = resolvedMethodSymbol->getFirstTreeTop();
174
_inFirstBlock = true;
175
vcount_t visitCount = comp()->incVisitCount();
176
TR::TreeTop *tt;
177
comp()->resetVisitCounts(0, startTree);
178
for (tt = startTree; tt; tt = tt->getNextTreeTop())
179
{
180
TR::Node *node = tt->getNode();
181
//dumpOptDetails("Node = %p node vc %d comp vc %d\n", node, node->getVisitCount(), visitCount);
182
if (!examineNode(tt->getNextTreeTop(), NULL, NULL, -1, node, visitCount))
183
{
184
_classFieldInfo->setFirst(0);
185
_classInfo->setCannotTrustStaticFinal();
186
comp()->setNeedsClassLookahead(b);
187
return 2;
188
}
189
}
190
191
if (_inInitializerMethod)
192
{
193
updateFieldInfo();
194
_inFirstInitializerMethod = false;
195
}
196
}
197
}
198
199
resolvedIt.set(&resolvedMethodSyms);
200
resolvedMethodSymbol = NULL;
201
resolvedMethod = NULL;
202
for (resolvedMethodSymbol = resolvedIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedIt.getNext())
203
{
204
_currentMethodSymbol = resolvedMethodSymbol;
205
resolvedMethod = resolvedMethodSymbol->getResolvedMethod();
206
if (strncmp(resolvedMethod->nameChars(), "<clinit>", 8))
207
{
208
if (!findMethod(&initializerMethodsInClass, resolvedMethodSymbol))
209
{
210
////fprintf(stderr, "looking at method %s\n", resolvedMethod->nameChars()); fflush(stderr);
211
_inInitializerMethod = false;
212
_inFirstInitializerMethod = false;
213
214
TR::TreeTop *startTree = resolvedMethodSymbol->getFirstTreeTop();
215
_inFirstBlock = true;
216
vcount_t visitCount = comp()->incVisitCount();
217
TR::TreeTop *tt;
218
comp()->resetVisitCounts(0, startTree);
219
for (tt = startTree; tt; tt = tt->getNextTreeTop())
220
{
221
TR::Node *node = tt->getNode();
222
//dumpOptDetails("Node = %p node vc %d comp vc %d\n", node, node->getVisitCount(), visitCount);
223
////fprintf(stderr, "looking at node in method %s\n", resolvedMethod->nameChars()); fflush(stderr);
224
if (!examineNode(tt->getNextTreeTop(), NULL, NULL, -1, node, visitCount))
225
{
226
_classFieldInfo->setFirst(0);
227
_classInfo->setCannotTrustStaticFinal();
228
comp()->setNeedsClassLookahead(b);
229
return 2;
230
}
231
}
232
}
233
}
234
}
235
236
if (_classFieldInfo->getFirst())
237
makeInfoPersistent();
238
239
classInfo->setFieldInfo(_classFieldInfo);
240
241
comp()->setNeedsClassLookahead(b);
242
return 2;
243
}
244
245
246
static bool isCalledByNonConstructorMethodsInClass(TR_ResolvedMethod *calleeMethod, List<TR::ResolvedMethodSymbol> *resolvedMethodSyms)
247
{
248
ListIterator<TR::ResolvedMethodSymbol> resolvedIt(resolvedMethodSyms);
249
TR::ResolvedMethodSymbol *resolvedMethodSymbol;
250
for (resolvedMethodSymbol = resolvedIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedIt.getNext())
251
{
252
TR_ResolvedMethod *resolvedMethod = resolvedMethodSymbol->getResolvedMethod();
253
if (!resolvedMethod->isConstructor())
254
{
255
for (TR::TreeTop *tt = resolvedMethodSymbol->getFirstTreeTop(); tt; tt = tt->getNextTreeTop())
256
{
257
TR::Node *node = tt->getNode();
258
if (node->getNumChildren() > 0 &&
259
node->getFirstChild()->getOpCode().isCall() &&
260
!node->getFirstChild()->getOpCode().isIndirect())
261
{
262
TR::Method *calleeMethod1 = node->getFirstChild()->getSymbol()->getMethodSymbol()->getMethod();
263
if (calleeMethod1 &&
264
calleeMethod1->nameLength() == calleeMethod->nameLength() &&
265
calleeMethod1->signatureLength() == calleeMethod->signatureLength() &&
266
calleeMethod1->classNameLength() == calleeMethod->classNameLength() &&
267
!strncmp(calleeMethod1->nameChars(), calleeMethod->nameChars(), calleeMethod->nameLength()) &&
268
!strncmp(calleeMethod1->signatureChars(), calleeMethod->signatureChars(), calleeMethod->signatureLength()) &&
269
!strncmp(calleeMethod1->classNameChars(), calleeMethod->classNameChars(), calleeMethod->classNameLength()))
270
return true;
271
}
272
}
273
}
274
}
275
276
return false;
277
}
278
279
280
281
void
282
TR_ClassLookahead::findInitializerMethods(List<TR_ResolvedMethod> *resolvedMethodsInClass, List<TR::ResolvedMethodSymbol> *initializerMethodsInClass, List<TR::ResolvedMethodSymbol> *resolvedMethodSyms, TR::ResolvedMethodSymbol **classInitializer, bool *peekFailedForAnyMethod)
283
{
284
TR_IlGenerator *prevIlGen = comp()->getCurrentIlGenerator();
285
286
ListIterator<TR_ResolvedMethod> resolvedIt(resolvedMethodsInClass);
287
TR_ResolvedMethod *resolvedMethod;
288
for (resolvedMethod = resolvedIt.getFirst(); resolvedMethod; resolvedMethod = resolvedIt.getNext())
289
{
290
TR::SymbolReference *methodSymRef;
291
if (resolvedMethod->isStatic())
292
methodSymRef = _symRefTab->findOrCreateMethodSymbol(JITTED_METHOD_INDEX, -1, resolvedMethod, TR::MethodSymbol::Static);
293
else
294
methodSymRef = _symRefTab->findOrCreateMethodSymbol(JITTED_METHOD_INDEX, -1, resolvedMethod, TR::MethodSymbol::Interface);
295
296
TR::ResolvedMethodSymbol *resolvedMethodSymbol = methodSymRef->getSymbol()->castToResolvedMethodSymbol();
297
if (resolvedMethod->isCompilable(comp()->trMemory()) && !resolvedMethod->isNewInstanceImplThunk() && !resolvedMethod->isJNINative())
298
{
299
resolvedMethodSyms->add(resolvedMethodSymbol);
300
//printf("IL gen succeeded for %s resolvedMethod %x ramMethod %x\n", resolvedMethod->signature(), resolvedMethod, resolvedMethod->getPersistentIdentifier());
301
_symRefTab->addParameters(resolvedMethodSymbol);
302
//ilGenSuccess = (0 != TR_J9ByteCodeIlGenerator::genMethodILForPeeking(resolvedMethodSymbol, comp()));
303
*peekFailedForAnyMethod = (NULL == resolvedMethodSymbol->getResolvedMethod()->genMethodILForPeeking(resolvedMethodSymbol, comp(), true));
304
}
305
}
306
307
if (*peekFailedForAnyMethod)
308
{
309
comp()->setCurrentIlGenerator(prevIlGen);
310
return;
311
}
312
313
ListIterator<TR::ResolvedMethodSymbol> resolvedMethodSymsIt(resolvedMethodSyms);
314
TR::ResolvedMethodSymbol *resolvedMethodSymbol;
315
for (resolvedMethodSymbol = resolvedMethodSymsIt.getFirst(); resolvedMethodSymbol; resolvedMethodSymbol = resolvedMethodSymsIt.getNext())
316
{
317
resolvedMethod = resolvedMethodSymbol->getResolvedMethod();
318
if ((resolvedMethod->isConstructor() || (!strncmp(resolvedMethod->nameChars(), "<clinit>", 8))) && resolvedMethodSymbol->getFirstTreeTop())
319
{
320
if (!strncmp(resolvedMethod->nameChars(), "<clinit>", 8))
321
*classInitializer = resolvedMethodSymbol;
322
else
323
{
324
TR::ResolvedMethodSymbol *initializerMethodSymbol = resolvedMethodSymbol;
325
326
TR::TreeTop * tt = resolvedMethodSymbol->getFirstTreeTop()->getNextRealTreeTop();
327
TR::Node *firstRealNode = tt->getNode();
328
if (firstRealNode->getOpCodeValue() == TR::treetop)
329
{
330
TR::Node *callChild = firstRealNode->getFirstChild();
331
if ((callChild->getOpCodeValue() == TR::call) &&
332
!callChild->getSymbolReference()->isUnresolved())
333
{
334
TR_ResolvedMethod *calleeMethod = callChild->getSymbol()->castToResolvedMethodSymbol()->getResolvedMethod();
335
if (!strncmp(calleeMethod->classNameChars(), "java/lang/Object", 16))
336
{
337
if (calleeMethod->isConstructor())
338
{
339
if (!strncmp(calleeMethod->signatureChars(), "()V", 3))
340
tt = tt->getNextRealTreeTop();
341
}
342
}
343
}
344
}
345
346
TR::Node *node = tt->getNode();
347
if (node->getOpCode().isTreeTop() &&
348
(node->getNumChildren() > 0))
349
node = node->getFirstChild();
350
351
if (node->getOpCode().isCall() &&
352
!node->getOpCode().isIndirect() &&
353
!node->getSymbolReference()->isUnresolved())
354
{
355
TR::ResolvedMethodSymbol *calleeSymbol = node->getSymbol()->castToResolvedMethodSymbol();
356
TR_ResolvedMethod *calleeMethod = calleeSymbol->getResolvedMethod();
357
if (calleeMethod->containingClass() == _classPointer &&
358
(!strncmp(calleeMethod->nameChars(), "<init>", 6) ||
359
(calleeMethod->isPrivate() &&
360
!isCalledByNonConstructorMethodsInClass(calleeMethod, resolvedMethodSyms))))
361
initializerMethodSymbol = calleeSymbol;
362
}
363
364
//if (!initializerMethodsInClass->find(initializerMethodSymbol))
365
if (!findMethod(initializerMethodsInClass, initializerMethodSymbol))
366
initializerMethodsInClass->add(initializerMethodSymbol);
367
///initializerMethodsInClass->addAfter(initializerMethodSymbol, initializerMethodsInClass->getListHead());
368
}
369
}
370
}
371
372
ListElement<TR::ResolvedMethodSymbol> *initMethodSymElem = initializerMethodsInClass->getListHead();
373
while (initMethodSymElem)
374
{
375
TR::ResolvedMethodSymbol *initMethodSym = initMethodSymElem->getData();
376
if (!resolvedMethodSyms->find(initMethodSym))
377
{
378
ListIterator<TR::ResolvedMethodSymbol> resolvedIt(resolvedMethodSyms);
379
TR::ResolvedMethodSymbol *resolvedMethodSym;
380
for (resolvedMethodSym = resolvedIt.getFirst(); resolvedMethodSym; resolvedMethodSym = resolvedIt.getNext())
381
{
382
if (resolvedMethodSym->getResolvedMethod()->isSameMethod(initMethodSym->getResolvedMethod()))
383
{
384
initMethodSymElem->setData(resolvedMethodSym);
385
break;
386
}
387
}
388
}
389
390
initMethodSymElem = initMethodSymElem->getNextElement();
391
}
392
393
comp()->setCurrentIlGenerator(prevIlGen);
394
}
395
396
397
398
399
400
401
402
bool
403
TR_ClassLookahead::examineNode(TR::TreeTop *nextTree, TR::Node *grandParent, TR::Node *parent, int32_t childNum, TR::Node *node, vcount_t visitCount)
404
{
405
if (node->getVisitCount() == visitCount)
406
{
407
if (node->getOpCode().isLoadVar())
408
invalidateIfEscapingLoad(nextTree, grandParent, parent, childNum, node);
409
return true;
410
}
411
412
if (node->getOpCode().isStore())
413
{
414
TR::SymbolReference *storedSymRef = node->getSymbolReference();
415
TR::Symbol *sym = storedSymRef->getSymbol();
416
//dumpOptDetails("Store node %p fieldInfo %p\n", node, fieldInfo);
417
418
if (isProperFieldAccess(node))
419
{
420
//dumpOptDetails("Proper store node %p fieldInfo %p\n", node, fieldInfo);
421
int32_t childAdjust = (node->getOpCode().isWrtBar()) ? 2 : 1;
422
TR::Node *rhsOfStoreNode = node->getChild(node->getNumChildren() - childAdjust);
423
424
bool isConstantLengthArrayAllocation = false;
425
bool isInitialized = false;
426
int32_t numberOfDimensions = -1;
427
int32_t firstDimensionChild = 0;
428
int32_t firstConstantLengthArrayDim = -1;
429
int32_t rhsNumChildren = rhsOfStoreNode->getNumChildren();
430
const char *sig = NULL;
431
int32_t length = 0;
432
bool isNewArray = true;
433
434
if ((rhsOfStoreNode->getOpCodeValue() == TR::newarray) ||
435
(rhsOfStoreNode->getOpCodeValue() == TR::anewarray) ||
436
(rhsOfStoreNode->getOpCodeValue() == TR::multianewarray))
437
{
438
if (rhsOfStoreNode->getOpCodeValue() == TR::multianewarray)
439
{
440
firstDimensionChild = 1;
441
numberOfDimensions = rhsOfStoreNode->getFirstChild()->getInt();
442
}
443
else
444
{
445
numberOfDimensions = 1;
446
447
if (rhsOfStoreNode->getOpCodeValue() == TR::anewarray)
448
{
449
// TODO: Do not consider types for arrays yet; have to
450
// be careful when appending '[' correct number of times
451
// for compatibility with constant propagation.
452
//
453
//
454
//sig = rhsOfStoreNode->getSecondChild()->getSymbolReference()->getTypeSignature(length);
455
}
456
}
457
458
int32_t j;
459
for (j=firstDimensionChild;j<rhsNumChildren - 1;j++)
460
{
461
TR::Node *rhsChild = rhsOfStoreNode->getChild(j);
462
if (rhsChild->getOpCodeValue() == TR::iconst)
463
{
464
isConstantLengthArrayAllocation = true;
465
firstConstantLengthArrayDim = j;
466
break;
467
}
468
}
469
}
470
else if (rhsOfStoreNode->getOpCodeValue() == TR::New)
471
{
472
isNewArray = false;
473
sig = rhsOfStoreNode->getFirstChild()->getSymbolReference()->getTypeSignature(length);
474
}
475
else
476
isNewArray = false;
477
478
// if this is a store to an arrayfield and a fieldInfo already
479
// exists (say created via a store seen in another ctor), then
480
// invalidate the fieldInfo
481
//
482
// check for stores of aconst null
483
//
484
bool canMorph = false;
485
if (rhsOfStoreNode->getOpCodeValue() == TR::aconst &&
486
rhsOfStoreNode->getInt() == 0)
487
canMorph = true;
488
489
TR_PersistentFieldInfo *fieldInfo = NULL;
490
491
if (isNewArray)
492
fieldInfo = getExistingArrayFieldInfo(sym, storedSymRef);
493
else
494
fieldInfo = getExistingFieldInfo(sym, storedSymRef, canMorph);
495
496
//
497
// TODO: remove restriction on number of dimensions
498
//
499
if (fieldInfo &&
500
!storedSymRef->isUnresolved() &&
501
(sym->isPrivate() ||
502
sym->isFinal()))
503
{
504
if (fieldInfo->isTypeInfoValid())
505
{
506
bool isClassPtrInitialized = false;
507
bool classPtrSame = true;
508
if (_inFirstBlock &&
509
_inInitializerMethod)
510
{
511
int32_t oldNumChars = fieldInfo->getNumChars();
512
if (oldNumChars > -1)
513
{
514
if (length != oldNumChars)
515
classPtrSame = false;
516
else
517
classPtrSame = (memcmp(sig, fieldInfo->getClassPointer(), length) == 0);
518
}
519
else
520
{
521
isClassPtrInitialized = true;
522
}
523
}
524
else
525
classPtrSame = false;
526
527
if (classPtrSame || isClassPtrInitialized)
528
{
529
if (isClassPtrInitialized)
530
{
531
//char *persistentSig = (char *)TR_Memory::jitPersistentAlloc(length);
532
//memcpy(persistentSig, sig, length);
533
//fieldInfo->setClassPointer(persistentSig);
534
fieldInfo->setClassPointer(sig);
535
}
536
537
fieldInfo->setNumChars(length);
538
if (_inClassInitializerMethod)
539
{
540
if (_traceIt)
541
traceMsg(comp(), "CStatically initializing type info for symbol %x at node %x\n", sym, node);
542
fieldInfo->setIsTypeInfoValid(VALID_AND_INITIALIZED_STATICALLY);
543
}
544
else
545
{
546
if (fieldInfo->isTypeInfoValid() == VALID_AND_INITIALIZED_STATICALLY)
547
{
548
if (!_inFirstInitializerMethod &&
549
!sym->isStatic())
550
{
551
if (_traceIt)
552
traceMsg(comp(), "C0Not always initializing type info for symbol %x at node %x\n", sym, node);
553
fieldInfo->setIsTypeInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);
554
}
555
else
556
{
557
if (!sym->isStatic())
558
{
559
if (_traceIt)
560
traceMsg(comp(), "C0Always initializing type info for symbol %x at node %x\n", sym, node);
561
fieldInfo->setIsTypeInfoValid(VALID_AND_ALWAYS_INITIALIZED);
562
}
563
}
564
}
565
else
566
{
567
if (!sym->isStatic())
568
{
569
if (_traceIt)
570
traceMsg(comp(), "C1Always initializing type info for symbol %x at node %x\n", sym, node);
571
fieldInfo->setIsTypeInfoValid(VALID_AND_ALWAYS_INITIALIZED);
572
}
573
else
574
{
575
if (_traceIt)
576
traceMsg(comp(), "C0Invalidating type info for symbol %x at node %x\n", sym, node);
577
fieldInfo->setIsTypeInfoValid(INVALID);
578
}
579
}
580
}
581
}
582
else
583
{
584
if (_traceIt)
585
traceMsg(comp(), "C0Invalidating type info for symbol %x at node %x\n", sym, node);
586
fieldInfo->setIsTypeInfoValid(INVALID);
587
}
588
}
589
590
TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
591
if (isNewArray &&
592
arrayFieldInfo &&
593
isConstantLengthArrayAllocation &&
594
(numberOfDimensions <= 2))
595
{
596
int32_t oldNumDimensions = arrayFieldInfo->getNumDimensions();
597
if (oldNumDimensions > -1)
598
{
599
if (arrayFieldInfo->isDimensionInfoValid())
600
{
601
if (oldNumDimensions != numberOfDimensions)
602
{
603
// Same field is assigned different dimension arrays
604
// at different program points within this class.
605
//
606
if (_traceIt)
607
traceMsg(comp(), "0Invalidating dimension info for symbol %x at node %x\n", sym, node);
608
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
609
}
610
}
611
}
612
else
613
{
614
isInitialized = true;
615
arrayFieldInfo->prepareArrayFieldInfo(numberOfDimensions, comp());
616
}
617
618
if (arrayFieldInfo->isDimensionInfoValid())
619
{
620
// Invalidate the dimensions that are known to be
621
// non constants at this stage
622
//
623
int32_t k;
624
for (k=0;k<firstConstantLengthArrayDim - firstDimensionChild;k++)
625
arrayFieldInfo->setDimensionInfo(k, -1);
626
627
for (;k<(rhsNumChildren - 1 - firstDimensionChild);k++)
628
{
629
TR::Node *rhsChild = rhsOfStoreNode->getChild(k+firstDimensionChild);
630
if (_inFirstBlock &&
631
_inInitializerMethod &&
632
(rhsChild->getOpCodeValue() == TR::iconst) &&
633
((rhsChild->getInt() == arrayFieldInfo->getDimensionInfo(k)) ||
634
isInitialized))
635
{
636
arrayFieldInfo->setDimensionInfo(k, rhsChild->getInt());
637
if (_inClassInitializerMethod)
638
{
639
if (_traceIt)
640
traceMsg(comp(), "Statically initializing dimension info for symbol %x at node %x\n", sym, node);
641
arrayFieldInfo->setIsDimensionInfoValid(VALID_AND_INITIALIZED_STATICALLY);
642
}
643
else
644
{
645
if (arrayFieldInfo->isDimensionInfoValid() == VALID_AND_INITIALIZED_STATICALLY)
646
{
647
if (!_inFirstInitializerMethod &&
648
!sym->isStatic())
649
{
650
if (_traceIt)
651
traceMsg(comp(), "0Not always initializing dimension info for symbol %x at node %x\n", sym, node);
652
arrayFieldInfo->setIsDimensionInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);
653
}
654
else
655
{
656
if (!sym->isStatic())
657
{
658
if (_traceIt)
659
traceMsg(comp(), "0Always initializing dimension info for symbol %x at node %x\n", sym, node);
660
arrayFieldInfo->setIsDimensionInfoValid(VALID_AND_ALWAYS_INITIALIZED);
661
}
662
}
663
}
664
else
665
{
666
if (!sym->isStatic())
667
{
668
if (_traceIt)
669
traceMsg(comp(), "1Always initializing dimension info for symbol %x at node %x\n", sym, node);
670
arrayFieldInfo->setIsDimensionInfoValid(VALID_AND_ALWAYS_INITIALIZED);
671
}
672
else
673
{
674
if (_traceIt)
675
traceMsg(comp(), "C0Invalidating dimension info for symbol %x at node %x\n", sym, node);
676
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
677
}
678
}
679
}
680
}
681
else
682
{
683
if (_traceIt)
684
traceMsg(comp(), "C1Invalidating dimension info for symbol %x at node %x\n", sym, node);
685
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
686
arrayFieldInfo->setDimensionInfo(k, -1);
687
}
688
}
689
}
690
}
691
else if (arrayFieldInfo)
692
{
693
// Not a constant length allocation event
694
//
695
if (_traceIt)
696
traceMsg(comp(), "1Invalidating dimension info for symbol %x at node %x\n", sym, node);
697
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
698
}
699
}
700
else if (fieldInfo)
701
{
702
// It is a store to this array field but not an allocation event
703
//
704
if (_traceIt)
705
traceMsg(comp(), "1Invalidating dimension and type info for symbol %x at node %x(%s)\n", sym, node, node->getOpCode().getName());
706
707
fieldInfo->setIsTypeInfoValid(INVALID);
708
TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
709
if (arrayFieldInfo)
710
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
711
else
712
fieldInfo->setCanChangeToArray(false);
713
}
714
}
715
else if ((sym->isShadow() ||
716
sym->isStatic()) &&
717
!storedSymRef->isUnresolved() &&
718
(sym->isPrivate() ||
719
sym->isFinal()))
720
{
721
TR_PersistentFieldInfo *fieldInfo = getExistingFieldInfo(sym, storedSymRef, false);
722
723
if (fieldInfo)
724
{
725
if (_traceIt)
726
traceMsg(comp(), "2Invalidating dimension and type info for symbol %x at node %x\n", sym, node);
727
728
fieldInfo->setIsTypeInfoValid(INVALID);
729
TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
730
if (arrayFieldInfo)
731
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
732
}
733
}
734
735
if (sym->isStatic() && sym->isFinal() && !_inClassInitializerMethod)
736
_classInfo->setCannotTrustStaticFinal();
737
738
if (isPrivateFieldAccess(node) || isProperFieldAccess(node))
739
{
740
//int32_t length = 0;
741
//char *sig = TR_ClassLookahead::getFieldSignature(comp(), sym, storedSymRef, length);
742
743
TR_PersistentFieldInfo *previousFieldInfo = _classFieldInfo->find(comp(), sym, storedSymRef);
744
TR_PersistentFieldInfo *fieldInfo = previousFieldInfo;
745
if (!fieldInfo)
746
{
747
fieldInfo = getExistingFieldInfo(sym, storedSymRef);
748
if (fieldInfo)
749
{
750
fieldInfo->setIsTypeInfoValid(INVALID);
751
TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
752
if (arrayFieldInfo)
753
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
754
else
755
fieldInfo->setCanChangeToArray(false);
756
}
757
}
758
759
//if (isProperFieldAccess(node))
760
{
761
if (fieldInfo)
762
{
763
if (!_inInitializerMethod && !_inClassInitializerMethod)
764
{
765
fieldInfo->setImmutable(false);
766
}
767
768
int32_t childAdjust = (node->getOpCode().isWrtBar()) ? 2 : 1;
769
TR::Node *rhsOfStoreNode = node->getChild(node->getNumChildren() - childAdjust);
770
771
int32_t length;
772
char *sig = getFieldSignature(comp(), sym, storedSymRef, length);
773
774
if (rhsOfStoreNode->getOpCode().isCall() &&
775
rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol())
776
{
777
if (rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_valueOf)
778
{
779
//fprintf(stderr, "0Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);
780
fieldInfo->setBigIntegerType(false);
781
}
782
else if ((rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_add) ||
783
(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_subtract) ||
784
(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_multiply))
785
{
786
//fprintf(stderr, "1Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);
787
fieldInfo->setBigIntegerType(false);
788
}
789
else if ((rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_add) ||
790
(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_subtract) ||
791
(rhsOfStoreNode->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_multiply))
792
{
793
fieldInfo->setBigDecimalType(false);
794
}
795
}
796
else
797
{
798
if (rhsOfStoreNode->getOpCode().isLoadVar() &&
799
rhsOfStoreNode->getSymbolReference()->getSymbol()->isStatic())
800
{
801
TR::Symbol::RecognizedField field = rhsOfStoreNode->getSymbolReference()->getSymbol()->getRecognizedField();
802
803
if (field != TR::Symbol::Java_math_BigInteger_ZERO)
804
{
805
//fprintf(stderr, "2Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);
806
fieldInfo->setBigIntegerType(false);
807
}
808
else
809
{
810
//fprintf(stderr, "Found load of big integer ZERO in for %s (big integer type %d) in %s compiling %s\n", sig, fieldInfo->isBigIntegerType(), _currentMethodSymbol->getResolvedMethod()->nameChars(), comp()->signature()); fflush(stderr);
811
}
812
}
813
else
814
{
815
//fprintf(stderr, "3Resetting big integer property for %s in %s\n", sig, _currentMethodSymbol->getResolvedMethod()->nameChars()); fflush(stderr);
816
fieldInfo->setBigIntegerType(false);
817
}
818
819
fieldInfo->setBigDecimalType(false);
820
}
821
}
822
}
823
}
824
}
825
else if (node->getOpCode().isLoadVar())
826
invalidateIfEscapingLoad(nextTree, grandParent, parent, childNum, node);
827
else if (node->getOpCodeValue() == TR::BBEnd)
828
_inFirstBlock = false;
829
830
if (node->getOpCode().isCall())
831
{
832
TR::Method *calleeMethod = node->getSymbol()->castToMethodSymbol()->getMethod();
833
if (calleeMethod != NULL && !strncmp(calleeMethod->classNameChars(), "java/lang/reflect", 17))
834
return false;
835
}
836
837
node->setVisitCount(visitCount);
838
839
int32_t i;
840
int32_t numChildren = node->getNumChildren();
841
for (i=0;i<numChildren;i++)
842
{
843
if (!examineNode(nextTree, parent, node, i, node->getChild(i), visitCount))
844
return false;
845
}
846
847
return true;
848
}
849
850
851
static bool isArithmeticForSameField(TR::Node *treeNode, TR::Node *grandParent, TR::Node *parent, TR::Node *node)
852
{
853
if ((node->getOpCodeValue() != TR::iloadi) &&
854
(node->getOpCodeValue() != TR::lloadi) &&
855
(node->getOpCodeValue() != TR::iload) &&
856
(node->getOpCodeValue() != TR::lload))
857
return false;
858
859
if (parent->getReferenceCount() != 1)
860
return false;
861
862
if (!grandParent)
863
return false;
864
865
TR::Node *storeNode = NULL;
866
if (!grandParent->getOpCode().isStore())
867
{
868
if (grandParent->getOpCode().isConversion())
869
{
870
if (treeNode->getOpCodeValue() == TR::treetop ||
871
treeNode->getOpCode().isNullCheck())
872
treeNode = treeNode->getFirstChild();
873
874
if (treeNode->getOpCode().isStore())
875
{
876
TR::Node *valueChild = NULL;
877
if (treeNode->getOpCode().isIndirect())
878
valueChild = treeNode->getSecondChild();
879
else
880
valueChild = treeNode->getFirstChild();
881
882
if (valueChild->getOpCode().isConversion() &&
883
(valueChild->getReferenceCount() == 1) &&
884
valueChild->getFirstChild()->getOpCode().isConversion() &&
885
(valueChild->getFirstChild()->getReferenceCount() == 1) &&
886
(grandParent == valueChild->getFirstChild()) &&
887
(treeNode->getDataType() == parent->getDataType()))
888
{
889
// Tree matches for update of byte/char/short datatype
890
storeNode = treeNode;
891
}
892
else
893
return false;
894
}
895
else
896
return false;
897
}
898
else
899
return false;
900
}
901
else
902
{
903
if (grandParent->getOpCode().isIndirect() &&
904
(grandParent->getSecondChild() != parent))
905
return false;
906
907
storeNode = grandParent;
908
}
909
910
911
if ((parent->getOpCodeValue() == TR::iadd) ||
912
(parent->getOpCodeValue() == TR::isub) ||
913
(parent->getOpCodeValue() == TR::imul))
914
{
915
if (node->getOpCodeValue() == TR::iloadi)
916
{
917
if (storeNode->getOpCodeValue() == TR::istorei)
918
{
919
if (storeNode->getSymbolReference() == node->getSymbolReference())
920
{
921
if (storeNode->getFirstChild()->getOpCodeValue() == node->getFirstChild()->getOpCodeValue())
922
{
923
if ((storeNode->getFirstChild() == node->getFirstChild()) ||
924
(storeNode->getFirstChild()->getSymbolReference() == node->getFirstChild()->getSymbolReference()))
925
return true;
926
}
927
}
928
}
929
}
930
else if ((node->getOpCodeValue() == TR::iload) &&
931
(storeNode->getOpCodeValue() == TR::istore) &&
932
(storeNode->getSymbolReference() == node->getSymbolReference()))
933
return true;
934
}
935
else if ((parent->getOpCodeValue() == TR::ladd) ||
936
(parent->getOpCodeValue() == TR::lsub) ||
937
(parent->getOpCodeValue() == TR::lmul))
938
{
939
if (node->getOpCodeValue() == TR::lloadi)
940
{
941
if (storeNode->getOpCodeValue() == TR::lstorei)
942
{
943
if (storeNode->getSymbolReference() == node->getSymbolReference())
944
{
945
if (storeNode->getFirstChild()->getOpCodeValue() == node->getFirstChild()->getOpCodeValue())
946
{
947
if ((storeNode->getFirstChild() == node->getFirstChild()) ||
948
(storeNode->getFirstChild()->getSymbolReference() == node->getFirstChild()->getSymbolReference()))
949
return true;
950
}
951
}
952
}
953
}
954
else if ((node->getOpCodeValue() == TR::lload) &&
955
(storeNode->getOpCodeValue() == TR::lstore) &&
956
(storeNode->getSymbolReference() == node->getSymbolReference()))
957
return true;
958
}
959
960
return false;
961
}
962
963
964
static bool isPureBigDecimalMethod(TR::Node *node, TR::Compilation *comp, TR_PersistentFieldInfo *fieldInfo, bool & isBigDecimal, bool & isBigInteger)
965
{
966
if (!node)
967
return false;
968
969
//fprintf(stderr, "0Calling isPure %s\n", node->getOpCode().getName()); fflush(stderr);
970
//if (node->getOpCodeValue() == TR::aloadi)
971
// {
972
// fprintf(stderr, "node sym ref %p offset %d vft %p\n", node->getSymbolReference(), node->getSymbolReference()->getOffset(), comp->getSymRefTab()->findVftSymbolRef());
973
// }
974
975
976
if (node->getOpCodeValue() != TR::acalli)
977
{
978
//fprintf(stderr, "1Returning false from isPure %s\n", node->getOpCode().getName()); fflush(stderr);
979
return false;
980
}
981
982
if (node->getSymbolReference()->isUnresolved())
983
{
984
//fprintf(stderr, "2Returning false from isPure\n"); fflush(stderr);
985
return false;
986
}
987
988
if ((fieldInfo->isBigDecimalType() &&
989
((node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_add) ||
990
(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_subtract) ||
991
(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigDecimal_multiply))))
992
{
993
isBigDecimal = true;
994
return true;
995
}
996
997
998
if ((fieldInfo->isBigIntegerType() &&
999
((node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_add) ||
1000
(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_subtract) ||
1001
(node->getSymbol()->getResolvedMethodSymbol()->getRecognizedMethod() == TR::java_math_BigInteger_multiply))))
1002
{
1003
isBigInteger = true;
1004
return true;
1005
}
1006
1007
//fprintf(stderr, "is big decimal %d is big integer %d\n", fieldInfo->isBigDecimalType(), fieldInfo->isBigIntegerType());
1008
return false;
1009
}
1010
1011
1012
static bool isStoreToSameField(TR::Node *callNode, TR::Node *nextNode, TR::Node *loadNode)
1013
{
1014
if (callNode->getReferenceCount() == 2)
1015
{
1016
if (nextNode->getOpCodeValue() == TR::treetop ||
1017
nextNode->getOpCode().isNullCheck())
1018
nextNode = nextNode->getFirstChild();
1019
1020
if ((nextNode->getOpCodeValue() == TR::awrtbari) ||
1021
(nextNode->getOpCodeValue() == TR::astorei))
1022
{
1023
if (nextNode->getSymbolReference() == loadNode->getSymbolReference())
1024
{
1025
if (nextNode->getFirstChild()->getOpCodeValue() == loadNode->getFirstChild()->getOpCodeValue())
1026
{
1027
if ((nextNode->getFirstChild() == loadNode->getFirstChild()) ||
1028
(nextNode->getFirstChild()->getSymbolReference() == loadNode->getFirstChild()->getSymbolReference()))
1029
{
1030
if (nextNode->getSecondChild() == callNode)
1031
return true;
1032
}
1033
}
1034
}
1035
}
1036
else if ((nextNode->getOpCodeValue() == TR::awrtbar) ||
1037
(nextNode->getOpCodeValue() == TR::astore))
1038
{
1039
if (nextNode->getSymbolReference() == loadNode->getSymbolReference())
1040
{
1041
if (nextNode->getFirstChild() == callNode)
1042
return true;
1043
}
1044
}
1045
}
1046
1047
return false;
1048
}
1049
1050
1051
void TR_ClassLookahead::invalidateIfEscapingLoad(TR::TreeTop *nextTree, TR::Node *grandParent, TR::Node *parent, int32_t childNum, TR::Node *node)
1052
{
1053
TR::SymbolReference *storedSymRef = node->getSymbolReference();
1054
TR::Symbol *sym = storedSymRef->getSymbol();
1055
1056
//fprintf(stderr, "Check escaping load for node %s\n", node->getOpCode().getName()); fflush(stderr);
1057
1058
if ((sym->isShadow() ||
1059
sym->isStatic()) &&
1060
(storedSymRef->isUnresolved() ||
1061
(sym->isPrivate() ||
1062
sym->isFinal())))
1063
{
1064
//fprintf(stderr, "2Check escaping load for node %s\n", node->getOpCode().getName()); fflush(stderr);
1065
TR_PersistentFieldInfo *previousFieldInfo = _classFieldInfo->find(comp(), sym, storedSymRef);
1066
TR_PersistentFieldInfo *fieldInfo = previousFieldInfo;
1067
if (!fieldInfo)
1068
{
1069
fieldInfo = getExistingFieldInfo(sym, storedSymRef);
1070
//fprintf(stderr, "Check escaping load for fieldInfo %p\n", fieldInfo); fflush(stderr);
1071
if (fieldInfo)
1072
{
1073
fieldInfo->setIsTypeInfoValid(INVALID);
1074
TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
1075
if (arrayFieldInfo)
1076
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
1077
else
1078
fieldInfo->setCanChangeToArray(false);
1079
}
1080
}
1081
1082
TR_PersistentArrayFieldInfo *arrayFieldInfo = NULL;
1083
if (fieldInfo)
1084
{
1085
int32_t length;
1086
char *sig = getFieldSignature(comp(), sym, storedSymRef, length);
1087
/////fprintf(stderr, "Check NOT read for field sig %s\n", sig); fflush(stderr);
1088
1089
bool knownRead = false;
1090
bool isBigDecimal = false;
1091
bool isBigInteger = false;
1092
1093
if (sym->isStatic() ||
1094
(sym->isShadow() &&
1095
node->getFirstChild()->isThisPointer()))
1096
{
1097
bool refCountMatches = false;
1098
int32_t refCount = 2;
1099
int32_t extraRefCount = comp()->useAnchors() ? 1 : 0;
1100
if ((node->getReferenceCount() == (refCount + extraRefCount)) ||
1101
(node->getReferenceCount() == (refCount + extraRefCount)))
1102
refCountMatches = true;
1103
1104
if (refCountMatches)
1105
{
1106
if (parent &&
1107
((parent->getOpCodeValue() == TR::treetop) || parent->getOpCode().isAnchor()))
1108
knownRead = true;
1109
1110
if (isPureBigDecimalMethod(parent, comp(), fieldInfo, isBigDecimal, isBigInteger) && (childNum == 1) &&
1111
(parent->getFirstChild()->getOpCodeValue() == TR::aloadi) &&
1112
(parent->getFirstChild()->getFirstChild() == node))
1113
{
1114
if ((parent->getReferenceCount() == 1) ||
1115
isStoreToSameField(parent, nextTree->getNode(), node))
1116
knownRead = true;
1117
}
1118
1119
if (parent && (parent->getOpCodeValue() == TR::aloadi) && comp()->getSymRefTab()->findVftSymbolRef() &&
1120
(parent->getSymbolReference()->getOffset() == comp()->getSymRefTab()->findVftSymbolRef()->getOffset()) &&
1121
isPureBigDecimalMethod(grandParent, comp(), fieldInfo, isBigDecimal, isBigInteger) &&
1122
(grandParent->getSecondChild() == node))
1123
{
1124
if ((grandParent->getReferenceCount() == 1) ||
1125
isStoreToSameField(grandParent, nextTree->getNode(), node))
1126
knownRead = true;
1127
}
1128
}
1129
else if (node->getReferenceCount() == 1)
1130
{
1131
if (isArithmeticForSameField(nextTree->getPrevTreeTop()->getNode(), grandParent, parent, node))
1132
knownRead = true;
1133
}
1134
}
1135
1136
if (!isBigDecimal)
1137
fieldInfo->setBigDecimalType(false);
1138
if (!isBigInteger)
1139
fieldInfo->setBigIntegerType(false);
1140
1141
if (!knownRead)
1142
{
1143
////int32_t length;
1144
////char *sig = getFieldSignature(comp(), sym, storedSymRef, length);
1145
////fprintf(stderr, "%s is read after all\n", sig); fflush(stderr);
1146
////traceMsg(comp(), "Field %s is read after all in node %p\n", sig, node);
1147
1148
fieldInfo->setNotRead(false);
1149
}
1150
else
1151
{
1152
if (isBigDecimal)
1153
fieldInfo->setBigDecimalAssumption(true);
1154
1155
if (isBigInteger)
1156
fieldInfo->setBigIntegerAssumption(true);
1157
}
1158
1159
1160
if (storedSymRef->isUnresolved() ||
1161
(sym->isPrivate() &&
1162
!sym->isFinal()))
1163
arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
1164
}
1165
1166
if (arrayFieldInfo)
1167
{
1168
if (!parent ||
1169
((!parent->isInternalPointer()) &&
1170
(parent->getOpCodeValue() != TR::treetop) &&
1171
(!parent->getOpCode().isArrayLength()) &&
1172
(!parent->getOpCode().isAnchor()) &&
1173
(parent->getOpCodeValue() != TR::ArrayStoreCHK) &&
1174
((parent->getOpCodeValue() != TR::awrtbari) || (childNum != 2))))
1175
{
1176
if (_traceIt)
1177
traceMsg(comp(), "2Invalidating dimension and type info for symbol %x at node %x\n", sym, node);
1178
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
1179
arrayFieldInfo->setIsTypeInfoValid(INVALID);
1180
}
1181
}
1182
}
1183
}
1184
1185
1186
1187
bool TR_ClassLookahead::isProperFieldAccess(TR::Node *node)
1188
{
1189
TR::SymbolReference *storedSymRef = node->getSymbolReference();
1190
TR::Symbol *sym = storedSymRef->getSymbol();
1191
if (((sym->isShadow() &&
1192
node->getFirstChild()->isThisPointer()) ||
1193
(sym->isStatic() && sym->isFinal())) &&
1194
!storedSymRef->isUnresolved() &&
1195
(sym->isPrivate() ||
1196
sym->isFinal()))
1197
return true;
1198
1199
return false;
1200
}
1201
1202
1203
bool TR_ClassLookahead::isPrivateFieldAccess(TR::Node *node)
1204
{
1205
TR::SymbolReference *storedSymRef = node->getSymbolReference();
1206
TR::Symbol *sym = storedSymRef->getSymbol();
1207
if ((sym->isShadow() ||
1208
(sym->isStatic() && sym->isFinal())) &&
1209
!storedSymRef->isUnresolved() &&
1210
sym->isPrivate())
1211
return true;
1212
1213
return false;
1214
}
1215
1216
1217
bool TR_ClassLookahead::findMethod(List<TR::ResolvedMethodSymbol> *methodSyms, TR::ResolvedMethodSymbol *methodSym)
1218
{
1219
ListIterator<TR::ResolvedMethodSymbol> methodsIt(methodSyms);
1220
TR_ResolvedMethod *method = methodSym->getResolvedMethod();
1221
TR::ResolvedMethodSymbol *cursorMethodSym;
1222
for (cursorMethodSym = methodsIt.getFirst(); cursorMethodSym; cursorMethodSym = methodsIt.getNext())
1223
{
1224
if (cursorMethodSym->getResolvedMethod()->isSameMethod(method))
1225
return true;
1226
}
1227
return false;
1228
}
1229
1230
1231
char *TR_ClassLookahead::getFieldSignature(TR::Compilation *comp, TR::Symbol *sym, TR::SymbolReference *symRef, int32_t &length)
1232
{
1233
if (!symRef->isUnresolved() ||
1234
!sym->isStatic() ||
1235
!sym->isConstObjectRef())
1236
{
1237
char *sig = NULL;
1238
if (sym->isStatic())
1239
sig = symRef->getOwningMethod(comp)->staticName(symRef->getCPIndex(), length, comp->trMemory());
1240
else if (sym->isShadow())
1241
sig = symRef->getOwningMethod(comp)->fieldName(symRef->getCPIndex(), length, comp->trMemory());
1242
1243
return sig;
1244
}
1245
1246
length = -1;
1247
return NULL;
1248
}
1249
1250
1251
void TR_PersistentArrayFieldInfo::prepareArrayFieldInfo(int32_t numDimensions, TR::Compilation * comp)
1252
{
1253
setNumDimensions(numDimensions);
1254
//int32_t *newDimensionInfo = (int32_t *)jitPersistentAlloc(numDimensions*sizeof(int32_t));
1255
int32_t *newDimensionInfo = (int32_t *)comp->trMemory()->allocateHeapMemory(numDimensions*sizeof(int32_t));
1256
memset(newDimensionInfo, 0xFF, numDimensions*sizeof(int32_t));
1257
setDimensionInfo(newDimensionInfo);
1258
}
1259
1260
TR_PersistentArrayFieldInfo *TR_ClassLookahead::getExistingArrayFieldInfo(TR::Symbol *fieldSym, TR::SymbolReference *fieldSymRef)
1261
{
1262
TR::ClassTableCriticalSection getExistingArrayFieldInfo(comp()->fej9());
1263
1264
TR_PersistentFieldInfo *newFieldInfo = _classFieldInfo->find(comp(), fieldSym, fieldSymRef);
1265
TR_PersistentArrayFieldInfo *newArrayFieldInfo = NULL;
1266
if (newFieldInfo)
1267
newArrayFieldInfo = newFieldInfo->asPersistentArrayFieldInfo();
1268
1269
if (!newArrayFieldInfo /* &&
1270
(_inFirstInitializerMethod || _inClassInitializerMethod) */)
1271
{
1272
int32_t length = 0;
1273
char *sig = TR_ClassLookahead::getFieldSignature(comp(), fieldSym, fieldSymRef, length);
1274
if (length > -1)
1275
{
1276
//char *persistentSig = (char *)TR_Memory::jitPersistentAlloc(length);
1277
//memcpy(persistentSig, sig, length);
1278
//printf("Creating persistent info for array field %s\n", sig);
1279
//newArrayFieldInfo = new (PERSISTENT_NEW) TR_PersistentArrayFieldInfo(persistentSig, length);
1280
newArrayFieldInfo = new (comp()->trHeapMemory()) TR_PersistentArrayFieldInfo(sig, length);
1281
if (newFieldInfo)
1282
{
1283
if (newFieldInfo->canChangeToArray())
1284
{
1285
newArrayFieldInfo->copyData(newFieldInfo);
1286
_classFieldInfo->remove(newFieldInfo);
1287
}
1288
else
1289
{
1290
traceMsg(comp(), "fieldInfo %p exists already for array field %s, so cannot morph\n", newFieldInfo, sig);
1291
newArrayFieldInfo = NULL;
1292
newFieldInfo->setIsTypeInfoValid(INVALID);
1293
}
1294
}
1295
1296
if (newArrayFieldInfo)
1297
_classFieldInfo->add(newArrayFieldInfo);
1298
}
1299
}
1300
1301
return newArrayFieldInfo;
1302
}
1303
1304
1305
TR_PersistentFieldInfo *TR_ClassLookahead::getExistingFieldInfo(TR::Symbol *fieldSym, TR::SymbolReference *fieldSymRef, bool canMorph)
1306
{
1307
TR::ClassTableCriticalSection getExistingFieldInfo(comp()->fej9());
1308
1309
TR_PersistentFieldInfo *newFieldInfo = _classFieldInfo->find(comp(), fieldSym, fieldSymRef);
1310
if (!newFieldInfo /* &&
1311
(_inFirstInitializerMethod || _inClassInitializerMethod) */)
1312
{
1313
int32_t length = 0;
1314
char *sig = TR_ClassLookahead::getFieldSignature(comp(), fieldSym, fieldSymRef, length);
1315
if (length > -1)
1316
{
1317
//char *persistentSig = (char *)TR_Memory::jitPersistentAlloc(length);
1318
//memcpy(persistentSig, sig, length);
1319
//printf("Creating persistent info for field %s\n", sig);
1320
//newFieldInfo = new (PERSISTENT_NEW) TR_PersistentFieldInfo(persistentSig, length);
1321
newFieldInfo = new (comp()->trHeapMemory()) TR_PersistentFieldInfo(sig, length);
1322
if (!canMorph)
1323
newFieldInfo->setCanChangeToArray(false);
1324
_classFieldInfo->add(newFieldInfo);
1325
}
1326
}
1327
1328
return newFieldInfo;
1329
}
1330
1331
1332
void TR_ClassLookahead::makeInfoPersistent()
1333
{
1334
TR::ClassTableCriticalSection makeInfoPersistent(comp()->fej9());
1335
1336
TR_PersistentFieldInfo *fieldInfo = _classFieldInfo->getFirst();
1337
TR_PersistentFieldInfo *prevInfo = NULL;
1338
1339
while (fieldInfo)
1340
{
1341
bool isTypeInfoValid = fieldInfo->isTypeInfoValid();
1342
bool isDimensionInfoValid = false;
1343
TR_PersistentArrayFieldInfo *arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
1344
if (arrayFieldInfo &&
1345
arrayFieldInfo->isDimensionInfoValid())
1346
isDimensionInfoValid = true;
1347
bool isImmutable = fieldInfo->isImmutable();
1348
bool isNotRead = fieldInfo->isNotRead();
1349
bool isBigDecimalType = fieldInfo->isBigDecimalType();
1350
bool isBigIntegerType = fieldInfo->isBigIntegerType();
1351
bool hasBigDecimalAssumption = fieldInfo->hasBigDecimalAssumption();
1352
bool hasBigIntegerAssumption = fieldInfo->hasBigIntegerAssumption();
1353
1354
TR_PersistentFieldInfo *newFieldInfo = NULL;
1355
if (isTypeInfoValid || isDimensionInfoValid || isImmutable || (isNotRead && ((!hasBigDecimalAssumption || isBigDecimalType) && (!hasBigIntegerAssumption || isBigIntegerType))))
1356
{
1357
//if (isImmutable &&
1358
// (!isTypeInfoValid && !isDimensionInfoValid))
1359
// {
1360
// printf("Type info and dimension info are invalid but field %s is immutable \n", fieldInfo->getFieldSignature());
1361
// fflush(stdout);
1362
// }
1363
1364
int32_t length = fieldInfo->getFieldSignatureLength();
1365
char *persistentSig = (char *)jitPersistentAlloc(length);
1366
memcpy(persistentSig, fieldInfo->getFieldSignature(), length);
1367
if (arrayFieldInfo)
1368
{
1369
if (_traceIt)
1370
printf("Creating persistent info for array field %s\n", persistentSig);
1371
newFieldInfo = new (PERSISTENT_NEW) TR_PersistentArrayFieldInfo(*arrayFieldInfo);
1372
}
1373
else
1374
{
1375
if (_traceIt)
1376
printf("Creating persistent info for field %s\n", persistentSig);
1377
newFieldInfo = new (PERSISTENT_NEW) TR_PersistentFieldInfo(*fieldInfo);
1378
}
1379
1380
newFieldInfo->setFieldSignature(persistentSig);
1381
newFieldInfo->setFieldSignatureLength(length);
1382
1383
char *persistentType = 0;
1384
if (isTypeInfoValid)
1385
{
1386
length = fieldInfo->getNumChars();
1387
persistentType = (char *)jitPersistentAlloc(length);
1388
memcpy(persistentType, fieldInfo->getClassPointer(), length);
1389
}
1390
newFieldInfo->setClassPointer(persistentType);
1391
1392
if (arrayFieldInfo)
1393
{
1394
TR_PersistentArrayFieldInfo *newArrayFieldInfo = newFieldInfo->asPersistentArrayFieldInfo();
1395
int32_t numDimensions = arrayFieldInfo->getNumDimensions();
1396
if (arrayFieldInfo->getDimensionInfo())
1397
{
1398
int32_t *newDimensionInfo = (int32_t *)jitPersistentAlloc(numDimensions*sizeof(int32_t));
1399
memcpy(newDimensionInfo, arrayFieldInfo->getDimensionInfo(), numDimensions*sizeof(int32_t));
1400
newArrayFieldInfo->setDimensionInfo(newDimensionInfo);
1401
}
1402
}
1403
1404
if (prevInfo)
1405
prevInfo->setNext(newFieldInfo);
1406
else
1407
_classFieldInfo->setFirst(newFieldInfo);
1408
prevInfo = newFieldInfo;
1409
}
1410
else
1411
{
1412
if (prevInfo)
1413
prevInfo->setNext(fieldInfo->getNext());
1414
else
1415
_classFieldInfo->setFirst(fieldInfo->getNext());
1416
}
1417
1418
fieldInfo = fieldInfo->getNext();
1419
}
1420
}
1421
1422
1423
TR_PersistentFieldInfo *TR_PersistentClassInfoForFields::find(TR::Compilation *comp, TR::Symbol *fieldSym, TR::SymbolReference *fieldSymRef)
1424
{
1425
int32_t length = 0;
1426
char *sig = TR_ClassLookahead::getFieldSignature(comp, fieldSym, fieldSymRef, length);
1427
1428
TR::ClassTableCriticalSection findFields(comp->fej9());
1429
for (TR_PersistentFieldInfo *fieldInfo = getFirst(); fieldInfo; fieldInfo = fieldInfo->getNext())
1430
{
1431
// Revisit
1432
//
1433
1434
if ((length == fieldInfo->getFieldSignatureLength()) &&
1435
(memcmp(sig, fieldInfo->getFieldSignature(), length) == 0))
1436
{
1437
return fieldInfo;
1438
}
1439
1440
//if ((fieldInfo->getFieldSymbol() == fieldSym) ||
1441
// (fieldInfo->getFieldSymRef() == fieldSymRef))
1442
// return fieldInfo;
1443
1444
/*
1445
else if (fieldSym->isShadow())
1446
{
1447
if (fieldsAreSame(fieldInfo->getOwningMethodSymbol()->getResolvedMethod(), fieldInfo->getFieldSymRef()->getCPIndex(), fieldSymRef->getOwningMethod(), fieldSymRef->getCPIndex()))
1448
return fieldInfo->asPersistentArrayFieldInfo();
1449
}
1450
else if (fieldSym->isStatic())
1451
{
1452
if (staticsAreSame(fieldInfo->getOwningMethodSymbol()->getResolvedMethod(), fieldInfo->getFieldSymRef()->getCPIndex(), fieldSymRef->getOwningMethod(), fieldSymRef->getCPIndex()))
1453
return fieldInfo->asPersistentArrayFieldInfo();
1454
}
1455
*/
1456
}
1457
1458
return 0;
1459
}
1460
1461
TR_PersistentFieldInfo *
1462
TR_PersistentClassInfoForFields::findFieldInfo(TR::Compilation *comp, TR::Node * & node, bool canBeArrayShadow)
1463
{
1464
if (!getFirst() || !node->getOpCode().hasSymbolReference())
1465
return 0;
1466
1467
TR::SymbolReference * symRef = node->getSymbolReference();
1468
if (symRef->isUnresolved())
1469
return 0;
1470
1471
TR::Symbol * sym = symRef->getSymbol();
1472
if (!sym->isPrivate() &&
1473
!sym->isFinal())
1474
return 0;
1475
1476
if (sym->isArrayShadowSymbol())
1477
{
1478
if (!canBeArrayShadow)
1479
return 0;
1480
TR::Node *firstChild = node->getFirstChild();
1481
if (firstChild->getNumChildren() > 0)
1482
firstChild = firstChild->getFirstChild();
1483
if (firstChild->getOpCode().hasSymbolReference())
1484
node = firstChild;
1485
}
1486
1487
if (sym->isStatic() ||
1488
(sym->isShadow() && node->getNumChildren() > 0 && node->getFirstChild()->isThisPointer()))
1489
return find(comp, sym, symRef);
1490
1491
return 0;
1492
}
1493
1494
void TR_ClassLookahead::initializeFieldInfo()
1495
{
1496
TR::ClassTableCriticalSection initializeFieldInfo(comp()->fej9());
1497
1498
TR_PersistentFieldInfo *fieldInfo = _classFieldInfo->getFirst();
1499
while (fieldInfo)
1500
{
1501
TR_PersistentArrayFieldInfo *arrayFieldInfo = NULL;
1502
arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
1503
1504
if (arrayFieldInfo)
1505
{
1506
if (arrayFieldInfo->isDimensionInfoValid() == VALID_AND_ALWAYS_INITIALIZED)
1507
arrayFieldInfo->setIsDimensionInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);
1508
}
1509
1510
if (fieldInfo->isTypeInfoValid() == VALID_AND_ALWAYS_INITIALIZED)
1511
fieldInfo->setIsTypeInfoValid(VALID_BUT_NOT_ALWAYS_INITIALIZED);
1512
fieldInfo = fieldInfo->getNext();
1513
}
1514
}
1515
1516
1517
1518
void TR_ClassLookahead::updateFieldInfo()
1519
{
1520
TR::ClassTableCriticalSection updateFieldInfo(comp()->fej9());
1521
1522
TR_PersistentFieldInfo *fieldInfo = _classFieldInfo->getFirst();
1523
while (fieldInfo)
1524
{
1525
TR_PersistentArrayFieldInfo *arrayFieldInfo = NULL;
1526
arrayFieldInfo = fieldInfo->asPersistentArrayFieldInfo();
1527
1528
if (arrayFieldInfo)
1529
{
1530
if (arrayFieldInfo->isDimensionInfoValid() < VALID_AND_ALWAYS_INITIALIZED)
1531
arrayFieldInfo->setIsDimensionInfoValid(INVALID);
1532
}
1533
1534
if (fieldInfo->isTypeInfoValid() < VALID_AND_ALWAYS_INITIALIZED)
1535
{
1536
fieldInfo->setIsTypeInfoValid(INVALID);
1537
if (!arrayFieldInfo)
1538
fieldInfo->setCanChangeToArray(false);
1539
}
1540
1541
fieldInfo = fieldInfo->getNext();
1542
}
1543
}
1544
1545
1546
#ifdef DEBUG
1547
void TR_PersistentFieldInfo::dumpInfo(TR_FrontEnd *fe, TR::FILE *logFile)
1548
{
1549
trfprintf(logFile, "\n\nPersistentFieldInfo for (%s) : (next : %x)\n", _signature, getNext());
1550
1551
if (_isTypeInfoValid)
1552
{
1553
trfprintf(logFile, "Type info : %s\n", *_classPointer);
1554
}
1555
else
1556
trfprintf(logFile, "Type info INVALID\n");
1557
1558
1559
if (getNext())
1560
getNext()->dumpInfo(fe, logFile);
1561
}
1562
1563
void TR_PersistentArrayFieldInfo::dumpInfo(TR_FrontEnd *fe, TR::FILE *logFile)
1564
{
1565
TR_PersistentFieldInfo::dumpInfo(fe, logFile);
1566
1567
if (_isDimensionInfoValid)
1568
{
1569
trfprintf(logFile, "numDimensions : %d\n", _numDimensions);
1570
int32_t i;
1571
for (i=0;i<_numDimensions;i++)
1572
trfprintf(logFile, "_dimensionInfo[%d] : %d\n", i, _dimensionInfo[i]);
1573
}
1574
else
1575
trfprintf(logFile, "Dimension info INVALID\n");
1576
}
1577
1578
#endif
1579
1580
1581