Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/arm/codegen/J9CodeGenerator.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 "codegen/AheadOfTimeCompile.hpp"
24
#include "codegen/ARMAOTRelocation.hpp"
25
#include "codegen/ARMJNILinkage.hpp"
26
#include "codegen/ARMPrivateLinkage.hpp"
27
#include "compile/SymbolReferenceTable.hpp"
28
#include "codegen/CodeGenerator.hpp"
29
#include "codegen/CodeGenerator_inlines.hpp"
30
#include "codegen/Linkage.hpp"
31
#include "codegen/Linkage_inlines.hpp"
32
#include "codegen/PrivateLinkage.hpp"
33
#include "arm/codegen/ARMSystemLinkage.hpp"
34
#include "arm/codegen/ARMRecompilation.hpp"
35
#include "env/OMRMemory.hpp"
36
#include "codegen/ARMInstruction.hpp"
37
#include "codegen/GenerateInstructions.hpp"
38
#include "env/VMJ9.h"
39
40
41
extern void TEMPORARY_initJ9ARMTreeEvaluatorTable(TR::CodeGenerator *cg);
42
43
J9::ARM::CodeGenerator::CodeGenerator(TR::Compilation *comp) :
44
J9::CodeGenerator(comp)
45
{
46
/**
47
* Do not add CodeGenerator initialization logic here.
48
* Use the \c initialize() method instead.
49
*/
50
}
51
52
void
53
J9::ARM::CodeGenerator::initialize()
54
{
55
self()->J9::CodeGenerator::initialize();
56
57
/*
58
* "Statically" initialize the FE-specific tree evaluator functions.
59
* This code only needs to execute once per JIT lifetime.
60
*/
61
static bool initTreeEvaluatorTable = false;
62
if (!initTreeEvaluatorTable)
63
{
64
TEMPORARY_initJ9ARMTreeEvaluatorTable(self());
65
initTreeEvaluatorTable = true;
66
}
67
}
68
69
static int32_t identifyFarConditionalBranches(int32_t estimate, TR::CodeGenerator *cg)
70
{
71
TR_Array<TR::ARMConditionalBranchInstruction *> candidateBranches(cg->trMemory(), 256);
72
TR::Instruction *cursorInstruction = cg->getFirstInstruction();
73
74
while (cursorInstruction)
75
{
76
TR::ARMConditionalBranchInstruction *branch = cursorInstruction->getARMConditionalBranchInstruction();
77
if (branch != NULL)
78
{
79
if (abs(branch->getEstimatedBinaryLocation() - branch->getLabelSymbol()->getEstimatedCodeLocation()) > 16384)
80
{
81
candidateBranches.add(branch);
82
}
83
}
84
cursorInstruction = cursorInstruction->getNext();
85
}
86
87
// The following heuristic algorithm penalizes backward branches in
88
// estimation, since it should be rare that a backward branch needs
89
// a far relocation.
90
91
for (int32_t i=candidateBranches.lastIndex(); i>=0; i--)
92
{
93
int32_t myLocation=candidateBranches[i]->getEstimatedBinaryLocation();
94
int32_t targetLocation=candidateBranches[i]->getLabelSymbol()->getEstimatedCodeLocation();
95
int32_t j;
96
97
if (targetLocation >= myLocation)
98
{
99
for (j=i+1; j<candidateBranches.size() &&
100
targetLocation>
101
candidateBranches[j]->getEstimatedBinaryLocation();
102
j++)
103
;
104
if ((targetLocation-myLocation + (j-i-1)*4) >= 32768)
105
{
106
candidateBranches[i]->setFarRelocation(true);
107
}
108
else
109
{
110
candidateBranches.remove(i);
111
}
112
}
113
else // backward branch
114
{
115
for (j=i-1; j>=0 && targetLocation<=
116
candidateBranches[j]->getEstimatedBinaryLocation();
117
j--)
118
;
119
if ((myLocation-targetLocation + (i-j-1)*4) > 32768)
120
{
121
candidateBranches[i]->setFarRelocation(true);
122
}
123
else
124
{
125
candidateBranches.remove(i);
126
}
127
}
128
}
129
return(estimate+4*candidateBranches.size());
130
}
131
132
void J9::ARM::CodeGenerator::doBinaryEncoding()
133
{
134
TR::Compilation *comp = self()->comp();
135
TR::CodeGenerator *cg = self();
136
int32_t estimate = 0;
137
TR::Recompilation *recomp = comp->getRecompilationInfo();
138
TR::Instruction *tempInstruction;
139
TR::Instruction *cursorInstruction = cg->getFirstInstruction();
140
TR::Instruction *i2jEntryInstruction;
141
TR::Instruction *j2jEntryInstruction;
142
TR::ResolvedMethodSymbol *methodSymbol = comp->getMethodSymbol();
143
bool isPrivateLinkage = (methodSymbol->getLinkageConvention() == TR_Private);
144
145
if (methodSymbol->isJNI())
146
{
147
// leave space for the JNI target address
148
cursorInstruction = cursorInstruction->getNext();
149
}
150
151
if (isPrivateLinkage)
152
{
153
j2jEntryInstruction = cursorInstruction->getNext();
154
self()->getLinkage()->loadUpArguments(cursorInstruction);
155
i2jEntryInstruction = cursorInstruction->getNext();
156
}
157
else
158
{
159
i2jEntryInstruction = j2jEntryInstruction = cursorInstruction;
160
161
// TODO: Probably bogus; what does loadUpArguments do when cursorInstruction == NULL?
162
cursorInstruction = NULL;
163
self()->getLinkage()->loadUpArguments(cursorInstruction);
164
}
165
166
if (recomp != NULL)
167
{
168
recomp->generatePrePrologue();
169
}
170
171
cursorInstruction = cg->getFirstInstruction();
172
173
while (cursorInstruction && cursorInstruction->getOpCodeValue() != TR::InstOpCode::proc)
174
{
175
estimate = cursorInstruction->estimateBinaryLength(estimate);
176
cursorInstruction = cursorInstruction->getNext();
177
}
178
tempInstruction = cursorInstruction;
179
180
if ((recomp != NULL) && (!recomp->useSampling()))
181
{
182
tempInstruction = recomp->generatePrologue(tempInstruction);
183
}
184
185
self()->getLinkage()->createPrologue(tempInstruction);
186
bool skipOneReturn = false;
187
while (cursorInstruction)
188
{
189
if (cursorInstruction->getOpCodeValue() == TR::InstOpCode::retn)
190
{
191
if (skipOneReturn == false)
192
{
193
TR::Instruction *temp = cursorInstruction->getPrev();
194
self()->getLinkage()->createEpilogue(temp);
195
cursorInstruction = temp->getNext();
196
skipOneReturn = true;
197
}
198
else
199
{
200
skipOneReturn = false;
201
}
202
}
203
estimate = cursorInstruction->estimateBinaryLength(estimate);
204
cursorInstruction = cursorInstruction->getNext();
205
}
206
estimate = self()->setEstimatedLocationsForSnippetLabels(estimate);
207
if (estimate > 32768)
208
{
209
estimate = identifyFarConditionalBranches(estimate, self());
210
}
211
212
self()->setEstimatedWarmLength(estimate);
213
214
cursorInstruction = cg->getFirstInstruction();
215
uint8_t *coldCode = NULL;
216
uint8_t *temp = self()->allocateCodeMemory(self()->getEstimatedWarmLength(), 0, &coldCode);
217
218
self()->setBinaryBufferStart(temp);
219
self()->setBinaryBufferCursor(temp);
220
221
while (cursorInstruction)
222
{
223
#ifdef DEBUG
224
uint32_t estLen = cursorInstruction->estimateBinaryLength((int32_t)0);
225
#endif
226
self()->setBinaryBufferCursor(cursorInstruction->generateBinaryEncoding());
227
self()->addToAtlas(cursorInstruction);
228
if (cursorInstruction->getNext() == i2jEntryInstruction)
229
{
230
self()->setPrePrologueSize(self()->getBinaryBufferCursor() - self()->getBinaryBufferStart());
231
comp->getSymRefTab()->findOrCreateStartPCSymbolRef()->getSymbol()->getStaticSymbol()->setStaticAddress(self()->getBinaryBufferCursor());
232
}
233
#ifdef DEBUG
234
uint32_t binLen;
235
binLen = cursorInstruction->getBinaryLength();
236
if(binLen > estLen)
237
{
238
TR_ASSERT(0, "bin length estimated too small");
239
}
240
#endif
241
242
cursorInstruction = cursorInstruction->getNext();
243
if (isPrivateLinkage && cursorInstruction == j2jEntryInstruction)
244
{
245
uint32_t linkageInfoWord = self()->initializeLinkageInfo(_returnTypeInfoInstruction->getBinaryEncoding());
246
((TR::ARMImmInstruction *)_returnTypeInfoInstruction)->setSourceImmediate(linkageInfoWord);
247
}
248
}
249
// Create exception table entries for outlined instructions.
250
//
251
ListIterator<TR_ARMOutOfLineCodeSection> oiIterator(&self()->getARMOutOfLineCodeSectionList());
252
TR_ARMOutOfLineCodeSection *oiCursor = oiIterator.getFirst();
253
254
while (oiCursor)
255
{
256
uint32_t startOffset = oiCursor->getFirstInstruction()->getBinaryEncoding() - self()->getCodeStart();
257
uint32_t endOffset = oiCursor->getAppendInstruction()->getBinaryEncoding() - self()->getCodeStart();
258
259
TR::Block * block = oiCursor->getBlock();
260
bool needsETE = oiCursor->getFirstInstruction()->getNode()->getOpCode().hasSymbolReference() &&
261
oiCursor->getFirstInstruction()->getNode()->getSymbolReference() &&
262
oiCursor->getFirstInstruction()->getNode()->getSymbolReference()->canCauseGC();
263
264
if (needsETE && block && !block->getExceptionSuccessors().empty())
265
block->addExceptionRangeForSnippet(startOffset, endOffset);
266
267
oiCursor = oiIterator.getNext();
268
}
269
}
270
271
// Get or create the TR::Linkage object that corresponds to the given linkage
272
// convention.
273
// Even though this method is common, its implementation is machine-specific.
274
//
275
TR::Linkage *J9::ARM::CodeGenerator::createLinkage(TR_LinkageConventions lc)
276
{
277
TR::Linkage *linkage;
278
switch (lc)
279
{
280
// case TR_InterpretedStatic:
281
// linkage = new (self()->trHeapMemory()) TR::ARMInterpretedStaticLinkage(this);
282
// break;
283
case TR_Private:
284
linkage = new (self()->trHeapMemory()) J9::ARM::PrivateLinkage(self());
285
break;
286
case TR_System:
287
linkage = new (self()->trHeapMemory()) TR::ARMSystemLinkage(self());
288
break;
289
// case TR_AllRegister:
290
// linkage = new (self()->trHeapMemory()) TR::ARMAllRegisterLinkage(this);
291
// break;
292
case TR_CHelper:
293
case TR_Helper:
294
linkage = new (self()->trHeapMemory()) J9::ARM::HelperLinkage(self());
295
break;
296
case TR_J9JNILinkage:
297
linkage = new (self()->trHeapMemory()) J9::ARM::JNILinkage(self());
298
break;
299
default :
300
TR_ASSERT(0, "using system linkage for unrecognized convention %d\n", lc);
301
linkage = new (self()->trHeapMemory()) TR::ARMSystemLinkage(self());
302
}
303
self()->setLinkage(lc, linkage);
304
return linkage;
305
}
306
307
TR::Recompilation *J9::ARM::CodeGenerator::allocateRecompilationInfo()
308
{
309
return TR_ARMRecompilation::allocate(TR::comp());
310
}
311
312