-
Notifications
You must be signed in to change notification settings - Fork 747
/
Copy pathJ9CodeGenerator.hpp
740 lines (583 loc) · 29.6 KB
/
J9CodeGenerator.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
/*******************************************************************************
* Copyright IBM Corp. and others 2000
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] https://openjdk.org/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 OR GPL-2.0-only WITH OpenJDK-assembly-exception-1.0
*******************************************************************************/
#ifndef J9_CODEGENERATOR_INCL
#define J9_CODEGENERATOR_INCL
/*
* The following #define and typedef must appear before any #includes in this file
*/
#ifndef J9_CODEGENERATOR_CONNECTOR
#define J9_CODEGENERATOR_CONNECTOR
namespace J9 { class CodeGenerator; }
namespace J9 { typedef J9::CodeGenerator CodeGeneratorConnector; }
#endif
#include "codegen/OMRCodeGenerator.hpp"
#include <stdint.h>
#include "env/IO.hpp"
#include "env/jittypes.h"
#include "infra/List.hpp"
#include "infra/HashTab.hpp"
#include "codegen/RecognizedMethods.hpp"
#if defined(J9VM_OPT_JITSERVER)
#include "control/CompilationRuntime.hpp"
#endif /* defined(J9VM_OPT_JITSERVER) */
#include "control/Recompilation.hpp"
#include "control/RecompilationInfo.hpp"
#include "optimizer/Dominators.hpp"
class NVVMIRBuffer;
class TR_BitVector;
class TR_SharedMemoryAnnotations;
class TR_J9VMBase;
namespace TR { class Block; }
namespace TR { class Node; }
namespace TR { class SymbolReference; }
namespace TR { class TreeTop; }
namespace J9
{
class OMR_EXTENSIBLE CodeGenerator : public OMR::CodeGeneratorConnector
{
protected:
CodeGenerator(TR::Compilation *comp);
public:
void initialize();
TR_J9VMBase *fej9();
TR::TreeTop *lowerTree(TR::Node *root, TR::TreeTop *treeTop);
void preLowerTrees();
void lowerTreesPreTreeTopVisit(TR::TreeTop *tt, vcount_t visitCount);
void lowerTreesPreChildrenVisit(TR::Node * parent, TR::TreeTop * treeTop, vcount_t visitCount);
void lowerTreeIfNeeded(TR::Node *node, int32_t childNumber, TR::Node *parent, TR::TreeTop *tt);
void lowerDualOperator(TR::Node *parent, int32_t childNumber, TR::TreeTop *treeTop);
public:
bool collectSymRefs(TR::Node *node, TR_BitVector *symRefs, vcount_t secondVisitCount);
void moveUpArrayLengthStores(TR::TreeTop *insertionPoint);
void doInstructionSelection();
void createReferenceReadBarrier(TR::TreeTop* treeTop, TR::Node* parent);
TR::list<TR_Pair<TR_ResolvedMethod,TR::Instruction> *> &getJNICallSites() { return _jniCallSites; } // registerAssumptions()
// OSR, not code generator
void populateOSRBuffer();
void lowerCompressedRefs(TR::TreeTop *, TR::Node*, vcount_t, TR_BitVector *);
void compressedReferenceRematerialization(); // J9
void rematerializeCompressedRefs(TR::SymbolReference * &, TR::TreeTop *, TR::Node*, int32_t, TR::Node*, vcount_t, List<TR::Node> *);
void anchorRematNodesIfNeeded(TR::Node*, TR::TreeTop *, List<TR::Node> *);
void yankCompressedRefs(TR::TreeTop *, TR::Node *, int32_t, TR::Node *, vcount_t, vcount_t);
void setUpForInstructionSelection();
void insertEpilogueYieldPoints();
void allocateLinkageRegisters();
void fixUpProfiledInterfaceGuardTest();
/**
* \brief
* This query is used by both fixUpProfiledInterfaceGuardTest (a codegen level optimization) and virtual guard evaluators
* to decide whether a NOP guard should be generated. It's used on all platforms and compilation phases so that the decision
* of generating VG NOPs is made in a consistent way.
*
* \param node
* the virtual guard node
*
* \return
* true if a NOP virtual guard should be generated. Otherwise, false.
*/
bool willGenerateNOPForVirtualGuard(TR::Node* node);
void zeroOutAutoOnEdge(TR::SymbolReference * liveAutoSym, TR::Block *block, TR::Block *succBlock, TR::list<TR::Block*> *newBlocks, TR_ScratchList<TR::Node> *fsdStores);
TR::Linkage *createLinkageForCompilation();
bool enableAESInHardwareTransformations() {return false;}
bool isMethodInAtomicLongGroup(TR::RecognizedMethod rm);
bool arithmeticNeedsLiteralFromPool(TR::Node *node) { return false; }
// OSR
//
TR::TreeTop* genSymRefStoreToArray(TR::Node* refNode, TR::Node* arrayAddressNode, TR::Node* firstOffset,
TR::Node* symRefLoad, int32_t secondOffset, TR::TreeTop* insertionPoint);
// --------------------------------------
// AOT Relocations
//
#if defined(J9VM_OPT_JITSERVER)
void addExternalRelocation(TR::Relocation *r, const char *generatingFileName, uintptr_t generatingLineNumber, TR::Node *node, TR::ExternalRelocationPositionRequest where = TR::ExternalRelocationAtBack);
void addExternalRelocation(TR::Relocation *r, TR::RelocationDebugInfo *info, TR::ExternalRelocationPositionRequest where = TR::ExternalRelocationAtBack);
#endif /* defined(J9VM_OPT_JITSERVER) */
void processRelocations();
//TR::ExternalRelocation
void addProjectSpecializedRelocation(uint8_t *location,
uint8_t *target,
uint8_t *target2, //pass in NULL when no target2
TR_ExternalRelocationTargetKind kind,
const char *generatingFileName,
uintptr_t generatingLineNumber,
TR::Node *node);
//TR::ExternalOrderedPair32BitRelocation
void addProjectSpecializedPairRelocation(uint8_t *location1,
uint8_t *location2,
uint8_t *target,
TR_ExternalRelocationTargetKind kind,
const char *generatingFileName,
uintptr_t generatingLineNumber,
TR::Node *node);
//TR::BeforeBinaryEncodingExternalRelocation
void addProjectSpecializedRelocation(TR::Instruction *instr,
uint8_t *target,
uint8_t *target2, //pass in NULL when no target2
TR_ExternalRelocationTargetKind kind,
const char *generatingFileName,
uintptr_t generatingLineNumber,
TR::Node *node);
bool needClassAndMethodPointerRelocations();
bool needRelocationsForLookupEvaluationData();
bool needRelocationsForStatics();
bool needRelocationsForHelpers();
bool needRelocationsForCurrentMethodPC();
bool needRelocationsForCurrentMethodStartPC();
#if defined(J9VM_OPT_JITSERVER)
bool needRelocationsForBodyInfoData();
bool needRelocationsForPersistentInfoData();
#endif /* defined(J9VM_OPT_JITSERVER) */
// ----------------------------------------
TR::Node *createOrFindClonedNode(TR::Node *node, int32_t numChildren);
void jitAddUnresolvedAddressMaterializationToPatchOnClassRedefinition(void *firstInstruction);
uint32_t getStackLimitOffset() {return _stackLimitOffsetInMetaData;}
uint32_t setStackLimitOffset(uint32_t o) {return (_stackLimitOffsetInMetaData = o);}
bool alwaysGeneratesAKnownCleanSign(TR::Node *node) { return false; } // no virt
bool alwaysGeneratesAKnownPositiveCleanSign(TR::Node *node) { return false; } // no virt
TR_RawBCDSignCode alwaysGeneratedSign(TR::Node *node) { return raw_bcd_sign_unknown; } // no virt
void swapChildrenIfNeeded(TR::Node *store, char *optDetails);
TR::AutomaticSymbol *allocateVariableSizeSymbol(int32_t size);
TR::SymbolReference *allocateVariableSizeSymRef(int32_t byteLength);
void pendingFreeVariableSizeSymRef(TR::SymbolReference *sym);
void freeVariableSizeSymRef(TR::SymbolReference *sym, bool freeAddressTakenSymbol=false);
void freeAllVariableSizeSymRefs();
TR::SymbolReference *getFreeVariableSizeSymRef(int byteLength);
void checkForUnfreedVariableSizeSymRefs();
bool allowGuardMerging();
void registerAssumptions();
void jitAddPicToPatchOnClassUnload(void *classPointer, void *addressToBePatched);
void jitAdd32BitPicToPatchOnClassUnload(void *classPointer, void *addressToBePatched);
void jitAddPicToPatchOnClassRedefinition(void *classPointer, void *addressToBePatched, bool unresolved = false);
void jitAdd32BitPicToPatchOnClassRedefinition(void *classPointer, void *addressToBePatched, bool unresolved = false);
void createHWPRecords();
void createStackAtlas();
// --------------------------------------------------------------------------
// GPU
//
static const int32_t GPUAlignment = 128;
uintptr_t objectLengthOffset();
uintptr_t objectHeaderInvariant();
enum GPUScopeType
{
naturalLoopScope = 0,
singleKernelScope = 1
};
enum GPUResult
{
GPUSuccess = 0,
GPUNullCheck = 1,
GPUBndCheck = 2,
GPUDivException = 3,
GPUInvalidProgram = 4,
GPUHelperError = 5,
GPULaunchError = 6,
GPUBadDevicePointer = 7
};
enum GPUAccessKind {None = 0, ReadAccess= 1, WriteAccess = 2, ReadWriteAccesses = 3};
class gpuMapElement
{
public:
TR_ALLOC(TR_Memory::CodeGenerator); // dummy
gpuMapElement() : _node(NULL), _hostSymRef(NULL), _hostSymRefTemp(NULL), _devSymRef(NULL), _hoistAccess(false), _elementSize(-1), _parmSlot(-1), _accessKind(None), _lhsAddrExpr(NULL), _rhsAddrExpr(NULL) {}
gpuMapElement(TR::Node *node, TR::SymbolReference *hostSymRef, int32_t elementSize, int32_t parmSlot)
:
_node(node), _hostSymRef(hostSymRef), _hostSymRefTemp(NULL), _devSymRef(NULL), _hoistAccess(false),
_elementSize(elementSize), _parmSlot(parmSlot), _accessKind(None), _lhsAddrExpr(NULL), _rhsAddrExpr(NULL) {}
TR::Node *_node;
TR::SymbolReference *_hostSymRef;
TR::SymbolReference *_hostSymRefTemp;
TR::SymbolReference *_devSymRef;
int32_t _elementSize;
int32_t _parmSlot;
uint32_t _accessKind;
bool _hoistAccess;
TR::Node *_rhsAddrExpr;
TR::Node *_lhsAddrExpr;
};
class gpuParameter
{
public:
TR_ALLOC(TR_Memory::CodeGenerator); // dummy
gpuParameter() : _hostSymRef(NULL), _parmSlot(-1) {}
gpuParameter(TR::SymbolReference *hostSymRef, int32_t parmSlot)
: _hostSymRef(hostSymRef), _parmSlot(parmSlot) {}
TR::SymbolReference *_hostSymRef;
int32_t _parmSlot;
};
CS2::ArrayOf<gpuMapElement, TR::Allocator> _gpuSymbolMap;
bool _gpuHasNullCheck;
bool _gpuHasBndCheck;
bool _gpuHasDivCheck;
scount_t _gpuNodeCount;
TR::Block *_gpuCurrentBlock;
TR::DataTypes _gpuReturnType;
TR_Dominators *_gpuPostDominators;
TR::Block *_gpuStartBlock;
uint64_t _gpuNeedNullCheckArguments_vector;
bool _gpuCanUseReadOnlyCache;
bool _gpuUseOldLdgCalls;
TR_BitVector *getLiveMonitors() {return _liveMonitors;}
TR_BitVector *setLiveMonitors(TR_BitVector *v) {return (_liveMonitors = v);}
public:
/*
* \brief
* Get the most abstract type the monitor may be operating on.
*
* \note
* java.lang.Object is only returned when the monitor object is of type java.lang.Object but not any subclasses
*/
TR_OpaqueClassBlock* getMonClass(TR::Node* monNode);
/*
* \brief
* Whether a monitor object is of value based class type or value type.
* This API checks if value based or value type is enabled first.
*
* \return
* TR_yes The monitor object is definitely value based class type or value type
* TR_no The monitor object is definitely not value based class type or value type
* TR_maybe It is unknown whether the monitor object is value based class type or value type
*/
TR_YesNoMaybe isMonitorValueBasedOrValueType(TR::Node* monNode);
protected:
typedef TR::typed_allocator<std::pair<const ncount_t , TR_OpaqueClassBlock*>, TR::Region &> MonitorMapAllocator;
typedef std::map<ncount_t , TR_OpaqueClassBlock *, std::less<ncount_t>, MonitorMapAllocator> MonitorTypeMap;
MonitorTypeMap _monitorMapping; // map global node index to monitor object class
void addMonClass(TR::Node* monNode, TR_OpaqueClassBlock* clazz);
private:
TR_HashTabInt _uncommonedNodes; // uncommoned nodes keyed by the original nodes
TR::list<TR::Node*> _nodesSpineCheckedList;
TR::list<TR_Pair<TR_ResolvedMethod, TR::Instruction> *> _jniCallSites; // list of instrutions representing direct jni call sites
uint16_t changeParmLoadsToRegLoads(TR::Node*node, TR::Node **regLoads, TR_BitVector *globalRegsWithRegLoad, TR_BitVector &killedParms, vcount_t visitCount); // returns number of RegLoad nodes created
uint32_t _stackLimitOffsetInMetaData;
/*
* Scratch data for refined aliasing walk during
*/
struct RefinedAliasWalkCollector
{
TR_PersistentMethodInfo *methodInfo;
bool killsEverything;
bool killsAddressStatics;
bool killsIntStatics;
bool killsNonIntPrimitiveStatics;
bool killsAddressFields;
bool killsIntFields;
bool killsNonIntPrimitiveFields;
bool killsAddressArrayShadows;
bool killsIntArrayShadows;
bool killsNonIntPrimitiveArrayShadows;
};
RefinedAliasWalkCollector _refinedAliasWalkCollector;
TR_BitVector *_liveMonitors;
protected:
// isTemporaryBased storageReferences just have a symRef but some other routines expect a node so use the below to fill in this symRef on this node
TR::Node *_dummyTempStorageRefNode;
public:
bool getSupportsBigDecimalLongLookasideVersioning() { return _flags3.testAny(SupportsBigDecimalLongLookasideVersioning);}
void setSupportsBigDecimalLongLookasideVersioning() { _flags3.set(SupportsBigDecimalLongLookasideVersioning);}
bool constLoadNeedsLiteralFromPool(TR::Node *node) { return false; }
// Java, likely Z
bool supportsTrapsInTMRegion() { return true; }
// J9
int32_t getInternalPtrMapBit() { return 31;}
// --------------------------------------------------------------------------
// GPU
//
void generateGPU();
void dumpInvariant(CS2::ArrayOf<gpuParameter, TR::Allocator>::Cursor pit, NVVMIRBuffer &ir, bool isbufferalign);
GPUResult dumpNVVMIR(TR::TreeTop *firstTreeTop, TR::TreeTop *lastTreeTop, TR_RegionStructure *loop, SharedSparseBitVector *blocksinLoop, ListBase<TR::AutomaticSymbol> *autos, ListBase<TR::ParameterSymbol> *parms, bool staticMethod, char * &nvvmIR, TR::Node * &errorNode, int gpuPtxCount, bool* hasExceptionChecks);
GPUResult printNVVMIR(NVVMIRBuffer &ir, TR::Node * node, TR_RegionStructure *loop, TR_BitVector *targetBlocks, vcount_t visitCount, TR_SharedMemoryAnnotations *sharedMemory, int32_t &nextParmNum, TR::Node * &errorNode);
void findExtraParms(TR::Node *node, int32_t &numExtraParms, TR_SharedMemoryAnnotations *sharedMemory, vcount_t visitCount);
bool handleRecognizedMethod(TR::Node *node, NVVMIRBuffer &ir, TR::Compilation *comp);
bool handleRecognizedField(TR::Node *node, NVVMIRBuffer &ir);
void printArrayCopyNVVMIR(TR::Node *node, NVVMIRBuffer &ir, TR::Compilation *comp);
bool hasFixedFrameC_CallingConvention() {return _j9Flags.testAny(HasFixedFrameC_CallingConvention);}
void setHasFixedFrameC_CallingConvention() {_j9Flags.set(HasFixedFrameC_CallingConvention);}
bool supportsJitMethodEntryAlignment();
/** \brief
* Determines whether the code generator supports inlining of java/lang/Class.isAssignableFrom
*/
bool supportsInliningOfIsAssignableFrom() { return false; } // no virt, default
/** \brief
* Determines whether the code generator must generate the switch to interpreter snippet in the preprologue.
*/
bool mustGenerateSwitchToInterpreterPrePrologue();
bool buildInterpreterEntryPoint() { return true; }
void generateCatchBlockBBStartPrologue(TR::Node *node, TR::Instruction *fenceInstruction);
bool supportsUnneededLabelRemoval() { return false; }
// Determines whether high-resolution timer can be used to implement java/lang/System.currentTimeMillis()
bool getSupportsMaxPrecisionMilliTime() {return _j9Flags.testAny(SupportsMaxPrecisionMilliTime);}
void setSupportsMaxPrecisionMilliTime() {_j9Flags.set(SupportsMaxPrecisionMilliTime);}
/** \brief
* Determines whether the code generator supports inlining of java/lang/String.toUpperCase() and toLowerCase()
*/
bool getSupportsInlineStringCaseConversion() { return _j9Flags.testAny(SupportsInlineStringCaseConversion);}
/** \brief
* The code generator supports inlining of java/lang/String.toUpperCase() and toLowerCase()
*/
void setSupportsInlineStringCaseConversion() { _j9Flags.set(SupportsInlineStringCaseConversion);}
/** \brief
* Determines whether the code generator supports inlining of java/lang/String.indexOf()
*/
bool getSupportsInlineStringIndexOf() { return _j9Flags.testAny(SupportsInlineStringIndexOf);}
/** \brief
* The code generator supports inlining of java/lang/String.indexOf()
*/
void setSupportsInlineStringIndexOf() { _j9Flags.set(SupportsInlineStringIndexOf);}
/** \brief
* Determines whether the code generator supports inlining of java/lang/String.hashCode()
*/
bool getSupportsInlineStringHashCode() { return _j9Flags.testAny(SupportsInlineStringHashCode); }
/** \brief
* The code generator supports inlining of java/lang/String.hashCode()
*/
void setSupportsInlineStringHashCode() { _j9Flags.set(SupportsInlineStringHashCode); }
/** \brief
* Determines whether the code generator supports inlining of java/lang/StringCoding.countPositives
*/
bool getSupportsInlineStringCodingCountPositives() { return _j9Flags.testAny(SupportsInlineStringCodingCountPositives); }
/** \brief
* The code generator supports inlining of java/lang/StringCoding.countPositives
*/
void setSupportsInlineStringCodingCountPositives() { _j9Flags.set(SupportsInlineStringCodingCountPositives); }
/** \brief
* Determines whether the code generator supports inlining of java/lang/StringCoding.hasNegatives
*/
bool getSupportsInlineStringCodingHasNegatives() { return _j9Flags.testAny(SupportsInlineStringCodingHasNegatives); }
/** \brief
* The code generator supports inlining of java/lang/StringCoding.hasNegatives
*/
void setSupportsInlineStringCodingHasNegatives() { _j9Flags.set(SupportsInlineStringCodingHasNegatives); }
/** \brief
* Determines whether the code generator supports inlining of java/lang/StringLatin1.inflate
*/
bool getSupportsInlineStringLatin1Inflate() { return _j9Flags.testAny(SupportsInlineStringLatin1Inflate); }
/** \brief
* The code generator supports inlining of java/lang/StringLatin1.inflate
*/
void setSupportsInlineStringLatin1Inflate() { _j9Flags.set(SupportsInlineStringLatin1Inflate); }
/** \brief
* Determines whether the code generator supports inlining of java_util_concurrent_ConcurrentLinkedQueue_tm*
* methods
*/
bool getSupportsInlineConcurrentLinkedQueue() { return _j9Flags.testAny(SupportsInlineConcurrentLinkedQueue); }
/** \brief
* The code generator supports inlining of java_util_concurrent_ConcurrentLinkedQueue_tm* methods
*/
void setSupportsInlineConcurrentLinkedQueue() { _j9Flags.set(SupportsInlineConcurrentLinkedQueue); }
/** \brief
* Determines whether the code generator supports inlining of java/lang/StringCoding.encodeASCII
*/
bool getSupportsInlineEncodeASCII() { return _j9Flags.testAny(SupportsInlineEncodeASCII); }
/** \brief
* The code generator supports inlining of java/lang/StringCoding.encodeASCII
*/
void setSupportsInlineEncodeASCII() { _j9Flags.set(SupportsInlineEncodeASCII); }
/** \brief
* Determines whether the code generator supports inlining of jdk/internal/util/ArraysSupport.vectorizedMismatch
*/
bool getSupportsInlineVectorizedMismatch() { return _j9Flags.testAny(SupportsInlineVectorizedMismatch); }
/** \brief
* The code generator supports inlining of jdk/internal/util/ArraysSupport.vectorizedMismatch
*/
void setSupportsInlineVectorizedMismatch() { _j9Flags.set(SupportsInlineVectorizedMismatch); }
/** \brief
* Determines whether the code generator supports inlining of jdk/internal/util/ArraysSupport.vectorizedHashCode
*/
bool getSupportsInlineVectorizedHashCode() { return _j9Flags.testAny(SupportsInlineVectorizedHashCode); }
/** \brief
* The code generator supports inlining of jdk/internal/util/ArraysSupport.vectorizedHashCode
*/
void setSupportsInlineVectorizedHashCode() { _j9Flags.set(SupportsInlineVectorizedHashCode); }
/** \brief
* Determines whether the code generator supports inlining of java_lang_Math_max/min_F/D
*/
bool getSupportsInlineMath_MaxMin_FD() { return _j9Flags.testAny(SupportsInlineMath_MaxMin_FD); }
/** \brief
* The code generator supports inlining of java_lang_Math_max/min_F/D
*/
void setSupportsInlineMath_MaxMin_FD() { _j9Flags.set(SupportsInlineMath_MaxMin_FD); }
/** \brief
* Determines whether the code generator supports inlining of jdk/internal/misc/Unsafe.CompareAndSet[Object|Reference|Int|Long]
*/
bool getSupportsInlineUnsafeCompareAndSet() { return _j9Flags.testAny(SupportsInlineUnsafeCompareAndSet); }
/** \brief
* The code generator supports inlining of jdk/internal/misc/Unsafe.CompareAndSet[Object|Reference|Int|Long]
*/
void setSupportsInlineUnsafeCompareAndSet() { _j9Flags.set(SupportsInlineUnsafeCompareAndSet); }
/** \brief
* Determines whether the code generator supports inlining of jdk/internal/misc/Unsafe.CompareAndExchange[Object|Reference|Int|Long]
*/
bool getSupportsInlineUnsafeCompareAndExchange() { return _j9Flags.testAny(SupportsInlineUnsafeCompareAndExchange); }
/** \brief
* The code generator supports inlining of jdk/internal/misc/Unsafe.CompareAndExchange[Object|Reference|Int|Long]
*/
void setSupportsInlineUnsafeCompareAndExchange() { _j9Flags.set(SupportsInlineUnsafeCompareAndExchange); }
/**
* \brief
* The number of nodes between a monext and the next monent before
* transforming a monitored region with transactional lock elision.
*/
int32_t getMinimumNumberOfNodesBetweenMonitorsForTLE() { return 15; }
/**
* \brief Trim the size of code memory required by this method to match the
* actual code length required, allowing the reclaimed memory to be
* reused. This is needed when the conservative length estimate
* exceeds the actual memory requirement.
*/
void trimCodeMemoryToActualSize();
/**
* \brief Request and reserve a CodeCache for use by this compilation. Fail
* the compilation appropriately if a CodeCache cannot be allocated.
*/
void reserveCodeCache();
/**
* \brief Allocates code memory of the specified size in the specified area of
* the code cache. Fail the compilation on failure.
*
* \param[in] warmCodeSizeInBytes : the number of bytes to allocate in the warm area
* \param[in] coldCodeSizeInBytes : the number of bytes to allocate in the cold area
* \param[out] coldCode : address of the cold code (if allocated)
* \param[in] isMethodHeaderNeeded : boolean indicating whether space for a
* method header must be allocated
*
* \return address of the allocated warm code (if allocated)
*/
uint8_t *allocateCodeMemoryInner(
uint32_t warmCodeSizeInBytes,
uint32_t coldCodeSizeInBytes,
uint8_t **coldCode,
bool isMethodHeaderNeeded);
/**
* \brief Store a poison value in an auto slot that should have gone dead. Used for debugging.
*
* \param[in] currentBlock : block in which the auto slot appears
* \param[in] liveAutoSymRef : SymbolReference of auto slot to poison
*
* \return poisoned store node
*/
TR::Node *generatePoisonNode(
TR::Block *currentBlock,
TR::SymbolReference *liveAutoSymRef);
/**
* \brief Determines whether VM Internal Natives is supported or not
*/
bool supportVMInternalNatives();
/**
* \brief Determines whether the code generator supports stack allocations
*/
bool supportsStackAllocations() { return false; }
/**
* \brief Initializes the Linkage Info word found before the interpreter entry point.
*
* \param[in] linkageInfo : pointer to the linkage info word
*
* \return Linkage Info word
*/
uint32_t initializeLinkageInfo(void *linkageInfoPtr);
/**
* \brief Check if a profiled class is compatible with the call site
*
* \param[in] profiledClass : The J9Class obtained from profiling data
* \param[in] callSiteMethodClass : The J9Class from the J9Method of the call site target
*
* \return True if it can be determined that the profiled class is compatible, otherwise False
*/
bool isProfiledClassAndCallSiteCompatible(TR_OpaqueClassBlock *profiledClass, TR_OpaqueClassBlock *callSiteMethodClass);
/** \brief
* Determines whether the code generator supports inlining of java/lang/Integer.stringSize() or java/lang/Long.stringSize()
*/
bool getSupportsIntegerStringSize() { return _j9Flags.testAny(SupportsIntegerStringSize); }
/** \brief
* The code generator supports inlining of java/lang/Integer.stringSize() or java/lang/Long.stringSize()
*/
void setSupportsIntegerStringSize() {_j9Flags.set(SupportsIntegerStringSize); }
/** \brief
* Determines whether the code generator supports inlining of
* - Integer.getChars,
* - Long.getChars,
* - StringUTF16.getChars(JI[B)I,
* - StringUTF16.getChars(II[B)I
*/
bool getSupportsIntegerToChars() { return _j9Flags.testAny(SupportsIntegerToChars); }
/** \brief
* The code generator supports inlining of
* - Integer.getChars,
* - Long.getChars,
* - StringUTF16.getChars(JI[B)I,
* - StringUTF16.getChars(II[B)I
*/
void setSupportsIntegerToChars() {_j9Flags.set(SupportsIntegerToChars); }
/**
* \brief Determine whether this code generator guarantees resolved direct
* dispatch under AOT with SVM.
*
* \return true if resolved direct dispatch is guaranteed, false otherwise
* \see TR_J9VMBase::isResolvedDirectDispatchGuaranteed
*/
bool guaranteesResolvedDirectDispatchForSVM() { return false; } // safe default
/**
* \brief Determine whether this code generator guarantees resolved virtual
* dispatch under AOT with SVM.
*
* \return true if resolved virtual dispatch is guaranteed, false otherwise
* \see TR_J9VMBase::isResolvedVirtualDispatchGuaranteed
*/
bool guaranteesResolvedVirtualDispatchForSVM() { return false; } // safe default
/** \brief
* Determines if this method is saving all Non Volatile registers for the GC
*/
bool getSavesNonVolatileGPRsForGC() { return _j9Flags.testAny(SavesNonVolatileGPRsForGC); }
/** \brief
* Set the flag specifying that this method is saving all Non Volatile registers for the GC
*/
void setSavesNonVolatileGPRsForGC() {_j9Flags.set(SavesNonVolatileGPRsForGC); }
/// Determine whether \c jitDispatchJ9Method is (supported and) enabled.
bool enableJitDispatchJ9Method();
/// Determine whether to stress the J2I path for \c jitDispatchJ9Method.
bool stressJitDispatchJ9MethodJ2I();
private:
enum // Flags
{
HasFixedFrameC_CallingConvention = 0x00000001,
SupportsMaxPrecisionMilliTime = 0x00000002,
SupportsInlineStringCaseConversion = 0x00000004, /*! codegen inlining of Java string case conversion */
SupportsInlineStringIndexOf = 0x00000008, /*! codegen inlining of Java string index of */
SupportsInlineStringHashCode = 0x00000010, /*! codegen inlining of Java string hash code */
SupportsInlineConcurrentLinkedQueue = 0x00000020,
SupportsBigDecimalLongLookasideVersioning = 0x00000040,
SupportsInlineStringLatin1Inflate = 0x00000080, /*! codegen inlining of Java StringLatin1.inflate */
SupportsIntegerStringSize = 0x00000100,
SupportsIntegerToChars = 0x00000200,
SupportsInlineEncodeASCII = 0x00000400,
SavesNonVolatileGPRsForGC = 0x00000800,
SupportsInlineVectorizedMismatch = 0x00001000,
SupportsInlineVectorizedHashCode = 0x00002000,
SupportsInlineStringCodingHasNegatives = 0x00004000,
SupportsInlineStringCodingCountPositives = 0x00008000,
SupportsInlineMath_MaxMin_FD = 0x00010000,
SupportsInlineUnsafeCompareAndSet = 0x00020000,
SupportsInlineUnsafeCompareAndExchange = 0x00040000,
};
flags32_t _j9Flags;
};
}
#endif