Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/il/J9SymbolReference.cpp
6000 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 "il/J9SymbolReference.hpp"
24
25
#include <stdint.h>
26
#include "compile/Compilation.hpp"
27
#include "compile/Method.hpp"
28
#include "env/CompilerEnv.hpp"
29
#include "env/VMAccessCriticalSection.hpp"
30
#include "il/ParameterSymbol.hpp"
31
#include "il/StaticSymbol.hpp"
32
#include "il/Symbol.hpp"
33
#include "il/SymbolReference.hpp"
34
#include "env/KnownObjectTable.hpp"
35
#include "runtime/RuntimeAssumptions.hpp"
36
#include "env/CHTable.hpp"
37
#include "env/PersistentCHTable.hpp"
38
#include "env/VMJ9.h"
39
40
namespace J9
41
{
42
43
SymbolReference::SymbolReference(
44
TR::SymbolReferenceTable *symRefTab,
45
TR::Symbol *sym,
46
mcount_t owningMethodIndex,
47
int32_t cpIndex,
48
int32_t unresolvedIndex,
49
TR::KnownObjectTable::Index knownObjectIndex)
50
{
51
self()->init(symRefTab,
52
symRefTab->assignSymRefNumber(self()),
53
sym,
54
0, // Offset 0
55
owningMethodIndex,
56
cpIndex,
57
unresolvedIndex);
58
59
_knownObjectIndex = knownObjectIndex;
60
61
if (sym->isResolvedMethod())
62
symRefTab->comp()->registerResolvedMethodSymbolReference(self());
63
64
//Check for init method
65
if (sym->isMethod() &&
66
sym->castToMethodSymbol()->getMethod()->isConstructor())
67
{
68
self()->setInitMethod();
69
}
70
71
symRefTab->checkImmutable(self());
72
}
73
74
75
static char * dataTypeToSig[] = {0,"B","Z","C","S","I","J","F","D",0,0,0};
76
77
/**
78
* This method is used when _cpIndex is to be used for resolution.
79
* For any other purpose, use getCPIndex().
80
*
81
* This method explicitly clears unused higher order bits in _cpIndex to
82
* avoid undesired sign extension.
83
*/
84
uint32_t
85
SymbolReference::getCPIndexForVM()
86
{
87
uint32_t index = (uint32_t) self()->getCPIndex();
88
return index & 0x3FFFF; // return lower order 18 bits
89
}
90
91
bool
92
SymbolReference::isClassArray(TR::Compilation * c)
93
{
94
TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();
95
if (sym == NULL || self()->isUnresolved())
96
return false;
97
98
return TR::Compiler->cls.isClassArray(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());
99
}
100
101
bool
102
SymbolReference::isClassFinal(TR::Compilation * c)
103
{
104
TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();
105
if (sym == NULL || self()->isUnresolved())
106
return false;
107
108
return TR::Compiler->cls.isClassFinal(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());
109
}
110
111
bool
112
SymbolReference::isClassAbstract(TR::Compilation * c)
113
{
114
TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();
115
if (sym == NULL || self()->isUnresolved())
116
return false;
117
118
return TR::Compiler->cls.isAbstractClass(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());
119
}
120
121
bool
122
SymbolReference::isClassInterface(TR::Compilation * c)
123
{
124
TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();
125
if (sym == NULL || self()->isUnresolved())
126
return false;
127
128
return TR::Compiler->cls.isInterfaceClass(c, (TR_OpaqueClassBlock *) sym->getStaticAddress());
129
}
130
131
// resolved final class that is not an array returns TRUE
132
bool
133
SymbolReference::isNonArrayFinal(TR::Compilation * c)
134
{
135
TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();
136
if (sym == NULL || self()->isUnresolved())
137
{
138
return false;
139
}
140
return !self()->isClassArray(c) && self()->isClassFinal(c);
141
}
142
143
int32_t
144
SymbolReference::classDepth(TR::Compilation * c)
145
{
146
TR::StaticSymbol * sym = self()->getSymbol()->getStaticSymbol();
147
if (sym == NULL || self()->isUnresolved())
148
{
149
return -1;
150
}
151
return (int32_t)TR::Compiler->cls.classDepthOf((TR_OpaqueClassBlock *) sym->getStaticAddress());
152
}
153
154
155
char *
156
prependNumParensToSig(const char *name, int32_t &len, int32_t numParens, TR_AllocationKind allocKind)
157
{
158
TR::Compilation * comp = TR::comp();
159
char * sig;
160
161
len += numParens;
162
sig = (char *)comp->trMemory()->allocateMemory(len, allocKind);
163
int32_t i = 0;
164
while (i < numParens)
165
{
166
sig[i] = '[';
167
i++;
168
}
169
memcpy(sig+i,name,len-numParens);
170
171
return sig;
172
}
173
174
175
const char *
176
SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bool *isFixed)
177
{
178
TR::Compilation * comp = TR::comp();
179
bool allowForAOT = comp->getOption(TR_UseSymbolValidationManager);
180
181
TR_PersistentClassInfo * persistentClassInfo = NULL;
182
switch (_symbol->getKind())
183
{
184
case TR::Symbol::IsParameter:
185
return _symbol->castToParmSymbol()->getTypeSignature(len);
186
187
case TR::Symbol::IsShadow:
188
persistentClassInfo =
189
(comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL :
190
comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp, allowForAOT);
191
if (persistentClassInfo &&
192
persistentClassInfo->getFieldInfo() &&
193
persistentClassInfo->getFieldInfo()->getFirst() &&
194
!self()->isUnresolved() &&
195
!_symbol->isArrayShadowSymbol() &&
196
!_symbol->isArrayletShadowSymbol())
197
{
198
TR_PersistentFieldInfo *fieldInfo = NULL;
199
if (_symbol->isPrivate() ||
200
_symbol->isFinal())
201
fieldInfo = persistentClassInfo->getFieldInfo()->find(comp, _symbol, self());
202
203
if (fieldInfo &&
204
fieldInfo->isTypeInfoValid() &&
205
(fieldInfo->getNumChars() > 0) &&
206
performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",
207
fieldInfo->getClassPointer(), _symbol))
208
{
209
if (isFixed)
210
*isFixed = true;
211
len = fieldInfo->getNumChars();
212
return fieldInfo->getClassPointer();
213
}
214
215
if (fieldInfo &&
216
fieldInfo->isBigDecimalType() &&
217
performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",
218
"Ljava/math/BigDecimal;", _symbol))
219
{
220
len = 22;
221
return "Ljava/math/BigDecimal;";
222
}
223
224
if (fieldInfo &&
225
fieldInfo->isBigIntegerType() &&
226
performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",
227
"Ljava/math/BigInteger;", _symbol))
228
{
229
len = 22;
230
return "Ljava/math/BigInteger;";
231
}
232
}
233
234
return (_cpIndex > 0 ? self()->getOwningMethod(comp)->fieldSignatureChars(_cpIndex, len) : 0);
235
236
case TR::Symbol::IsStatic:
237
if (_symbol->isStatic() && _symbol->isFinal() && !self()->isUnresolved())
238
{
239
TR::StaticSymbol * symbol = _symbol->castToStaticSymbol();
240
TR::DataType type = symbol->getDataType();
241
TR_OpaqueClassBlock * classOfStatic = self()->getOwningMethod(comp)->classOfStatic(_cpIndex, allowForAOT);
242
243
bool isClassInitialized = false;
244
TR_PersistentClassInfo * classInfo =
245
(comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL :
246
comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(classOfStatic, comp, allowForAOT);
247
if (classInfo && classInfo->isInitialized())
248
{
249
if (classInfo->getFieldInfo() && !classInfo->cannotTrustStaticFinal())
250
isClassInitialized = true;
251
}
252
253
if ((classOfStatic != comp->getSystemClassPointer() &&
254
isClassInitialized &&
255
(type == TR::Address)))
256
{
257
TR::VMAccessCriticalSection vmAccessCriticalSection(comp->fej9(),
258
TR::VMAccessCriticalSection::tryToAcquireVMAccess,
259
comp);
260
if (vmAccessCriticalSection.hasVMAccess())
261
{
262
uintptr_t objectStaticAddress = (uintptr_t)symbol->getStaticAddress();
263
uintptr_t objectRef = comp->fej9()->getStaticReferenceFieldAtAddress(objectStaticAddress);
264
if (objectRef != 0)
265
{
266
TR_OpaqueClassBlock *classOfObject = comp->fej9()->getObjectClass(objectRef);
267
const char * s = TR::Compiler->cls.classNameChars(comp, classOfObject, len);
268
if (s && (s[0] != '['))
269
{
270
s = TR::Compiler->cls.classNameToSignature(s, len, comp);
271
}
272
else
273
{
274
int32_t numParens = 0;
275
while (s && (s[0] == '[') && (s[1] == 'L' || s[1] == 'Q'))
276
{
277
numParens++;
278
classOfObject = comp->fe()->getComponentClassFromArrayClass(classOfObject);
279
s = TR::Compiler->cls.classNameChars(comp, classOfObject, len);
280
}
281
s = TR::Compiler->cls.classNameToSignature(s, len, comp);
282
s = prependNumParensToSig(s, len, numParens);
283
}
284
285
if (isFixed)
286
*isFixed = true;
287
return s;
288
}
289
}
290
}
291
}
292
293
if (_symbol->isClassObject())
294
{
295
const char * sig = TR::Compiler->cls.classNameChars(comp, self(), len);
296
if (!sig)
297
{
298
len = 18;
299
return "Ljava/lang/Object;";
300
}
301
return TR::Compiler->cls.classNameToSignature(sig, len, comp, allocKind);
302
}
303
304
if (_symbol->isConstString())
305
{
306
len = 18;
307
return "Ljava/lang/String;";
308
}
309
if (_symbol->isConstMethodType())
310
{
311
len = 21;
312
return "Ljava/lang/invoke/MethodType;";
313
}
314
if (_symbol->isConstMethodHandle())
315
{
316
len = 23;
317
return "Ljava/lang/invoke/MethodHandle;";
318
}
319
if (_symbol->isConstantDynamic())
320
{
321
TR::StaticSymbol * symbol = _symbol->castToStaticSymbol();
322
int32_t condySigLength;
323
char *returnType = symbol->getConstantDynamicClassSignature(condySigLength);
324
len = condySigLength;
325
return returnType;
326
}
327
if (_symbol->isNonSpecificConstObject())
328
{
329
TR::StaticSymbol * symbol = _symbol->castToStaticSymbol();
330
uintptr_t objectLocation = (uintptr_t)symbol->getStaticAddress();
331
TR_OpaqueClassBlock *clazz = comp->fej9()->getObjectClassAt(objectLocation);
332
char *type = comp->fej9()->getClassSignature(clazz, comp->trMemory());
333
len = strlen(type);
334
return type;
335
}
336
if (_symbol->isConst())
337
{
338
len = 1;
339
return dataTypeToSig[_symbol->getDataType()];
340
}
341
342
persistentClassInfo =
343
(comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL :
344
comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(comp->getCurrentMethod()->containingClass(), comp, allowForAOT);
345
if (persistentClassInfo &&
346
persistentClassInfo->getFieldInfo() &&
347
persistentClassInfo->getFieldInfo()->getFirst() &&
348
!self()->isUnresolved() &&
349
!_symbol->isArrayShadowSymbol() &&
350
!_symbol->isArrayletShadowSymbol())
351
{
352
TR_PersistentFieldInfo *fieldInfo = NULL;
353
if (_symbol->isPrivate() ||
354
_symbol->isFinal())
355
fieldInfo = persistentClassInfo->getFieldInfo()->find(comp, _symbol, self());
356
357
if (fieldInfo &&
358
fieldInfo->isTypeInfoValid() &&
359
(fieldInfo->getNumChars() > 0) &&
360
performTransformation(comp, "O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",
361
fieldInfo->getClassPointer(), _symbol))
362
{
363
if (isFixed)
364
*isFixed = true;
365
len = fieldInfo->getNumChars();
366
return fieldInfo->getClassPointer();
367
}
368
369
if (fieldInfo &&
370
fieldInfo->isBigDecimalType() &&
371
performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",
372
"Ljava/math/BigDecimal;", _symbol))
373
{
374
len = 22;
375
return "Ljava/math/BigDecimal;";
376
}
377
378
if (fieldInfo &&
379
fieldInfo->isBigIntegerType() &&
380
performTransformation(comp,"O^O CLASS LOOKAHEAD: Returning type %s info for symbol %p based on class file examination\n",
381
"Ljava/math/BigInteger;", _symbol))
382
{
383
len = 22;
384
return "Ljava/math/BigInteger;";
385
}
386
}
387
388
return self()->getOwningMethod(comp)->staticSignatureChars(_cpIndex, len);
389
390
case TR::Symbol::IsMethod:
391
case TR::Symbol::IsResolvedMethod:
392
{
393
TR::Method * method = _symbol->castToMethodSymbol()->getMethod();
394
if (method)
395
{
396
char * sig = method->signatureChars();
397
char *returnType = strchr(sig,')')+1;
398
len = method->signatureLength() - (returnType-sig);
399
return returnType;
400
}
401
return 0;
402
}
403
404
case TR::Symbol::IsAutomatic:
405
if (_symbol->isLocalObject())
406
{
407
// todo:
408
}
409
return 0;
410
411
case TR::Symbol::IsMethodMetaData:
412
case TR::Symbol::IsLabel:
413
default:
414
return 0;
415
}
416
}
417
418
}
419
420