Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/z/codegen/J9SystemLinkagezOS.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 "z/codegen/J9SystemLinkagezOS.hpp"
24
25
#include "codegen/BackingStore.hpp"
26
#include "codegen/CodeGenerator.hpp"
27
#include "codegen/GCStackAtlas.hpp"
28
#include "codegen/GCStackMap.hpp"
29
#include "codegen/Linkage.hpp"
30
#include "codegen/Linkage_inlines.hpp"
31
#include "codegen/S390PrivateLinkage.hpp"
32
#include "compile/Compilation.hpp"
33
#include "env/CHTable.hpp"
34
#include "env/CompilerEnv.hpp"
35
#include "env/VMJ9.h"
36
#include "env/jittypes.h"
37
#include "il/LabelSymbol.hpp"
38
#include "il/MethodSymbol.hpp"
39
#include "il/Node.hpp"
40
#include "il/Node_inlines.hpp"
41
#include "il/RegisterMappedSymbol.hpp"
42
#include "il/ResolvedMethodSymbol.hpp"
43
#include "il/StaticSymbol.hpp"
44
#include "il/Symbol.hpp"
45
#include "runtime/Runtime.hpp"
46
#include "runtime/RuntimeAssumptions.hpp"
47
#include "z/codegen/CallSnippet.hpp"
48
#include "z/codegen/OpMemToMem.hpp"
49
#include "z/codegen/S390Evaluator.hpp"
50
#include "z/codegen/S390GenerateInstructions.hpp"
51
#include "z/codegen/S390HelperCallSnippet.hpp"
52
#include "z/codegen/S390J9CallSnippet.hpp"
53
#include "z/codegen/S390StackCheckFailureSnippet.hpp"
54
55
////////////////////////////////////////////////////////////////////////////////
56
// J9::Z::zOSSystemLinkage Implementations
57
////////////////////////////////////////////////////////////////////////////////
58
J9::Z::zOSSystemLinkage::zOSSystemLinkage(TR::CodeGenerator * cg)
59
: TR::S390zOSSystemLinkage(cg)
60
{
61
}
62
63
/////////////////////////////////////////////////////////////////////////////////
64
// J9::Z::zOSSystemLinkage::generateInstructionsForCall - Front-end
65
// customization of callNativeFunction
66
////////////////////////////////////////////////////////////////////////////////
67
void
68
J9::Z::zOSSystemLinkage::generateInstructionsForCall(TR::Node * callNode, TR::RegisterDependencyConditions * deps, intptr_t targetAddress,
69
TR::Register * methodAddressReg, TR::Register * javaLitOffsetReg, TR::LabelSymbol * returnFromJNICallLabel,
70
TR::Snippet * callDataSnippet, bool isJNIGCPoint)
71
{
72
TR::S390JNICallDataSnippet * jniCallDataSnippet = static_cast<TR::S390JNICallDataSnippet *>(callDataSnippet);
73
TR::CodeGenerator * codeGen = cg();
74
TR::Compilation *comp = codeGen->comp();
75
TR_J9VMBase *fej9 = (TR_J9VMBase *)(codeGen->fe());
76
// privateLinkage refers to linkage of caller
77
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
78
79
TR::Instruction * gcPoint;
80
TR::Register * javaStackRegister = privateLinkage->getStackPointerRealRegister();
81
TR::Register * systemStackRegister = deps->searchPreConditionRegister(getNormalStackPointerRegister());
82
83
if (systemStackRegister == NULL || (!cg()->supportsJITFreeSystemStackPointer()))
84
systemStackRegister = getNormalStackPointerRealRegister();
85
86
TR::Register * systemCAARegister = deps->searchPostConditionRegister(getCAAPointerRegister());
87
TR::Register * systemEntryPointRegister = deps->searchPostConditionRegister(getEntryPointRegister());
88
TR::Register * systemReturnAddressRegister = deps->searchPostConditionRegister(getReturnAddressRegister());
89
TR::Register * systemEnvironmentRegister = javaStackRegister;
90
TR::Register * javaLitPoolRegister = privateLinkage->getLitPoolRealRegister();
91
bool passLitPoolReg = false;
92
93
if (codeGen->isLiteralPoolOnDemandOn())
94
{
95
passLitPoolReg = true;
96
}
97
98
if (((TR::RealRegister *)javaLitPoolRegister)->getState() != TR::RealRegister::Locked)
99
{
100
javaLitPoolRegister = deps->searchPostConditionRegister(privateLinkage->getLitPoolRegister());
101
}
102
103
/*
104
* for AOT we create a relocation where uint8_t *_targetAddress is set to callNode->getSymbolReference(),
105
* _targetAddress is used in different relocation types, where sometimes it's an actual address and sometimes (eg. TR_HelperAddress) it's a symref
106
* for cases when _targetAddress is actually a symref we cast it back to symref in TR::AheadOfTimeCompile::initializeAOTRelocationHeader
107
*
108
* In this case
109
* generateRegLitRefInstruction creates a ConstantDataSnippet with reloType: TR_HelperAddress, which creates a 32Bit/64Bit ExternalRelocation
110
* of type TR_AbsoluteHelperAddress with _targetAddress set to TR::SymbolReference from the call
111
*
112
*/
113
// get the address of the function descriptor
114
if (fej9->needRelocationsForHelpers()
115
&& !(callNode->getSymbol()->isResolvedMethod() || jniCallDataSnippet))
116
{
117
generateRegLitRefInstruction(cg(), TR::InstOpCode::getLoadOpCode(), callNode, methodAddressReg, (uintptr_t) callNode->getSymbolReference(),
118
TR_HelperAddress, NULL, NULL, NULL);
119
}
120
else if (!callNode->getSymbol()->isResolvedMethod() || !jniCallDataSnippet) // An unresolved method means a helper being called using system linkage
121
{
122
if (codeGen->needClassAndMethodPointerRelocations() && callNode->isPreparedForDirectJNI())
123
{
124
TR_ExternalRelocationTargetKind reloType;
125
if (callNode->getSymbol()->castToResolvedMethodSymbol()->isSpecial())
126
reloType = TR_JNISpecialTargetAddress;
127
else if (callNode->getSymbol()->castToResolvedMethodSymbol()->isStatic())
128
reloType = TR_JNIStaticTargetAddress;
129
else if (callNode->getSymbol()->castToResolvedMethodSymbol()->isVirtual())
130
reloType = TR_JNIVirtualTargetAddress;
131
else
132
{
133
reloType = TR_NoRelocation;
134
TR_ASSERT(0,"JNI relocation not supported.");
135
}
136
generateRegLitRefInstruction(cg(), TR::InstOpCode::getLoadOpCode(), callNode, methodAddressReg, (uintptr_t) targetAddress, reloType, NULL, NULL, NULL);
137
}
138
else
139
genLoadAddressConstant(codeGen, callNode, targetAddress, methodAddressReg, NULL, NULL, javaLitPoolRegister);
140
}
141
else
142
{
143
generateRXInstruction(codeGen, TR::InstOpCode::getLoadOpCode(), callNode, methodAddressReg,
144
generateS390MemoryReference(jniCallDataSnippet->getBaseRegister(),
145
jniCallDataSnippet->getTargetAddressOffset(), codeGen));
146
}
147
148
//save litpool reg GPR6
149
generateRRInstruction(codeGen, TR::InstOpCode::getLoadRegOpCode(), callNode, javaLitOffsetReg, systemEntryPointRegister);
150
151
if (comp->target().is64Bit())
152
{
153
//Load Environment Pointer in R5 and entry point of the JNI function in R6
154
generateRSInstruction(codeGen, TR::InstOpCode::getLoadMultipleOpCode(), callNode, systemEnvironmentRegister,
155
systemEntryPointRegister, generateS390MemoryReference(methodAddressReg, 0, codeGen));
156
}
157
else
158
{
159
int32_t J9TR_CAA_save_offset = fej9->getCAASaveOffset();
160
generateRXInstruction(codeGen, TR::InstOpCode::getLoadOpCode(), callNode, systemCAARegister,
161
generateS390MemoryReference(systemStackRegister, J9TR_CAA_save_offset, codeGen));
162
//Load Environment Pointer in R5 and entry point of the JNI function in R6
163
generateRSInstruction(codeGen, TR::InstOpCode::getLoadMultipleOpCode(), callNode, systemEnvironmentRegister,
164
systemEntryPointRegister, generateS390MemoryReference(methodAddressReg, 16, codeGen));
165
}
166
// call the JNI function
167
TR::Register * methodMetaDataVirtualRegister = privateLinkage->getMethodMetaDataRealRegister();
168
169
if (cg()->supportsJITFreeSystemStackPointer())
170
{
171
auto* systemSPOffsetMR = generateS390MemoryReference(methodMetaDataVirtualRegister, static_cast<int32_t>(fej9->thisThreadGetSystemSPOffset()), codeGen);
172
generateSILInstruction(codeGen, TR::InstOpCode::getMoveHalfWordImmOpCode(), callNode, systemSPOffsetMR, 0);
173
}
174
175
/**
176
* NOP padding is needed because returning from XPLINK functions skips the XPLink eyecatcher and
177
* always return to a point that's 2 or 4 bytes after the return address.
178
*
179
* In 64 bit XPLINK, the caller returns with a 'branch relative on condition' instruction with a 2 byte offset:
180
*
181
* 0x47F07002 B 2(,r7)
182
*
183
* In 31-bit XPLINK, this offset is 4-byte.
184
*
185
* 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.
186
*
187
* The BASR and NOP padding must stick together and can't have reverse spills in the middle.
188
* Hence, splitting the dependencies to avoid spill instructions.
189
*/
190
TR::RegisterDependencyConditions* callPreDeps = new (self()->trHeapMemory()) TR::RegisterDependencyConditions(deps->getPreConditions(), NULL, deps->getAddCursorForPre(), 0, codeGen);
191
TR::RegisterDependencyConditions* callPostDeps = new (self()->trHeapMemory()) TR::RegisterDependencyConditions(NULL, deps->getPostConditions(), 0, deps->getAddCursorForPost(), codeGen);
192
193
gcPoint = generateRRInstruction(codeGen, TR::InstOpCode::BASR, callNode, systemReturnAddressRegister, systemEntryPointRegister, callPreDeps);
194
if (isJNIGCPoint)
195
gcPoint->setNeedsGCMap(0x00000000);
196
197
TR::Instruction * cursor = generateS390LabelInstruction(codeGen, TR::InstOpCode::label, callNode, returnFromJNICallLabel);
198
199
cursor = genCallNOPAndDescriptor(cursor, callNode, callNode, TR_XPLinkCallType_BASR);
200
cursor->setDependencyConditions(callPostDeps);
201
202
if (cg()->supportsJITFreeSystemStackPointer())
203
{
204
generateRXInstruction(codeGen, TR::InstOpCode::getStoreOpCode(), callNode, systemStackRegister,
205
new (trHeapMemory()) TR::MemoryReference(methodMetaDataVirtualRegister, (int32_t)fej9->thisThreadGetSystemSPOffset(), codeGen));
206
if (getStackPointerRealRegister()->getState() != TR::RealRegister::Locked)
207
codeGen->stopUsingRegister(systemStackRegister);
208
}
209
210
//restore litpool reg GPR6
211
generateRRInstruction(codeGen, TR::InstOpCode::getLoadRegOpCode(), callNode, systemEntryPointRegister, javaLitOffsetReg);
212
}
213
214
void
215
J9::Z::zOSSystemLinkage::setupRegisterDepForLinkage(TR::Node * callNode, TR_DispatchType dispatchType,
216
TR::RegisterDependencyConditions * &deps, int64_t & killMask, TR::SystemLinkage * systemLinkage,
217
TR::Node * &GlobalRegDeps, bool &hasGlRegDeps, TR::Register ** methodAddressReg, TR::Register * &javaLitOffsetReg)
218
{
219
// call j9 private linkage specialization
220
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
221
privateLinkage->setupRegisterDepForLinkage(callNode, dispatchType, deps, killMask, systemLinkage, GlobalRegDeps, hasGlRegDeps, methodAddressReg, javaLitOffsetReg);
222
}
223
224
void
225
J9::Z::zOSSystemLinkage::setupBuildArgForLinkage(TR::Node * callNode, TR_DispatchType dispatchType, TR::RegisterDependencyConditions * deps, bool isFastJNI,
226
bool isPassReceiver, int64_t & killMask, TR::Node * GlobalRegDeps, bool hasGlRegDeps, TR::SystemLinkage * systemLinkage)
227
{
228
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
229
privateLinkage->setupBuildArgForLinkage(callNode, dispatchType, deps, isFastJNI, isPassReceiver, killMask, GlobalRegDeps, hasGlRegDeps, systemLinkage);
230
}
231
232
void
233
J9::Z::zOSSystemLinkage::performCallNativeFunctionForLinkage(TR::Node * callNode, TR_DispatchType dispatchType, TR::Register * &javaReturnRegister, TR::SystemLinkage * systemLinkage,
234
TR::RegisterDependencyConditions * &deps, TR::Register * javaLitOffsetReg, TR::Register * methodAddressReg, bool isJNIGCPoint)
235
{
236
// call base class implementation first
237
OMR::Z::Linkage::performCallNativeFunctionForLinkage(callNode, dispatchType, javaReturnRegister, systemLinkage, deps, javaLitOffsetReg, methodAddressReg, isJNIGCPoint);
238
239
// get javaStack Real Register
240
TR::CodeGenerator * codeGen = cg();
241
TR_J9VMBase *fej9 = (TR_J9VMBase *)(codeGen->fe());
242
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
243
TR::RealRegister * javaStackPointerRealRegister = privateLinkage->getStackPointerRealRegister();
244
245
// get methodMetaDataVirtualRegister
246
TR::Register * methodMetaDataVirtualRegister = privateLinkage->getMethodMetaDataRealRegister();
247
248
// restore java stack pointer
249
generateRXInstruction(codeGen, TR::InstOpCode::getLoadOpCode(), callNode, javaStackPointerRealRegister,
250
new (trHeapMemory()) TR::MemoryReference(methodMetaDataVirtualRegister, (int32_t)fej9->thisThreadGetJavaSPOffset(), codeGen));
251
}
252
253
void
254
J9::Z::zOSSystemLinkage::doNotKillSpecialRegsForBuildArgs (TR::Linkage *linkage, bool isFastJNI, int64_t &killMask)
255
{
256
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
257
privateLinkage->doNotKillSpecialRegsForBuildArgs(linkage, isFastJNI, killMask);
258
}
259
260
void
261
J9::Z::zOSSystemLinkage::addSpecialRegDepsForBuildArgs(TR::Node * callNode, TR::RegisterDependencyConditions * dependencies, int32_t& from, int32_t step)
262
{
263
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
264
privateLinkage->addSpecialRegDepsForBuildArgs(callNode, dependencies, from, step);
265
}
266
267
int32_t
268
J9::Z::zOSSystemLinkage::storeExtraEnvRegForBuildArgs(TR::Node * callNode, TR::Linkage* linkage, TR::RegisterDependencyConditions * dependencies,
269
bool isFastJNI, int32_t stackOffset, int8_t gprSize, uint32_t &numIntegerArgs)
270
{
271
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
272
stackOffset = privateLinkage->storeExtraEnvRegForBuildArgs(callNode, linkage, dependencies, isFastJNI, stackOffset, gprSize, numIntegerArgs);
273
return stackOffset;
274
}
275
276
int64_t
277
J9::Z::zOSSystemLinkage::addFECustomizedReturnRegDependency(int64_t killMask, TR::Linkage* linkage, TR::DataType resType, TR::RegisterDependencyConditions * dependencies)
278
{
279
J9::Z::PrivateLinkage * privateLinkage = static_cast<J9::Z::PrivateLinkage *>(cg()->getLinkage(TR_Private));
280
killMask = privateLinkage->addFECustomizedReturnRegDependency(killMask, linkage, resType, dependencies);
281
return killMask;
282
}
283
284