Path: blob/master/runtime/compiler/z/codegen/J9SystemLinkagezOS.cpp
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#include "z/codegen/J9SystemLinkagezOS.hpp"2324#include "codegen/BackingStore.hpp"25#include "codegen/CodeGenerator.hpp"26#include "codegen/GCStackAtlas.hpp"27#include "codegen/GCStackMap.hpp"28#include "codegen/Linkage.hpp"29#include "codegen/Linkage_inlines.hpp"30#include "codegen/S390PrivateLinkage.hpp"31#include "compile/Compilation.hpp"32#include "env/CHTable.hpp"33#include "env/CompilerEnv.hpp"34#include "env/VMJ9.h"35#include "env/jittypes.h"36#include "il/LabelSymbol.hpp"37#include "il/MethodSymbol.hpp"38#include "il/Node.hpp"39#include "il/Node_inlines.hpp"40#include "il/RegisterMappedSymbol.hpp"41#include "il/ResolvedMethodSymbol.hpp"42#include "il/StaticSymbol.hpp"43#include "il/Symbol.hpp"44#include "runtime/Runtime.hpp"45#include "runtime/RuntimeAssumptions.hpp"46#include "z/codegen/CallSnippet.hpp"47#include "z/codegen/OpMemToMem.hpp"48#include "z/codegen/S390Evaluator.hpp"49#include "z/codegen/S390GenerateInstructions.hpp"50#include "z/codegen/S390HelperCallSnippet.hpp"51#include "z/codegen/S390J9CallSnippet.hpp"52#include "z/codegen/S390StackCheckFailureSnippet.hpp"5354////////////////////////////////////////////////////////////////////////////////55// J9::Z::zOSSystemLinkage Implementations56////////////////////////////////////////////////////////////////////////////////57J9::Z::zOSSystemLinkage::zOSSystemLinkage(TR::CodeGenerator * cg)58: TR::S390zOSSystemLinkage(cg)59{60}6162/////////////////////////////////////////////////////////////////////////////////63// J9::Z::zOSSystemLinkage::generateInstructionsForCall - Front-end64// customization of callNativeFunction65////////////////////////////////////////////////////////////////////////////////66void67J9::Z::zOSSystemLinkage::generateInstructionsForCall(TR::Node * callNode, TR::RegisterDependencyConditions * deps, intptr_t targetAddress,68TR::Register * methodAddressReg, TR::Register * javaLitOffsetReg, TR::LabelSymbol * returnFromJNICallLabel,69TR::Snippet * callDataSnippet, bool isJNIGCPoint)70{71TR::S390JNICallDataSnippet * jniCallDataSnippet = static_cast<TR::S390JNICallDataSnippet *>(callDataSnippet);72TR::CodeGenerator * codeGen = cg();73TR::Compilation *comp = codeGen->comp();74TR_J9VMBase *fej9 = (TR_J9VMBase *)(codeGen->fe());75// privateLinkage refers to linkage of caller76J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));7778TR::Instruction * gcPoint;79TR::Register * javaStackRegister = privateLinkage->getStackPointerRealRegister();80TR::Register * systemStackRegister = deps->searchPreConditionRegister(getNormalStackPointerRegister());8182if (systemStackRegister == NULL || (!cg()->supportsJITFreeSystemStackPointer()))83systemStackRegister = getNormalStackPointerRealRegister();8485TR::Register * systemCAARegister = deps->searchPostConditionRegister(getCAAPointerRegister());86TR::Register * systemEntryPointRegister = deps->searchPostConditionRegister(getEntryPointRegister());87TR::Register * systemReturnAddressRegister = deps->searchPostConditionRegister(getReturnAddressRegister());88TR::Register * systemEnvironmentRegister = javaStackRegister;89TR::Register * javaLitPoolRegister = privateLinkage->getLitPoolRealRegister();90bool passLitPoolReg = false;9192if (codeGen->isLiteralPoolOnDemandOn())93{94passLitPoolReg = true;95}9697if (((TR::RealRegister *)javaLitPoolRegister)->getState() != TR::RealRegister::Locked)98{99javaLitPoolRegister = deps->searchPostConditionRegister(privateLinkage->getLitPoolRegister());100}101102/*103* for AOT we create a relocation where uint8_t *_targetAddress is set to callNode->getSymbolReference(),104* _targetAddress is used in different relocation types, where sometimes it's an actual address and sometimes (eg. TR_HelperAddress) it's a symref105* for cases when _targetAddress is actually a symref we cast it back to symref in TR::AheadOfTimeCompile::initializeAOTRelocationHeader106*107* In this case108* generateRegLitRefInstruction creates a ConstantDataSnippet with reloType: TR_HelperAddress, which creates a 32Bit/64Bit ExternalRelocation109* of type TR_AbsoluteHelperAddress with _targetAddress set to TR::SymbolReference from the call110*111*/112// get the address of the function descriptor113if (fej9->needRelocationsForHelpers()114&& !(callNode->getSymbol()->isResolvedMethod() || jniCallDataSnippet))115{116generateRegLitRefInstruction(cg(), TR::InstOpCode::getLoadOpCode(), callNode, methodAddressReg, (uintptr_t) callNode->getSymbolReference(),117TR_HelperAddress, NULL, NULL, NULL);118}119else if (!callNode->getSymbol()->isResolvedMethod() || !jniCallDataSnippet) // An unresolved method means a helper being called using system linkage120{121if (codeGen->needClassAndMethodPointerRelocations() && callNode->isPreparedForDirectJNI())122{123TR_ExternalRelocationTargetKind reloType;124if (callNode->getSymbol()->castToResolvedMethodSymbol()->isSpecial())125reloType = TR_JNISpecialTargetAddress;126else if (callNode->getSymbol()->castToResolvedMethodSymbol()->isStatic())127reloType = TR_JNIStaticTargetAddress;128else if (callNode->getSymbol()->castToResolvedMethodSymbol()->isVirtual())129reloType = TR_JNIVirtualTargetAddress;130else131{132reloType = TR_NoRelocation;133TR_ASSERT(0,"JNI relocation not supported.");134}135generateRegLitRefInstruction(cg(), TR::InstOpCode::getLoadOpCode(), callNode, methodAddressReg, (uintptr_t) targetAddress, reloType, NULL, NULL, NULL);136}137else138genLoadAddressConstant(codeGen, callNode, targetAddress, methodAddressReg, NULL, NULL, javaLitPoolRegister);139}140else141{142generateRXInstruction(codeGen, TR::InstOpCode::getLoadOpCode(), callNode, methodAddressReg,143generateS390MemoryReference(jniCallDataSnippet->getBaseRegister(),144jniCallDataSnippet->getTargetAddressOffset(), codeGen));145}146147//save litpool reg GPR6148generateRRInstruction(codeGen, TR::InstOpCode::getLoadRegOpCode(), callNode, javaLitOffsetReg, systemEntryPointRegister);149150if (comp->target().is64Bit())151{152//Load Environment Pointer in R5 and entry point of the JNI function in R6153generateRSInstruction(codeGen, TR::InstOpCode::getLoadMultipleOpCode(), callNode, systemEnvironmentRegister,154systemEntryPointRegister, generateS390MemoryReference(methodAddressReg, 0, codeGen));155}156else157{158int32_t J9TR_CAA_save_offset = fej9->getCAASaveOffset();159generateRXInstruction(codeGen, TR::InstOpCode::getLoadOpCode(), callNode, systemCAARegister,160generateS390MemoryReference(systemStackRegister, J9TR_CAA_save_offset, codeGen));161//Load Environment Pointer in R5 and entry point of the JNI function in R6162generateRSInstruction(codeGen, TR::InstOpCode::getLoadMultipleOpCode(), callNode, systemEnvironmentRegister,163systemEntryPointRegister, generateS390MemoryReference(methodAddressReg, 16, codeGen));164}165// call the JNI function166TR::Register * methodMetaDataVirtualRegister = privateLinkage->getMethodMetaDataRealRegister();167168if (cg()->supportsJITFreeSystemStackPointer())169{170auto* systemSPOffsetMR = generateS390MemoryReference(methodMetaDataVirtualRegister, static_cast<int32_t>(fej9->thisThreadGetSystemSPOffset()), codeGen);171generateSILInstruction(codeGen, TR::InstOpCode::getMoveHalfWordImmOpCode(), callNode, systemSPOffsetMR, 0);172}173174/**175* NOP padding is needed because returning from XPLINK functions skips the XPLink eyecatcher and176* always return to a point that's 2 or 4 bytes after the return address.177*178* In 64 bit XPLINK, the caller returns with a 'branch relative on condition' instruction with a 2 byte offset:179*180* 0x47F07002 B 2(,r7)181*182* In 31-bit XPLINK, this offset is 4-byte.183*184* As a result of this, JIT'ed code that does XPLINK calls needs 2 or 4-byte NOP paddings to ensure entry to valid instruction.185*186* The BASR and NOP padding must stick together and can't have reverse spills in the middle.187* Hence, splitting the dependencies to avoid spill instructions.188*/189TR::RegisterDependencyConditions* callPreDeps = new (self()->trHeapMemory()) TR::RegisterDependencyConditions(deps->getPreConditions(), NULL, deps->getAddCursorForPre(), 0, codeGen);190TR::RegisterDependencyConditions* callPostDeps = new (self()->trHeapMemory()) TR::RegisterDependencyConditions(NULL, deps->getPostConditions(), 0, deps->getAddCursorForPost(), codeGen);191192gcPoint = generateRRInstruction(codeGen, TR::InstOpCode::BASR, callNode, systemReturnAddressRegister, systemEntryPointRegister, callPreDeps);193if (isJNIGCPoint)194gcPoint->setNeedsGCMap(0x00000000);195196TR::Instruction * cursor = generateS390LabelInstruction(codeGen, TR::InstOpCode::label, callNode, returnFromJNICallLabel);197198cursor = genCallNOPAndDescriptor(cursor, callNode, callNode, TR_XPLinkCallType_BASR);199cursor->setDependencyConditions(callPostDeps);200201if (cg()->supportsJITFreeSystemStackPointer())202{203generateRXInstruction(codeGen, TR::InstOpCode::getStoreOpCode(), callNode, systemStackRegister,204new (trHeapMemory()) TR::MemoryReference(methodMetaDataVirtualRegister, (int32_t)fej9->thisThreadGetSystemSPOffset(), codeGen));205if (getStackPointerRealRegister()->getState() != TR::RealRegister::Locked)206codeGen->stopUsingRegister(systemStackRegister);207}208209//restore litpool reg GPR6210generateRRInstruction(codeGen, TR::InstOpCode::getLoadRegOpCode(), callNode, systemEntryPointRegister, javaLitOffsetReg);211}212213void214J9::Z::zOSSystemLinkage::setupRegisterDepForLinkage(TR::Node * callNode, TR_DispatchType dispatchType,215TR::RegisterDependencyConditions * &deps, int64_t & killMask, TR::SystemLinkage * systemLinkage,216TR::Node * &GlobalRegDeps, bool &hasGlRegDeps, TR::Register ** methodAddressReg, TR::Register * &javaLitOffsetReg)217{218// call j9 private linkage specialization219J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));220privateLinkage->setupRegisterDepForLinkage(callNode, dispatchType, deps, killMask, systemLinkage, GlobalRegDeps, hasGlRegDeps, methodAddressReg, javaLitOffsetReg);221}222223void224J9::Z::zOSSystemLinkage::setupBuildArgForLinkage(TR::Node * callNode, TR_DispatchType dispatchType, TR::RegisterDependencyConditions * deps, bool isFastJNI,225bool isPassReceiver, int64_t & killMask, TR::Node * GlobalRegDeps, bool hasGlRegDeps, TR::SystemLinkage * systemLinkage)226{227J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));228privateLinkage->setupBuildArgForLinkage(callNode, dispatchType, deps, isFastJNI, isPassReceiver, killMask, GlobalRegDeps, hasGlRegDeps, systemLinkage);229}230231void232J9::Z::zOSSystemLinkage::performCallNativeFunctionForLinkage(TR::Node * callNode, TR_DispatchType dispatchType, TR::Register * &javaReturnRegister, TR::SystemLinkage * systemLinkage,233TR::RegisterDependencyConditions * &deps, TR::Register * javaLitOffsetReg, TR::Register * methodAddressReg, bool isJNIGCPoint)234{235// call base class implementation first236OMR::Z::Linkage::performCallNativeFunctionForLinkage(callNode, dispatchType, javaReturnRegister, systemLinkage, deps, javaLitOffsetReg, methodAddressReg, isJNIGCPoint);237238// get javaStack Real Register239TR::CodeGenerator * codeGen = cg();240TR_J9VMBase *fej9 = (TR_J9VMBase *)(codeGen->fe());241J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));242TR::RealRegister * javaStackPointerRealRegister = privateLinkage->getStackPointerRealRegister();243244// get methodMetaDataVirtualRegister245TR::Register * methodMetaDataVirtualRegister = privateLinkage->getMethodMetaDataRealRegister();246247// restore java stack pointer248generateRXInstruction(codeGen, TR::InstOpCode::getLoadOpCode(), callNode, javaStackPointerRealRegister,249new (trHeapMemory()) TR::MemoryReference(methodMetaDataVirtualRegister, (int32_t)fej9->thisThreadGetJavaSPOffset(), codeGen));250}251252void253J9::Z::zOSSystemLinkage::doNotKillSpecialRegsForBuildArgs (TR::Linkage *linkage, bool isFastJNI, int64_t &killMask)254{255J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));256privateLinkage->doNotKillSpecialRegsForBuildArgs(linkage, isFastJNI, killMask);257}258259void260J9::Z::zOSSystemLinkage::addSpecialRegDepsForBuildArgs(TR::Node * callNode, TR::RegisterDependencyConditions * dependencies, int32_t& from, int32_t step)261{262J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));263privateLinkage->addSpecialRegDepsForBuildArgs(callNode, dependencies, from, step);264}265266int32_t267J9::Z::zOSSystemLinkage::storeExtraEnvRegForBuildArgs(TR::Node * callNode, TR::Linkage* linkage, TR::RegisterDependencyConditions * dependencies,268bool isFastJNI, int32_t stackOffset, int8_t gprSize, uint32_t &numIntegerArgs)269{270J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));271stackOffset = privateLinkage->storeExtraEnvRegForBuildArgs(callNode, linkage, dependencies, isFastJNI, stackOffset, gprSize, numIntegerArgs);272return stackOffset;273}274275int64_t276J9::Z::zOSSystemLinkage::addFECustomizedReturnRegDependency(int64_t killMask, TR::Linkage* linkage, TR::DataType resType, TR::RegisterDependencyConditions * dependencies)277{278J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));279killMask = privateLinkage->addFECustomizedReturnRegDependency(killMask, linkage, resType, dependencies);280return killMask;281}282283284