Path: blob/master/runtime/compiler/x/codegen/X86PrivateLinkage.hpp
6004 views
/*******************************************************************************1* Copyright (c) 2000, 2021 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 X86PRIVATELINKAGE_INCL23#define X86PRIVATELINKAGE_INCL2425#include "codegen/PrivateLinkage.hpp"2627#include "env/jittypes.h"28#include "codegen/RegisterDependency.hpp"29#include "x/codegen/X86Register.hpp"3031class TR_J2IThunk;32class TR_ResolvedMethod;33namespace TR { class Instruction; }3435//36// Hack markers37//3839// This is an overkill way to make sure the preconditions survive up to the call instruction.40// It's also necessary to make sure any spills happen below the internal control flow, due41// to the nature of the backward register assignment pass.42// TODO: Put the preconditions on the call instruction itself.43//44#define COPY_PRECONDITIONS_TO_POSTCONDITIONS (1)4546namespace TR {4748enum49{50BranchJNE = 0,51BranchJE = 1,52BranchNopJMP = 253};5455enum56{57PicSlot_NeedsShortConditionalBranch = 0x01,58PicSlot_NeedsLongConditionalBranch = 0x02,59PicSlot_NeedsPicSlotAlignment = 0x04,60PicSlot_NeedsPicCallAlignment = 0x08,61PicSlot_NeedsJumpToDone = 0x10,62PicSlot_GenerateNextSlotLabelInstruction = 0x2063};6465class X86PICSlot66{67public:6869TR_ALLOC(TR_Memory::Linkage);7071X86PICSlot(uintptr_t classAddress, TR_ResolvedMethod *method, bool jumpToDone=true, TR_OpaqueMethodBlock *m = NULL, int32_t slot = -1):72_classAddress(classAddress), _method(method), _helperMethodSymbolRef(NULL), _branchType(BranchJNE), _methodAddress(m), _slot(slot)73{74if (jumpToDone) setNeedsJumpToDone(); // TODO: Remove this oddball. We can tell whether we need a dump to done based on whether a doneLabel is passed to buildPICSlot75}7677uintptr_t getClassAddress() { return _classAddress; }78TR_ResolvedMethod *getMethod() { return _method; }7980TR_OpaqueMethodBlock *getMethodAddress() { return _methodAddress; }8182int32_t getSlot() { return _slot; }8384void setHelperMethodSymbolRef(TR::SymbolReference *symRef)85{ _helperMethodSymbolRef = symRef; }86TR::SymbolReference *getHelperMethodSymbolRef() { return _helperMethodSymbolRef; }8788void setJumpOnNotEqual() { _branchType = BranchJNE; }89bool needsJumpOnNotEqual() { return _branchType == BranchJNE; }9091void setJumpOnEqual() { _branchType = BranchJE; }92bool needsJumpOnEqual() { return _branchType == BranchJE; }9394void setNopAndJump() { _branchType = BranchNopJMP; }95bool needsNopAndJump() { return _branchType == BranchNopJMP; }9697bool needsShortConditionalBranch() {return _flags.testAny(PicSlot_NeedsShortConditionalBranch);}98void setNeedsShortConditionalBranch() {_flags.set(PicSlot_NeedsShortConditionalBranch);}99100bool needsLongConditionalBranch() {return _flags.testAny(PicSlot_NeedsLongConditionalBranch);}101void setNeedsLongConditionalBranch() {_flags.set(PicSlot_NeedsLongConditionalBranch);}102103bool needsPicSlotAlignment() {return _flags.testAny(PicSlot_NeedsPicSlotAlignment);}104void setNeedsPicSlotAlignment() {_flags.set(PicSlot_NeedsPicSlotAlignment);}105106bool needsPicCallAlignment() {return _flags.testAny(PicSlot_NeedsPicCallAlignment);}107void setNeedsPicCallAlignment() {_flags.set(PicSlot_NeedsPicCallAlignment);}108109bool needsJumpToDone() {return _flags.testAny(PicSlot_NeedsJumpToDone);}110void setNeedsJumpToDone() {_flags.set(PicSlot_NeedsJumpToDone);}111112bool generateNextSlotLabelInstruction() {return _flags.testAny(PicSlot_GenerateNextSlotLabelInstruction);}113void setGenerateNextSlotLabelInstruction() {_flags.set(PicSlot_GenerateNextSlotLabelInstruction);}114115protected:116117flags8_t _flags;118uintptr_t _classAddress;119TR_ResolvedMethod *_method;120TR::SymbolReference *_helperMethodSymbolRef;121TR_OpaqueMethodBlock *_methodAddress;122int32_t _slot;123uint8_t _branchType;124};125126class X86CallSite127{128public:129130X86CallSite(TR::Node *callNode, TR::Linkage *calleeLinkage);131132TR::Node *getCallNode(){ return _callNode; }133TR::Linkage *getLinkage(){ return _linkage; }134135TR::CodeGenerator *cg(){ return _linkage->cg(); }136TR::Compilation *comp(){ return _linkage->comp(); }137TR_FrontEnd *fe(){ return _linkage->fe(); }138139// Register dependency construction140TR::RegisterDependencyConditions *getPreConditionsUnderConstruction() { return _preConditionsUnderConstruction; }141TR::RegisterDependencyConditions *getPostConditionsUnderConstruction(){ return _postConditionsUnderConstruction; }142143void addPreCondition (TR::Register *virtualReg, TR::RealRegister::RegNum realReg){ _preConditionsUnderConstruction->unionPreCondition(virtualReg, realReg, cg()); }144void addPostCondition(TR::Register *virtualReg, TR::RealRegister::RegNum realReg){ _postConditionsUnderConstruction->unionPostCondition(virtualReg, realReg, cg()); }145void stopAddingConditions();146147// Immutable call site properties148TR::ResolvedMethodSymbol *getCallerSym(){ return comp()->getMethodSymbol(); }149TR::MethodSymbol *getMethodSymbol(){ return _callNode->getSymbol()->castToMethodSymbol(); }150TR::ResolvedMethodSymbol *getResolvedMethodSymbol(){ return _callNode->getSymbol()->getResolvedMethodSymbol(); }151TR_ResolvedMethod *getResolvedMethod(){ return getResolvedMethodSymbol()? getResolvedMethodSymbol()->getResolvedMethod() : NULL; }152TR::SymbolReference *getSymbolReference(){ return _callNode->getSymbolReference(); }153TR_OpaqueClassBlock *getInterfaceClassOfMethod(){ return _interfaceClassOfMethod; } // NULL for virtual methods154155// Abstraction of complex decision logic156bool shouldUseInterpreterLinkage();157bool vftPointerMayPersist();158TR_ScratchList<TR::X86PICSlot> *getProfiledTargets(){ return _profiledTargets; } // NULL if there aren't any159TR_VirtualGuardKind getVirtualGuardKind(){ return _virtualGuardKind; }160TR_ResolvedMethod *getDevirtualizedMethod(){ return _devirtualizedMethod; } // The method to be dispatched statically161TR::SymbolReference *getDevirtualizedMethodSymRef(){ return _devirtualizedMethodSymRef; }162TR::Register *evaluateVFT();163TR::Instruction *getImplicitExceptionPoint(){ return _vftImplicitExceptionPoint; }164TR::Instruction *setImplicitExceptionPoint(TR::Instruction *instr){ return _vftImplicitExceptionPoint = instr; }165uint32_t getPreservedRegisterMask(){ return _preservedRegisterMask; }166bool resolvedVirtualShouldUseVFTCall();167168TR::Instruction *getFirstPICSlotInstruction() {return _firstPICSlotInstruction;}169void setFirstPICSlotInstruction(TR::Instruction *f) {_firstPICSlotInstruction = f;}170uint8_t *getThunkAddress() {return _thunkAddress;}171void setThunkAddress(uint8_t *t) {_thunkAddress = t;}172173float getMinProfiledCallFrequency(){ return .075F; } // Tuned for megamorphic site in jess; so bear in mind before changing174175public:176177bool argsHaveBeenBuilt(){ return _argSize >= 0; }178void setArgSize(int32_t s){ TR_ASSERT(!argsHaveBeenBuilt(), "assertion failure"); _argSize = s; }179int32_t getArgSize(){ TR_ASSERT(argsHaveBeenBuilt(), "assertion failure"); return _argSize; }180181bool useLastITableCache(){ return _useLastITableCache; }182183private:184185TR::Node *_callNode;186TR::Linkage *_linkage;187TR_OpaqueClassBlock *_interfaceClassOfMethod;188int32_t _argSize;189uint32_t _preservedRegisterMask;190TR::RegisterDependencyConditions *_preConditionsUnderConstruction;191TR::RegisterDependencyConditions *_postConditionsUnderConstruction;192TR::Instruction *_vftImplicitExceptionPoint;193TR::Instruction *_firstPICSlotInstruction;194195void computeProfiledTargets();196TR_ScratchList<TR::X86PICSlot> *_profiledTargets;197198void setupVirtualGuardInfo();199TR_VirtualGuardKind _virtualGuardKind;200TR_ResolvedMethod *_devirtualizedMethod;201TR::SymbolReference *_devirtualizedMethodSymRef;202203uint8_t *_thunkAddress;204205bool _useLastITableCache;206};207208209struct PicParameters210{211intptr_t defaultSlotAddress;212int32_t roundedSizeOfSlot;213int32_t defaultNumberOfSlots;214};215216}217218219namespace J9220{221222namespace X86223{224225class PrivateLinkage : public J9::PrivateLinkage226{227protected:228229TR::X86LinkageProperties _properties;230231public:232233PrivateLinkage(TR::CodeGenerator *cg);234235virtual const TR::X86LinkageProperties& getProperties();236237virtual void createPrologue(TR::Instruction *cursor);238virtual void createEpilogue(TR::Instruction *cursor);239virtual TR::Register *buildDirectDispatch(TR::Node *callNode, bool spillFPRegs);240241// This interface pre-dates buildCallArguments and could be removed as a cleanup item242//243virtual int32_t buildArgs(TR::Node *callNode, TR::RegisterDependencyConditions *dependencies)=0;244virtual TR::Register *buildIndirectDispatch(TR::Node *callNode);245246// Building the actual call instruction (or equivalent)247//248// If entryLabel is NULL, these functions assume the caller will want to run the249// sequence as-is (ie. the entry point of the sequence is its first instruction).250// If it's non-NULL, they will use it in a labelInstruction at the start of the251// call sequence, which may allow them to produce a more efficient sequence.252//253// doneLabel (always provided) is placed at the end of the call sequence by the caller of these functions.254//255virtual void buildDirectCall(TR::SymbolReference *methodSymRef, TR::X86CallSite &site); // NOTE: the methodSymRef being called is not necessarily site.getSymbolReference()256virtual void buildVirtualOrComputedCall(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel, uint8_t *thunk)=0;257virtual void buildInterfaceCall(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel, uint8_t *thunk);258259// Building various parts of a call site260//261// buildPicSlot and buildVFTCall return the FIRST instruction generated, which is262// suitable for passing to a TR::X86PatchableCodeAlignmentInstruction if necessary.263//264virtual void buildCallArguments(TR::X86CallSite &site);265virtual bool buildVirtualGuard(TR::X86CallSite &site, TR::LabelSymbol *revirtualizeLabel); // returns false if it can't build the guard266virtual void buildRevirtualizedCall(TR::X86CallSite &site, TR::LabelSymbol *revirtualizeLabel, TR::LabelSymbol *doneLabel);267virtual TR::Register *buildCallPostconditions(TR::X86CallSite &site); // Returns the result register if any268virtual TR::Instruction *buildPICSlot(TR::X86PICSlot picSlot, TR::LabelSymbol *mismatchLabel, TR::LabelSymbol *doneLabel, TR::X86CallSite &site)=0;269virtual void buildVPIC(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel);270virtual void buildIPIC(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel, uint8_t *thunk)=0;271virtual TR::Instruction *buildVFTCall(TR::X86CallSite &site, TR::InstOpCode dispatchOp, TR::Register *targetAddressReg, TR::MemoryReference *targetAddressMemref);272virtual void buildInterfaceDispatchUsingLastITable (TR::X86CallSite &site, int32_t numIPicSlots, TR::X86PICSlot &lastPicSlot, TR::Instruction *&slotPatchInstruction, TR::LabelSymbol *doneLabel, TR::LabelSymbol *lookupDispatchSnippetLabel, TR_OpaqueClassBlock *declaringClass, uintptr_t itableIndex);273274// Creates a thunk for interpreted virtual calls, used to initialize275// the vTable slot for the called method.276//277virtual uint8_t *generateVirtualIndirectThunk(TR::Node *callNode){ TR_ASSERT(0, "Thunks not implemented in X86Linkage"); return NULL; }278virtual TR_J2IThunk *generateInvokeExactJ2IThunk(TR::Node *callNode, char *signature){ TR_ASSERT(0, "Thunks not implemented in X86Linkage"); return NULL; }279280struct TR::PicParameters IPicParameters;281struct TR::PicParameters VPicParameters;282283protected:284285virtual TR::Instruction *savePreservedRegisters(TR::Instruction *cursor)=0;286virtual TR::Instruction *restorePreservedRegisters(TR::Instruction *cursor)=0;287virtual bool needsFrameDeallocation();288virtual TR::Instruction *deallocateFrameIfNeeded(TR::Instruction *cursor, int32_t size);289290void copyLinkageInfoToParameterSymbols();291void copyGlRegDepsToParameterSymbols(TR::Node *bbStart, TR::CodeGenerator *cg);292TR::Instruction *copyStackParametersToLinkageRegisters(TR::Instruction *procEntryInstruction);293TR::Instruction *movLinkageRegisters(TR::Instruction *cursor, bool isStore);294TR::Instruction *copyParametersToHomeLocation(TR::Instruction *cursor, bool parmsHaveBeenStored);295296};297298}299300}301302#endif303304305