Path: blob/master/runtime/compiler/ilgen/J9ByteCodeIlGenerator.hpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2022 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#ifndef IlGenerator_h23#define IlGenerator_h2425#include "ilgen/J9ByteCodeIteratorWithState.hpp"2627#include "env/CompilerEnv.hpp"28#include "env/ExceptionTable.hpp"29#include "env/jittypes.h"30#include "il/Block.hpp"31#include "il/Node.hpp"32#include "il/SymbolReference.hpp"33#include "ilgen/IlGen.hpp"34#include "infra/Checklist.hpp"35#include "infra/Link.hpp"36#include "infra/Stack.hpp"37#include "env/VMJ9.h"3839class TR_InlineBlocks;40class TR_PersistentClassInfo;41class TR_BitVector;42namespace TR { class IlGeneratorMethodDetails; }4344class TR_J9ByteCodeIlGenerator : public TR_IlGenerator, public TR_J9ByteCodeIteratorWithState45{46public:47TR_J9ByteCodeIlGenerator(TR::IlGeneratorMethodDetails & details,48TR::ResolvedMethodSymbol *,49TR_J9VMBase *fe,50TR::Compilation *,51TR::SymbolReferenceTable *,52bool forceClassLookahead = false,53TR_InlineBlocks *blocksToInline=0,54int32_t argPlaceholderSlot=-1);5556TR_ALLOC(TR_Memory::IlGenerator)5758TR::CodeGenerator * cg() { return _compilation->cg(); }59TR::Compilation * comp() { return _compilation; }60TR_J9VMBase * fej9() { return (TR_J9VMBase *)_fe; }6162TR_Memory * trMemory() { return _trMemory; }63TR_StackMemory trStackMemory() { return _trMemory; }64TR_HeapMemory trHeapMemory() { return _trMemory; }65TR_PersistentMemory * trPersistentMemory() { return _trMemory->trPersistentMemory(); }6667TR::IlGeneratorMethodDetails & methodDetails() { return _methodDetails; }6869virtual bool genIL();70virtual int32_t currentByteCodeIndex() { return TR_J9ByteCodeIterator::currentByteCodeIndex(); }71virtual TR::Block * getCurrentBlock() { return _block; }7273virtual void performClassLookahead(TR_PersistentClassInfo *);7475bool isPeekingMethod() { return _compilation->isPeekingMethod();}76bool inliningCheckIfFinalizeObjectIsBeneficial()77{78return (comp()->getOption(TR_FullSpeedDebug) || comp()->getOptLevel() <= cold ||79(!comp()->getOption(TR_DisableInlineCheckIfFinalizeObject) && fej9()->isBenefitInliningCheckIfFinalizeObject()) ||80(comp()->getCurrentMethod()->isConstructor() && !comp()->getCurrentMethod()->isFinal()));81}82virtual TR::ResolvedMethodSymbol *methodSymbol() const { return _methodSymbol;}8384private:8586bool trace(){ return comp()->getOption(TR_TraceBC) || comp()->getOption(TR_TraceILGen); }8788virtual void saveStack(int32_t);89void saveStack(int32_t targetIndex, bool anchorLoads);9091// GenBranch92//93int32_t genGoto(int32_t);94int32_t genIfOneOperand(TR::ILOpCodes);95int32_t genIfTwoOperand(TR::ILOpCodes);96int32_t genIfAcmpEqNe(TR::ILOpCodes);97int32_t genIfImpl(TR::ILOpCodes);9899/** \brief100* Generates IL for a return bytecode.101*102* \param nodeop103* The IL opcode to use for the return.104*105* \param monitorExit106* Determines whether the method which contains this return is synchronized in which case <c>TR::monitorExit</c>107* nodes may need to be generated.108*109* \return110* The index of the next bytecode to generate.111*/112int32_t genReturn(TR::ILOpCodes nodeop, bool monitorExit);113114int32_t genLookupSwitch();115int32_t genTableSwitch();116117// GenCall118//119void genInvokeStatic(int32_t);120void genInvokeSpecial(int32_t);121void genInvokeVirtual(int32_t);122void genInvokeInterface(int32_t);123void genInvokeDynamic(int32_t callSiteIndex);124TR::Node * genInvokeHandle(int32_t cpIndex);125TR::Node * genInvokeHandleGeneric(int32_t cpIndex);126#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)127/**128* \brief129* Generates IL to load elements from invokeCacheArray, resulting in load of130* appendix and memberName objects into the stack to be used as131* parameters for adapter method call node. memberName object is only required132* to be loaded when the invokedynamic/invokehandle is unresolved133*134* \param tableEntrySymRef the symref representing the invokeCacheArray135* \param invokeCacheArray the static address of the invokeCacheArray136* \param isUnresolved137*/138void loadInvokeCacheArrayElements(TR::SymbolReference *tableEntrySymRef, uintptr_t * invokeCacheArray, bool isUnresolved);139#endif140141TR::Node * genHandleTypeCheck(TR::Node *handle, TR::Node *expectedType);142143TR::Node * genInvokeHandle(TR::SymbolReference *invokeExactSymRef, TR::Node *invokedynamicReceiver = NULL);144TR::Node * genILGenMacroInvokeExact(TR::SymbolReference *invokeExactSymRef);145146bool runMacro(TR::SymbolReference *);147bool runFEMacro(TR::SymbolReference *);148TR::Node * genInvoke(TR::SymbolReference *, TR::Node *indirectCallFirstChild, TR::Node *invokedynamicReceiver = NULL);149150TR::Node * genInvokeDirect(TR::SymbolReference *symRef){ return genInvoke(symRef, NULL); }151TR::Node * genInvokeWithVFTChild(TR::SymbolReference *);152TR::Node * getReceiverFor(TR::SymbolReference *);153void stashArgumentsForOSR(TR_J9ByteCode byteCode);154/** \brief155* Tell if the current bytecode is at start of a basic block156*/157bool isAtBBStart(int32_t bcIndex);158159// Placeholder manipulation160//161void genArgPlaceholderCall();162int32_t expandPlaceholderCall(); // TODO:JSR292: Combine these into a single function?163int32_t numPlaceholderCalls(int32_t depthLimit);164int32_t expandPlaceholderCalls(int32_t depthLimit);165TR::SymbolReference *expandPlaceholderSignature(TR::SymbolReference *symRef, int32_t numArgs);166TR::SymbolReference *expandPlaceholderSignature(TR::SymbolReference *symRef, int32_t numArgs, int32_t firstArgStackDepth);167TR::SymbolReference *placeholderWithDummySignature();168TR::SymbolReference *placeholderWithSignature(char *prefix, int prefixLength, char *middle, int middleLength, char *suffix, int suffixLength);169170void chopPlaceholder(TR::Node *placeholder, int32_t firstChild, int32_t numChildren);171172char *artificialSignature (TR_AllocationKind alloc, char *format, ...);173char *vartificialSignature(TR_AllocationKind alloc, char *format, va_list args);174TR::SymbolReference *symRefWithArtificialSignature(TR::SymbolReference *original, char *effectiveSigFormat, ...);175176// GenLoadStore177//178void loadInstance(int32_t);179void loadInstance(TR::SymbolReference *);180void loadFlattenableInstance(int32_t);181void loadFlattenableInstanceWithHelper(int32_t cpIndex);182void loadStatic(int32_t);183void loadAuto(TR::DataType type, int32_t slot, bool isAdjunct = false);184TR::Node *loadSymbol(TR::ILOpCodes, TR::SymbolReference *);185void loadConstant(TR::ILOpCodes, int32_t);186void loadConstant(TR::ILOpCodes, int64_t);187void loadConstant(TR::ILOpCodes, float);188void loadConstant(TR::ILOpCodes, double);189void loadConstant(TR::ILOpCodes, void *);190void loadFromCP(TR::DataType, int32_t);191void loadFromCallSiteTable(int32_t);192193void loadClassObjectAndIndirect(int32_t cpIndex);194195void loadClassObject(int32_t cpIndex);196TR::SymbolReference *loadClassObjectForTypeTest(int32_t cpIndex, TR_CompilationOptions aotInhibit);197void loadClassObject(TR_OpaqueClassBlock *opaqueClass);198void loadArrayElement(TR::DataType dt){ loadArrayElement(dt, comp()->il.opCodeForIndirectArrayLoad(dt)); }199void loadArrayElement(TR::DataType dt, TR::ILOpCodes opCode, bool checks = true, bool mayBeValueType = true);200void loadMonitorArg();201202void storeInstance(int32_t);203void storeInstance(TR::SymbolReference *);204void storeFlattenableInstance(int32_t);205void storeFlattenableInstanceWithHelper(int32_t);206void storeStatic(int32_t);207void storeAuto(TR::DataType type, int32_t slot, bool isAdjunct = false);208void storeArrayElement(TR::DataType dt){ storeArrayElement(dt, comp()->il.opCodeForIndirectArrayStore(dt)); }209void storeArrayElement(TR::DataType dt, TR::ILOpCodes opCode, bool checks = true);210211void calculateElementAddressInContiguousArray(int32_t, int32_t);212void calculateIndexFromOffsetInContiguousArray(int32_t, int32_t);213void calculateArrayElementAddress(TR::DataType, bool checks);214215// GenMisc216//217TR::TreeTop * genTreeTop(TR::Node *);218219TR::Node * loadConstantValueIfPossible(TR::Node *, uintptr_t, TR::DataType type = TR::Int32, bool isArrayLength = true);220221void genArrayLength();222void genContiguousArrayLength(int32_t width);223void genArrayBoundsCheck(TR::Node *, int32_t);224void genDivCheck();225void genIDiv();226void genLDiv();227void genIRem();228void genLRem();229TR::Node * genNullCheck(TR::Node *);230TR::Node * genResolveCheck(TR::Node *);231TR::Node * genResolveAndNullCheck(TR::Node *);232void genInc();233void genIncLong();234void genAsyncCheck();235void genNew(int32_t cpIndex);236void genNew(TR::ILOpCodes opCode=TR::New);237void genNewArray(int32_t typeIndex);238void genANewArray(int32_t cpIndex);239void genANewArray();240void genMultiANewArray(int32_t cpIndex, int32_t dims);241void genMultiANewArray(int32_t dims);242void genInstanceof(int32_t cpIndex);243void genCheckCast(int32_t);244void genCheckCast();245int32_t genAThrow();246void genMonitorEnter();247void genMonitorExit(bool);248TR_OpaqueClassBlock *loadValueClass(int32_t classCpIndex);249void genAconst_init(uint16_t classCpIndex);250void genAconst_init(TR_OpaqueClassBlock *valueTypeClass);251void genWithField(uint16_t fieldCpIndex);252void genWithField(TR::SymbolReference *, TR_OpaqueClassBlock *);253void genFlattenableWithField(uint16_t, TR_OpaqueClassBlock *);254void genFlattenableWithFieldWithHelper(uint16_t fieldCpIndex);255void genFlush(int32_t nargs);256void genFullFence(TR::Node *node);257void handlePendingPushSaveSideEffects(TR::Node *, int32_t stackSize = -1);258void handlePendingPushSaveSideEffects(TR::Node *, TR::NodeChecklist&, int32_t stackSize = -1);259void handleSideEffect(TR::Node *);260bool valueMayBeModified(TR::Node *, TR::Node *);261TR::Node * genCompressedRefs(TR::Node *, bool genTT = true, int32_t isLoad = 1);262void abortForUnresolvedValueTypeOp(const char* bytecodeName, const char* refType);263264// IlGenerator265//266bool internalGenIL();267bool genILFromByteCodes();268269void prependEntryCode(TR::Block *);270void prependGuardedCountForRecompilation(TR::Block * firstBlock);271TR::Node * genMethodEnterHook();272TR::Block * genExceptionHandlers(TR::Block *);273TR::Block * cloneHandler(TryCatchInfo *, TR::Block *, TR::Block *, TR::Block *, List<TR::Block> *);274void createGeneratedFirstBlock();275bool genJNIIL();276bool genNewInstanceImplThunk();277void genJavaLangSystemIdentityHashCode();278void genHWOptimizedStrProcessingAvailable();279void genJITIntrinsicsEnabled();280void genIsORBDeepCopyAvailable();281282TR::Node *genNewInstanceImplCall(TR::Node *classNode);283//TR::Node * transformNewInstanceImplCall(TR::TreeTop *, TR::Node *);284285// Dynamic Loop Transfer286void genDLTransfer(TR::Block *);287288// OSR289void stashPendingPushLivenessForOSR(int32_t offset = 0);290291void inlineJitCheckIfFinalizeObject(TR::Block *);292293// support for dual symbols, to generate adjunct symbol of the dual294TR::Node* genOrFindAdjunct(TR::Node* node);295void storeDualAuto(TR::Node * storeValue, int32_t slot);296297// Walker298//299TR::Block * walker(TR::Block *);300301int32_t cmp(TR::ILOpCodes, TR::ILOpCodes *, int32_t &);302int32_t cmpFollowedByIf(uint8_t, TR::ILOpCodes, int32_t &);303304// [PR 101228] To avoid class resolution on (null instanceof T) and (T)null.305void expandUnresolvedClassCheckcast(TR::TreeTop *tree);306void expandUnresolvedClassInstanceof(TR::TreeTop *tree);307308// [PR 124693] To check types on invokespecial within interface methods.309bool skipInvokeSpecialInterfaceTypeChecks();310void expandInvokeSpecialInterface(TR::TreeTop *tree);311312// Expand MethodHandle invoke313void expandInvokeHandle(TR::TreeTop *tree);314void expandInvokeExact(TR::TreeTop *tree);315void expandInvokeDynamic(TR::TreeTop *tree);316void expandInvokeHandleGeneric(TR::TreeTop *tree);317void expandMethodHandleInvokeCall(TR::TreeTop *tree);318void insertCustomizationLogicTreeIfEnabled(TR::TreeTop *tree, TR::Node* methodHandle);319TR::Node* loadCallSiteMethodTypeFromCP(TR::Node* methodHandleInvokeCall);320TR::Node* loadFromMethodTypeTable(TR::Node* methodHandleInvokeCall);321TR::Node* loadCallSiteMethodType(TR::Node* methodHandleInvokeCall);322323// inline functions324//325TR::SymbolReferenceTable * symRefTab() { return _symRefTab; }326TR::CFG * cfg() { return _methodSymbol->getFlowGraph(); }327bool isOutermostMethod() { return comp()->isOutermostMethod(); }328329bool swapChildren(TR::ILOpCodes, TR::Node *);330void removeIfNotOnStack(TR::Node *n);331void popAndDiscard(int n);332void discardEntireStack();333void startCountingStackRefs();334void stopCountingStackRefs();335void eat1()336{337popAndDiscard(1);338}339void eat2()340{341bool narrow = numberOfByteCodeStackSlots(node(_stack->topIndex())) == 4;342popAndDiscard(narrow ? 2 : 1);343}344345bool fieldsAreSame(TR::SymbolReference * s1, TR::SymbolReference * s2)346{347//bool sigSame = true;348//return s1->getOwningMethod(_compilation)->fieldsAreSame(s1->getCPIndex(), s2->getOwningMethod(_compilation), s2->getCPIndex(), sigSame);349return TR::Compiler->cls.jitFieldsAreSame(_compilation, s1->getOwningMethod(_compilation), s1->getCPIndex(), s2->getOwningMethod(_compilation), s2->getCPIndex(), false);350}351352bool staticsAreSame(TR::SymbolReference * s1, TR::SymbolReference * s2)353{354//bool sigSame = true;355//return s1->getOwningMethod(_compilation)->staticsAreSame(s1->getCPIndex(), s2->getOwningMethod(_compilation), s2->getCPIndex(), sigSame);356return TR::Compiler->cls.jitStaticsAreSame(_compilation, s1->getOwningMethod(_compilation), s1->getCPIndex(), s2->getOwningMethod(_compilation), s2->getCPIndex());357}358359TR::Node * genNodeAndPopChildren(TR::ILOpCodes, int32_t, TR::SymbolReference *, int32_t = 0);360TR::Node * genNodeAndPopChildren(TR::ILOpCodes, int32_t, TR::SymbolReference *, int32_t firstIndex, int32_t lastIndex);361362void genUnary(TR::ILOpCodes unaryOp, bool isForArrayAccess= false);363void genBinary(TR::ILOpCodes nodeop, int numChildren = 2);364365bool replaceMembersOfFormat();366bool replaceMethods(TR::TreeTop *tt, TR::Node *node);367bool replaceFieldsAndStatics(TR::TreeTop *tt, TR::Node *node);368bool replaceField(TR::Node* node, char* destClass, char* destFieldName, char* destFieldSignature, int ParmIndex);369bool replaceStatic(TR::Node* node, char* dstClassName, char* staticName, char* type);370371uintptr_t walkReferenceChain(TR::Node *node, uintptr_t receiver);372#if defined(J9VM_OPT_JITSERVER)373void packReferenceChainOffsets(TR::Node *node, std::vector<uintptr_t>& listOfOffsets);374#endif375376bool hasFPU();377378// data379//380TR::SymbolReferenceTable * _symRefTab;381TR::SymbolReferenceTable * _classLookaheadSymRefTab;382int32_t _firstTempCookie;383TR_PersistentClassInfo * _classInfo;384TR_ScratchList<TR::Node> _implicitMonitorExits;385TR_ScratchList<TR::Node> _finalizeCallsBeforeReturns;386TR::IlGeneratorMethodDetails &_methodDetails;387388// TAROK only. Suppress spine check trees. This is a debug feature only and will be389// removed when full support is available.390//391bool _suppressSpineChecks;392393bool _generateWriteBarriersForGC;394bool _generateWriteBarriersForFieldWatch;395bool _generateReadBarriersForFieldWatch;396vcount_t _blockAddedVisitCount;397bool _noLookahead;398bool _thisChanged;399TR_InlineBlocks *_blocksToInline;400bool _intrinsicErrorHandling;401bool _couldOSRAtNextBC;402403// JSR292404int32_t _argPlaceholderSlot;405int32_t _argPlaceholderSignatureOffset;406TR_BitVector *_methodHandleInvokeCalls;407TR_BitVector *_invokeHandleCalls;408TR_BitVector *_invokeHandleGenericCalls;409TR_BitVector *_invokeDynamicCalls;410TR_BitVector *_ilGenMacroInvokeExactCalls;411412// TenantScope field support, set to 'true' if a get/put static is encountered413// when option TR_DisableMultiTenancy is on and current method contains static414// field and method reference/invoke, skip compilation for such method415bool _staticFieldReferenceEncountered;416bool _staticMethodInvokeEncountered;417418TR_OpaqueClassBlock *_invokeSpecialInterface;419TR_BitVector *_invokeSpecialInterfaceCalls;420bool _invokeSpecialSeen;421422// OSR423TR::NodeChecklist *_processedOSRNodes;424425// DecimalFormatPeephole426struct methodRenamePair{427char* srcMethodSignature;428char* dstMethodSignature;429};430431static const int32_t _numDecFormatRenames = 9;432static struct methodRenamePair _decFormatRenames[_numDecFormatRenames];433TR::SymbolReference *_decFormatRenamesDstSymRef[_numDecFormatRenames];434};435436#endif437438439