Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/p/codegen/J9CodeGenerator.cpp
6004 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 "j9cfg.h"
24
#include "codegen/AheadOfTimeCompile.hpp"
25
#include "codegen/CodeGenerator.hpp"
26
#include "codegen/CodeGeneratorUtils.hpp"
27
#include "codegen/CodeGenerator_inlines.hpp"
28
#include "codegen/GenerateInstructions.hpp"
29
#include "codegen/Linkage.hpp"
30
#include "codegen/Linkage_inlines.hpp"
31
#include "codegen/PPCJNILinkage.hpp"
32
#include "codegen/PPCPrivateLinkage.hpp"
33
#include "env/CompilerEnv.hpp"
34
#include "env/OMRMemory.hpp"
35
#include "env/VMJ9.h"
36
#include "env/jittypes.h"
37
#include "il/Node.hpp"
38
#include "il/Node_inlines.hpp"
39
#include "il/TreeTop.hpp"
40
#include "il/TreeTop_inlines.hpp"
41
#include "p/codegen/PPCInstruction.hpp"
42
#include "p/codegen/PPCRecompilation.hpp"
43
#include "p/codegen/PPCSystemLinkage.hpp"
44
45
extern void TEMPORARY_initJ9PPCTreeEvaluatorTable(TR::CodeGenerator *cg);
46
47
J9::Power::CodeGenerator::CodeGenerator(TR::Compilation *comp) :
48
J9::CodeGenerator(comp)
49
{
50
/**
51
* Do not add CodeGenerator initialization logic here.
52
* Use the \c initialize() method instead.
53
*/
54
}
55
56
void
57
J9::Power::CodeGenerator::initialize()
58
{
59
self()->J9::CodeGenerator::initialize();
60
61
TR::CodeGenerator *cg = self();
62
TR::Compilation *comp = cg->comp();
63
TR_J9VMBase *fej9 = (TR_J9VMBase *) (comp->fe());
64
65
cg->setAheadOfTimeCompile(new (cg->trHeapMemory()) TR::AheadOfTimeCompile(cg));
66
67
if (!comp->getOption(TR_FullSpeedDebug))
68
cg->setSupportsDirectJNICalls();
69
70
if (!comp->getOption(TR_DisableBDLLVersioning))
71
{
72
cg->setSupportsBigDecimalLongLookasideVersioning();
73
}
74
75
if (cg->getSupportsTM())
76
{
77
cg->setSupportsInlineConcurrentLinkedQueue();
78
}
79
80
cg->setSupportsNewInstanceImplOpt();
81
82
static char *disableMonitorCacheLookup = feGetEnv("TR_disableMonitorCacheLookup");
83
if (!disableMonitorCacheLookup)
84
comp->setOption(TR_EnableMonitorCacheLookup);
85
86
cg->setSupportsPartialInlineOfMethodHooks();
87
cg->setSupportsInliningOfTypeCoersionMethods();
88
89
if (comp->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P8) && comp->target().cpu.supportsFeature(OMR_FEATURE_PPC_HAS_VSX) &&
90
comp->target().is64Bit() && !comp->getOption(TR_DisableFastStringIndexOf) &&
91
!TR::Compiler->om.canGenerateArraylets())
92
cg->setSupportsInlineStringIndexOf();
93
94
if (!comp->getOption(TR_DisableReadMonitors))
95
cg->setSupportsReadOnlyLocks();
96
97
static bool disableTLHPrefetch = (feGetEnv("TR_DisableTLHPrefetch") != NULL);
98
99
// Enable software prefetch of the TLH and configure the TLH prefetching
100
// geometry.
101
//
102
if (!disableTLHPrefetch && comp->getOption(TR_TLHPrefetch) && !comp->compileRelocatableCode())
103
{
104
cg->setEnableTLHPrefetching();
105
}
106
107
//This env-var does 3 things:
108
// 1. Prevents batch clear in frontend/j9/rossa.cpp
109
// 2. Prevents all allocations to nonZeroTLH
110
// 3. Maintains the old semantics zero-init and prefetch.
111
// The use of this env-var is more complete than the JIT Option then.
112
static bool disableDualTLH = (feGetEnv("TR_DisableDualTLH") != NULL);
113
// Enable use of non-zero initialized TLH for object allocations where
114
// zero-initialization is not required as detected by the optimizer.
115
//
116
if (!disableDualTLH && !comp->getOption(TR_DisableDualTLH) && !comp->compileRelocatableCode() && !comp->getOptions()->realTimeGC())
117
{
118
cg->setIsDualTLH();
119
}
120
121
/*
122
* "Statically" initialize the FE-specific tree evaluator functions.
123
* This code only needs to execute once per JIT lifetime.
124
*/
125
static bool initTreeEvaluatorTable = false;
126
if (!initTreeEvaluatorTable)
127
{
128
TEMPORARY_initJ9PPCTreeEvaluatorTable(cg);
129
initTreeEvaluatorTable = true;
130
}
131
132
if (comp->fej9()->hasFixedFrameC_CallingConvention())
133
cg->setHasFixedFrameC_CallingConvention();
134
135
}
136
137
bool
138
J9::Power::CodeGenerator::canEmitDataForExternallyRelocatableInstructions()
139
{
140
// On Power, data cannot be emitted inside instructions that will be associated with an
141
// external relocation record (ex. AOT or Remote compiles in OpenJ9). This is because when the
142
// relocation is applied when a method is loaded, the new data in the instruction is OR'ed in (The reason
143
// for OR'ing is that sometimes usefule information such as flags and hints can be stored during compilation in these data fields).
144
// Hence, for the relocation to be applied correctly, we must ensure that the data fields inside the instruction
145
// initially are zero.
146
#ifdef J9VM_OPT_JITSERVER
147
return !self()->comp()->compileRelocatableCode() && !self()->comp()->isOutOfProcessCompilation();
148
#endif
149
return !self()->comp()->compileRelocatableCode();
150
}
151
152
// Get or create the TR::Linkage object that corresponds to the given linkage
153
// convention.
154
// Even though this method is common, its implementation is machine-specific.
155
//
156
TR::Linkage *
157
J9::Power::CodeGenerator::createLinkage(TR_LinkageConventions lc)
158
{
159
TR::Linkage *linkage;
160
switch (lc)
161
{
162
case TR_Private:
163
linkage = new (self()->trHeapMemory()) J9::Power::PrivateLinkage(self());
164
break;
165
case TR_System:
166
linkage = new (self()->trHeapMemory()) TR::PPCSystemLinkage(self());
167
break;
168
case TR_CHelper:
169
case TR_Helper:
170
linkage = new (self()->trHeapMemory()) J9::Power::HelperLinkage(self(), lc);
171
break;
172
case TR_J9JNILinkage:
173
linkage = new (self()->trHeapMemory()) J9::Power::JNILinkage(self());
174
break;
175
default :
176
linkage = new (self()->trHeapMemory()) TR::PPCSystemLinkage(self());
177
TR_ASSERT(false, "Unexpected linkage convention");
178
}
179
180
self()->setLinkage(lc, linkage);
181
return linkage;
182
}
183
184
TR::Recompilation *
185
J9::Power::CodeGenerator::allocateRecompilationInfo()
186
{
187
return TR_PPCRecompilation::allocate(self()->comp());
188
}
189
190
void
191
J9::Power::CodeGenerator::generateBinaryEncodingPrologue(
192
TR_PPCBinaryEncodingData *data)
193
{
194
TR::Compilation *comp = self()->comp();
195
TR_J9VMBase *fej9 = (TR_J9VMBase *)(comp->fe());
196
TR::Instruction *tempInstruction;
197
198
data->recomp = comp->getRecompilationInfo();
199
data->cursorInstruction = self()->getFirstInstruction();
200
data->preProcInstruction = data->cursorInstruction;
201
data->jitTojitStart = data->cursorInstruction->getNext();
202
203
self()->getLinkage()->loadUpArguments(data->cursorInstruction);
204
205
if (data->recomp != NULL)
206
{
207
data->recomp->generatePrePrologue();
208
}
209
else
210
{
211
if (comp->getOption(TR_FullSpeedDebug) || comp->getOption(TR_SupportSwitchToInterpreter))
212
{
213
self()->generateSwitchToInterpreterPrePrologue(NULL, comp->getStartTree()->getNode());
214
}
215
else
216
{
217
TR::ResolvedMethodSymbol *methodSymbol = comp->getMethodSymbol();
218
/* save the original JNI native address if a JNI thunk is generated */
219
/* thunk is not recompilable, nor does it support FSD */
220
if (methodSymbol->isJNI())
221
{
222
uintptr_t JNIMethodAddress = (uintptr_t)methodSymbol->getResolvedMethod()->startAddressForJNIMethod(comp);
223
TR::Node *firstNode = comp->getStartTree()->getNode();
224
if (comp->target().is64Bit())
225
{
226
int32_t highBits = (int32_t)(JNIMethodAddress>>32), lowBits = (int32_t)JNIMethodAddress;
227
TR::Instruction *cursor = new (self()->trHeapMemory()) TR::PPCImmInstruction(TR::InstOpCode::dd, firstNode,
228
comp->target().cpu.isBigEndian()?highBits:lowBits, NULL, self());
229
generateImmInstruction(self(), TR::InstOpCode::dd, firstNode,
230
comp->target().cpu.isBigEndian()?lowBits:highBits, cursor);
231
}
232
else
233
{
234
new (self()->trHeapMemory()) TR::PPCImmInstruction(TR::InstOpCode::dd, firstNode, (int32_t)JNIMethodAddress, NULL, self());
235
}
236
}
237
}
238
}
239
240
data->cursorInstruction = self()->getFirstInstruction();
241
242
while (data->cursorInstruction && data->cursorInstruction->getOpCodeValue() != TR::InstOpCode::proc)
243
{
244
data->estimate = data->cursorInstruction->estimateBinaryLength(data->estimate);
245
data->cursorInstruction = data->cursorInstruction->getNext();
246
}
247
248
if (self()->supportsJitMethodEntryAlignment())
249
{
250
self()->setPreJitMethodEntrySize(data->estimate);
251
data->estimate += (self()->getJitMethodEntryAlignmentBoundary() - 1);
252
}
253
254
tempInstruction = data->cursorInstruction;
255
if ((data->recomp!=NULL) && (!data->recomp->useSampling()))
256
{
257
tempInstruction = data->recomp->generatePrologue(tempInstruction);
258
}
259
260
self()->getLinkage()->createPrologue(tempInstruction);
261
262
}
263
264
265
void
266
J9::Power::CodeGenerator::lowerTreeIfNeeded(
267
TR::Node *node,
268
int32_t childNumberOfNode,
269
TR::Node *parent,
270
TR::TreeTop *tt)
271
{
272
J9::CodeGenerator::lowerTreeIfNeeded(node, childNumberOfNode, parent, tt);
273
274
if ((node->getOpCode().isLeftShift() ||
275
node->getOpCode().isRightShift() || node->getOpCode().isRotate()) &&
276
self()->needsNormalizationBeforeShifts() &&
277
!node->isNormalizedShift())
278
{
279
TR::Node *second = node->getSecondChild();
280
int32_t normalizationAmount;
281
if (node->getType().isInt64())
282
normalizationAmount = 63;
283
else
284
normalizationAmount = 31;
285
286
// Some platforms like IA32 obey Java semantics for shifts even if the
287
// shift amount is greater than 31 or 63. However other platforms like PPC need
288
// to normalize the shift amount to range (0, 31) or (0, 63) before shifting in order
289
// to obey Java semantics. This can be captured in the IL and commoning/hoisting
290
// can be done (look at Compressor.compress).
291
//
292
if ( (second->getOpCodeValue() != TR::iconst) &&
293
((second->getOpCodeValue() != TR::iand) ||
294
(second->getSecondChild()->getOpCodeValue() != TR::iconst) ||
295
(second->getSecondChild()->getInt() != normalizationAmount)))
296
{
297
// Not normalized yet
298
//
299
TR::Node * normalizedNode = TR::Node::create(TR::iand, 2, second, TR::Node::create(second, TR::iconst, 0, normalizationAmount));
300
second->recursivelyDecReferenceCount();
301
node->setAndIncChild(1, normalizedNode);
302
node->setNormalizedShift(true);
303
}
304
}
305
306
}
307
308
309
bool J9::Power::CodeGenerator::suppressInliningOfRecognizedMethod(TR::RecognizedMethod method)
310
{
311
TR::Compilation *comp = self()->comp();
312
313
if (self()->isMethodInAtomicLongGroup(method))
314
{
315
return true;
316
}
317
318
#ifdef J9VM_OPT_JAVA_CRYPTO_ACCELERATION
319
if (self()->suppressInliningOfCryptoMethod(method))
320
{
321
return true;
322
}
323
#endif
324
325
if ((method==TR::java_util_concurrent_atomic_AtomicBoolean_getAndSet) ||
326
(method==TR::java_util_concurrent_atomic_AtomicInteger_getAndAdd) ||
327
(method==TR::java_util_concurrent_atomic_AtomicInteger_getAndIncrement) ||
328
(method==TR::java_util_concurrent_atomic_AtomicInteger_getAndDecrement) ||
329
(method==TR::java_util_concurrent_atomic_AtomicInteger_getAndSet) ||
330
(method==TR::java_util_concurrent_atomic_AtomicInteger_addAndGet) ||
331
(method==TR::java_util_concurrent_atomic_AtomicInteger_decrementAndGet) ||
332
(method==TR::java_util_concurrent_atomic_AtomicInteger_incrementAndGet))
333
{
334
return true;
335
}
336
337
if (method == TR::java_lang_Math_fma_D ||
338
method == TR::java_lang_Math_fma_F ||
339
method == TR::java_lang_StrictMath_fma_D ||
340
method == TR::java_lang_StrictMath_fma_F)
341
{
342
return true;
343
}
344
345
// Transactional Memory
346
if (self()->getSupportsInlineConcurrentLinkedQueue())
347
{
348
if (method == TR::java_util_concurrent_ConcurrentLinkedQueue_tmOffer ||
349
method == TR::java_util_concurrent_ConcurrentLinkedQueue_tmPoll ||
350
method == TR::java_util_concurrent_ConcurrentLinkedQueue_tmEnabled)
351
{
352
return true;
353
}
354
}
355
356
return false;
357
}
358
359
360
bool
361
J9::Power::CodeGenerator::enableAESInHardwareTransformations()
362
{
363
TR::Compilation *comp = self()->comp();
364
if ( (comp->target().cpu.getPPCSupportsAES() || (comp->target().cpu.supportsFeature(OMR_FEATURE_PPC_HAS_ALTIVEC) && comp->target().cpu.supportsFeature(OMR_FEATURE_PPC_HAS_VSX))) &&
365
!comp->getOption(TR_DisableAESInHardware))
366
return true;
367
else
368
return false;
369
}
370
371
void
372
J9::Power::CodeGenerator::insertPrefetchIfNecessary(TR::Node *node, TR::Register *targetRegister)
373
{
374
TR::Compilation *comp = self()->comp();
375
static bool disableHotFieldPrefetch = (feGetEnv("TR_DisableHotFieldPrefetch") != NULL);
376
static bool disableHotFieldNextElementPrefetch = (feGetEnv("TR_DisableHotFieldNextElementPrefetch") != NULL);
377
static bool disableIteratorPrefetch = (feGetEnv("TR_DisableIteratorPrefetch") != NULL);
378
static bool disableStringObjPrefetch = (feGetEnv("TR_DisableStringObjPrefetch") != NULL);
379
bool optDisabled = false;
380
381
if ((node->getOpCodeValue() == TR::aloadi && !comp->target().is64Bit()) ||
382
(comp->target().is64Bit() &&
383
comp->useCompressedPointers() &&
384
node->getOpCodeValue() == TR::l2a &&
385
comp->getMethodHotness() >= scorching &&
386
TR::Compiler->om.compressedReferenceShiftOffset() == 0 &&
387
comp->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P6))
388
)
389
{
390
int32_t prefetchOffset = comp->findPrefetchInfo(node);
391
TR::Node *firstChild = node->getFirstChild();
392
393
if (!disableHotFieldPrefetch && prefetchOffset >= 0) // Prefetch based on hot field information
394
{
395
bool canSkipNullChk = false;
396
static bool disableDelayPrefetch = (feGetEnv("TR_DisableDelayPrefetch") != NULL);
397
TR::LabelSymbol *endCtrlFlowLabel = generateLabelSymbol(self());
398
TR::Node *topNode = self()->getCurrentEvaluationTreeTop()->getNode();
399
// Search the current block for a check for NULL
400
TR::TreeTop *tt = self()->getCurrentEvaluationTreeTop()->getNextTreeTop();
401
TR::Node *checkNode = NULL;
402
403
while (!disableDelayPrefetch && tt && (tt->getNode()->getOpCodeValue() != TR::BBEnd))
404
{
405
checkNode = tt->getNode();
406
if (checkNode->getOpCodeValue() == TR::ifacmpeq &&
407
checkNode->getFirstChild() == node &&
408
checkNode->getSecondChild()->getDataType() == TR::Address &&
409
checkNode->getSecondChild()->isZero())
410
{
411
canSkipNullChk = true;
412
}
413
tt = tt->getNextTreeTop();
414
}
415
416
if (!canSkipNullChk)
417
{
418
TR::Register *condReg = self()->allocateRegister(TR_CCR);
419
TR::LabelSymbol *startCtrlFlowLabel = generateLabelSymbol(self());
420
startCtrlFlowLabel->setStartInternalControlFlow();
421
endCtrlFlowLabel->setEndInternalControlFlow();
422
generateLabelInstruction(self(), TR::InstOpCode::label, node, startCtrlFlowLabel);
423
424
// check for null
425
generateTrg1Src1ImmInstruction(self(), TR::InstOpCode::cmpli4, node, condReg, targetRegister, NULLVALUE);
426
generateConditionalBranchInstruction(self(), TR::InstOpCode::beql, node, endCtrlFlowLabel, condReg);
427
428
TR::Register *tempReg = self()->allocateRegister();
429
TR::RegisterDependencyConditions *deps = new (self()->trHeapMemory()) TR::RegisterDependencyConditions(1, 2, self()->trMemory());
430
deps->addPostCondition(tempReg, TR::RealRegister::NoReg);
431
TR::addDependency(deps, condReg, TR::RealRegister::NoReg, TR_CCR, self());
432
433
if (comp->target().is64Bit() && !comp->useCompressedPointers())
434
{
435
TR::MemoryReference *tempMR = TR::MemoryReference::createWithDisplacement(self(), targetRegister, prefetchOffset, 8);
436
generateTrg1MemInstruction(self(), TR::InstOpCode::ld, node, tempReg, tempMR);
437
}
438
else
439
{
440
TR::MemoryReference *tempMR = TR::MemoryReference::createWithDisplacement(self(), targetRegister, prefetchOffset, 4);
441
generateTrg1MemInstruction(self(), TR::InstOpCode::lwz, node, tempReg, tempMR);
442
}
443
444
TR::MemoryReference *targetMR = TR::MemoryReference::createWithDisplacement(self(), tempReg, (int32_t)0, 4);
445
targetMR->forceIndexedForm(node, self());
446
generateMemInstruction(self(), TR::InstOpCode::dcbt, node, targetMR);
447
448
self()->stopUsingRegister(tempReg);
449
self()->stopUsingRegister(condReg);
450
}
451
else
452
{
453
// Delay the dcbt to after the null check and fall through to the next block's treetop.
454
TR::TreeTop *useTree = tt->getNextTreeTop();
455
TR_ASSERT(useTree->getNode()->getOpCodeValue() == TR::BBStart, "Expecting a BBStart on the fall through\n");
456
TR::Node *useNode = useTree->getNode();
457
TR::Block *bb = useNode->getBlock();
458
if (bb->isExtensionOfPreviousBlock()) // Survived the null check
459
{
460
TR_PrefetchInfo *pf = new (self()->trHeapMemory())TR_PrefetchInfo(self()->getCurrentEvaluationTreeTop(), useTree, node, useNode, prefetchOffset, false);
461
comp->removeExtraPrefetchInfo(useNode);
462
comp->getExtraPrefetchInfo().push_front(pf);
463
}
464
}
465
466
// Do a prefetch on the next element of the array
467
// if the pointer came from an array. Seems to give no gain at all, disabled until later
468
TR::Register *pointerReg = NULL;
469
bool fromRegLoad = false;
470
if (!disableHotFieldNextElementPrefetch)
471
{
472
// 32bit
473
if (comp->target().is32Bit())
474
{
475
if (!(firstChild->getOpCodeValue() == TR::aiadd &&
476
firstChild->getFirstChild() &&
477
firstChild->isInternalPointer()) &&
478
!(firstChild->getOpCodeValue() == TR::aRegLoad &&
479
firstChild->getSymbolReference()->getSymbol()->isInternalPointer()))
480
{
481
optDisabled = true;
482
}
483
else
484
{
485
fromRegLoad = (firstChild->getOpCodeValue() == TR::aRegLoad);
486
pointerReg = fromRegLoad ? firstChild->getRegister() : self()->allocateRegister();
487
if (!fromRegLoad)
488
{
489
// Case for aiadd, there should be 2 children
490
TR::Node *baseObject = firstChild->getFirstChild();
491
TR::Register *baseReg = (baseObject) ? baseObject->getRegister() : NULL;
492
TR::Node *indexObject = firstChild->getSecondChild();
493
TR::Register *indexReg = (indexObject) ? indexObject->getRegister() : NULL;
494
// If the index is constant we just grab it
495
if (indexObject->getOpCode().isLoadConst())
496
{
497
int32_t len = indexObject->getInt();
498
if (len >= LOWER_IMMED && len <= UPPER_IMMED)
499
generateTrg1Src1ImmInstruction(self(), TR::InstOpCode::addi, node, pointerReg, baseReg, len);
500
else
501
{
502
indexReg = self()->allocateRegister();
503
loadConstant(self(), node, len, indexReg);
504
generateTrg1Src2Instruction(self(), TR::InstOpCode::add, node, pointerReg, baseReg, indexReg);
505
self()->stopUsingRegister(indexReg);
506
}
507
}
508
else
509
generateTrg1Src2Instruction(self(), TR::InstOpCode::add, node, pointerReg, baseReg, indexReg);
510
}
511
}
512
}
513
// 64bit CR
514
else if (comp->target().is64Bit() && comp->useCompressedPointers())
515
{
516
if (!(firstChild->getOpCodeValue() == TR::iu2l &&
517
firstChild->getFirstChild() &&
518
firstChild->getFirstChild()->getOpCodeValue() == TR::iloadi &&
519
firstChild->getFirstChild()->getNumChildren() == 1))
520
{
521
optDisabled = true;
522
}
523
else
524
{
525
fromRegLoad = true;
526
pointerReg = firstChild->getFirstChild()->getFirstChild()->getRegister();
527
}
528
}
529
// 64bit - TODO
530
else
531
optDisabled = true;
532
}
533
534
if (!optDisabled)
535
{
536
TR::Register *condReg = self()->allocateRegister(TR_CCR);
537
TR::Register *tempReg = self()->allocateRegister();
538
539
// 32 bit only.... For -Xgc:noconcurrentmark, heapBase will be 0 and heapTop will be ok
540
// Otherwise, for a 2.25Gb or bigger heap, heapTop will be 0. Relying on correct JIT initialization
541
uintptr_t heapTop = comp->getOptions()->getHeapTop() ? comp->getOptions()->getHeapTop() : 0xFFFFFFFF;
542
543
if (pointerReg && (heapTop > comp->getOptions()->getHeapBase())) // Check for gencon
544
{
545
TR::Register *temp3Reg = self()->allocateRegister();
546
static bool prefetch2Ahead = (feGetEnv("TR_Prefetch2Ahead") != NULL);
547
if (comp->target().is64Bit() && !comp->useCompressedPointers())
548
{
549
if (!prefetch2Ahead)
550
generateTrg1MemInstruction(self(), TR::InstOpCode::ld, node, temp3Reg, TR::MemoryReference::createWithDisplacement(self(), pointerReg, (int32_t)TR::Compiler->om.sizeofReferenceField(), 8));
551
else
552
generateTrg1MemInstruction(self(), TR::InstOpCode::ld, node, temp3Reg, TR::MemoryReference::createWithDisplacement(self(), pointerReg, (int32_t)(TR::Compiler->om.sizeofReferenceField()*2), 8));
553
}
554
else
555
{
556
if (!prefetch2Ahead)
557
generateTrg1MemInstruction(self(), TR::InstOpCode::lwz, node, temp3Reg, TR::MemoryReference::createWithDisplacement(self(), pointerReg, (int32_t)TR::Compiler->om.sizeofReferenceField(), 4));
558
else
559
generateTrg1MemInstruction(self(), TR::InstOpCode::lwz, node, temp3Reg, TR::MemoryReference::createWithDisplacement(self(), pointerReg, (int32_t)(TR::Compiler->om.sizeofReferenceField()*2), 4));
560
}
561
562
if (comp->getOptions()->getHeapBase() != NULL)
563
{
564
loadAddressConstant(self(), comp->compileRelocatableCode(), node, (intptr_t)(comp->getOptions()->getHeapBase()), tempReg);
565
generateTrg1Src2Instruction(self(), TR::InstOpCode::cmpl4, node, condReg, temp3Reg, tempReg);
566
generateConditionalBranchInstruction(self(), TR::InstOpCode::blt, node, endCtrlFlowLabel, condReg);
567
}
568
if (heapTop != 0xFFFFFFFF)
569
{
570
loadAddressConstant(self(), comp->compileRelocatableCode(), node, (intptr_t)(heapTop-prefetchOffset), tempReg);
571
generateTrg1Src2Instruction(self(), TR::InstOpCode::cmpl4, node, condReg, temp3Reg, tempReg);
572
generateConditionalBranchInstruction(self(), TR::InstOpCode::bgt, node, endCtrlFlowLabel, condReg);
573
}
574
TR::MemoryReference *targetMR = TR::MemoryReference::createWithDisplacement(self(), temp3Reg, (int32_t)0, 4);
575
targetMR->forceIndexedForm(node, self());
576
generateMemInstruction(self(), TR::InstOpCode::dcbt, node, targetMR); // use dcbt for prefetch next element
577
578
self()->stopUsingRegister(temp3Reg);
579
}
580
581
if (!fromRegLoad)
582
self()->stopUsingRegister(pointerReg);
583
self()->stopUsingRegister(tempReg);
584
self()->stopUsingRegister(condReg);
585
}
586
generateLabelInstruction(self(), TR::InstOpCode::label, node, endCtrlFlowLabel);
587
}
588
589
// Try prefetch all string objects, no apparent gain. Disabled for now.
590
if (!disableStringObjPrefetch && 0 &&
591
node->getSymbolReference() &&
592
!node->getSymbolReference()->isUnresolved() &&
593
(node->getSymbolReference()->getSymbol()->getKind() == TR::Symbol::IsShadow) &&
594
(node->getSymbolReference()->getCPIndex() >= 0))
595
{
596
int32_t len;
597
const char *fieldName = node->getSymbolReference()->getOwningMethod(comp)->fieldSignatureChars(
598
node->getSymbolReference()->getCPIndex(), len);
599
600
if (fieldName && strstr(fieldName, "Ljava/lang/String;"))
601
{
602
TR::MemoryReference *targetMR = TR::MemoryReference::createWithDisplacement(self(), targetRegister, (int32_t)0, 4);
603
targetMR->forceIndexedForm(node, self());
604
generateMemInstruction(self(), TR::InstOpCode::dcbt, node, targetMR);
605
}
606
}
607
}
608
609
if ((node->getOpCodeValue() == TR::aloadi && !comp->target().is64Bit()) ||
610
(comp->target().is64Bit() &&
611
comp->useCompressedPointers() &&
612
(node->getOpCodeValue() == TR::iloadi || node->getOpCodeValue() == TR::irdbari) &&
613
comp->getMethodHotness() >= hot))
614
{
615
TR::Node *firstChild = node->getFirstChild();
616
optDisabled = disableIteratorPrefetch;
617
if (!disableIteratorPrefetch)
618
{
619
// 32bit
620
if (comp->target().is32Bit())
621
{
622
if (!(firstChild &&
623
firstChild->getOpCodeValue() == TR::aiadd &&
624
firstChild->isInternalPointer() &&
625
(strstr(comp->fe()->sampleSignature(node->getOwningMethod(), 0, 0, self()->trMemory()),"java/util/TreeMap$UnboundedValueIterator.next()")
626
|| strstr(comp->fe()->sampleSignature(node->getOwningMethod(), 0, 0, self()->trMemory()),"java/util/ArrayList$Itr.next()"))
627
))
628
{
629
optDisabled = true;
630
}
631
}
632
// 64bit cr
633
else if (comp->target().is64Bit() && comp->useCompressedPointers())
634
{
635
if (!(firstChild &&
636
firstChild->getOpCodeValue() == TR::aladd &&
637
firstChild->isInternalPointer() &&
638
(strstr(comp->fe()->sampleSignature(node->getOwningMethod(), 0, 0, self()->trMemory()),"java/util/TreeMap$UnboundedValueIterator.next()")
639
|| strstr(comp->fe()->sampleSignature(node->getOwningMethod(), 0, 0, self()->trMemory()),"java/util/ArrayList$Itr.next()"))
640
))
641
{
642
optDisabled = true;
643
}
644
}
645
}
646
647
// The use of this prefetching can cause a SEGV when the object array is allocated at the every end of the heap.
648
// The GC will protected against the SEGV by adding a "tail-padding" page, but only when -XAggressive is enabled!
649
if (!optDisabled && comp->getOption(TR_AggressiveOpts))
650
{
651
int32_t loopSize = 0;
652
int32_t prefetchElementStride = 1;
653
TR::Block *b = self()->getCurrentEvaluationBlock();
654
TR_BlockStructure *blockStructure = b->getStructureOf();
655
if (blockStructure)
656
{
657
TR_Structure *containingLoop = blockStructure->getContainingLoop();
658
if (containingLoop)
659
{
660
TR_ScratchList<TR::Block> blocksInLoop(comp->trMemory());
661
662
containingLoop->getBlocks(&blocksInLoop);
663
ListIterator<TR::Block> blocksIt(&blocksInLoop);
664
TR::Block *nextBlock;
665
for (nextBlock = blocksIt.getCurrent(); nextBlock; nextBlock=blocksIt.getNext())
666
{
667
loopSize += nextBlock->getNumberOfRealTreeTops();
668
}
669
}
670
}
671
672
if (comp->useCompressedPointers())
673
{
674
prefetchElementStride = 2;
675
}
676
else
677
{
678
if (loopSize < 200) //comp->useCompressedPointers() is false && loopSize < 200.
679
{
680
prefetchElementStride = 4;
681
}
682
else if (loopSize < 300) //comp->useCompressedPointers() is false && loopsize >=200 && loopsize < 300.
683
{
684
prefetchElementStride = 2;
685
}
686
//If comp->useCompressedPointers() is false and loopsize >= 300, prefetchElementStride does not get changed.
687
}
688
689
// Look at the aiadd's children
690
TR::Node *baseObject = firstChild->getFirstChild();
691
TR::Register *baseReg = (baseObject) ? baseObject->getRegister() : NULL;
692
TR::Node *indexObject = firstChild->getSecondChild();
693
TR::Register *indexReg = (indexObject) ? indexObject->getRegister() : NULL;
694
if (baseReg && indexReg && loopSize > 0)
695
{
696
TR::Register *tempReg = self()->allocateRegister();
697
generateTrg1Src1ImmInstruction(self(), TR::InstOpCode::addi, node, tempReg, indexReg, prefetchElementStride * TR::Compiler->om.sizeofReferenceField());
698
if (comp->target().is64Bit() && !comp->useCompressedPointers())
699
{
700
TR::MemoryReference *targetMR = TR::MemoryReference::createWithIndexReg(self(), baseReg, tempReg, 8);
701
generateTrg1MemInstruction(self(), TR::InstOpCode::ld, node, tempReg, targetMR);
702
}
703
else
704
{
705
TR::MemoryReference *targetMR = TR::MemoryReference::createWithIndexReg(self(), baseReg, tempReg, 4);
706
generateTrg1MemInstruction(self(), TR::InstOpCode::lwz, node, tempReg, targetMR);
707
}
708
709
if (comp->useCompressedPointers())
710
{
711
generateShiftLeftImmediateLong(self(), node, tempReg, tempReg, TR::Compiler->om.compressedReferenceShiftOffset());
712
}
713
TR::MemoryReference *target2MR = TR::MemoryReference::createWithDisplacement(self(), tempReg, 0, 4);
714
target2MR->forceIndexedForm(node, self());
715
generateMemInstruction(self(), TR::InstOpCode::dcbt, node, target2MR);
716
self()->stopUsingRegister(tempReg);
717
}
718
}
719
}
720
else if (node->getOpCodeValue() == TR::awrtbari &&
721
comp->getMethodHotness() >= scorching &&
722
comp->target().cpu.isAtLeast(OMR_PROCESSOR_PPC_P6) &&
723
(comp->target().is32Bit() ||
724
(comp->target().is64Bit() &&
725
comp->useCompressedPointers() &&
726
TR::Compiler->om.compressedReferenceShiftOffset() == 0
727
)
728
)
729
)
730
{
731
// Take the source register of the store and apply on the prefetchOffset right away
732
int32_t prefetchOffset = comp->findPrefetchInfo(node);
733
if (prefetchOffset >= 0)
734
{
735
TR::MemoryReference *targetMR = TR::MemoryReference::createWithDisplacement(self(), targetRegister, prefetchOffset, TR::Compiler->om.sizeofReferenceAddress());
736
targetMR->forceIndexedForm(node, self());
737
generateMemInstruction(self(), TR::InstOpCode::dcbt, node, targetMR);
738
}
739
}
740
}
741
742
TR::Linkage *
743
J9::Power::CodeGenerator::deriveCallingLinkage(TR::Node *node, bool isIndirect)
744
{
745
TR::SymbolReference *symRef = node->getSymbolReference();
746
TR::MethodSymbol *callee = symRef->getSymbol()->castToMethodSymbol();
747
TR_J9VMBase *fej9 = (TR_J9VMBase *)(self()->fe());
748
749
static char * disableDirectNativeCall = feGetEnv("TR_DisableDirectNativeCall");
750
751
// Clean-up: the fej9 checking seemed unnecessary
752
if (!isIndirect && callee->isJNI() && fej9->canRelocateDirectNativeCalls() &&
753
(node->isPreparedForDirectJNI() ||
754
(disableDirectNativeCall == NULL && callee->getResolvedMethodSymbol()->canDirectNativeCall())))
755
return self()->getLinkage(TR_J9JNILinkage);
756
757
return self()->getLinkage(callee->getLinkageConvention());
758
}
759
760