Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/ilgen/J9IlGeneratorMethodDetails.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 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 "env/FrontEnd.hpp"
24
#include "env/KnownObjectTable.hpp"
25
#include "compile/Compilation.hpp"
26
#include "compile/InlineBlock.hpp"
27
#include "compile/Method.hpp"
28
#include "compile/ResolvedMethod.hpp"
29
#include "env/CompilerEnv.hpp"
30
#include "env/IO.hpp"
31
#include "env/jittypes.h"
32
#include "env/VMAccessCriticalSection.hpp"
33
#include "il/TreeTop.hpp"
34
#include "il/TreeTop_inlines.hpp"
35
#include "ilgen/IlGeneratorMethodDetails_inlines.hpp"
36
#include "ilgen/J9ByteCodeIlGenerator.hpp"
37
#include "env/VMJ9.h"
38
39
40
41
namespace J9
42
{
43
44
TR::IlGeneratorMethodDetails *
45
IlGeneratorMethodDetails::clone(TR::IlGeneratorMethodDetails &storage, const TR::IlGeneratorMethodDetails & other)
46
{
47
// The if nest below covers every concrete subclass of IlGeneratorMethodDetails.
48
// If other is not one of these classes, then it will assert.
49
50
if (other.isOrdinaryMethod())
51
return new (&storage) TR::IlGeneratorMethodDetails(static_cast<const TR::IlGeneratorMethodDetails &>(other));
52
else if (other.isJitDumpMethod())
53
return new (&storage) JitDumpMethodDetails(static_cast<const JitDumpMethodDetails &>(other));
54
else if (other.isNewInstanceThunk())
55
return new (&storage) NewInstanceThunkDetails(static_cast<const NewInstanceThunkDetails &>(other));
56
else if (other.isMethodInProgress())
57
return new (&storage) MethodInProgressDetails(static_cast<const MethodInProgressDetails &>(other));
58
else if (other.isMethodHandleThunk())
59
{
60
if (static_cast<const MethodHandleThunkDetails &>(other).isShareable())
61
return new (&storage) ShareableInvokeExactThunkDetails(static_cast<const ShareableInvokeExactThunkDetails &>(other));
62
else if (static_cast<const MethodHandleThunkDetails &>(other).isCustom())
63
return new (&storage) CustomInvokeExactThunkDetails(static_cast<const CustomInvokeExactThunkDetails &>(other));
64
}
65
66
TR_ASSERT(0, "Unexpected IlGeneratorMethodDetails object\n");
67
return NULL; // error case
68
}
69
70
71
#if defined(J9VM_OPT_JITSERVER)
72
TR::IlGeneratorMethodDetails *
73
IlGeneratorMethodDetails::clone(TR::IlGeneratorMethodDetails &storage, const TR::IlGeneratorMethodDetails & other, const IlGeneratorMethodDetailsType type)
74
{
75
// The if nest below covers every concrete subclass of IlGeneratorMethodDetails.
76
// If other is not one of these classes, then it will assert.
77
78
if (type & ORDINARY_METHOD)
79
return new (&storage) TR::IlGeneratorMethodDetails(static_cast<const TR::IlGeneratorMethodDetails &>(other));
80
else if (type & DUMP_METHOD)
81
return new (&storage) JitDumpMethodDetails(static_cast<const JitDumpMethodDetails &>(other));
82
else if (type & NEW_INSTANCE_THUNK)
83
return new (&storage) NewInstanceThunkDetails(static_cast<const NewInstanceThunkDetails &>(other));
84
else if (type & METHOD_IN_PROGRESS)
85
return new (&storage) MethodInProgressDetails(static_cast<const MethodInProgressDetails &>(other));
86
else if (type & METHOD_HANDLE_THUNK)
87
{
88
if (type & SHAREABLE_THUNK)
89
return new (&storage) ShareableInvokeExactThunkDetails(static_cast<const ShareableInvokeExactThunkDetails &>(other));
90
else if (type & CUSTOM_THUNK)
91
return new (&storage) CustomInvokeExactThunkDetails(static_cast<const CustomInvokeExactThunkDetails &>(other));
92
}
93
94
TR_ASSERT(0, "Unexpected IlGeneratorMethodDetails object\n");
95
return NULL; // error case
96
}
97
#endif /* defined(J9VM_OPT_JITSERVER) */
98
99
100
IlGeneratorMethodDetails::IlGeneratorMethodDetails(const TR::IlGeneratorMethodDetails & other) :
101
_method(other.getMethod())
102
{
103
}
104
105
106
IlGeneratorMethodDetails::IlGeneratorMethodDetails(TR_ResolvedMethod *method)
107
{
108
_method = (J9Method *)(method->getPersistentIdentifier());
109
}
110
111
const J9ROMClass *
112
IlGeneratorMethodDetails::getRomClass() const
113
{
114
return J9_CLASS_FROM_METHOD(self()->getMethod())->romClass;
115
}
116
117
const J9ROMMethod *
118
IlGeneratorMethodDetails::getRomMethod(TR_J9VMBase *fe)
119
{
120
return fe->getROMMethodFromRAMMethod(self()->getMethod());
121
}
122
123
#if defined(J9VM_OPT_JITSERVER)
124
IlGeneratorMethodDetailsType
125
IlGeneratorMethodDetails::getType() const
126
{
127
int type = EMPTY;
128
if (self()->isOrdinaryMethod()) type |= ORDINARY_METHOD;
129
if (self()->isJitDumpMethod()) type |= DUMP_METHOD;
130
if (self()->isNewInstanceThunk()) type |= NEW_INSTANCE_THUNK;
131
if (self()->isMethodInProgress()) type |= METHOD_IN_PROGRESS;
132
if (self()->isArchetypeSpecimen()) type |= ARCHETYPE_SPECIMEN;
133
if (self()->isMethodHandleThunk())
134
{
135
type |= METHOD_HANDLE_THUNK;
136
if (static_cast<const MethodHandleThunkDetails *>(self())->isShareable())
137
type |= SHAREABLE_THUNK;
138
else if (static_cast<const MethodHandleThunkDetails *>(self())->isCustom())
139
type |= CUSTOM_THUNK;
140
}
141
return (IlGeneratorMethodDetailsType) type;
142
}
143
#endif /* defined(J9VM_OPT_JITSERVER) */
144
145
146
bool
147
IlGeneratorMethodDetails::sameAs(TR::IlGeneratorMethodDetails & other, TR_FrontEnd *fe)
148
{
149
return other.isOrdinaryMethod() && self()->sameMethod(other);
150
}
151
152
153
bool
154
IlGeneratorMethodDetails::sameMethod(TR::IlGeneratorMethodDetails & other)
155
{
156
return (other.getMethod() == self()->getMethod());
157
}
158
159
160
TR::IlGeneratorMethodDetails & IlGeneratorMethodDetails::create(
161
TR::IlGeneratorMethodDetails & target,
162
TR_ResolvedMethod *method)
163
{
164
165
TR_ResolvedJ9Method * j9method = static_cast<TR_ResolvedJ9Method *>(method);
166
167
if (j9method->isNewInstanceImplThunk())
168
return * new (&target) NewInstanceThunkDetails((J9Method *)j9method->getNonPersistentIdentifier(), (J9Class *)j9method->classOfMethod());
169
170
else if (j9method->convertToMethod()->isArchetypeSpecimen())
171
{
172
if (j9method->getMethodHandleLocation())
173
return * new (&target) CustomInvokeExactThunkDetails((J9Method *)j9method->getNonPersistentIdentifier(), j9method->getMethodHandleLocation(), NULL);
174
else
175
return * new (&target) ArchetypeSpecimenDetails((J9Method *)j9method->getNonPersistentIdentifier());
176
}
177
178
return * new (&target) TR::IlGeneratorMethodDetails((J9Method *)j9method->getNonPersistentIdentifier());
179
180
}
181
182
183
TR_IlGenerator *
184
IlGeneratorMethodDetails::getIlGenerator(TR::ResolvedMethodSymbol *methodSymbol,
185
TR_FrontEnd * fe,
186
TR::Compilation *comp,
187
TR::SymbolReferenceTable *symRefTab,
188
bool forceClassLookahead,
189
TR_InlineBlocks *blocksToInline)
190
{
191
TR_ASSERT((J9Method *)methodSymbol->getResolvedMethod()->getNonPersistentIdentifier() == self()->getMethod(),
192
"getIlGenerator methodSymbol must match _method");
193
194
return new (comp->trHeapMemory()) TR_J9ByteCodeIlGenerator(*(self()),
195
methodSymbol,
196
static_cast<TR_J9VMBase *>(fe),
197
comp,
198
symRefTab,
199
forceClassLookahead,
200
blocksToInline,
201
-1);
202
}
203
204
205
void
206
IlGeneratorMethodDetails::print(TR_FrontEnd *fe, TR::FILE *file)
207
{
208
if (file == NULL)
209
return;
210
211
trfprintf(file, "%s(", self()->name());
212
self()->printDetails(fe, file);
213
trfprintf(file, ")");
214
}
215
216
217
void
218
IlGeneratorMethodDetails::printDetails(TR_FrontEnd *fe, TR::FILE *file)
219
{
220
trfprintf(file, "%s", fe->sampleSignature((TR_OpaqueMethodBlock *)(self()->getMethod())));
221
}
222
223
J9Class *
224
IlGeneratorMethodDetails::getClass() const
225
{
226
return J9_CLASS_FROM_METHOD(self()->getMethod());
227
}
228
229
230
void
231
IlGeneratorMethodDetailsOverrideForReplay::changeMethod(
232
TR::IlGeneratorMethodDetails & details,
233
J9Method *newMethod)
234
{
235
details._method = newMethod;
236
}
237
238
239
void
240
NewInstanceThunkDetails::printDetails(TR_FrontEnd *fe, TR::FILE *file)
241
{
242
int32_t len;
243
TR_J9VMBase *fej9 = (TR_J9VMBase *)fe;
244
char *className = fej9->getClassNameChars((TR_OpaqueClassBlock *)getClass(), len);
245
trfprintf(file, "%.*s.newInstancePrototype(Ljava/lang/Class;)Ljava/lang/Object;", len, className);
246
}
247
248
249
void
250
MethodInProgressDetails::printDetails(TR_FrontEnd *fe, TR::FILE *file)
251
{
252
trfprintf(file, "DLT %d,%s", getByteCodeIndex(), fe->sampleSignature((TR_OpaqueMethodBlock *)getMethod()));
253
}
254
255
256
TR_IlGenerator *
257
ArchetypeSpecimenDetails::getIlGenerator(TR::ResolvedMethodSymbol *methodSymbol,
258
TR_FrontEnd * fe,
259
TR::Compilation *comp,
260
TR::SymbolReferenceTable *symRefTab,
261
bool forceClassLookahead,
262
TR_InlineBlocks *blocksToInline)
263
{
264
TR_ASSERT((J9Method *)methodSymbol->getResolvedMethod()->getNonPersistentIdentifier() == getMethod(),
265
"getIlGenerator methodSymbol must match _method");
266
267
// Figure out the argPlaceholderSlot, which is the slot number of the last argument.
268
// Note that this creates and discards a TR_ResolvedMethod. TODO: A query
269
// on J9MethodBase could avoid this.
270
//
271
TR_ResolvedMethod *method = fe->createResolvedMethod(comp->trMemory(), (TR_OpaqueMethodBlock *)getMethod());
272
int32_t argPlaceholderSlot = method->numberOfParameterSlots()-1; // Assumes the arg placeholder is a 1-slot type
273
274
return new (comp->trHeapMemory()) TR_J9ByteCodeIlGenerator(*this,
275
methodSymbol,
276
static_cast<TR_J9VMBase *>(fe),
277
comp,
278
symRefTab,
279
forceClassLookahead,
280
blocksToInline,
281
argPlaceholderSlot);
282
}
283
284
285
void
286
MethodHandleThunkDetails::printDetails(TR_FrontEnd *fe, TR::FILE *file)
287
{
288
#if 0
289
// annoying: knot can only be accessed from the compilation object which isn't always handy: wait for thread locals
290
TR::KnownObjectTable *knot = fe->getKnownObjectTable();
291
if (knot)
292
trfprintf(file, "obj%d,%s", knot->getOrCreateIndexAt(getHandleRef()), fe->sampleSignature((TR_OpaqueMethodBlock *)getMethod()));
293
else
294
#endif
295
trfprintf(file, "%p,%s", getHandleRef(), fe->sampleSignature((TR_OpaqueMethodBlock *)getMethod()));
296
}
297
298
299
bool
300
MethodHandleThunkDetails::isSameThunk(MethodHandleThunkDetails &other, TR_J9VMBase *fe)
301
{
302
TR_ASSERT(0, "MethodHandleThunk must be either shareable or custom");
303
return false;
304
}
305
306
307
bool
308
ShareableInvokeExactThunkDetails::isSameThunk(MethodHandleThunkDetails & other, TR_J9VMBase *fe)
309
{
310
if (!other.isShareable())
311
return false;
312
313
uintptr_t thisThunkTuple, otherThunkTuple;
314
315
// Consider: there is a race condition here. If there are two shareable thunks requested,
316
// and then we change the thunktuple of one of the handles, then this code will not detect
317
// the dup and we'll end up compiling two identical thunks.
318
//
319
{
320
TR::VMAccessCriticalSection isSameThunk(fe);
321
thisThunkTuple = fe->getReferenceField(*this->getHandleRef(), "thunks", "Ljava/lang/invoke/ThunkTuple;");
322
otherThunkTuple = fe->getReferenceField(*other.getHandleRef(), "thunks", "Ljava/lang/invoke/ThunkTuple;");
323
}
324
325
// Same MethodHandle thunk request iff the two requests point to the same ThunkTuple
326
return thisThunkTuple == otherThunkTuple;
327
}
328
329
330
bool
331
CustomInvokeExactThunkDetails::isSameThunk(MethodHandleThunkDetails & other, TR_J9VMBase *fe)
332
{
333
if (!other.isCustom())
334
return false;
335
336
bool bothHaveNullArg = false;
337
if (this->getArgRef() == NULL)
338
{
339
if (other.getArgRef() == NULL)
340
bothHaveNullArg = true;
341
else
342
return false;
343
}
344
else if (other.getArgRef() == NULL)
345
return false;
346
347
bool sameHandle, sameArg;
348
349
{
350
TR::VMAccessCriticalSection isSameThunk(fe);
351
sameHandle = (*this->getHandleRef()) == (*other.getHandleRef());
352
sameArg = bothHaveNullArg || ((*this->getArgRef()) == (*other.getArgRef()));
353
}
354
355
// Same thunk request iff it's for the same handle with the same arg
356
return sameHandle && sameArg;
357
}
358
359
}
360
361