Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/env/J9ClassEnv.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 "compile/Compilation.hpp"
24
#if defined(J9VM_OPT_JITSERVER)
25
#include "control/CompilationRuntime.hpp"
26
#include "control/CompilationThread.hpp"
27
#include "control/JITServerHelpers.hpp"
28
#include "runtime/JITClientSession.hpp"
29
#endif /* defined(J9VM_OPT_JITSERVER) */
30
#include "env/ClassEnv.hpp"
31
#include "env/CompilerEnv.hpp"
32
#include "env/jittypes.h"
33
#include "env/TypeLayout.hpp"
34
#include "env/VMJ9.h"
35
#include "j9.h"
36
#include "j9cfg.h"
37
#include "j9cp.h"
38
#include "j9fieldsInfo.h"
39
#include "j9nonbuilder.h"
40
#include "j9protos.h"
41
#include "rommeth.h"
42
#include "runtime/RuntimeAssumptions.hpp"
43
44
class TR_PersistentClassInfo;
45
template <typename ListKind> class List;
46
47
/* REQUIRES STATE (_vmThread). MOVE vmThread to COMPILATION
48
49
TR_OpaqueClassBlock *
50
J9::ClassEnv::getClassFromJavaLangClass(uintptr_t objectPointer)
51
{
52
return (TR_OpaqueClassBlock*)J9VM_J9CLASS_FROM_HEAPCLASS(_vmThread, objectPointer);
53
}
54
*/
55
56
TR::ClassEnv *
57
J9::ClassEnv::self()
58
{
59
return static_cast<TR::ClassEnv *>(this);
60
}
61
62
J9Class *
63
J9::ClassEnv::convertClassOffsetToClassPtr(TR_OpaqueClassBlock *clazzOffset)
64
{
65
// NOTE : We could pass down vmThread() in the call below if the conversion
66
// required the VM thread. Currently it does not. If we did change that
67
// such that the VM thread was reqd, we would need to handle AOT where the
68
// TR_FrontEnd is created with a NULL J9VMThread object.
69
//
70
return (J9Class*)((TR_OpaqueClassBlock *)clazzOffset);
71
}
72
73
TR_OpaqueClassBlock *
74
J9::ClassEnv::convertClassPtrToClassOffset(J9Class *clazzPtr)
75
{
76
// NOTE : We could pass down vmThread() in the call below if the conversion
77
// required the VM thread. Currently it does not. If we did change that
78
// such that the VM thread was reqd, we would need to handle AOT where the
79
// TR_FrontEnd is created with a NULL J9VMThread object.
80
//
81
return (TR_OpaqueClassBlock*)(clazzPtr);
82
}
83
84
bool
85
J9::ClassEnv::isClassSpecialForStackAllocation(TR_OpaqueClassBlock * clazz)
86
{
87
const UDATA mask = (J9AccClassReferenceWeak |
88
J9AccClassReferenceSoft |
89
J9AccClassFinalizeNeeded |
90
J9AccClassOwnableSynchronizer);
91
92
#if defined(J9VM_OPT_JITSERVER)
93
if (auto stream = TR::CompilationInfo::getStream())
94
{
95
uintptr_t classDepthAndFlags = 0;
96
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_DEPTH_AND_FLAGS, (void *)&classDepthAndFlags);
97
return ((classDepthAndFlags & mask)?true:false);
98
}
99
else
100
#endif /* defined(J9VM_OPT_JITSERVER) */
101
{
102
if (((J9Class *)clazz)->classDepthAndFlags & mask)
103
{
104
return true;
105
}
106
}
107
108
return false;
109
}
110
111
uintptr_t
112
J9::ClassEnv::classFlagsValue(TR_OpaqueClassBlock * classPointer)
113
{
114
#if defined(J9VM_OPT_JITSERVER)
115
if (auto stream = TR::CompilationInfo::getStream())
116
{
117
stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, classPointer);
118
return std::get<0>(stream->read<uintptr_t>());
119
}
120
#endif /* defined(J9VM_OPT_JITSERVER) */
121
return (TR::Compiler->cls.convertClassOffsetToClassPtr(classPointer)->classFlags);
122
}
123
124
uintptr_t
125
J9::ClassEnv::classFlagReservableWordInitValue(TR_OpaqueClassBlock * classPointer)
126
{
127
#if defined(J9VM_OPT_JITSERVER)
128
if (auto stream = TR::CompilationInfo::getStream())
129
{
130
uintptr_t classFlags = 0;
131
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)classPointer, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags);
132
#ifdef DEBUG
133
stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, classPointer);
134
uintptr_t classFlagsRemote = std::get<0>(stream->read<uintptr_t>());
135
// Check that class flags from remote call is equal to the cached ones
136
classFlags = classFlags & J9ClassReservableLockWordInit;
137
classFlagsRemote = classFlagsRemote & J9ClassReservableLockWordInit;
138
TR_ASSERT(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags");
139
#endif
140
return classFlags & J9ClassReservableLockWordInit;
141
}
142
#endif /* defined(J9VM_OPT_JITSERVER) */
143
return (TR::Compiler->cls.convertClassOffsetToClassPtr(classPointer)->classFlags) & J9ClassReservableLockWordInit;
144
}
145
146
uintptr_t
147
J9::ClassEnv::classDepthOf(TR_OpaqueClassBlock * clazzPointer)
148
{
149
#if defined(J9VM_OPT_JITSERVER)
150
if (auto stream = TR::CompilationInfo::getStream())
151
{
152
uintptr_t classDepthAndFlags = 0;
153
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazzPointer, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_DEPTH_AND_FLAGS, (void *)&classDepthAndFlags);
154
return (classDepthAndFlags & J9AccClassDepthMask);
155
}
156
#endif /* defined(J9VM_OPT_JITSERVER) */
157
return J9CLASS_DEPTH(TR::Compiler->cls.convertClassOffsetToClassPtr(clazzPointer));
158
}
159
160
161
uintptr_t
162
J9::ClassEnv::classInstanceSize(TR_OpaqueClassBlock * clazzPointer)
163
{
164
#if defined(J9VM_OPT_JITSERVER)
165
if (auto stream = TR::CompilationInfo::getStream())
166
{
167
uintptr_t totalInstanceSize = 0;
168
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazzPointer, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_TOTAL_INSTANCE_SIZE, (void *)&totalInstanceSize);
169
return totalInstanceSize;
170
}
171
#endif /* defined(J9VM_OPT_JITSERVER) */
172
return TR::Compiler->cls.convertClassOffsetToClassPtr(clazzPointer)->totalInstanceSize;
173
}
174
175
176
J9ROMClass *
177
J9::ClassEnv::romClassOf(TR_OpaqueClassBlock * clazz)
178
{
179
J9Class *j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz);
180
#if defined(J9VM_OPT_JITSERVER)
181
if (TR::compInfoPT && TR::compInfoPT->getStream())
182
{
183
return TR::compInfoPT->getAndCacheRemoteROMClass(j9clazz);
184
}
185
#endif /* defined(J9VM_OPT_JITSERVER) */
186
return j9clazz->romClass;
187
}
188
189
J9Class **
190
J9::ClassEnv::superClassesOf(TR_OpaqueClassBlock * clazz)
191
{
192
#if defined(J9VM_OPT_JITSERVER)
193
if (auto stream = TR::CompilationInfo::getStream())
194
{
195
stream->write(JITServer::MessageType::ClassEnv_superClassesOf, clazz);
196
return std::get<0>(stream->read<J9Class **>());
197
}
198
#endif /* defined(J9VM_OPT_JITSERVER) */
199
return TR::Compiler->cls.convertClassOffsetToClassPtr(clazz)->superclasses;
200
}
201
202
J9ROMClass *
203
J9::ClassEnv::romClassOfSuperClass(TR_OpaqueClassBlock * clazz, size_t index)
204
{
205
#if defined(J9VM_OPT_JITSERVER)
206
if (auto stream = TR::CompilationInfo::getStream())
207
{
208
stream->write(JITServer::MessageType::ClassEnv_indexedSuperClassOf, clazz, index);
209
J9Class *j9clazz = std::get<0>(stream->read<J9Class *>());
210
return TR::compInfoPT->getAndCacheRemoteROMClass(j9clazz);
211
}
212
#endif /* defined(J9VM_OPT_JITSERVER) */
213
return self()->superClassesOf(clazz)[index]->romClass;
214
}
215
216
J9ITable *
217
J9::ClassEnv::iTableOf(TR_OpaqueClassBlock * clazz)
218
{
219
#if defined(J9VM_OPT_JITSERVER)
220
if (auto stream = TR::CompilationInfo::getStream())
221
{
222
stream->write(JITServer::MessageType::ClassEnv_iTableOf, clazz);
223
return std::get<0>(stream->read<J9ITable*>());
224
}
225
#endif /* defined(J9VM_OPT_JITSERVER) */
226
return (J9ITable*) self()->convertClassOffsetToClassPtr(clazz)->iTable;
227
}
228
229
J9ITable *
230
J9::ClassEnv::iTableNext(J9ITable *current)
231
{
232
#if defined(J9VM_OPT_JITSERVER)
233
if (auto stream = TR::CompilationInfo::getStream())
234
{
235
stream->write(JITServer::MessageType::ClassEnv_iTableNext, current);
236
return std::get<0>(stream->read<J9ITable*>());
237
}
238
#endif /* defined(J9VM_OPT_JITSERVER) */
239
return current->next;
240
}
241
242
J9ROMClass *
243
J9::ClassEnv::iTableRomClass(J9ITable *current)
244
{
245
#if defined(J9VM_OPT_JITSERVER)
246
if (auto stream = TR::CompilationInfo::getStream())
247
{
248
stream->write(JITServer::MessageType::ClassEnv_iTableRomClass, current);
249
return std::get<0>(stream->read<J9ROMClass*>());
250
}
251
#endif /* defined(J9VM_OPT_JITSERVER) */
252
return current->interfaceClass->romClass;
253
}
254
255
#if defined(J9VM_OPT_JITSERVER)
256
std::vector<TR_OpaqueClassBlock *>
257
J9::ClassEnv::getITable(TR_OpaqueClassBlock *clazz)
258
{
259
if (auto stream = TR::CompilationInfo::getStream())
260
{
261
// This normally shouldn't be called from the server,
262
// because it will have a cached table
263
stream->write(JITServer::MessageType::ClassEnv_getITable, clazz);
264
return std::get<0>(stream->read<std::vector<TR_OpaqueClassBlock *>>());
265
}
266
std::vector<TR_OpaqueClassBlock *> iTableSerialization;
267
iTableSerialization.reserve((TR::Compiler->cls.romClassOf(clazz)->interfaceCount));
268
for (J9ITable *iTableCur = TR::Compiler->cls.iTableOf(clazz); iTableCur; iTableCur = iTableCur->next)
269
iTableSerialization.push_back((TR_OpaqueClassBlock *) iTableCur->interfaceClass);
270
return iTableSerialization;
271
}
272
#endif /* defined(J9VM_OPT_JITSERVER) */
273
274
bool
275
J9::ClassEnv::isStringClass(TR_OpaqueClassBlock *clazz)
276
{
277
//return (J9Class*)clazz == J9VMJAVALANGSTRING(jitConfig->javaVM);
278
return false;
279
}
280
281
bool
282
J9::ClassEnv::isAbstractClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazzPointer)
283
{
284
return comp->fej9()->isAbstractClass(clazzPointer);
285
}
286
287
bool
288
J9::ClassEnv::isInterfaceClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazzPointer)
289
{
290
return comp->fej9()->isInterfaceClass(clazzPointer);
291
}
292
293
bool
294
J9::ClassEnv::isConcreteClass(TR::Compilation *comp, TR_OpaqueClassBlock * clazzPointer)
295
{
296
return comp->fej9()->isConcreteClass(clazzPointer);
297
}
298
299
bool
300
J9::ClassEnv::isEnumClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazzPointer, TR_ResolvedMethod *method)
301
{
302
return comp->fej9()->isEnumClass(clazzPointer, method);
303
}
304
305
bool
306
J9::ClassEnv::isPrimitiveClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
307
{
308
return comp->fej9()->isPrimitiveClass(clazz);
309
}
310
311
bool
312
J9::ClassEnv::isPrimitiveArray(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
313
{
314
return comp->fej9()->isPrimitiveArray(clazz);
315
}
316
317
bool
318
J9::ClassEnv::isReferenceArray(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
319
{
320
return comp->fej9()->isReferenceArray(clazz);
321
}
322
323
bool
324
J9::ClassEnv::isClassArray(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
325
{
326
return comp->fej9()->isClassArray(clazz);
327
}
328
329
bool
330
J9::ClassEnv::isClassFinal(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
331
{
332
return comp->fej9()->isClassFinal(clazz);
333
}
334
335
bool
336
J9::ClassEnv::hasFinalizer(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
337
{
338
return comp->fej9()->hasFinalizer(clazz);
339
}
340
341
bool
342
J9::ClassEnv::isClassInitialized(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
343
{
344
return comp->fej9()->isClassInitialized(clazz);
345
}
346
347
bool
348
J9::ClassEnv::classHasIllegalStaticFinalFieldModification(TR_OpaqueClassBlock * clazzPointer)
349
{
350
J9Class* j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazzPointer);
351
#if defined(J9VM_OPT_JITSERVER)
352
if (auto stream = TR::CompilationInfo::getStream())
353
{
354
// J9ClassHasIllegalFinalFieldModifications bit is cached by ClientSessionData::processIllegalFinalFieldModificationList()
355
// before the compilation takes place.
356
uintptr_t classFlags = 0;
357
JITServerHelpers::getAndCacheRAMClassInfo(j9clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags);
358
return J9_ARE_ANY_BITS_SET(classFlags, J9ClassHasIllegalFinalFieldModifications);
359
}
360
#endif /* defined(J9VM_OPT_JITSERVER) */
361
return J9_ARE_ANY_BITS_SET(j9clazz->classFlags, J9ClassHasIllegalFinalFieldModifications);
362
}
363
364
bool
365
J9::ClassEnv::hasFinalFieldsInClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
366
{
367
return comp->fej9()->hasFinalFieldsInClass(clazz);
368
}
369
370
bool
371
J9::ClassEnv::sameClassLoaders(TR::Compilation *comp, TR_OpaqueClassBlock *class1, TR_OpaqueClassBlock *class2)
372
{
373
return comp->fej9()->sameClassLoaders(class1, class2);
374
}
375
376
bool
377
J9::ClassEnv::isString(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
378
{
379
return comp->fej9()->isString(clazz);
380
}
381
382
bool
383
J9::ClassEnv::jitStaticsAreSame(
384
TR::Compilation *comp,
385
TR_ResolvedMethod * method1,
386
int32_t cpIndex1,
387
TR_ResolvedMethod * method2,
388
int32_t cpIndex2)
389
{
390
return comp->fej9()->jitStaticsAreSame(method1, cpIndex1, method2, cpIndex2);
391
}
392
393
bool
394
J9::ClassEnv::jitFieldsAreSame(
395
TR::Compilation *comp,
396
TR_ResolvedMethod * method1,
397
int32_t cpIndex1,
398
TR_ResolvedMethod * method2,
399
int32_t cpIndex2,
400
int32_t isStatic)
401
{
402
return comp->fej9()->jitFieldsAreSame(method1, cpIndex1, method2, cpIndex2, isStatic);
403
}
404
405
bool
406
J9::ClassEnv::isAnonymousClass(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
407
{
408
return comp->fej9()->isAnonymousClass(clazz);
409
}
410
411
/*
412
* Merges the prefix with the field name to a new string.
413
*
414
* \param prefix
415
* prefix could be NULL.
416
* \param prefixLength
417
* The length of the prefix string.
418
* \param mergedLength
419
* The merged length of the concatenated field name that is returned to the caller.
420
*/
421
static char * mergeFieldNames(char *prefix, uint32_t prefixLength, J9ROMFieldShape *field,
422
TR::Region &region, uint32_t &mergedLength)
423
{
424
J9UTF8 *fieldNameUTF = J9ROMFIELDSHAPE_NAME(field);
425
char *fieldName = reinterpret_cast<char *>(J9UTF8_DATA(fieldNameUTF));
426
uint32_t nameLength = J9UTF8_LENGTH(fieldNameUTF);
427
428
mergedLength = nameLength + prefixLength;
429
mergedLength++; // for adding '\0' at the end
430
431
char *newName = new (region) char[mergedLength];
432
433
if (prefixLength > 0)
434
strncpy(newName, prefix, prefixLength);
435
strncpy(newName + prefixLength, fieldName, nameLength);
436
437
newName[mergedLength-1] = '\0';
438
439
return newName;
440
}
441
442
/*
443
* Builds a new string with the prefix and the field name and appends the string with "." to be used
444
* as a part of the flattened field chain name.
445
*
446
* \param prefix
447
* prefix could be ended with `.` or NULL.
448
* \param prefixLength
449
* The length of the prefix string.
450
* \param mergedLength
451
* The merged length of the concatenated field name that is returned to the caller.
452
*/
453
static char * buildTransitiveFieldNames(char *prefix, uint32_t prefixLength, J9ROMFieldShape *field,
454
TR::Region &region, uint32_t &mergedLength)
455
{
456
J9UTF8 *fieldNameUTF = J9ROMFIELDSHAPE_NAME(field);
457
char *fieldName = reinterpret_cast<char *>(J9UTF8_DATA(fieldNameUTF));
458
uint32_t nameLength = J9UTF8_LENGTH(fieldNameUTF);
459
460
mergedLength = nameLength + prefixLength;
461
mergedLength++; // for appending '.'
462
mergedLength++; // for adding '\0' at the end
463
464
char *newName = new (region) char[mergedLength];
465
466
if (prefixLength > 0)
467
strncpy(newName, prefix, prefixLength);
468
strncpy(newName + prefixLength, fieldName, nameLength);
469
470
newName[mergedLength-2] = '.';
471
newName[mergedLength-1] = '\0';
472
473
return newName;
474
}
475
476
static void addEntryForFieldImpl(TR_VMField *field, TR::TypeLayoutBuilder &tlb, TR::Region &region, J9Class *definingClass,
477
char *prefix, uint32_t prefixLength, IDATA offsetBase, TR::Compilation *comp)
478
{
479
J9JavaVM *vm = comp->fej9()->getJ9JITConfig()->javaVM;
480
bool trace = comp->getOption(TR_TraceILGen);
481
uint32_t mergedLength = 0;
482
J9UTF8 *signature = J9ROMFIELDSHAPE_SIGNATURE(field->shape);
483
484
if (TR::Compiler->om.areValueTypesEnabled() &&
485
vm->internalVMFunctions->isNameOrSignatureQtype(signature) &&
486
vm->internalVMFunctions->isFlattenableFieldFlattened(definingClass, field->shape))
487
{
488
char *prefixForChild = buildTransitiveFieldNames(prefix, prefixLength, field->shape, comp->trMemory()->currentStackRegion(), mergedLength);
489
uint32_t prefixLengthForChild = mergedLength-1;
490
IDATA offsetBaseForChild = field->offset + offsetBase;
491
492
if (trace)
493
traceMsg(comp, "field %s:%s is flattened. offset from TR_VMField %d, offset from fcc %d\n",
494
field->name, field->signature, field->offset,
495
vm->internalVMFunctions->getFlattenableFieldOffset(definingClass, field->shape));
496
497
J9Class *fieldClass = vm->internalVMFunctions->getFlattenableFieldType(definingClass, field->shape);
498
TR_VMFieldsInfo fieldsInfo(comp, fieldClass, 1, stackAlloc);
499
ListIterator<TR_VMField> iter(fieldsInfo.getFields());
500
for (TR_VMField *childField = iter.getFirst(); childField; childField = iter.getNext())
501
{
502
IDATA offsetBaseForChild = field->offset + offsetBase;
503
/* Types with fields (flat or non-flat) that require double (64bit) alignment are pre-padded if there isn't
504
* a smaller type that can be used as pre-padding. Pre-padding is eliminated when a type is flattened within
505
* its container. As a result pre-padding must be subtracted from the base offset of the flattened field.
506
*/
507
offsetBaseForChild -= J9CLASS_PREPADDING_SIZE(fieldClass);
508
509
addEntryForFieldImpl(childField, tlb, region, fieldClass, prefixForChild, prefixLengthForChild, offsetBaseForChild, comp);
510
}
511
}
512
else
513
{
514
char *signature = field->signature;
515
char charSignature = *signature;
516
TR::DataType dataType;
517
switch(charSignature)
518
{
519
case 'Z':
520
case 'B':
521
case 'C':
522
case 'S':
523
case 'I':
524
{
525
dataType = TR::Int32;
526
break;
527
}
528
case 'J':
529
{
530
dataType = TR::Int64;
531
break;
532
}
533
case 'F':
534
{
535
dataType = TR::Float;
536
break;
537
}
538
case 'D':
539
{
540
dataType = TR::Double;
541
break;
542
}
543
case 'L':
544
case 'Q':
545
case '[':
546
{
547
dataType = TR::Address;
548
break;
549
}
550
}
551
552
char *fieldName = mergeFieldNames(prefix, prefixLength, field->shape, region, mergedLength);
553
int32_t offset = offsetBase + field->offset + TR::Compiler->om.objectHeaderSizeInBytes();
554
bool isVolatile = (field->modifiers & J9AccVolatile) ? true : false;
555
bool isPrivate = (field->modifiers & J9AccPrivate) ? true : false;
556
bool isFinal = (field->modifiers & J9AccFinal) ? true : false;
557
558
int sigLen = strlen(signature);
559
char *fieldSignature = new (region) char[sigLen+1];
560
memcpy(fieldSignature, signature, sigLen);
561
fieldSignature[sigLen] = '\0';
562
563
if (trace)
564
traceMsg(comp, "type layout definingClass %p field: %s signature: %s field offset: %d offsetBase %d\n", definingClass, fieldName, fieldSignature, field->offset, offsetBase);
565
tlb.add(TR::TypeLayoutEntry(dataType, offset, fieldName, isVolatile, isPrivate, isFinal, fieldSignature));
566
}
567
}
568
569
static void addEntryForField(TR_VMField *field, TR::TypeLayoutBuilder &tlb, TR::Region &region, TR_OpaqueClassBlock *opaqueClazz, TR::Compilation *comp)
570
{
571
char *prefix = NULL;
572
uint32_t prefixLength = 0;
573
IDATA offsetBase = 0;
574
J9Class *definingClass = reinterpret_cast<J9Class*>(opaqueClazz);
575
576
addEntryForFieldImpl(field, tlb, region, definingClass, prefix, prefixLength, offsetBase, comp);
577
}
578
579
const TR::TypeLayout*
580
J9::ClassEnv::enumerateFields(TR::Region &region, TR_OpaqueClassBlock *opaqueClazz, TR::Compilation *comp)
581
{
582
TR::TypeLayoutBuilder tlb(region);
583
#if defined(J9VM_OPT_JITSERVER)
584
if (comp->isOutOfProcessCompilation())
585
{
586
auto stream = TR::CompilationInfo::getStream();
587
stream->write(JITServer::MessageType::ClassEnv_enumerateFields, opaqueClazz);
588
auto recv = stream->read<std::vector<TR::TypeLayoutEntry>, std::vector<std::string>, std::vector<std::string>>();
589
auto entries = std::get<0>(recv);
590
auto fieldNames = std::get<1>(recv);
591
auto typeSignatures = std::get<2>(recv);
592
for (int32_t idx = 0; idx < entries.size(); ++idx)
593
{
594
TR::TypeLayoutEntry entry = entries[idx];
595
char *fieldname = new (region) char[fieldNames[idx].length() + 1];
596
memcpy(fieldname, fieldNames[idx].c_str(), fieldNames[idx].length() + 1);
597
entry._fieldname = fieldname;
598
char *typeSignature = new (region) char[typeSignatures[idx].length() + 1];
599
memcpy(typeSignature, typeSignatures[idx].c_str(), typeSignatures[idx].length() + 1);
600
entry._typeSignature = typeSignature;
601
tlb.add(entry);
602
}
603
604
}
605
else
606
#endif
607
{
608
TR_VMFieldsInfo fieldsInfo(comp, reinterpret_cast<J9Class*>(opaqueClazz), 1, stackAlloc);
609
ListIterator<TR_VMField> iter(fieldsInfo.getFields());
610
for (TR_VMField *field = iter.getFirst(); field; field = iter.getNext())
611
{
612
addEntryForField(field, tlb, region, opaqueClazz, comp);
613
}
614
}
615
616
return tlb.build();
617
}
618
619
int32_t
620
J9::ClassEnv::vTableSlot(TR::Compilation *comp, TR_OpaqueMethodBlock *method, TR_OpaqueClassBlock *clazz)
621
{
622
return comp->fej9()->getVTableSlot(method, clazz);
623
}
624
625
626
int32_t
627
J9::ClassEnv::flagValueForPrimitiveTypeCheck(TR::Compilation *comp)
628
{
629
return comp->fej9()->getFlagValueForPrimitiveTypeCheck();
630
}
631
632
633
int32_t
634
J9::ClassEnv::flagValueForArrayCheck(TR::Compilation *comp)
635
{
636
return comp->fej9()->getFlagValueForArrayCheck();
637
}
638
639
640
int32_t
641
J9::ClassEnv::flagValueForFinalizerCheck(TR::Compilation *comp)
642
{
643
return comp->fej9()->getFlagValueForFinalizerCheck();
644
}
645
646
647
// this should be a method of TR_SymbolReference
648
char *
649
J9::ClassEnv::classNameChars(TR::Compilation *comp, TR::SymbolReference * symRef, int32_t & length)
650
{
651
return comp->fej9()->classNameChars(comp, symRef, length);
652
}
653
654
655
char *
656
J9::ClassEnv::classNameChars(TR::Compilation *comp, TR_OpaqueClassBlock *clazz, int32_t & length)
657
{
658
return comp->fej9()->getClassNameChars(clazz, length);
659
}
660
661
662
char *
663
J9::ClassEnv::classSignature_DEPRECATED(TR::Compilation *comp, TR_OpaqueClassBlock * clazz, int32_t & length, TR_Memory *m)
664
{
665
return comp->fej9()->getClassSignature_DEPRECATED(clazz, length, m);
666
}
667
668
669
char *
670
J9::ClassEnv::classSignature(TR::Compilation *comp, TR_OpaqueClassBlock * clazz, TR_Memory *m)
671
{
672
return comp->fej9()->getClassSignature(clazz, m);
673
}
674
675
uintptr_t
676
J9::ClassEnv::persistentClassPointerFromClassPointer(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
677
{
678
return comp->fej9()->getPersistentClassPointerFromClassPointer(clazz);
679
}
680
681
TR_OpaqueClassBlock *
682
J9::ClassEnv::objectClass(TR::Compilation *comp, uintptr_t objectPointer)
683
{
684
return comp->fej9()->getObjectClass(objectPointer);
685
}
686
687
TR_OpaqueClassBlock *
688
J9::ClassEnv::classFromJavaLangClass(TR::Compilation *comp, uintptr_t objectPointer)
689
{
690
return comp->fej9()->getClassFromJavaLangClass(objectPointer);
691
}
692
693
694
uint16_t
695
J9::ClassEnv::getStringCharacter(TR::Compilation *comp, uintptr_t objectPointer, int32_t index)
696
{
697
return comp->fej9()->getStringCharacter(objectPointer, index);
698
}
699
700
701
bool
702
J9::ClassEnv::getStringFieldByName(TR::Compilation *comp, TR::SymbolReference *stringRef, TR::SymbolReference *fieldRef, void* &pResult)
703
{
704
return comp->fej9()->getStringFieldByName(comp, stringRef, fieldRef, pResult);
705
}
706
707
uintptr_t
708
J9::ClassEnv::getArrayElementWidthInBytes(TR::Compilation *comp, TR_OpaqueClassBlock* arrayClass)
709
{
710
TR_ASSERT(TR::Compiler->cls.isClassArray(comp, arrayClass), "Class must be array");
711
int32_t logElementSize = ((J9ROMArrayClass*)((J9Class*)arrayClass)->romClass)->arrayShape & 0x0000FFFF;
712
return 1 << logElementSize;
713
}
714
715
intptr_t
716
J9::ClassEnv::getVFTEntry(TR::Compilation *comp, TR_OpaqueClassBlock* clazz, int32_t offset)
717
{
718
return comp->fej9()->getVFTEntry(clazz, offset);
719
}
720
721
uint8_t *
722
J9::ClassEnv::getROMClassRefName(TR::Compilation *comp, TR_OpaqueClassBlock *clazz, uint32_t cpIndex, int &classRefLen)
723
{
724
J9ROMConstantPoolItem *romCP = self()->getROMConstantPool(comp, clazz);
725
J9ROMFieldRef *romFieldRef = (J9ROMFieldRef *)&romCP[cpIndex];
726
J9ROMClassRef *romClassRef = (J9ROMClassRef *)&romCP[romFieldRef->classRefCPIndex];
727
J9UTF8 *classRefNameUtf8 = J9ROMCLASSREF_NAME(romClassRef);
728
classRefLen = J9UTF8_LENGTH(classRefNameUtf8);
729
uint8_t *classRefName = J9UTF8_DATA(classRefNameUtf8);
730
return classRefName;
731
}
732
733
J9ROMConstantPoolItem *
734
J9::ClassEnv::getROMConstantPool(TR::Compilation *comp, TR_OpaqueClassBlock *clazz)
735
{
736
#if defined(J9VM_OPT_JITSERVER)
737
if (comp->isOutOfProcessCompilation())
738
{
739
J9ROMClass *romClass = TR::compInfoPT->getAndCacheRemoteROMClass(reinterpret_cast<J9Class *>(clazz));
740
return (J9ROMConstantPoolItem *) ((UDATA) romClass + sizeof(J9ROMClass));
741
}
742
#endif /* defined(J9VM_OPT_JITSERVER) */
743
J9ConstantPool *ramCP = reinterpret_cast<J9ConstantPool *>(comp->fej9()->getConstantPoolFromClass(clazz));
744
return ramCP->romConstantPool;
745
}
746
747
bool
748
J9::ClassEnv::isValueTypeClass(TR_OpaqueClassBlock *clazz)
749
{
750
#if defined(J9VM_OPT_JITSERVER)
751
if (auto stream = TR::CompilationInfo::getStream())
752
{
753
uintptr_t classFlags = 0;
754
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags);
755
#ifdef DEBUG
756
stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, clazz);
757
uintptr_t classFlagsRemote = std::get<0>(stream->read<uintptr_t>());
758
// Check that class flags from remote call is equal to the cached ones
759
classFlags = classFlags & J9ClassIsValueType;
760
classFlagsRemote = classFlagsRemote & J9ClassIsValueType;
761
TR_ASSERT(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags");
762
#endif
763
return classFlags & J9ClassIsValueType;
764
}
765
#endif /* defined(J9VM_OPT_JITSERVER) */
766
J9Class *j9class = reinterpret_cast<J9Class*>(clazz);
767
return J9_IS_J9CLASS_VALUETYPE(j9class);
768
}
769
770
bool
771
J9::ClassEnv::isValueTypeClassFlattened(TR_OpaqueClassBlock *clazz)
772
{
773
#if defined(J9VM_OPT_JITSERVER)
774
if (auto stream = TR::CompilationInfo::getStream())
775
{
776
uintptr_t classFlags = 0;
777
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags);
778
#ifdef DEBUG
779
stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, clazz);
780
uintptr_t classFlagsRemote = std::get<0>(stream->read<uintptr_t>());
781
// Check that class flags from remote call is equal to the cached ones
782
classFlags = classFlags & J9ClassIsFlattened;
783
classFlagsRemote = classFlagsRemote & J9ClassIsFlattened;
784
TR_ASSERT(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags");
785
#endif
786
return classFlags & J9ClassIsFlattened;
787
}
788
#endif /* defined(J9VM_OPT_JITSERVER) */
789
790
return (clazz && J9_IS_J9CLASS_FLATTENED(reinterpret_cast<J9Class*>(clazz)));
791
}
792
793
bool
794
J9::ClassEnv::isValueBasedOrValueTypeClass(TR_OpaqueClassBlock *clazz)
795
{
796
#if defined(J9VM_OPT_JITSERVER)
797
if (auto stream = TR::CompilationInfo::getStream())
798
{
799
uintptr_t classFlags = 0;
800
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags);
801
#ifdef DEBUG
802
stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, clazz);
803
uintptr_t classFlagsRemote = std::get<0>(stream->read<uintptr_t>());
804
// Check that class flags from remote call is equal to the cached ones
805
classFlags = classFlags & J9_CLASS_DISALLOWS_LOCKING_FLAGS;
806
classFlagsRemote = classFlagsRemote & J9_CLASS_DISALLOWS_LOCKING_FLAGS;
807
TR_ASSERT_FATAL(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags");
808
#endif
809
return J9_ARE_ANY_BITS_SET(classFlags, J9_CLASS_DISALLOWS_LOCKING_FLAGS);
810
}
811
#endif /* defined(J9VM_OPT_JITSERVER) */
812
J9Class *j9class = reinterpret_cast<J9Class*>(clazz);
813
return J9_ARE_ANY_BITS_SET(j9class->classFlags, J9_CLASS_DISALLOWS_LOCKING_FLAGS);
814
}
815
816
bool
817
J9::ClassEnv::classHasIdentity(TR_OpaqueClassBlock *clazz)
818
{
819
#if defined(J9VM_OPT_JITSERVER)
820
if (auto stream = TR::CompilationInfo::getStream())
821
{
822
uintptr_t classFlags = 0;
823
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags);
824
#ifdef DEBUG
825
stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, clazz);
826
uintptr_t classFlagsRemote = std::get<0>(stream->read<uintptr_t>());
827
// Check that class flags from remote call is equal to the cached ones
828
classFlags = classFlags & J9ClassHasIdentity;
829
classFlagsRemote = classFlagsRemote & J9ClassHasIdentity;
830
TR_ASSERT_FATAL(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags");
831
#endif
832
return J9_ARE_ANY_BITS_SET(classFlags, J9ClassHasIdentity);
833
}
834
#endif /* defined(J9VM_OPT_JITSERVER) */
835
J9Class *j9class = reinterpret_cast<J9Class*>(clazz);
836
return J9_ARE_ANY_BITS_SET(j9class->classFlags, J9ClassHasIdentity);
837
}
838
839
bool
840
J9::ClassEnv::isZeroInitializable(TR_OpaqueClassBlock *clazz)
841
{
842
#if defined(J9VM_OPT_JITSERVER)
843
if (auto stream = TR::CompilationInfo::getStream())
844
{
845
uintptr_t classFlags = 0;
846
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)clazz, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void *)&classFlags);
847
#ifdef DEBUG
848
stream->write(JITServer::MessageType::ClassEnv_classFlagsValue, clazz);
849
uintptr_t classFlagsRemote = std::get<0>(stream->read<uintptr_t>());
850
// Check that class flags from remote call is equal to the cached ones
851
classFlags = classFlags & J9ClassContainsUnflattenedFlattenables;
852
classFlagsRemote = classFlagsRemote & J9ClassContainsUnflattenedFlattenables;
853
TR_ASSERT(classFlags == classFlagsRemote, "remote call class flags is not equal to cached class flags");
854
#endif
855
return classFlags & J9ClassContainsUnflattenedFlattenables;
856
}
857
#endif
858
return (self()->classFlagsValue(clazz) & J9ClassContainsUnflattenedFlattenables) == 0;
859
}
860
861
bool
862
J9::ClassEnv::containsZeroOrOneConcreteClass(TR::Compilation *comp, List<TR_PersistentClassInfo>* subClasses)
863
{
864
int count = 0;
865
#if defined(J9VM_OPT_JITSERVER)
866
if (comp->isOutOfProcessCompilation())
867
{
868
ListIterator<TR_PersistentClassInfo> j(subClasses);
869
TR_ScratchList<TR_PersistentClassInfo> subClassesNotCached(comp->trMemory());
870
871
// Process classes cached at the server first
872
ClientSessionData * clientData = TR::compInfoPT->getClientData();
873
for (TR_PersistentClassInfo *ptClassInfo = j.getFirst(); ptClassInfo; ptClassInfo = j.getNext())
874
{
875
TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId();
876
J9Class *j9clazz = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz);
877
auto romClass = JITServerHelpers::getRemoteROMClassIfCached(clientData, j9clazz);
878
if (romClass == NULL)
879
{
880
subClassesNotCached.add(ptClassInfo);
881
}
882
else
883
{
884
if (TR::Compiler->cls.isConcreteClass(comp, clazz))
885
{
886
if (++count > 1)
887
return false;
888
}
889
}
890
}
891
// Traverse through classes that are not cached on server
892
ListIterator<TR_PersistentClassInfo> i(&subClassesNotCached);
893
for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext())
894
{
895
TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId();
896
if (TR::Compiler->cls.isConcreteClass(comp, clazz))
897
{
898
if (++count > 1)
899
return false;
900
}
901
}
902
}
903
else // non-jitserver
904
#endif /* defined(J9VM_OPT_JITSERVER) */
905
{
906
ListIterator<TR_PersistentClassInfo> i(subClasses);
907
for (TR_PersistentClassInfo *ptClassInfo = i.getFirst(); ptClassInfo; ptClassInfo = i.getNext())
908
{
909
TR_OpaqueClassBlock *clazz = ptClassInfo->getClassId();
910
if (TR::Compiler->cls.isConcreteClass(comp, clazz))
911
{
912
if (++count > 1)
913
return false;
914
}
915
}
916
}
917
return true;
918
}
919
920
bool
921
J9::ClassEnv::isClassRefValueType(TR::Compilation *comp, TR_OpaqueClassBlock *cpContextClass, int32_t cpIndex)
922
{
923
#if defined(J9VM_OPT_JITSERVER)
924
if (auto stream = TR::CompilationInfo::getStream())
925
{
926
stream->write(JITServer::MessageType::ClassEnv_isClassRefValueType, cpContextClass, cpIndex);
927
return std::get<0>(stream->read<bool>());
928
}
929
else // non-jitserver
930
#endif /* defined(J9VM_OPT_JITSERVER) */
931
{
932
J9Class * j9class = reinterpret_cast<J9Class *>(cpContextClass);
933
J9JavaVM *vm = comp->fej9()->getJ9JITConfig()->javaVM;
934
return vm->internalVMFunctions->isClassRefQtype(j9class, cpIndex);
935
}
936
}
937
938
char *
939
J9::ClassEnv::classNameToSignature(const char *name, int32_t &len, TR::Compilation *comp, TR_AllocationKind allocKind, TR_OpaqueClassBlock *clazz)
940
{
941
char *sig;
942
943
if (name[0] == '[')
944
{
945
sig = (char *)comp->trMemory()->allocateMemory(len+1, allocKind);
946
memcpy(sig,name,len);
947
}
948
else
949
{
950
len += 2;
951
sig = (char *)comp->trMemory()->allocateMemory(len+1, allocKind);
952
if (clazz && TR::Compiler->om.areValueTypesEnabled() && self()->isValueTypeClass(clazz))
953
sig[0] = 'Q';
954
else
955
sig[0] = 'L';
956
memcpy(sig+1,name,len-2);
957
sig[len-1]=';';
958
}
959
960
sig[len] = '\0';
961
return sig;
962
}
963
964
int32_t
965
J9::ClassEnv::flattenedArrayElementSize(TR::Compilation *comp, TR_OpaqueClassBlock *arrayClass)
966
{
967
#if defined(J9VM_OPT_JITSERVER)
968
if (auto stream = TR::CompilationInfo::getStream())
969
{
970
int32_t arrayElementSize = 0;
971
JITServerHelpers::getAndCacheRAMClassInfo((J9Class *)arrayClass, TR::compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_ARRAY_ELEMENT_SIZE, (void *)&arrayElementSize);
972
return arrayElementSize;
973
}
974
else
975
#endif /* defined(J9VM_OPT_JITSERVER) */
976
{
977
J9JavaVM *vm = comp->fej9()->getJ9JITConfig()->javaVM;
978
return vm->internalVMFunctions->arrayElementSize((J9ArrayClass*)self()->convertClassOffsetToClassPtr(arrayClass));
979
}
980
}
981
982