Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/env/J2IThunk.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2022 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 "env/J2IThunk.hpp"
24
25
#include "env/CompilerEnv.hpp"
26
#include "codegen/CodeGenerator.hpp"
27
#include "infra/Array.hpp"
28
#include "infra/Monitor.hpp"
29
#include "env/IO.hpp"
30
#include "infra/CriticalSection.hpp"
31
#include "env/j9method.h"
32
#include "env/VMJ9.h"
33
#include "env/VerboseLog.hpp"
34
35
#if defined(OSX) && defined(AARCH64)
36
#include <pthread.h> // for pthread_jit_write_protect_np
37
#endif
38
39
static int32_t
40
computeSignatureLength(char *signature)
41
{
42
char *currentArgument;
43
for (currentArgument = signature+1; currentArgument[0] != ')'; currentArgument = nextSignatureArgument(currentArgument))
44
{}
45
currentArgument = nextSignatureArgument(currentArgument+1);
46
return currentArgument - signature;
47
}
48
49
50
TR_J2IThunk *
51
TR_J2IThunk::allocate(
52
int16_t codeSize,
53
char *signature,
54
TR::CodeGenerator *cg,
55
TR_J2IThunkTable *thunkTable)
56
{
57
int16_t terseSignatureBufLength = thunkTable->terseSignatureLength(signature)+1;
58
int16_t totalSize = (int16_t)sizeof(TR_J2IThunk) + codeSize + terseSignatureBufLength;
59
TR_J2IThunk *result;
60
#if defined(J9VM_OPT_JITSERVER)
61
if (cg->comp()->isOutOfProcessCompilation())
62
{
63
// Don't need to use code cache because the entire thunk will be copied and sent to the client
64
result = (TR_J2IThunk*)cg->comp()->trMemory()->allocateMemory(totalSize, heapAlloc);
65
}
66
else
67
#endif /* defined(J9VM_OPT_JITSERVER) */
68
{
69
result = (TR_J2IThunk*)cg->allocateCodeMemory(totalSize, true, false);
70
}
71
#if defined(OSX) && defined(AARCH64)
72
pthread_jit_write_protect_np(0);
73
#endif
74
result->_codeSize = codeSize;
75
result->_totalSize = totalSize;
76
thunkTable->getTerseSignature(result->terseSignature(), terseSignatureBufLength, signature);
77
#if defined(OSX) && defined(AARCH64)
78
pthread_jit_write_protect_np(1);
79
#endif
80
return result;
81
}
82
83
84
TR_J2IThunkTable::TR_J2IThunkTable(TR_PersistentMemory *m, char *name):
85
_name(name),
86
_monitor(TR::Monitor::create(name)),
87
_nodes(m)
88
{
89
_nodes.setSize(1); // Initially just the root node
90
}
91
92
93
int16_t
94
TR_J2IThunkTable::terseSignatureLength(char *signature)
95
{
96
int16_t numArgs = 0;
97
for (char *currentArgument = signature+1; currentArgument[0] != ')'; currentArgument = nextSignatureArgument(currentArgument))
98
numArgs++;
99
return numArgs+1; // +1 for return type char
100
}
101
102
103
void TR_J2IThunkTable::getTerseSignature(char *buf, int16_t bufLength, char *signature)
104
{
105
int16_t i=0;
106
char *currentArgument;
107
for (currentArgument = signature+1; currentArgument[0] != ')'; currentArgument = nextSignatureArgument(currentArgument))
108
buf[i++] = terseTypeChar(currentArgument);
109
TR_ASSERT(i <= bufLength-2, "Must have room for return type and null terminator");
110
buf[i++] = terseTypeChar(currentArgument+1); // return type
111
buf[i++] = 0; // null terminator
112
}
113
114
115
char TR_J2IThunkTable::terseTypeChar(char *type)
116
{
117
switch (type[0])
118
{
119
case '[':
120
case 'L':
121
case 'Q':
122
return TR::Compiler->target.is64Bit()? 'L' : 'I';
123
case 'Z':
124
case 'B':
125
case 'S':
126
case 'C':
127
return 'I';
128
default:
129
return type[0];
130
}
131
}
132
133
134
TR_J2IThunkTable::Node *
135
TR_J2IThunkTable::Node::get(
136
char *terseSignature,
137
TR_PersistentArray<Node> &nodeArray,
138
bool createIfMissing)
139
{
140
Node *result = NULL;
141
if (terseSignature[0] == 0)
142
{
143
// We've reached the matching node
144
result = this;
145
}
146
else
147
{
148
int32_t typeIndex = typeCharIndex(terseSignature[0]);
149
ChildIndex childIndex = _children[typeIndex];
150
if (!childIndex && createIfMissing)
151
{
152
_children[typeIndex] = childIndex = nodeArray.size();
153
Node emptyNode = {0};
154
155
// CAREFUL! The following call can realloc the node array, including the
156
// receiver of this very method we're in. Don't access "this" anymore
157
// in this function after this point!
158
//
159
nodeArray.add(emptyNode);
160
}
161
if (childIndex)
162
result = nodeArray[childIndex].get(terseSignature+1, nodeArray, createIfMissing);
163
else
164
result = NULL;
165
}
166
return result;
167
}
168
169
170
TR_J2IThunk *
171
TR_J2IThunkTable::findThunk(
172
char *signature,
173
TR_FrontEnd *fe,
174
bool isForCurrentRun)
175
{
176
char terseSignature[260]; // 256 args + 1 return type + null terminator
177
getTerseSignature(terseSignature, sizeof(terseSignature), signature);
178
return findThunkFromTerseSignature(terseSignature, fe, isForCurrentRun);
179
}
180
181
182
TR_J2IThunk *
183
TR_J2IThunkTable::getThunk(char *signature, TR_FrontEnd *fe, bool isForCurrentRun)
184
{
185
TR_J2IThunk *result = findThunk(signature, fe, isForCurrentRun);
186
if (!result)
187
{
188
char terseSignature[260]; // 256 args + 1 return type + null terminator
189
dumpTo(fe, TR::IO::Stderr);
190
getTerseSignature(terseSignature, sizeof(terseSignature), signature);
191
trfprintf(TR::IO::Stderr, "\nERROR: Failed to find J2I thunk for %s signature %.*s\n", terseSignature, computeSignatureLength(signature), signature);
192
TR_ASSERT(result != NULL, "Expected a J2I thunk for %s signature %.*s", terseSignature, computeSignatureLength(signature), signature);
193
}
194
return result;
195
}
196
197
198
TR_J2IThunk *
199
TR_J2IThunkTable::findThunkFromTerseSignature(
200
char *terseSignature,
201
TR_FrontEnd *fe,
202
bool isForCurrentRun)
203
{
204
TR_J9VMBase *fej9 = (TR_J9VMBase *)(fe);
205
TR_J2IThunk *returnThunk = NULL;
206
207
if (fej9->isAOT_DEPRECATED_DO_NOT_USE() && !isForCurrentRun)
208
{
209
// Must use persistent thunks for compiles that will persist
210
return (TR_J2IThunk *)fej9->findPersistentJ2IThunk(terseSignature);
211
}
212
else
213
{
214
OMR::CriticalSection critialSection(_monitor);
215
216
Node *match = root()->get(terseSignature, _nodes, false);
217
returnThunk = match ? match->_thunk : NULL;
218
}
219
220
return returnThunk;
221
}
222
223
224
void
225
TR_J2IThunkTable::addThunk(
226
TR_J2IThunk *thunk,
227
TR_FrontEnd *fe, bool
228
isForCurrentRun)
229
{
230
TR_J9VMBase *fej9 = (TR_J9VMBase *)(fe);
231
232
if (fej9->isAOT_DEPRECATED_DO_NOT_USE() && !isForCurrentRun)
233
{
234
// Must use persistent thunks for compiles that will persist
235
fej9->persistJ2IThunk(thunk);
236
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJ2IThunks))
237
TR_VerboseLog::writeLineLocked(TR_Vlog_J2I,"persist %s @%p", thunk->terseSignature(), thunk);
238
}
239
else
240
{
241
OMR::CriticalSection criticalSection(_monitor);
242
243
Node *match = root()->get(thunk->terseSignature(), _nodes, true);
244
match->_thunk = thunk;
245
246
// This assume must be in the monitor or else another thread could break it
247
TR_ASSERT(findThunkFromTerseSignature(thunk->terseSignature(), fe, isForCurrentRun) == thunk, "TR_J2IThunkTable: setThunk must cause findThunk(%s) to return %p", thunk->terseSignature(), thunk);
248
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJ2IThunks))
249
TR_VerboseLog::writeLineLocked(TR_Vlog_J2I,"add %s @%p", thunk->terseSignature(), thunk);
250
}
251
}
252
253
254
void
255
TR_J2IThunkTable::Node::dumpTo(
256
TR_FrontEnd *fe,
257
TR::FILE *file,
258
TR_PersistentArray<Node> &nodeArray,
259
int indent)
260
{
261
static const char typeChars[] = "VIJFDL";
262
if (_thunk)
263
trfprintf(file, " %s @%p\n", _thunk->terseSignature(), _thunk);
264
else
265
trfprintf(file, "\n");
266
for (int32_t typeIndex = 0; typeIndex < NUM_TYPE_CHARS; typeIndex++)
267
{
268
if (_children[typeIndex])
269
{
270
trfprintf(file, "%*s%c @%d:", indent*3, "", typeChars[typeIndex], _children[typeIndex]);
271
nodeArray[_children[typeIndex]].dumpTo(fe, file, nodeArray, indent+1);
272
}
273
}
274
}
275
276
277
void
278
TR_J2IThunkTable::dumpTo(TR_FrontEnd *fe, TR::FILE *file)
279
{
280
OMR::CriticalSection criticalSection(_monitor);
281
trfprintf(file, "J2IThunkTable \"%s\":", _name);
282
root()->dumpTo(fe, file, _nodes, 1);
283
}
284
285