Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/x/codegen/X86PrivateLinkage.hpp
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
#ifndef X86PRIVATELINKAGE_INCL
24
#define X86PRIVATELINKAGE_INCL
25
26
#include "codegen/PrivateLinkage.hpp"
27
28
#include "env/jittypes.h"
29
#include "codegen/RegisterDependency.hpp"
30
#include "x/codegen/X86Register.hpp"
31
32
class TR_J2IThunk;
33
class TR_ResolvedMethod;
34
namespace TR { class Instruction; }
35
36
//
37
// Hack markers
38
//
39
40
// This is an overkill way to make sure the preconditions survive up to the call instruction.
41
// It's also necessary to make sure any spills happen below the internal control flow, due
42
// to the nature of the backward register assignment pass.
43
// TODO: Put the preconditions on the call instruction itself.
44
//
45
#define COPY_PRECONDITIONS_TO_POSTCONDITIONS (1)
46
47
namespace TR {
48
49
enum
50
{
51
BranchJNE = 0,
52
BranchJE = 1,
53
BranchNopJMP = 2
54
};
55
56
enum
57
{
58
PicSlot_NeedsShortConditionalBranch = 0x01,
59
PicSlot_NeedsLongConditionalBranch = 0x02,
60
PicSlot_NeedsPicSlotAlignment = 0x04,
61
PicSlot_NeedsPicCallAlignment = 0x08,
62
PicSlot_NeedsJumpToDone = 0x10,
63
PicSlot_GenerateNextSlotLabelInstruction = 0x20
64
};
65
66
class X86PICSlot
67
{
68
public:
69
70
TR_ALLOC(TR_Memory::Linkage);
71
72
X86PICSlot(uintptr_t classAddress, TR_ResolvedMethod *method, bool jumpToDone=true, TR_OpaqueMethodBlock *m = NULL, int32_t slot = -1):
73
_classAddress(classAddress), _method(method), _helperMethodSymbolRef(NULL), _branchType(BranchJNE), _methodAddress(m), _slot(slot)
74
{
75
if (jumpToDone) setNeedsJumpToDone(); // TODO: Remove this oddball. We can tell whether we need a dump to done based on whether a doneLabel is passed to buildPICSlot
76
}
77
78
uintptr_t getClassAddress() { return _classAddress; }
79
TR_ResolvedMethod *getMethod() { return _method; }
80
81
TR_OpaqueMethodBlock *getMethodAddress() { return _methodAddress; }
82
83
int32_t getSlot() { return _slot; }
84
85
void setHelperMethodSymbolRef(TR::SymbolReference *symRef)
86
{ _helperMethodSymbolRef = symRef; }
87
TR::SymbolReference *getHelperMethodSymbolRef() { return _helperMethodSymbolRef; }
88
89
void setJumpOnNotEqual() { _branchType = BranchJNE; }
90
bool needsJumpOnNotEqual() { return _branchType == BranchJNE; }
91
92
void setJumpOnEqual() { _branchType = BranchJE; }
93
bool needsJumpOnEqual() { return _branchType == BranchJE; }
94
95
void setNopAndJump() { _branchType = BranchNopJMP; }
96
bool needsNopAndJump() { return _branchType == BranchNopJMP; }
97
98
bool needsShortConditionalBranch() {return _flags.testAny(PicSlot_NeedsShortConditionalBranch);}
99
void setNeedsShortConditionalBranch() {_flags.set(PicSlot_NeedsShortConditionalBranch);}
100
101
bool needsLongConditionalBranch() {return _flags.testAny(PicSlot_NeedsLongConditionalBranch);}
102
void setNeedsLongConditionalBranch() {_flags.set(PicSlot_NeedsLongConditionalBranch);}
103
104
bool needsPicSlotAlignment() {return _flags.testAny(PicSlot_NeedsPicSlotAlignment);}
105
void setNeedsPicSlotAlignment() {_flags.set(PicSlot_NeedsPicSlotAlignment);}
106
107
bool needsPicCallAlignment() {return _flags.testAny(PicSlot_NeedsPicCallAlignment);}
108
void setNeedsPicCallAlignment() {_flags.set(PicSlot_NeedsPicCallAlignment);}
109
110
bool needsJumpToDone() {return _flags.testAny(PicSlot_NeedsJumpToDone);}
111
void setNeedsJumpToDone() {_flags.set(PicSlot_NeedsJumpToDone);}
112
113
bool generateNextSlotLabelInstruction() {return _flags.testAny(PicSlot_GenerateNextSlotLabelInstruction);}
114
void setGenerateNextSlotLabelInstruction() {_flags.set(PicSlot_GenerateNextSlotLabelInstruction);}
115
116
protected:
117
118
flags8_t _flags;
119
uintptr_t _classAddress;
120
TR_ResolvedMethod *_method;
121
TR::SymbolReference *_helperMethodSymbolRef;
122
TR_OpaqueMethodBlock *_methodAddress;
123
int32_t _slot;
124
uint8_t _branchType;
125
};
126
127
class X86CallSite
128
{
129
public:
130
131
X86CallSite(TR::Node *callNode, TR::Linkage *calleeLinkage);
132
133
TR::Node *getCallNode(){ return _callNode; }
134
TR::Linkage *getLinkage(){ return _linkage; }
135
136
TR::CodeGenerator *cg(){ return _linkage->cg(); }
137
TR::Compilation *comp(){ return _linkage->comp(); }
138
TR_FrontEnd *fe(){ return _linkage->fe(); }
139
140
// Register dependency construction
141
TR::RegisterDependencyConditions *getPreConditionsUnderConstruction() { return _preConditionsUnderConstruction; }
142
TR::RegisterDependencyConditions *getPostConditionsUnderConstruction(){ return _postConditionsUnderConstruction; }
143
144
void addPreCondition (TR::Register *virtualReg, TR::RealRegister::RegNum realReg){ _preConditionsUnderConstruction->unionPreCondition(virtualReg, realReg, cg()); }
145
void addPostCondition(TR::Register *virtualReg, TR::RealRegister::RegNum realReg){ _postConditionsUnderConstruction->unionPostCondition(virtualReg, realReg, cg()); }
146
void stopAddingConditions();
147
148
// Immutable call site properties
149
TR::ResolvedMethodSymbol *getCallerSym(){ return comp()->getMethodSymbol(); }
150
TR::MethodSymbol *getMethodSymbol(){ return _callNode->getSymbol()->castToMethodSymbol(); }
151
TR::ResolvedMethodSymbol *getResolvedMethodSymbol(){ return _callNode->getSymbol()->getResolvedMethodSymbol(); }
152
TR_ResolvedMethod *getResolvedMethod(){ return getResolvedMethodSymbol()? getResolvedMethodSymbol()->getResolvedMethod() : NULL; }
153
TR::SymbolReference *getSymbolReference(){ return _callNode->getSymbolReference(); }
154
TR_OpaqueClassBlock *getInterfaceClassOfMethod(){ return _interfaceClassOfMethod; } // NULL for virtual methods
155
156
// Abstraction of complex decision logic
157
bool shouldUseInterpreterLinkage();
158
bool vftPointerMayPersist();
159
TR_ScratchList<TR::X86PICSlot> *getProfiledTargets(){ return _profiledTargets; } // NULL if there aren't any
160
TR_VirtualGuardKind getVirtualGuardKind(){ return _virtualGuardKind; }
161
TR_ResolvedMethod *getDevirtualizedMethod(){ return _devirtualizedMethod; } // The method to be dispatched statically
162
TR::SymbolReference *getDevirtualizedMethodSymRef(){ return _devirtualizedMethodSymRef; }
163
TR::Register *evaluateVFT();
164
TR::Instruction *getImplicitExceptionPoint(){ return _vftImplicitExceptionPoint; }
165
TR::Instruction *setImplicitExceptionPoint(TR::Instruction *instr){ return _vftImplicitExceptionPoint = instr; }
166
uint32_t getPreservedRegisterMask(){ return _preservedRegisterMask; }
167
bool resolvedVirtualShouldUseVFTCall();
168
169
TR::Instruction *getFirstPICSlotInstruction() {return _firstPICSlotInstruction;}
170
void setFirstPICSlotInstruction(TR::Instruction *f) {_firstPICSlotInstruction = f;}
171
uint8_t *getThunkAddress() {return _thunkAddress;}
172
void setThunkAddress(uint8_t *t) {_thunkAddress = t;}
173
174
float getMinProfiledCallFrequency(){ return .075F; } // Tuned for megamorphic site in jess; so bear in mind before changing
175
176
public:
177
178
bool argsHaveBeenBuilt(){ return _argSize >= 0; }
179
void setArgSize(int32_t s){ TR_ASSERT(!argsHaveBeenBuilt(), "assertion failure"); _argSize = s; }
180
int32_t getArgSize(){ TR_ASSERT(argsHaveBeenBuilt(), "assertion failure"); return _argSize; }
181
182
bool useLastITableCache(){ return _useLastITableCache; }
183
184
private:
185
186
TR::Node *_callNode;
187
TR::Linkage *_linkage;
188
TR_OpaqueClassBlock *_interfaceClassOfMethod;
189
int32_t _argSize;
190
uint32_t _preservedRegisterMask;
191
TR::RegisterDependencyConditions *_preConditionsUnderConstruction;
192
TR::RegisterDependencyConditions *_postConditionsUnderConstruction;
193
TR::Instruction *_vftImplicitExceptionPoint;
194
TR::Instruction *_firstPICSlotInstruction;
195
196
void computeProfiledTargets();
197
TR_ScratchList<TR::X86PICSlot> *_profiledTargets;
198
199
void setupVirtualGuardInfo();
200
TR_VirtualGuardKind _virtualGuardKind;
201
TR_ResolvedMethod *_devirtualizedMethod;
202
TR::SymbolReference *_devirtualizedMethodSymRef;
203
204
uint8_t *_thunkAddress;
205
206
bool _useLastITableCache;
207
};
208
209
210
struct PicParameters
211
{
212
intptr_t defaultSlotAddress;
213
int32_t roundedSizeOfSlot;
214
int32_t defaultNumberOfSlots;
215
};
216
217
}
218
219
220
namespace J9
221
{
222
223
namespace X86
224
{
225
226
class PrivateLinkage : public J9::PrivateLinkage
227
{
228
protected:
229
230
TR::X86LinkageProperties _properties;
231
232
public:
233
234
PrivateLinkage(TR::CodeGenerator *cg);
235
236
virtual const TR::X86LinkageProperties& getProperties();
237
238
virtual void createPrologue(TR::Instruction *cursor);
239
virtual void createEpilogue(TR::Instruction *cursor);
240
virtual TR::Register *buildDirectDispatch(TR::Node *callNode, bool spillFPRegs);
241
242
// This interface pre-dates buildCallArguments and could be removed as a cleanup item
243
//
244
virtual int32_t buildArgs(TR::Node *callNode, TR::RegisterDependencyConditions *dependencies)=0;
245
virtual TR::Register *buildIndirectDispatch(TR::Node *callNode);
246
247
// Building the actual call instruction (or equivalent)
248
//
249
// If entryLabel is NULL, these functions assume the caller will want to run the
250
// sequence as-is (ie. the entry point of the sequence is its first instruction).
251
// If it's non-NULL, they will use it in a labelInstruction at the start of the
252
// call sequence, which may allow them to produce a more efficient sequence.
253
//
254
// doneLabel (always provided) is placed at the end of the call sequence by the caller of these functions.
255
//
256
virtual void buildDirectCall(TR::SymbolReference *methodSymRef, TR::X86CallSite &site); // NOTE: the methodSymRef being called is not necessarily site.getSymbolReference()
257
virtual void buildVirtualOrComputedCall(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel, uint8_t *thunk)=0;
258
virtual void buildInterfaceCall(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel, uint8_t *thunk);
259
260
// Building various parts of a call site
261
//
262
// buildPicSlot and buildVFTCall return the FIRST instruction generated, which is
263
// suitable for passing to a TR::X86PatchableCodeAlignmentInstruction if necessary.
264
//
265
virtual void buildCallArguments(TR::X86CallSite &site);
266
virtual bool buildVirtualGuard(TR::X86CallSite &site, TR::LabelSymbol *revirtualizeLabel); // returns false if it can't build the guard
267
virtual void buildRevirtualizedCall(TR::X86CallSite &site, TR::LabelSymbol *revirtualizeLabel, TR::LabelSymbol *doneLabel);
268
virtual TR::Register *buildCallPostconditions(TR::X86CallSite &site); // Returns the result register if any
269
virtual TR::Instruction *buildPICSlot(TR::X86PICSlot picSlot, TR::LabelSymbol *mismatchLabel, TR::LabelSymbol *doneLabel, TR::X86CallSite &site)=0;
270
virtual void buildVPIC(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel);
271
virtual void buildIPIC(TR::X86CallSite &site, TR::LabelSymbol *entryLabel, TR::LabelSymbol *doneLabel, uint8_t *thunk)=0;
272
virtual TR::Instruction *buildVFTCall(TR::X86CallSite &site, TR::InstOpCode dispatchOp, TR::Register *targetAddressReg, TR::MemoryReference *targetAddressMemref);
273
virtual 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);
274
275
// Creates a thunk for interpreted virtual calls, used to initialize
276
// the vTable slot for the called method.
277
//
278
virtual uint8_t *generateVirtualIndirectThunk(TR::Node *callNode){ TR_ASSERT(0, "Thunks not implemented in X86Linkage"); return NULL; }
279
virtual TR_J2IThunk *generateInvokeExactJ2IThunk(TR::Node *callNode, char *signature){ TR_ASSERT(0, "Thunks not implemented in X86Linkage"); return NULL; }
280
281
struct TR::PicParameters IPicParameters;
282
struct TR::PicParameters VPicParameters;
283
284
protected:
285
286
virtual TR::Instruction *savePreservedRegisters(TR::Instruction *cursor)=0;
287
virtual TR::Instruction *restorePreservedRegisters(TR::Instruction *cursor)=0;
288
virtual bool needsFrameDeallocation();
289
virtual TR::Instruction *deallocateFrameIfNeeded(TR::Instruction *cursor, int32_t size);
290
291
void copyLinkageInfoToParameterSymbols();
292
void copyGlRegDepsToParameterSymbols(TR::Node *bbStart, TR::CodeGenerator *cg);
293
TR::Instruction *copyStackParametersToLinkageRegisters(TR::Instruction *procEntryInstruction);
294
TR::Instruction *movLinkageRegisters(TR::Instruction *cursor, bool isStore);
295
TR::Instruction *copyParametersToHomeLocation(TR::Instruction *cursor, bool parmsHaveBeenStored);
296
297
};
298
299
}
300
301
}
302
303
#endif
304
305