Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/aarch64/codegen/J9CodeGenerator.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2019, 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/ARM64JNILinkage.hpp"
25
#include "codegen/ARM64PrivateLinkage.hpp"
26
#include "codegen/ARM64Recompilation.hpp"
27
#include "codegen/ARM64SystemLinkage.hpp"
28
#include "codegen/CodeGenerator.hpp"
29
#include "codegen/CodeGenerator_inlines.hpp"
30
#include "codegen/GenerateInstructions.hpp"
31
#include "compile/Compilation.hpp"
32
#include "runtime/CodeCacheManager.hpp"
33
34
extern void TEMPORARY_initJ9ARM64TreeEvaluatorTable(TR::CodeGenerator *cg);
35
36
J9::ARM64::CodeGenerator::CodeGenerator(TR::Compilation *comp) :
37
J9::CodeGenerator(comp)
38
{
39
/**
40
* Do not add CodeGenerator initialization logic here.
41
* Use the \c initialize() method instead.
42
*/
43
}
44
45
void
46
J9::ARM64::CodeGenerator::initialize()
47
{
48
self()->J9::CodeGenerator::initialize();
49
50
TR::CodeGenerator *cg = self();
51
TR::Compilation *comp = cg->comp();
52
53
cg->setAheadOfTimeCompile(new (cg->trHeapMemory()) TR::AheadOfTimeCompile(cg));
54
55
/*
56
* "Statically" initialize the FE-specific tree evaluator functions.
57
* This code only needs to execute once per JIT lifetime.
58
*/
59
static bool initTreeEvaluatorTable = false;
60
if (!initTreeEvaluatorTable)
61
{
62
TEMPORARY_initJ9ARM64TreeEvaluatorTable(cg);
63
initTreeEvaluatorTable = true;
64
}
65
66
cg->setSupportsInliningOfTypeCoersionMethods();
67
cg->setSupportsDivCheck();
68
if (!comp->getOption(TR_FullSpeedDebug))
69
cg->setSupportsDirectJNICalls();
70
71
cg->setSupportsPrimitiveArrayCopy();
72
cg->setSupportsReferenceArrayCopy();
73
74
static char *disableMonitorCacheLookup = feGetEnv("TR_disableMonitorCacheLookup");
75
if (!disableMonitorCacheLookup)
76
{
77
comp->setOption(TR_EnableMonitorCacheLookup);
78
}
79
}
80
81
TR::Linkage *
82
J9::ARM64::CodeGenerator::createLinkage(TR_LinkageConventions lc)
83
{
84
TR::Linkage *linkage;
85
switch (lc)
86
{
87
case TR_Private:
88
linkage = new (self()->trHeapMemory()) J9::ARM64::PrivateLinkage(self());
89
break;
90
case TR_System:
91
linkage = new (self()->trHeapMemory()) TR::ARM64SystemLinkage(self());
92
break;
93
case TR_CHelper:
94
case TR_Helper:
95
linkage = new (self()->trHeapMemory()) J9::ARM64::HelperLinkage(self(), lc);
96
break;
97
case TR_J9JNILinkage:
98
linkage = new (self()->trHeapMemory()) J9::ARM64::JNILinkage(self());
99
break;
100
default :
101
linkage = new (self()->trHeapMemory()) TR::ARM64SystemLinkage(self());
102
TR_ASSERT_FATAL(false, "Unexpected linkage convention");
103
}
104
105
self()->setLinkage(lc, linkage);
106
return linkage;
107
}
108
109
TR::Recompilation *
110
J9::ARM64::CodeGenerator::allocateRecompilationInfo()
111
{
112
return TR_ARM64Recompilation::allocate(self()->comp());
113
}
114
115
uint32_t
116
J9::ARM64::CodeGenerator::encodeHelperBranchAndLink(TR::SymbolReference *symRef, uint8_t *cursor, TR::Node *node, bool omitLink)
117
{
118
TR::CodeGenerator *cg = self();
119
uintptr_t target = (uintptr_t)symRef->getMethodAddress();
120
121
if (cg->directCallRequiresTrampoline(target, (intptr_t)cursor))
122
{
123
target = TR::CodeCacheManager::instance()->findHelperTrampoline(symRef->getReferenceNumber(), (void *)cursor);
124
125
TR_ASSERT_FATAL(cg->comp()->target().cpu.isTargetWithinUnconditionalBranchImmediateRange(target, (intptr_t)cursor),
126
"Target address is out of range");
127
}
128
129
cg->addExternalRelocation(new (cg->trHeapMemory()) TR::ExternalRelocation(
130
cursor,
131
(uint8_t *)symRef,
132
TR_HelperAddress, cg),
133
__FILE__, __LINE__, node);
134
135
uintptr_t distance = target - (uintptr_t)cursor;
136
return TR::InstOpCode::getOpCodeBinaryEncoding(omitLink ? (TR::InstOpCode::b) : (TR::InstOpCode::bl)) | ((distance >> 2) & 0x3ffffff); /* imm26 */
137
}
138
139
void
140
J9::ARM64::CodeGenerator::generateBinaryEncodingPrePrologue(TR_ARM64BinaryEncodingData &data)
141
{
142
TR::Compilation *comp = self()->comp();
143
TR::Node *startNode = comp->getStartTree()->getNode();
144
145
data.recomp = comp->getRecompilationInfo();
146
data.cursorInstruction = self()->getFirstInstruction();
147
data.i2jEntryInstruction = data.cursorInstruction;
148
149
if (data.recomp != NULL)
150
{
151
data.recomp->generatePrePrologue();
152
}
153
else
154
{
155
if (comp->getOption(TR_FullSpeedDebug) || comp->getOption(TR_SupportSwitchToInterpreter))
156
{
157
self()->generateSwitchToInterpreterPrePrologue(NULL, startNode);
158
}
159
else
160
{
161
TR::ResolvedMethodSymbol *methodSymbol = comp->getMethodSymbol();
162
/* save the original JNI native address if a JNI thunk is generated */
163
/* thunk is not recompilable, nor does it support FSD */
164
if (methodSymbol->isJNI())
165
{
166
uintptr_t methodAddress = reinterpret_cast<uintptr_t>(methodSymbol->getResolvedMethod()->startAddressForJNIMethod(comp));
167
uint32_t low = methodAddress & static_cast<uint32_t>(0xffffffff);
168
uint32_t high = (methodAddress >> 32) & static_cast<uint32_t>(0xffffffff);
169
TR::Instruction *cursor = new (self()->trHeapMemory()) TR::ARM64ImmInstruction(TR::InstOpCode::dd, startNode, low, NULL, self());
170
generateImmInstruction(self(), TR::InstOpCode::dd, startNode, high, cursor);
171
}
172
}
173
}
174
}
175
176
TR::Instruction *
177
J9::ARM64::CodeGenerator::generateSwitchToInterpreterPrePrologue(TR::Instruction *cursor, TR::Node *node)
178
{
179
TR::Compilation *comp = self()->comp();
180
TR::Register *x8 = self()->machine()->getRealRegister(TR::RealRegister::x8);
181
TR::Register *lr = self()->machine()->getRealRegister(TR::RealRegister::x30); // link register
182
TR::Register *xzr = self()->machine()->getRealRegister(TR::RealRegister::xzr); // zero register
183
TR::ResolvedMethodSymbol *methodSymbol = comp->getJittedMethodSymbol();
184
TR::SymbolReference *revertToInterpreterSymRef = self()->symRefTab()->findOrCreateRuntimeHelper(TR_ARM64revertToInterpreterGlue);
185
uintptr_t ramMethod = (uintptr_t)methodSymbol->getResolvedMethod()->resolvedMethodAddress();
186
TR::SymbolReference *helperSymRef = self()->symRefTab()->findOrCreateRuntimeHelper(TR_j2iTransition);
187
uintptr_t helperAddr = (uintptr_t)helperSymRef->getMethodAddress();
188
189
// x8 must contain the saved LR; see Recompilation.s
190
// cannot use generateMovInstruction() here
191
cursor = new (self()->trHeapMemory()) TR::ARM64Trg1Src2Instruction(TR::InstOpCode::orrx, node, x8, xzr, lr, cursor, self());
192
cursor = self()->getLinkage()->saveParametersToStack(cursor);
193
cursor = generateImmSymInstruction(self(), TR::InstOpCode::bl, node,
194
(uintptr_t)revertToInterpreterSymRef->getMethodAddress(),
195
new (self()->trHeapMemory()) TR::RegisterDependencyConditions(0, 0, self()->trMemory()),
196
revertToInterpreterSymRef, NULL, cursor);
197
cursor = generateRelocatableImmInstruction(self(), TR::InstOpCode::dd, node, (uintptr_t)ramMethod, TR_RamMethod, cursor);
198
199
if (comp->getOption(TR_EnableHCR))
200
comp->getStaticHCRPICSites()->push_front(cursor);
201
202
cursor = generateRelocatableImmInstruction(self(), TR::InstOpCode::dd, node, (uintptr_t)helperAddr, TR_AbsoluteHelperAddress, helperSymRef, cursor);
203
// Used in FSD to store an instruction
204
cursor = generateImmInstruction(self(), TR::InstOpCode::dd, node, 0, cursor);
205
206
return cursor;
207
}
208
209
bool
210
J9::ARM64::CodeGenerator::supportsInliningOfIsInstance()
211
{
212
return !self()->comp()->getOption(TR_DisableInlineIsInstance);
213
}
214
215
bool
216
J9::ARM64::CodeGenerator::suppressInliningOfRecognizedMethod(TR::RecognizedMethod method)
217
{
218
return false;
219
}
220
221