Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/aarch64/codegen/J9ARM64Snippet.cpp
6004 views
1
/*******************************************************************************
2
* Copyright (c) 2019, 2020 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 "j9.h"
24
25
#include "codegen/ARM64Instruction.hpp"
26
#include "codegen/CodeGenerator.hpp"
27
#include "codegen/GCStackAtlas.hpp"
28
#include "codegen/J9ARM64Snippet.hpp"
29
#include "codegen/Relocation.hpp"
30
#include "codegen/SnippetGCMap.hpp"
31
#include "runtime/CodeCacheManager.hpp"
32
33
TR::ARM64MonitorEnterSnippet::ARM64MonitorEnterSnippet(
34
TR::CodeGenerator *codeGen,
35
TR::Node *monitorNode,
36
TR::LabelSymbol *incLabel,
37
TR::LabelSymbol *callLabel,
38
TR::LabelSymbol *restartLabel)
39
: _incLabel(incLabel),
40
TR::ARM64HelperCallSnippet(codeGen, monitorNode, callLabel, monitorNode->getSymbolReference(), restartLabel)
41
{
42
// Helper call, preserves all registers
43
incLabel->setSnippet(this);
44
gcMap().setGCRegisterMask(0xFFFFFFFF);
45
}
46
47
uint8_t *
48
TR::ARM64MonitorEnterSnippet::emitSnippetBody()
49
{
50
// The AArch64 code for the snippet looks like:
51
//
52
// incLabel:
53
// and tempReg, dataReg, ~(OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT)
54
// cmp metaReg, tempReg
55
// bne callLabel
56
// add dataReg, dataReg, LOCK_INC_DEC_VALUE
57
// str dataReg, [addrReg]
58
// b restartLabel
59
// callLabel:
60
// bl jitMonitorEntry
61
// b restartLabel
62
63
TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();
64
65
TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();
66
TR::RealRegister *dataReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
67
TR::RealRegister *addrReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
68
TR::RealRegister *tempReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());
69
TR::RealRegister *zeroReg = cg()->machine()->getRealRegister(TR::RealRegister::xzr);
70
71
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());
72
TR::InstOpCode::Mnemonic op;
73
74
uint8_t *buffer = cg()->getBinaryBufferCursor();
75
76
_incLabel->setCodeLocation(buffer);
77
78
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::andimmx);
79
tempReg->setRegisterFieldRD((uint32_t *)buffer);
80
dataReg->setRegisterFieldRN((uint32_t *)buffer);
81
// OBJECT_HEADER_LOCK_BITS_MASK is 0xFF
82
// OBJECT_HEADER_LOCK_RECURSION_BIT is 0x80
83
// (OBJECT_HEADER_LOCK_BITS_MASK - OBJECT_HEADER_LOCK_LAST_RECURSION_BIT) is 0x7F
84
*(int32_t *)buffer |= 0x79E000; // immr=57, imms=56 for 0xFFFFFFFFFFFFFF80
85
buffer += ARM64_INSTRUCTION_LENGTH;
86
87
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::subsx); // for cmp
88
metaReg->setRegisterFieldRN((uint32_t *)buffer);
89
tempReg->setRegisterFieldRM((uint32_t *)buffer);
90
zeroReg->setRegisterFieldRD((uint32_t *)buffer);
91
buffer += ARM64_INSTRUCTION_LENGTH;
92
93
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b_cond);
94
*(int32_t *)buffer |= ((4 << 5) | TR::CC_NE); // 4 instructions forward, bne
95
buffer += ARM64_INSTRUCTION_LENGTH;
96
97
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::addimmx);
98
dataReg->setRegisterFieldRD((uint32_t *)buffer);
99
dataReg->setRegisterFieldRN((uint32_t *)buffer);
100
*(int32_t *)buffer |= ((LOCK_INC_DEC_VALUE & 0xFFF) << 10); // imm12
101
buffer += ARM64_INSTRUCTION_LENGTH;
102
103
op = fej9->generateCompressedLockWord() ? TR::InstOpCode::strimmw : TR::InstOpCode::strimmx;
104
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(op);
105
dataReg->setRegisterFieldRT((uint32_t *)buffer);
106
addrReg->setRegisterFieldRN((uint32_t *)buffer);
107
// offset 0 -- no need to encode
108
buffer += ARM64_INSTRUCTION_LENGTH;
109
110
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b);
111
intptr_t destination = (intptr_t)getRestartLabel()->getCodeLocation();
112
TR_ASSERT(!cg()->directCallRequiresTrampoline(destination, (intptr_t)buffer), "Jump target too far away.");
113
intptr_t distance = (intptr_t)destination - (intptr_t)buffer;
114
*(int32_t *)buffer |= ((distance >> 2) & 0x3FFFFFF); // imm26
115
buffer += ARM64_INSTRUCTION_LENGTH;
116
117
cg()->setBinaryBufferCursor(buffer);
118
buffer = TR::ARM64HelperCallSnippet::emitSnippetBody(); // x0 holds the object
119
120
return buffer;
121
}
122
123
void
124
TR::ARM64MonitorEnterSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)
125
{
126
uint8_t *cursor = getIncLabel()->getCodeLocation();
127
128
debug->printSnippetLabel(pOutFile, getIncLabel(), cursor, "Inc Monitor Counter");
129
}
130
131
uint32_t TR::ARM64MonitorEnterSnippet::getLength(int32_t estimatedSnippetStart)
132
{
133
int32_t len = 6 * ARM64_INSTRUCTION_LENGTH;
134
return len + TR::ARM64HelperCallSnippet::getLength(estimatedSnippetStart+len);
135
}
136
137
int32_t TR::ARM64MonitorEnterSnippet::setEstimatedCodeLocation(int32_t estimatedSnippetStart)
138
{
139
_incLabel->setEstimatedCodeLocation(estimatedSnippetStart);
140
getSnippetLabel()->setEstimatedCodeLocation(estimatedSnippetStart + 6 * ARM64_INSTRUCTION_LENGTH);
141
return estimatedSnippetStart;
142
}
143
144
145
TR::ARM64MonitorExitSnippet::ARM64MonitorExitSnippet(
146
TR::CodeGenerator *codeGen,
147
TR::Node *monitorNode,
148
TR::LabelSymbol *decLabel,
149
TR::LabelSymbol *callLabel,
150
TR::LabelSymbol *restartLabel)
151
: _decLabel(decLabel),
152
TR::ARM64HelperCallSnippet(codeGen, monitorNode, callLabel, monitorNode->getSymbolReference(), restartLabel)
153
{
154
// Helper call, preserves all registers
155
decLabel->setSnippet(this);
156
gcMap().setGCRegisterMask(0xFFFFFFFF);
157
}
158
159
uint8_t *
160
TR::ARM64MonitorExitSnippet::emitSnippetBody()
161
{
162
// The AArch64 code for the snippet looks like:
163
//
164
// decLabel:
165
// and tempReg, dataReg, ~OBJECT_HEADER_LOCK_RECURSION_MASK
166
// cmp metaReg, tempReg
167
// bne callLabel
168
// sub dataReg, dataReg, LOCK_INC_DEC_VALUE
169
// str dataReg, [addrReg]
170
// b restartLabel
171
// callLabel:
172
// bl jitMonitorExit
173
// b restartLabel
174
175
TR::RegisterDependencyConditions *deps = getRestartLabel()->getInstruction()->getDependencyConditions();
176
177
TR::RealRegister *metaReg = cg()->getMethodMetaDataRegister();
178
TR::RealRegister *dataReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(1)->getRealRegister());
179
TR::RealRegister *addrReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(2)->getRealRegister());
180
TR::RealRegister *tempReg = cg()->machine()->getRealRegister(deps->getPostConditions()->getRegisterDependency(3)->getRealRegister());
181
TR::RealRegister *zeroReg = cg()->machine()->getRealRegister(TR::RealRegister::xzr);
182
183
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg()->fe());
184
TR::InstOpCode::Mnemonic op;
185
186
uint8_t *buffer = cg()->getBinaryBufferCursor();
187
188
_decLabel->setCodeLocation(buffer);
189
190
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::andimmx);
191
tempReg->setRegisterFieldRD((uint32_t *)buffer);
192
dataReg->setRegisterFieldRN((uint32_t *)buffer);
193
// OBJECT_HEADER_LOCK_RECURSION_MASK is 0xF8
194
*(int32_t *)buffer |= 0x78E800; // immr=56, imms=58 for 0xFFFFFFFFFFFFFF07
195
buffer += ARM64_INSTRUCTION_LENGTH;
196
197
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::subsx); // for cmp
198
metaReg->setRegisterFieldRN((uint32_t *)buffer);
199
tempReg->setRegisterFieldRM((uint32_t *)buffer);
200
zeroReg->setRegisterFieldRD((uint32_t *)buffer);
201
buffer += ARM64_INSTRUCTION_LENGTH;
202
203
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b_cond);
204
*(int32_t *)buffer |= ((4 << 5) | TR::CC_NE); // 4 instructions forward, bne
205
buffer += ARM64_INSTRUCTION_LENGTH;
206
207
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::subimmx);
208
dataReg->setRegisterFieldRD((uint32_t *)buffer);
209
dataReg->setRegisterFieldRN((uint32_t *)buffer);
210
*(int32_t *)buffer |= ((LOCK_INC_DEC_VALUE & 0xFFF) << 10); // imm12
211
buffer += ARM64_INSTRUCTION_LENGTH;
212
213
op = fej9->generateCompressedLockWord() ? TR::InstOpCode::strimmw : TR::InstOpCode::strimmx;
214
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(op);
215
dataReg->setRegisterFieldRT((uint32_t *)buffer);
216
addrReg->setRegisterFieldRN((uint32_t *)buffer);
217
// offset 0 -- no need to encode
218
buffer += ARM64_INSTRUCTION_LENGTH;
219
220
*(int32_t *)buffer = TR::InstOpCode::getOpCodeBinaryEncoding(TR::InstOpCode::b);
221
intptr_t destination = (intptr_t)getRestartLabel()->getCodeLocation();
222
TR_ASSERT(!cg()->directCallRequiresTrampoline(destination, (intptr_t)buffer), "Jump target too far away.");
223
intptr_t distance = (intptr_t)destination - (intptr_t)buffer;
224
*(int32_t *)buffer |= ((distance >> 2) & 0x3FFFFFF); // imm26
225
buffer += ARM64_INSTRUCTION_LENGTH;
226
227
cg()->setBinaryBufferCursor(buffer);
228
buffer = TR::ARM64HelperCallSnippet::emitSnippetBody(); // x0 holds the object
229
230
return buffer;
231
}
232
233
void
234
TR::ARM64MonitorExitSnippet::print(TR::FILE *pOutFile, TR_Debug *debug)
235
{
236
uint8_t *cursor = getDecLabel()->getCodeLocation();
237
debug->printSnippetLabel(pOutFile, getDecLabel(), cursor, "Dec Monitor Counter");
238
}
239
240
uint32_t
241
TR::ARM64MonitorExitSnippet::getLength(int32_t estimatedSnippetStart)
242
{
243
int32_t len = 6 * ARM64_INSTRUCTION_LENGTH;
244
return len + TR::ARM64HelperCallSnippet::getLength(estimatedSnippetStart+len);
245
}
246
247
int32_t TR::ARM64MonitorExitSnippet::setEstimatedCodeLocation(int32_t estimatedSnippetStart)
248
{
249
_decLabel->setEstimatedCodeLocation(estimatedSnippetStart);
250
getSnippetLabel()->setEstimatedCodeLocation(estimatedSnippetStart + 6 * ARM64_INSTRUCTION_LENGTH);
251
return estimatedSnippetStart;
252
}
253
254