Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcutil/ROMClassWriter.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2001, 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
* ROMClassWriter.cpp
24
*/
25
#include "ROMClassWriter.hpp"
26
27
#include "BufferManager.hpp"
28
#include "ClassFileOracle.hpp"
29
#include "ConstantPoolMap.hpp"
30
#include "Cursor.hpp"
31
#include "SRPKeyProducer.hpp"
32
#include "ROMClassVerbosePhase.hpp"
33
34
#include "bcnames.h"
35
#include "cfreader.h"
36
#include "j9.h"
37
#include "j9protos.h"
38
#include "ut_j9bcu.h"
39
40
const U_8 PARAM_VOID = 0;
41
const U_8 PARAM_BOOLEAN = 1;
42
const U_8 PARAM_BYTE = 2;
43
const U_8 PARAM_CHAR = 3;
44
const U_8 PARAM_SHORT = 4;
45
const U_8 PARAM_FLOAT = 5;
46
const U_8 PARAM_INT = 6;
47
const U_8 PARAM_DOUBLE = 7;
48
const U_8 PARAM_LONG = 8;
49
const U_8 PARAM_OBJECT = 9;
50
51
class ROMClassWriter::CheckSize
52
{
53
public:
54
CheckSize(Cursor *cursor, UDATA expectedSize) :
55
_cursor(cursor),
56
_expectedSize(expectedSize),
57
_start(cursor->getCount())
58
{
59
}
60
61
~CheckSize()
62
{
63
Trc_BCU_Assert_Equals(_cursor->getCount() - _start, _expectedSize);
64
}
65
66
private:
67
Cursor *_cursor;
68
UDATA _expectedSize;
69
UDATA _start;
70
};
71
72
class ROMClassWriter::AnnotationElementWriter : public ClassFileOracle::AnnotationElementVisitor
73
{
74
public:
75
AnnotationElementWriter(Cursor *cursor, ConstantPoolMap *constantPoolMap, ClassFileOracle *classFileOracle) :
76
_constantPoolMap(constantPoolMap),
77
_cursor(cursor),
78
_classFileOracle(classFileOracle)
79
{
80
}
81
82
virtual void visitConstant(U_16 elementNameIndex, U_16 cpIndex, U_8 elementType)
83
{
84
_cursor->writeU8(elementType, Cursor::GENERIC);
85
_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForAnnotation(cpIndex), Cursor::GENERIC);
86
}
87
88
virtual void visitEnum(U_16 elementNameIndex, U_16 typeNameIndex, U_16 constNameIndex)
89
{
90
_cursor->writeU8('e', Cursor::GENERIC);
91
_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForAnnotation(typeNameIndex), Cursor::GENERIC);
92
_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForAnnotation(constNameIndex), Cursor::GENERIC);
93
}
94
95
virtual void visitClass(U_16 elementNameIndex, U_16 cpIndex)
96
{
97
AnnotationElementWriter::visitConstant(elementNameIndex, cpIndex, 'c');
98
}
99
100
virtual void visitArray(U_16 elementNameIndex, U_16 elementCount, ClassFileOracle::ArrayAnnotationElements *arrayAnnotationElements)
101
{
102
_cursor->writeU8('[', Cursor::GENERIC);
103
_cursor->writeBigEndianU16(elementCount, Cursor::GENERIC);
104
105
AnnotationElementWriter annotationElementWriter(_cursor, _constantPoolMap, _classFileOracle);
106
arrayAnnotationElements->elementsDo(&annotationElementWriter);
107
}
108
109
virtual void visitNestedAnnotation(U_16 elementNameIndex, ClassFileOracle::NestedAnnotation *nestedAnnotation);
110
111
protected:
112
ConstantPoolMap *_constantPoolMap;
113
Cursor *_cursor;
114
ClassFileOracle *_classFileOracle;
115
};
116
117
class ROMClassWriter::AnnotationWriter :
118
public ROMClassWriter::AnnotationElementWriter,
119
public ClassFileOracle::AnnotationsAttributeVisitor,
120
public ClassFileOracle::AnnotationVisitor
121
{
122
public:
123
AnnotationWriter(Cursor *cursor, ConstantPoolMap *constantPoolMap, ClassFileOracle *classFileOracle) :
124
AnnotationElementWriter(cursor, constantPoolMap, classFileOracle)
125
{
126
}
127
128
void visitConstant(U_16 elementNameIndex, U_16 cpIndex, U_8 elementType)
129
{
130
writeElementName(elementNameIndex);
131
AnnotationElementWriter::visitConstant(elementNameIndex, cpIndex, elementType);
132
}
133
134
void visitEnum(U_16 elementNameIndex, U_16 typeNameIndex, U_16 constNameIndex)
135
{
136
writeElementName(elementNameIndex);
137
AnnotationElementWriter::visitEnum(elementNameIndex, typeNameIndex, constNameIndex);
138
}
139
140
void visitClass(U_16 elementNameIndex, U_16 cpIndex)
141
{
142
writeElementName(elementNameIndex);
143
AnnotationElementWriter::visitClass(elementNameIndex, cpIndex);
144
}
145
146
void visitArray(U_16 elementNameIndex, U_16 elementCount, ClassFileOracle::ArrayAnnotationElements *arrayAnnotationElements)
147
{
148
writeElementName(elementNameIndex);
149
AnnotationElementWriter::visitArray(elementNameIndex, elementCount, arrayAnnotationElements);
150
}
151
152
void visitNestedAnnotation(U_16 elementNameIndex, ClassFileOracle::NestedAnnotation *nestedAnnotation)
153
{
154
writeElementName(elementNameIndex);
155
AnnotationElementWriter::visitNestedAnnotation(elementNameIndex, nestedAnnotation);
156
}
157
158
void visitAnnotationsAttribute(U_16 fieldOrMethodIndex, U_32 length, U_16 numberOfAnnotations)
159
{
160
writeAnnotationAttribute(length);
161
_cursor->writeBigEndianU16(numberOfAnnotations, Cursor::GENERIC);
162
}
163
164
void visitDefaultAnnotationAttribute(U_16 fieldOrMethodIndex, U_32 length)
165
{
166
writeAnnotationAttribute(length);
167
}
168
169
void visitParameterAnnotationsAttribute(U_16 fieldOrMethodIndex, U_32 length, U_8 numberOfParameters)
170
{
171
writeAnnotationAttribute(length);
172
_cursor->writeU8(numberOfParameters, Cursor::GENERIC);
173
}
174
175
void visitTypeAnnotationsAttribute(U_16 fieldOrMethodIndex, U_32 length, U_16 numberOfAnnotations)
176
{
177
writeAnnotationAttribute(length);
178
_cursor->writeBigEndianU16(numberOfAnnotations, Cursor::GENERIC);
179
}
180
181
void visitAnnotation(U_16 typeIndex, U_16 elementValuePairCount)
182
{
183
_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForReference(typeIndex), Cursor::GENERIC);
184
_cursor->writeBigEndianU16(elementValuePairCount, Cursor::GENERIC);
185
}
186
187
void visitTypeAnnotation(U_8 targetType, J9CfrTypeAnnotationTargetInfo *targetInfo, J9CfrTypePath *typePath)
188
{
189
_cursor->writeU8(targetType, Cursor::GENERIC);
190
switch (targetType) { /* use values from the JVM spec. Java SE 8 Edition, table 4.7.20-A&B */
191
case CFR_TARGET_TYPE_TypeParameterGenericClass:
192
case CFR_TARGET_TYPE_TypeParameterGenericMethod:
193
_cursor->writeU8(targetInfo->typeParameterTarget.typeParameterIndex, Cursor::GENERIC);
194
break;
195
case CFR_TARGET_TYPE_TypeInExtends:
196
_cursor->writeBigEndianU16(targetInfo->supertypeTarget.supertypeIndex, Cursor::GENERIC);
197
break;
198
199
case CFR_TARGET_TYPE_TypeInBoundOfGenericClass:
200
case CFR_TARGET_TYPE_TypeInBoundOfGenericMethod:
201
_cursor->writeU8(targetInfo->typeParameterBoundTarget.typeParameterIndex, Cursor::GENERIC);
202
_cursor->writeU8(targetInfo->typeParameterBoundTarget.boundIndex, Cursor::GENERIC);
203
break;
204
case CFR_TARGET_TYPE_TypeInFieldDecl:
205
case CFR_TARGET_TYPE_ReturnType:
206
case CFR_TARGET_TYPE_ReceiverType: /* empty_target */
207
break;
208
209
case CFR_TARGET_TYPE_TypeInFormalParam:
210
_cursor->writeU8(targetInfo->methodFormalParameterTarget.formalParameterIndex, Cursor::GENERIC);
211
break;
212
213
case CFR_TARGET_TYPE_TypeInThrows:
214
_cursor->writeBigEndianU16(targetInfo->throwsTarget.throwsTypeIndex, Cursor::GENERIC);
215
break;
216
217
case CFR_TARGET_TYPE_TypeInLocalVar:
218
case CFR_TARGET_TYPE_TypeInResourceVar: {
219
J9CfrLocalvarTarget *t = &(targetInfo->localvarTarget);
220
_cursor->writeBigEndianU16(t->tableLength, Cursor::GENERIC);
221
for (U_32 ti=0; ti < t->tableLength; ++ti) {
222
J9CfrLocalvarTargetEntry *te = &(t->table[ti]);
223
_cursor->writeBigEndianU16(te->startPC, Cursor::GENERIC);
224
_cursor->writeBigEndianU16(te->length, Cursor::GENERIC);
225
_cursor->writeBigEndianU16(te->index, Cursor::GENERIC);
226
}
227
};
228
break;
229
case CFR_TARGET_TYPE_TypeInExceptionParam:
230
_cursor->writeBigEndianU16(targetInfo->catchTarget.exceptiontableIndex, Cursor::GENERIC);
231
break;
232
233
case CFR_TARGET_TYPE_TypeInInstanceof:
234
case CFR_TARGET_TYPE_TypeInNew:
235
case CFR_TARGET_TYPE_TypeInMethodrefNew:
236
case CFR_TARGET_TYPE_TypeInMethodrefIdentifier:
237
_cursor->writeBigEndianU16(targetInfo->offsetTarget.offset, Cursor::GENERIC);
238
break;
239
240
case CFR_TARGET_TYPE_TypeInCast:
241
case CFR_TARGET_TYPE_TypeForGenericConstructorInNew:
242
case CFR_TARGET_TYPE_TypeForGenericMethodInvocation:
243
case CFR_TARGET_TYPE_TypeForGenericConstructorInMethodRef:
244
case CFR_TARGET_TYPE_TypeForGenericMethodInvocationInMethodRef:
245
_cursor->writeBigEndianU16(targetInfo->typeArgumentTarget.offset, Cursor::GENERIC);
246
_cursor->writeU8(targetInfo->typeArgumentTarget.typeArgumentIndex, Cursor::GENERIC);
247
break;
248
249
default:
250
break;
251
}
252
_cursor->writeU8(typePath->pathLength, Cursor::GENERIC);
253
for (U_8 pathIndex = 0; pathIndex < typePath->pathLength; ++pathIndex) {
254
J9CfrTypePathEntry* pathEntry = &(typePath->path[pathIndex]);
255
_cursor->writeU8(pathEntry->typePathKind, Cursor::GENERIC);
256
_cursor->writeU8(pathEntry->typeArgumentIndex, Cursor::GENERIC);
257
}
258
}
259
260
void visitMalformedAnnotationsAttribute(U_32 rawDataLength, U_8 *rawAttributeData)
261
{
262
writeAnnotationAttribute(rawDataLength);
263
for (U_32 byteIndex = 0; byteIndex < rawDataLength; ++byteIndex) {
264
_cursor->writeU8(rawAttributeData[byteIndex], Cursor::GENERIC);
265
}
266
267
}
268
269
void visitParameter(U_16 numberOfAnnotations)
270
{
271
_cursor->writeBigEndianU16(numberOfAnnotations, Cursor::GENERIC);
272
}
273
274
private:
275
void writeElementName(U_16 elementNameIndex)
276
{
277
_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForReference(elementNameIndex), Cursor::GENERIC);
278
}
279
280
void writeAnnotationAttribute(U_32 length)
281
{
282
_cursor->writeU32(length, Cursor::GENERIC); /* Native Endian */
283
}
284
};
285
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
286
ROMClassWriter::ROMClassWriter(BufferManager *bufferManager, ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, ConstantPoolMap *constantPoolMap, ROMClassCreationContext *context, InterfaceInjectionInfo *interfaceInjectionInfo) :
287
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
288
ROMClassWriter::ROMClassWriter(BufferManager *bufferManager, ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, ConstantPoolMap *constantPoolMap, ROMClassCreationContext *context) :
289
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
290
_bufferManager(bufferManager),
291
_classFileOracle(classFileOracle),
292
_srpKeyProducer(srpKeyProducer),
293
_constantPoolMap(constantPoolMap),
294
_srpOffsetTable(NULL),
295
_context(context),
296
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
297
_interfaceInjectionInfo(interfaceInjectionInfo),
298
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
299
_buildResult(OK),
300
_interfacesSRPKey(srpKeyProducer->generateKey()),
301
_methodsSRPKey(srpKeyProducer->generateKey()),
302
_fieldsSRPKey(srpKeyProducer->generateKey()),
303
_cpDescriptionShapeSRPKey(srpKeyProducer->generateKey()),
304
_innerClassesSRPKey(srpKeyProducer->generateKey()),
305
_enclosedInnerClassesSRPKey(srpKeyProducer->generateKey()),
306
#if JAVA_SPEC_VERSION >= 11
307
_nestMembersSRPKey(srpKeyProducer->generateKey()),
308
#endif /* JAVA_SPEC_VERSION >= 11 */
309
_optionalInfoSRPKey(srpKeyProducer->generateKey()),
310
_enclosingMethodSRPKey(srpKeyProducer->generateKey()),
311
_sourceDebugExtensionSRPKey(srpKeyProducer->generateKey()),
312
_intermediateClassDataSRPKey(srpKeyProducer->generateKey()),
313
_annotationInfoClassSRPKey(srpKeyProducer->generateKey()),
314
_typeAnnotationInfoSRPKey(srpKeyProducer->generateKey()),
315
_recordInfoSRPKey(srpKeyProducer->generateKey()),
316
_callSiteDataSRPKey(srpKeyProducer->generateKey()),
317
_staticSplitTableSRPKey(srpKeyProducer->generateKey()),
318
_specialSplitTableSRPKey(srpKeyProducer->generateKey()),
319
#if defined(J9VM_OPT_METHOD_HANDLE)
320
_varHandleMethodTypeLookupTableSRPKey(srpKeyProducer->generateKey()),
321
#endif /* defined(J9VM_OPT_METHOD_HANDLE) */
322
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
323
_injectedInterfaceInfoSRPKey(srpKeyProducer->generateKey()),
324
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
325
_permittedSubclassesInfoSRPKey(srpKeyProducer->generateKey())
326
{
327
_methodNotes = (MethodNotes *) _bufferManager->alloc(classFileOracle->getMethodsCount() * sizeof(MethodNotes));
328
if (NULL == _methodNotes) {
329
_buildResult = OutOfMemory;
330
return;
331
}
332
memset(_methodNotes, 0, classFileOracle->getMethodsCount() * sizeof(MethodNotes));
333
}
334
335
ROMClassWriter::~ROMClassWriter()
336
{
337
_bufferManager->free(_methodNotes);
338
}
339
340
void
341
ROMClassWriter::writeROMClass(Cursor *cursor,
342
Cursor *lineNumberCursor,
343
Cursor *variableInfoCursor,
344
Cursor *utf8Cursor,
345
Cursor *classDataCursor,
346
U_32 romSize, U_32 modifiers, U_32 extraModifiers, U_32 optionalFlags,
347
MarkOrWrite markOrWrite)
348
{
349
bool markAndCountOnly = (MARK_AND_COUNT_ONLY== markOrWrite);
350
/*
351
* Write the J9ROMClass structure (AKA Header).
352
*/
353
if (markAndCountOnly) {
354
if (!_context->isIntermediateDataAClassfile()) {
355
if (NULL == _context->intermediateClassData()) {
356
/* In case intermediate data is not explicitly provided in the _context,
357
* ROMClass being created can itself be used as intermediateClassData.
358
*/
359
cursor->mark(_intermediateClassDataSRPKey);
360
} else {
361
_srpOffsetTable->setInternedAt(_intermediateClassDataSRPKey, _context->intermediateClassData());
362
}
363
}
364
cursor->skip(sizeof(J9ROMClass));
365
} else {
366
CheckSize _(cursor, sizeof(J9ROMClass));
367
cursor->writeU32(romSize, Cursor::ROM_SIZE);
368
cursor->writeU32(_classFileOracle->getSingleScalarStaticCount(), Cursor::GENERIC);
369
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getClassNameIndex()), Cursor::SRP_TO_UTF8_CLASS_NAME);
370
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getSuperClassNameIndex()), Cursor::SRP_TO_UTF8);
371
cursor->writeU32(modifiers, Cursor::GENERIC);
372
cursor->writeU32(extraModifiers, Cursor::GENERIC);
373
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
374
cursor->writeU32(_classFileOracle->getInterfacesCount() + _interfaceInjectionInfo->numOfInterfaces, Cursor::GENERIC);
375
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
376
cursor->writeU32(_classFileOracle->getInterfacesCount(), Cursor::GENERIC);
377
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
378
cursor->writeSRP(_interfacesSRPKey, Cursor::SRP_TO_GENERIC);
379
cursor->writeU32(_classFileOracle->getMethodsCount(), Cursor::GENERIC);
380
cursor->writeSRP(_methodsSRPKey, Cursor::SRP_TO_GENERIC);
381
cursor->writeU32(_classFileOracle->getFieldsCount(), Cursor::GENERIC);
382
cursor->writeSRP(_fieldsSRPKey, Cursor::SRP_TO_GENERIC);
383
cursor->writeU32(_classFileOracle->getObjectStaticCount(), Cursor::GENERIC);
384
cursor->writeU32(_classFileOracle->getDoubleScalarStaticCount(), Cursor::GENERIC);
385
cursor->writeU32(_constantPoolMap->getRAMConstantPoolCount(), Cursor::GENERIC);
386
cursor->writeU32(_constantPoolMap->getROMConstantPoolCount(), Cursor::GENERIC);
387
cursor->writeWSRP(_intermediateClassDataSRPKey, Cursor::SRP_TO_INTERMEDIATE_CLASS_DATA);
388
if (NULL == _context->intermediateClassData()) {
389
/* In case intermediate data is not explicitly provided in the _context,
390
* ROMClass being created is itself used as intermediateClassData,
391
* therefore intermediateDataLength should be the ROMClass size.
392
*/
393
cursor->writeU32(romSize, Cursor::INTERMEDIATE_CLASS_DATA_LENGTH);
394
} else {
395
cursor->writeU32(_context->intermediateClassDataLength(), Cursor::INTERMEDIATE_CLASS_DATA_LENGTH);
396
}
397
cursor->writeU32(OBJECT_HEADER_SHAPE_MIXED, Cursor::GENERIC);
398
cursor->writeSRP(_cpDescriptionShapeSRPKey, Cursor::SRP_TO_GENERIC);
399
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getOuterClassNameIndex()), Cursor::SRP_TO_UTF8);
400
cursor->writeU32(_classFileOracle->getMemberAccessFlags(), Cursor::GENERIC);
401
cursor->writeU32(_classFileOracle->getInnerClassCount(), Cursor::GENERIC);
402
cursor->writeSRP(_innerClassesSRPKey, Cursor::SRP_TO_GENERIC);
403
cursor->writeU32(_classFileOracle->getEnclosedInnerClassCount(), Cursor::GENERIC);
404
cursor->writeSRP(_enclosedInnerClassesSRPKey, Cursor::SRP_TO_GENERIC);
405
#if JAVA_SPEC_VERSION >= 11
406
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getNestHostNameIndex()), Cursor::SRP_TO_UTF8);
407
cursor->writeU16(_classFileOracle->getNestMembersCount(), Cursor::GENERIC);
408
cursor->writeU16(0, Cursor::GENERIC); /* padding */
409
cursor->writeSRP(_nestMembersSRPKey, Cursor::SRP_TO_GENERIC);
410
#endif /* JAVA_SPEC_VERSION >= 11 */
411
cursor->writeU16(_classFileOracle->getMajorVersion(), Cursor::GENERIC);
412
cursor->writeU16(_classFileOracle->getMinorVersion(), Cursor::GENERIC);
413
cursor->writeU32(optionalFlags, Cursor::OPTIONAL_FLAGS);
414
cursor->writeSRP(_optionalInfoSRPKey, Cursor::SRP_TO_GENERIC);
415
cursor->writeU32(_classFileOracle->getMaxBranchCount(), Cursor::GENERIC);
416
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
417
cursor->writeU32(_constantPoolMap->getInvokeCacheCount(), Cursor::GENERIC);
418
#else /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
419
cursor->writeU32(_constantPoolMap->getMethodTypeCount(), Cursor::GENERIC);
420
cursor->writeU32(_constantPoolMap->getVarHandleMethodTypeCount(), Cursor::GENERIC);
421
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
422
cursor->writeU32(_classFileOracle->getBootstrapMethodCount(), Cursor::GENERIC);
423
cursor->writeU32(_constantPoolMap->getCallSiteCount(), Cursor::GENERIC);
424
cursor->writeSRP(_callSiteDataSRPKey, Cursor::SRP_TO_GENERIC);
425
cursor->writeU32(_classFileOracle->getClassFileSize(), Cursor::CLASS_FILE_SIZE);
426
cursor->writeU32((U_32)_classFileOracle->getConstantPoolCount(), Cursor::GENERIC);
427
cursor->writeU16(_constantPoolMap->getStaticSplitEntryCount(), Cursor::GENERIC);
428
cursor->writeU16(_constantPoolMap->getSpecialSplitEntryCount(), Cursor::GENERIC);
429
cursor->writeSRP(_staticSplitTableSRPKey, Cursor::SRP_TO_GENERIC);
430
cursor->writeSRP(_specialSplitTableSRPKey, Cursor::SRP_TO_GENERIC);
431
#if defined(J9VM_OPT_METHOD_HANDLE)
432
cursor->writeSRP(_varHandleMethodTypeLookupTableSRPKey, Cursor::SRP_TO_GENERIC);
433
#endif /* defined(J9VM_OPT_METHOD_HANDLE) */
434
cursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);
435
}
436
437
/*
438
* Write the rest of the contiguous portion of the ROMClass
439
*/
440
441
cursor->setClassNameIndex((_classFileOracle->getClassNameIndex()));
442
writeConstantPool(cursor, markAndCountOnly);
443
writeFields(cursor, markAndCountOnly);
444
writeInterfaces(cursor, markAndCountOnly);
445
writeInnerClasses(cursor, markAndCountOnly);
446
writeEnclosedInnerClasses(cursor, markAndCountOnly);
447
#if JAVA_SPEC_VERSION >= 11
448
writeNestMembers(cursor, markAndCountOnly);
449
#endif /* JAVA_SPEC_VERSION >= 11 */
450
writeNameAndSignatureBlock(cursor);
451
writeMethods(cursor, lineNumberCursor, variableInfoCursor, markAndCountOnly);
452
writeConstantPoolShapeDescriptions(cursor, markAndCountOnly);
453
writeAnnotationInfo(cursor);
454
writeSourceDebugExtension(cursor);
455
writeRecordComponents(cursor, markAndCountOnly);
456
writePermittedSubclasses(cursor, markAndCountOnly);
457
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
458
writeInjectedInterfaces(cursor, markAndCountOnly);
459
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
460
writeOptionalInfo(cursor);
461
writeCallSiteData(cursor, markAndCountOnly);
462
#if defined(J9VM_OPT_METHOD_HANDLE)
463
writeVarHandleMethodTypeLookupTable(cursor, markAndCountOnly);
464
#endif /* defined(J9VM_OPT_METHOD_HANDLE) */
465
writeStaticSplitTable(cursor, markAndCountOnly);
466
writeSpecialSplitTable(cursor, markAndCountOnly);
467
/* aligned to U_64 required by the shared classes */
468
cursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);
469
470
/*
471
* Write UTF8s
472
*/
473
if ( NULL != utf8Cursor ) {
474
ROMClassVerbosePhase v(_context, markAndCountOnly ? MarkAndCountUTF8s : WriteUTF8s);
475
writeUTF8s(utf8Cursor);
476
}
477
478
/*
479
* Write Intermediate Class File bytes if
480
* (-Xshareclasses:enableBCI is specified and class file has not been modified by BCI agent) or
481
* (re-transformation is enabled and -Xshareclasses:enableBCI is not present).
482
*/
483
if ((NULL != classDataCursor)
484
&& !_srpOffsetTable->isInterned(_intermediateClassDataSRPKey)
485
) {
486
classDataCursor->mark(_intermediateClassDataSRPKey);
487
classDataCursor->writeData(_context->intermediateClassData(), _context->intermediateClassDataLength(), Cursor::INTERMEDIATE_CLASS_DATA);
488
/* aligned to U_64 required by the shared classes */
489
classDataCursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);
490
}
491
}
492
493
/*
494
* Global table for ROMClassWriter::ConstantPoolWriter::visitMethodHandle().
495
*/
496
static const UDATA splitTypeMap[] = {
497
0, /* UNUSED */
498
ConstantPoolMap::GET_FIELD, /* GETFIELD */
499
ConstantPoolMap::GET_STATIC, /* GETSTATIC */
500
ConstantPoolMap::PUT_FIELD, /* PUTFIELD */
501
ConstantPoolMap::PUT_STATIC, /* PUTSTATIC */
502
ConstantPoolMap::INVOKE_VIRTUAL, /* INVOKEVIRTUAL */
503
ConstantPoolMap::INVOKE_STATIC, /* INVOKESTATIC */
504
ConstantPoolMap::INVOKE_SPECIAL, /* INVOKESPECIAL */
505
ConstantPoolMap::INVOKE_SPECIAL, /* NEWINVOKESPECIAL */
506
ConstantPoolMap::INVOKE_INTERFACE /* INVOKEINTERFACE */
507
};
508
509
class ROMClassWriter::ConstantPoolWriter : public ConstantPoolMap::ConstantPoolVisitor
510
{
511
public:
512
ConstantPoolWriter(Cursor *cursor, SRPKeyProducer *srpKeyProducer, ConstantPoolMap *constantPoolMap) :
513
_cursor(cursor),
514
_srpKeyProducer(srpKeyProducer),
515
_constantPoolMap(constantPoolMap)
516
{
517
}
518
519
void visitClass(U_16 cfrCPIndex)
520
{
521
/* if the cfrCPIndex is for the class name, the data type should be SRP_TO_UTF8_CLASS_NAME to avoid comparing lambda class names */
522
U_16 classNameIndex = _cursor->getClassNameIndex();
523
if (((U_16)-1 != classNameIndex) && (_srpKeyProducer->mapCfrConstantPoolIndexToKey(classNameIndex) == _srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex))) {
524
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8_CLASS_NAME);
525
} else {
526
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8);
527
}
528
_cursor->writeU32(BCT_J9DescriptionCpTypeClass, Cursor::GENERIC);
529
}
530
531
void visitString(U_16 cfrCPIndex)
532
{
533
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8);
534
_cursor->writeU32(BCT_J9DescriptionCpTypeObject, Cursor::GENERIC);
535
}
536
537
void visitMethodType(U_16 cfrCPIndex, U_16 originFlags)
538
{
539
/* Assumes format: { SRP to UTF8, cpType } */
540
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_UTF8);
541
_cursor->writeU32((originFlags << BCT_J9DescriptionCpTypeShift) | BCT_J9DescriptionCpTypeMethodType, Cursor::GENERIC);
542
}
543
544
void visitMethodHandle(U_16 cfrKind, U_16 cfrCPIndex)
545
{
546
U_32 cpIndex = _constantPoolMap->getROMClassCPIndex(cfrCPIndex, splitTypeMap[cfrKind]);
547
548
Trc_BCU_Assert_NotEquals(cpIndex, 0);
549
550
/* assumes format: { U32 cpIndex, (cfrKind << 4) || cpType } */
551
_cursor->writeU32(cpIndex, Cursor::GENERIC);
552
_cursor->writeU32((cfrKind << BCT_J9DescriptionCpTypeShift) | BCT_J9DescriptionCpTypeMethodHandle, Cursor::GENERIC);
553
}
554
555
void visitConstantDynamic(U_16 bsmIndex, U_16 cfrCPIndex, U_32 primitiveFlag)
556
{
557
/* assumes format: { SRP to NameAndSignature, primitiveFlag || (bsmIndex << 4) || cpType } */
558
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cfrCPIndex), Cursor::SRP_TO_NAME_AND_SIGNATURE);
559
_cursor->writeU32((bsmIndex << BCT_J9DescriptionCpTypeShift) | BCT_J9DescriptionCpTypeConstantDynamic | primitiveFlag, Cursor::GENERIC);
560
}
561
562
void visitSingleSlotConstant(U_32 slot1)
563
{
564
_cursor->writeU32(slot1, Cursor::GENERIC);
565
_cursor->writeU32(BCT_J9DescriptionCpTypeScalar, Cursor::GENERIC);
566
}
567
568
void visitDoubleSlotConstant(U_32 slot1, U_32 slot2)
569
{
570
#ifdef J9VM_ENV_DATA64
571
_cursor->writeU64(slot1, slot2, Cursor::GENERIC);
572
#else
573
_cursor->writeU32(slot1, Cursor::GENERIC);
574
_cursor->writeU32(slot2, Cursor::GENERIC);
575
#endif
576
}
577
578
void visitFieldOrMethod(U_16 classRefCPIndex, U_16 nameAndSignatureCfrCPIndex)
579
{
580
_cursor->writeU32(classRefCPIndex, Cursor::GENERIC);
581
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(nameAndSignatureCfrCPIndex), Cursor::SRP_TO_NAME_AND_SIGNATURE);
582
}
583
584
private:
585
Cursor *_cursor;
586
SRPKeyProducer *_srpKeyProducer;
587
ConstantPoolMap *_constantPoolMap;
588
};
589
590
void
591
ROMClassWriter::writeConstantPool(Cursor *cursor, bool markAndCountOnly)
592
{
593
UDATA constantPoolSize = UDATA(_constantPoolMap->getROMConstantPoolCount()) * sizeof(J9ROMConstantPoolItem);
594
if (markAndCountOnly) {
595
cursor->skip(constantPoolSize);
596
} else {
597
CheckSize _(cursor, constantPoolSize);
598
599
/* Write the zeroth entry */
600
cursor->writeU32(0, Cursor::GENERIC);
601
cursor->writeU32(0, Cursor::GENERIC);
602
603
ConstantPoolWriter writer(cursor, _srpKeyProducer, _constantPoolMap);
604
_constantPoolMap->constantPoolDo(&writer);
605
}
606
}
607
608
/*
609
* The ROM class field has the following layout:
610
* J9ROMFieldShape
611
* 4 or 8 bytes unsigned constant value if this is a static const field
612
* 4 bytes SRP to generic field signature if the field has a generic signature
613
* 4 bytes length of annotation data in bytes, followed by annotation data. Omitted if there are no field annotations.
614
* 4 bytes length of type annotation data in bytes followed by type annotation data. Omitted if there are no type annotations.
615
*/
616
617
void
618
ROMClassWriter::writeFields(Cursor *cursor, bool markAndCountOnly)
619
{
620
cursor->mark(_fieldsSRPKey);
621
ClassFileOracle::FieldIterator iterator = _classFileOracle->getFieldIterator();
622
while ( iterator.isNotDone() ) {
623
if (markAndCountOnly) {
624
cursor->skip(sizeof(J9ROMFieldShape));
625
} else {
626
CheckSize _(cursor, sizeof(J9ROMFieldShape));
627
628
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getNameIndex()), Cursor::SRP_TO_UTF8);
629
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getDescriptorIndex()), Cursor::SRP_TO_UTF8);
630
631
U_32 fieldSignatureFlags(fieldModifiersLookupTable[iterator.getFirstByteOfDescriptor() - 'A']);
632
U_32 modifiers(iterator.getAccessFlags() | (fieldSignatureFlags << 16));
633
if (iterator.isConstant()) {
634
modifiers |= J9FieldFlagConstant;
635
}
636
if (iterator.hasGenericSignature()) {
637
modifiers |= J9FieldFlagHasGenericSignature;
638
}
639
if (iterator.isSynthetic()) {
640
/* handle the synthetic attribute. In java 1.5 synthetic may be specified in the access flags as well so do not unset bit here */
641
modifiers |= J9AccSynthetic;
642
}
643
if (iterator.isFieldContended()) {
644
modifiers |= J9FieldFlagIsContended;
645
}
646
if (iterator.hasAnnotation()) {
647
modifiers |= J9FieldFlagHasFieldAnnotations;
648
}
649
if (iterator.hasTypeAnnotation()) {
650
modifiers |= J9FieldFlagHasTypeAnnotations;
651
}
652
653
cursor->writeU32(modifiers, Cursor::GENERIC);
654
}
655
656
if (iterator.isConstant()) { // Check not absolutely necessary, but might provide small performance win
657
if (iterator.isConstantFloat() || iterator.isConstantInteger()) {
658
cursor->writeU32(iterator.getConstantValueSlot1(), Cursor::GENERIC);
659
} else if (iterator.isConstantDouble() || iterator.isConstantLong()) {
660
cursor->writeU32(iterator.getConstantValueSlot1(), Cursor::GENERIC);
661
cursor->writeU32(iterator.getConstantValueSlot2(), Cursor::GENERIC);
662
} else if (iterator.isConstantString()) {
663
cursor->writeU32(U_32(_constantPoolMap->getROMClassCPIndexForReference(iterator.getConstantValueConstantPoolIndex())), Cursor::GENERIC);
664
}
665
}
666
667
if (iterator.hasGenericSignature()) {
668
if (markAndCountOnly) { // TODO check if this is a performance win
669
cursor->skip(sizeof(J9SRP));
670
} else {
671
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);
672
}
673
}
674
675
if (iterator.hasAnnotation()) {
676
/*
677
* u_32 length
678
* length * u_8
679
* pad to u_32 size
680
*/
681
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
682
_classFileOracle->fieldAnnotationDo(iterator.getFieldIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
683
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
684
}
685
686
if (iterator.hasTypeAnnotation()) {
687
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
688
_classFileOracle->fieldTypeAnnotationDo(iterator.getFieldIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
689
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
690
}
691
692
693
iterator.next();
694
}
695
}
696
697
/* mapping characters A..Z,[ */
698
const U_8 primitiveArrayTypeCharConversion[] = {
699
0, CFR_STACKMAP_TYPE_BYTE_ARRAY, CFR_STACKMAP_TYPE_CHAR_ARRAY, CFR_STACKMAP_TYPE_DOUBLE_ARRAY,
700
0, CFR_STACKMAP_TYPE_FLOAT_ARRAY, 0, 0,
701
CFR_STACKMAP_TYPE_INT_ARRAY, CFR_STACKMAP_TYPE_LONG_ARRAY, 0, 0,
702
0, 0, 0, 0,
703
0, 0, CFR_STACKMAP_TYPE_SHORT_ARRAY, 0,
704
0, 0, 0, 0,
705
0, CFR_STACKMAP_TYPE_BOOL_ARRAY, 0};
706
707
class ROMClassWriter::CallSiteWriter : public ConstantPoolMap::CallSiteVisitor
708
{
709
public:
710
CallSiteWriter(Cursor *cursor) :
711
_cursor(cursor)
712
{
713
}
714
715
void visitCallSite(U_16 nameAndSignatureIndex, U_16 bootstrapMethodIndex)
716
{
717
_cursor->writeU16(bootstrapMethodIndex, Cursor::GENERIC);
718
}
719
720
private:
721
Cursor *_cursor;
722
};
723
724
class ROMClassWriter::Helper :
725
private ClassFileOracle::ConstantPoolIndexVisitor,
726
private ClassFileOracle::ExceptionHandlerVisitor,
727
private ClassFileOracle::StackMapFrameVisitor,
728
private ClassFileOracle::VerificationTypeInfoVisitor,
729
private ClassFileOracle::BootstrapMethodVisitor,
730
private ClassFileOracle::MethodParametersVisitor,
731
private ConstantPoolMap::SplitEntryVisitor,
732
private ConstantPoolMap::CallSiteVisitor
733
{
734
public:
735
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
736
Helper(Cursor *cursor, bool markAndCountOnly,
737
ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, SRPOffsetTable *srpOffsetTable, ConstantPoolMap *constantPoolMap,
738
UDATA expectedSize, InterfaceInjectionInfo *interfaceInjectionInfo) :
739
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
740
Helper(Cursor *cursor, bool markAndCountOnly,
741
ClassFileOracle *classFileOracle, SRPKeyProducer *srpKeyProducer, SRPOffsetTable *srpOffsetTable, ConstantPoolMap *constantPoolMap,
742
UDATA expectedSize) :
743
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
744
_cursor(cursor),
745
_classFileOracle(classFileOracle),
746
_srpKeyProducer(srpKeyProducer),
747
_srpOffsetTable(srpOffsetTable),
748
_constantPoolMap(constantPoolMap),
749
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
750
_interfaceInjectionInfo(interfaceInjectionInfo),
751
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
752
_markAndCountOnly(markAndCountOnly)
753
{
754
if (_markAndCountOnly) {
755
_cursor->skip(expectedSize);
756
}
757
}
758
759
void writeInnerClasses()
760
{
761
if (!_markAndCountOnly) {
762
_classFileOracle->innerClassesDo(this); /* visitConstantPoolIndex */
763
}
764
}
765
766
void writeEnclosedInnerClasses()
767
{
768
if (!_markAndCountOnly) {
769
_classFileOracle->enclosedInnerClassesDo(this); /* visitConstantPoolIndex */
770
}
771
}
772
773
#if JAVA_SPEC_VERSION >= 11
774
void writeNestMembers()
775
{
776
if (!_markAndCountOnly) {
777
_classFileOracle->nestMembersDo(this); /* visitConstantPoolIndex */
778
}
779
}
780
#endif /* JAVA_SPEC_VERSION >= 11 */
781
782
void writeInterfaces()
783
{
784
if (!_markAndCountOnly) {
785
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
786
_classFileOracle->interfacesDo(this, _interfaceInjectionInfo->numOfInterfaces); /* visitConstantPoolIndex */
787
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
788
_classFileOracle->interfacesDo(this); /* visitConstantPoolIndex */
789
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
790
}
791
}
792
793
void writeNameAndSignatureBlock()
794
{
795
if (!_markAndCountOnly) {
796
for (ClassFileOracle::NameAndTypeIterator iterator = _classFileOracle->getNameAndTypeIterator();
797
iterator.isNotDone();
798
iterator.next()) {
799
U_16 cpIndex = iterator.getCPIndex();
800
801
if (_constantPoolMap->isNATConstantReferenced(cpIndex)) {
802
U_16 nameIndex = iterator.getNameIndex();
803
U_16 descriptorIndex = iterator.getDescriptorIndex();
804
805
_cursor->mark(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex));
806
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(nameIndex), Cursor::SRP_TO_UTF8);
807
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(descriptorIndex), Cursor::SRP_TO_UTF8);
808
}
809
}
810
}
811
}
812
813
void writeUTF8Block()
814
{
815
if (!_markAndCountOnly) {
816
for (ClassFileOracle::UTF8Iterator iterator = _classFileOracle->getUTF8Iterator();
817
iterator.isNotDone();
818
iterator.next()) {
819
U_16 cpIndex = iterator.getCPIndex();
820
821
if (_constantPoolMap->isUTF8ConstantReferenced(cpIndex)) {
822
UDATA key = _srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex);
823
824
if (!_srpOffsetTable->isInterned(key)) {
825
U_8* utf8Data = iterator.getUTF8Data();
826
U_16 utf8Length = iterator.getUTF8Length();
827
828
_cursor->mark(key);
829
_cursor->writeUTF8(utf8Data, utf8Length, Cursor::GENERIC);
830
}
831
}
832
}
833
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
834
for (int i = 0; i < _interfaceInjectionInfo->numOfInterfaces; i++) {
835
/* if the class requires injected interfaces an "extra" CP slot in the key table is added for each interface */
836
_cursor->mark(_classFileOracle->getConstantPoolCount() + i);
837
_cursor->writeUTF8((U_8*)J9UTF8_DATA(_interfaceInjectionInfo->interfaces[i]), J9UTF8_LENGTH(_interfaceInjectionInfo->interfaces[i]), Cursor::GENERIC);
838
}
839
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
840
}
841
}
842
843
void writeExceptionBlock(ClassFileOracle::MethodIterator *iterator)
844
{
845
if (!_markAndCountOnly) {
846
iterator->exceptionHandlersDo(this); /* visitExceptionHandler */
847
iterator->exceptionsThrownDo(this); /* visitConstantPoolIndex */
848
}
849
}
850
851
void writeMethodParameters(ClassFileOracle::MethodIterator *iterator)
852
{
853
if (!_markAndCountOnly) {
854
iterator->methodParametersDo(this); /* visitMethodParameters */
855
}
856
}
857
858
void writeStackMap(ClassFileOracle::MethodIterator *methodIterator)
859
{
860
if (!_markAndCountOnly) {
861
methodIterator->stackMapFramesDo(this); /* visitStackMapFrame */
862
}
863
}
864
865
void writeCallSiteData()
866
{
867
if (!_markAndCountOnly) {
868
CallSiteWriter callSiteWriter(_cursor);
869
_constantPoolMap->callSitesDo(this); /* visitCallSite */
870
_constantPoolMap->callSitesDo(&callSiteWriter);
871
}
872
}
873
874
#if defined(J9VM_OPT_METHOD_HANDLE)
875
void writeVarHandleMethodTypeLookupTable()
876
{
877
if (!_markAndCountOnly) {
878
U_16 lookupTableCount = _constantPoolMap->getVarHandleMethodTypeCount();
879
if (lookupTableCount > 0) {
880
U_16 *lookupTable = _constantPoolMap->getVarHandleMethodTypeLookupTable();
881
882
/* The lookup table is a U_16[], so we need to pad it in order to keep the J9ROMClass alignment. */
883
U_16 lookupTablePaddedCount = _constantPoolMap->getVarHandleMethodTypePaddedCount();
884
U_16 *lookupTablePadding = lookupTable + lookupTableCount;
885
UDATA lookupTablePaddingLength = lookupTablePaddedCount - lookupTableCount;
886
887
/* Write the data section of the array */
888
_cursor->writeData((U_8 *)lookupTable, lookupTableCount * sizeof(U_16), Cursor::GENERIC);
889
890
/* Write the padding section of the array */
891
if (lookupTablePaddingLength > 0) {
892
_cursor->writeData((U_8 *)lookupTablePadding, lookupTablePaddingLength * sizeof(U_16), Cursor::GENERIC);
893
}
894
}
895
}
896
}
897
#endif /* defined(J9VM_OPT_METHOD_HANDLE) */
898
899
void writeBootstrapMethods()
900
{
901
if (!_markAndCountOnly) {
902
_classFileOracle->bootstrapMethodsDo(this); /* visitBootstrapMethod */
903
}
904
}
905
906
void writeStaticSplitTable()
907
{
908
if (!_markAndCountOnly) {
909
_constantPoolMap->staticSplitEntriesDo(this); /* visitSplitEntry */
910
}
911
}
912
913
void writeSpecialSplitTable()
914
{
915
if (!_markAndCountOnly) {
916
_constantPoolMap->specialSplitEntriesDo(this); /* visitSplitEntry */
917
}
918
}
919
920
private:
921
/*
922
* Implement interfaces
923
*/
924
void visitConstantPoolIndex(U_16 cpIndex)
925
{
926
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex), Cursor::SRP_TO_UTF8);
927
}
928
929
void visitMethodParameters(U_16 cpIndex, U_16 flag) {
930
if (0 == cpIndex) {
931
_cursor->writeU32(0, Cursor::GENERIC);
932
} else {
933
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(cpIndex), Cursor::SRP_TO_UTF8);
934
}
935
_cursor->writeU16(flag, Cursor::GENERIC);
936
}
937
938
void visitExceptionHandler(U_32 startPC, U_32 endPC, U_32 handlerPC, U_16 exceptionClassCPIndex)
939
{
940
_cursor->writeU32(startPC, Cursor::GENERIC);
941
_cursor->writeU32(endPC, Cursor::GENERIC);
942
_cursor->writeU32(handlerPC, Cursor::GENERIC);
943
_cursor->writeU32(_constantPoolMap->getROMClassCPIndexForReference(exceptionClassCPIndex), Cursor::GENERIC);
944
}
945
946
void visitStackMapObject(U_8 slotType, U_16 classCPIndex, U_16 classNameCPIndex)
947
{
948
U_8 *nameData = _classFileOracle->getUTF8Data(classNameCPIndex);
949
U_16 nameLength = _classFileOracle->getUTF8Length(classNameCPIndex);
950
/* special conversion of primitive array objects
951
* detect whether or not this is a primitive array e.g.,
952
* [I or [[F, etc..
953
* vs. an array of Objects e.g.,
954
* [Lcom/ibm/foo/Bar;
955
*/
956
if ((nameData[0] == '[') && (nameData[nameLength - 1] != ';')) {
957
/*
958
* This is a primitive array object.
959
*
960
* Encode the primitive array type in the tag field.
961
* One of:
962
* CFR_STACKMAP_TYPE_BYTE_ARRAY
963
* CFR_STACKMAP_TYPE_BOOL_ARRAY
964
* CFR_STACKMAP_TYPE_CHAR_ARRAY
965
* CFR_STACKMAP_TYPE_DOUBLE_ARRAY
966
* CFR_STACKMAP_TYPE_FLOAT_ARRAY
967
* CFR_STACKMAP_TYPE_INT_ARRAY
968
* CFR_STACKMAP_TYPE_LONG_ARRAY
969
* CFR_STACKMAP_TYPE_SHORT_ARRAY
970
*/
971
_cursor->writeU8(primitiveArrayTypeCharConversion[nameData[nameLength - 1] - 'A'], Cursor::GENERIC);
972
973
/* Also, encode the arity beyond 1
974
* (i.e., number of dimensions of the array - 1)
975
* in the next 2 bytes in Big Endian (since we are maintaining Sun StackMapTable format).
976
*
977
* The reason for encoding arity - 1 in verification type info in Stack maps for primitive array special cases are:
978
* The newarray and anewarray bytecodes assume that the array has only a single dimension.
979
* To create a multidimension array, multianewarray must be used.
980
* The primitive array access bytecodes (ie: iaload) can only be used on single dimension arrays.
981
* aaload must be used to access every dimension prior to the base dimension in a multi-arity primitive array.
982
* The constants in vrfytbl.c are based off the constants for the primitive types, and can't have the arity of 1 encoded if the constant is to be used for both purposes.
983
* (See rtverify.c verifyBytecodes() - the RTV_ARRAY_FETCH_PUSH & RTV_ARRAY_STORE cases of the switch)
984
* In addition, the code all through the verifier assumes this condition.
985
* Notes:
986
* See util/vrfytbl.c for bytecode tables.
987
* See constant definitions in cfreader.h and oti/bytecodewalk.h.
988
* bcverify/bcverify.c simulateStack() is the other place that creates stack maps.
989
*/
990
_cursor->writeBigEndianU16(nameLength - 2, Cursor::GENERIC);
991
} else {
992
/*
993
* Object_variable_info
994
* u1 tag
995
* u2 cpIndex (ROMClass constant pool index)
996
*/
997
_cursor->writeU8(slotType, Cursor::GENERIC);
998
_cursor->writeBigEndianU16(_constantPoolMap->getROMClassCPIndexForReference(classCPIndex), Cursor::GENERIC);
999
}
1000
}
1001
1002
void visitStackMapNewObject(U_8 slotType, U_16 offset)
1003
{
1004
/*
1005
* Uninitialized_variable_info
1006
* u1 tag
1007
* u2 offset (offset of the new instruction that created the object being stored in the location)
1008
*/
1009
_cursor->writeU8(slotType, Cursor::GENERIC);
1010
/* output the offset delta */
1011
_cursor->writeBigEndianU16(offset, Cursor::GENERIC);
1012
}
1013
1014
void visitStackMapItem(U_8 slotType)
1015
{
1016
_cursor->writeU8(slotType, Cursor::GENERIC);
1017
}
1018
1019
void visitStackMapFrame(U_16 localsCount, U_16 stackItemsCount, U_16 offsetDelta, U_8 frameType, ClassFileOracle::VerificationTypeInfo *typeInfo)
1020
{
1021
/*
1022
* Stack Map Frame:
1023
* consists of a 1 byte tag followed by zero or more bytes depending on the tag
1024
*
1025
* union stack_map_frame {
1026
* SAME
1027
* SAME_LOCALS_1_STACK
1028
* Reserved
1029
* SAME_LOCALS_1_STACK_EXTENDED
1030
* CHOP
1031
* SAME_EXTENDED
1032
* APPEND
1033
* FULL
1034
* }
1035
*/
1036
1037
/* output the frame tag */
1038
_cursor->writeU8(frameType, Cursor::GENERIC);
1039
1040
if (CFR_STACKMAP_SAME_LOCALS_1_STACK > frameType) { /* 0..63 */
1041
/* SAME frame - no extra data */
1042
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_END > frameType) { /* 64..127 */
1043
/*
1044
* SAME_LOCALS_1_STACK {
1045
* TypeInfo stackItems[1]
1046
* };
1047
*/
1048
typeInfo->stackItemsDo(this);
1049
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED > frameType) { /* 128..246 */
1050
/* Reserved frame types - no extra data */
1051
Trc_BCU_Assert_ShouldNeverHappen();
1052
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED == frameType) { /* 247 */
1053
/*
1054
* SAME_LOCALS_1_STACK_EXTENDED {
1055
* U_16 offsetDelta
1056
* TypeInfo stackItems[1]
1057
* };
1058
*/
1059
_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);
1060
typeInfo->stackItemsDo(this);
1061
} else if (CFR_STACKMAP_SAME_EXTENDED > frameType) { /* 248..250 */
1062
/*
1063
* CHOP {
1064
* U_16 offsetDelta
1065
* };
1066
*/
1067
_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);
1068
} else if (CFR_STACKMAP_SAME_EXTENDED == frameType) { /* 251 */
1069
/*
1070
* SAME_EXTENDED {
1071
* U_16 offsetDelta
1072
* };
1073
*/
1074
_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);
1075
} else if (CFR_STACKMAP_FULL > frameType) { /* 252..254 */
1076
/*
1077
* APPEND {
1078
* U_16 offsetDelta
1079
* TypeInfo locals[frameType - CFR_STACKMAP_APPEND_BASE]
1080
* };
1081
*/
1082
_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);
1083
typeInfo->localsDo(this);
1084
} else if (CFR_STACKMAP_FULL == frameType) { /* 255 */
1085
/*
1086
* FULL {
1087
* U_16 offsetDelta
1088
* U_16 localsCount
1089
* TypeInfo locals[localsCount]
1090
* U_16 stackItemsCount
1091
* TypeInfo stackItems[stackItemsCount]
1092
* };
1093
*/
1094
1095
/* u2 offset delta */
1096
_cursor->writeBigEndianU16(offsetDelta, Cursor::GENERIC);
1097
1098
/* handle locals */
1099
/* u2 number of locals */
1100
_cursor->writeBigEndianU16(localsCount, Cursor::GENERIC);
1101
/* verification_type_info locals[number of locals] */
1102
typeInfo->localsDo(this);
1103
1104
/* handle stack */
1105
/* u2 number of stack items */
1106
_cursor->writeBigEndianU16(stackItemsCount, Cursor::GENERIC);
1107
/* verification_type_info stack[number of stack items] */
1108
typeInfo->stackItemsDo(this);
1109
}
1110
}
1111
1112
void visitBootstrapMethod(U_16 cpIndex, U_16 argumentCount)
1113
{
1114
_cursor->writeU16(_constantPoolMap->getROMClassCPIndexForReference(cpIndex), Cursor::GENERIC);
1115
_cursor->writeU16(argumentCount, Cursor::GENERIC);
1116
}
1117
1118
void visitBootstrapArgument(U_16 cpIndex)
1119
{
1120
_cursor->writeU16(_constantPoolMap->getROMClassCPIndexForReference(cpIndex), Cursor::GENERIC);
1121
}
1122
1123
void visitCallSite(U_16 nameAndSignatureIndex, U_16 bootstrapMethodIndex)
1124
{
1125
_cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(nameAndSignatureIndex), Cursor::SRP_TO_NAME_AND_SIGNATURE);
1126
}
1127
1128
void visitSplitEntry(U_16 cpIndex)
1129
{
1130
_cursor->writeU16(cpIndex, Cursor::GENERIC);
1131
}
1132
1133
Cursor *_cursor;
1134
ClassFileOracle *_classFileOracle;
1135
SRPKeyProducer *_srpKeyProducer;
1136
SRPOffsetTable *_srpOffsetTable;
1137
ConstantPoolMap *_constantPoolMap;
1138
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1139
InterfaceInjectionInfo *_interfaceInjectionInfo;
1140
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1141
bool _markAndCountOnly;
1142
};
1143
1144
void
1145
ROMClassWriter::writeInterfaces(Cursor *cursor, bool markAndCountOnly)
1146
{
1147
cursor->mark(_interfacesSRPKey);
1148
UDATA size = UDATA(_classFileOracle->getInterfacesCount()) * sizeof(J9SRP);
1149
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1150
size += UDATA(_interfaceInjectionInfo->numOfInterfaces) * sizeof(J9SRP);
1151
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1152
CheckSize _(cursor, size);
1153
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1154
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeInterfaces();
1155
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1156
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeInterfaces();
1157
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1158
}
1159
1160
void
1161
ROMClassWriter::writeInnerClasses(Cursor *cursor, bool markAndCountOnly)
1162
{
1163
cursor->mark(_innerClassesSRPKey);
1164
UDATA size = UDATA(_classFileOracle->getInnerClassCount()) * sizeof(J9SRP);
1165
CheckSize _(cursor, size);
1166
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1167
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeInnerClasses();
1168
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1169
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeInnerClasses();
1170
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1171
}
1172
1173
void
1174
ROMClassWriter::writeEnclosedInnerClasses(Cursor *cursor, bool markAndCountOnly)
1175
{
1176
cursor->mark(_enclosedInnerClassesSRPKey);
1177
UDATA size = UDATA(_classFileOracle->getEnclosedInnerClassCount()) * sizeof(J9SRP);
1178
CheckSize _(cursor, size);
1179
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1180
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeEnclosedInnerClasses();
1181
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1182
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeEnclosedInnerClasses();
1183
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1184
}
1185
1186
#if JAVA_SPEC_VERSION >= 11
1187
void
1188
ROMClassWriter::writeNestMembers(Cursor *cursor, bool markAndCountOnly)
1189
{
1190
cursor->mark(_nestMembersSRPKey);
1191
UDATA size = UDATA(_classFileOracle->getNestMembersCount()) * sizeof(J9SRP);
1192
CheckSize _(cursor,size);
1193
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1194
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeNestMembers();
1195
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1196
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeNestMembers();
1197
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1198
}
1199
#endif /* JAVA_SPEC_VERSION >= 11 */
1200
1201
void
1202
ROMClassWriter::writeNameAndSignatureBlock(Cursor *cursor)
1203
{
1204
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1205
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeNameAndSignatureBlock();
1206
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1207
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeNameAndSignatureBlock();
1208
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1209
}
1210
1211
void
1212
ROMClassWriter::writeUTF8s(Cursor *cursor)
1213
{
1214
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1215
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeUTF8Block();
1216
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1217
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeUTF8Block();
1218
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1219
/* aligned to U_64 required by the shared classes */
1220
cursor->padToAlignment(sizeof(U_64), Cursor::GENERIC);
1221
}
1222
1223
void
1224
ROMClassWriter::writeMethods(Cursor *cursor, Cursor *lineNumberCursor, Cursor *variableInfoCursor, bool markAndCountOnly)
1225
{
1226
/*
1227
* ****************************** PLEASE READ ***********************************
1228
*
1229
* When changing the format of a ROMMethod these are places that assume ROMMethod format
1230
* and would need to be updated:
1231
* - nextROMMethod() in util/mthutil.c
1232
* - allSlotsInROMMethodsSectionDo() in util/romclasswalk.c
1233
* - dbgNextROMMethod() in dbgext/j9dbgext.c
1234
* - createBreakpointedMethod() in jvmti/jvmtiHelpers.c
1235
* All the above are involved in walking or walking over ROMMethods.
1236
*
1237
*/
1238
1239
cursor->mark(_methodsSRPKey);
1240
for (ClassFileOracle::MethodIterator iterator = _classFileOracle->getMethodIterator();
1241
iterator.isNotDone();
1242
iterator.next()) {
1243
U_8 argCount = iterator.getSendSlotCount();
1244
U_16 tempCount = iterator.getMaxLocals();
1245
U_32 modifiers = iterator.getModifiers();
1246
U_32 extendedModifiers = iterator.getExtendedModifiers();
1247
bool writeDebugInfo =
1248
((iterator.getLineNumbersCount() > 0) || (iterator.getLocalVariablesCount() > 0)) &&
1249
(_context->shouldPreserveLineNumbers() || _context->shouldPreserveLocalVariablesInfo());
1250
1251
/* If an existing method is being compared to, then calling
1252
* romMethodCacheCurrentRomMethod will cache the existing
1253
* rom method in the context. This prevents the need to constantly
1254
* retrieve the method from the existing rom class.
1255
*/
1256
_context->romMethodCacheCurrentRomMethod(cursor->getCount());
1257
1258
if (!markAndCountOnly) {
1259
if (! iterator.isStatic()) {
1260
++argCount;
1261
}
1262
if (tempCount >= argCount) {
1263
tempCount -= argCount;
1264
} else {
1265
Trc_BCU_Assert_Equals(0, tempCount);
1266
}
1267
1268
/*
1269
* ROMMethod->modifier what does each bit represent?
1270
*
1271
* Bottom 16 bits are defined by the specification and set by the call to
1272
* iterator.getAccessFlags() the rest are set 'by hand' below.
1273
*
1274
* NOTE: some of the bottom 16 bits are used for J9 specific flags as specified by a '*'
1275
*
1276
* 0000 0000 0000 0000 0000 0000 0000 0000
1277
* + AccPublic
1278
* + AccPrivate
1279
* + AccProtected
1280
* + AccStatic
1281
*
1282
* + AccFinal
1283
* + AccSynchronized
1284
* + AccBridge
1285
* + AccVarArgs
1286
*
1287
* + AccNative
1288
* + AccGetterMethod * (Not currently used by specification)
1289
* + AccAbstract
1290
* + AccStrict
1291
*
1292
* + AccSynthetic
1293
* + AccForwarderMethod * (Not currently used by specification)
1294
* + AccEmptyMethod * (Not currently used by specification)
1295
* + UNUSED
1296
*
1297
* Top 16 bits are defined by J9.
1298
* + AccMethodVTable
1299
* + AccMethodHasExceptionInfo
1300
* + AccMethodHasDebugInfo
1301
* + AccMethodFrameIteratorSkip
1302
*
1303
* + AccMethodCallerSensitive (has @CallerSensitive annotation)
1304
* + AccMethodHasBackwardBranches
1305
* + AccMethodObjectConstructor
1306
* + AccMethodHasMethodParameters
1307
*
1308
* + AccMethodAllowFinalFieldWrites
1309
* + AccMethodHasGenericSignature
1310
* + AccMethodHasExtendedModifiers
1311
* + AccMethodHasMethodHandleInvokes
1312
*
1313
* + AccMethodHasStackMap
1314
* + AccMethodHasMethodAnnotations
1315
* + AccMethodHasParameterAnnotations
1316
* + AccMethodHasDefaultAnnotation
1317
*/
1318
1319
/* In class files prior to version 53, any method in the declaring class of a final field
1320
* may write to it. For 53 and later, only initializers (<init> for instance fields, <clinit>
1321
* for static fields) are allowed to write to final fields.
1322
*/
1323
if ((_classFileOracle->getMajorVersion() < 53) || ('<' == *_classFileOracle->getUTF8Data(iterator.getNameIndex()))) {
1324
modifiers |= J9AccMethodAllowFinalFieldWrites;
1325
}
1326
1327
if (iterator.hasFrameIteratorSkipAnnotation()) {
1328
modifiers |= J9AccMethodFrameIteratorSkip;
1329
}
1330
1331
if (writeDebugInfo) {
1332
modifiers |= J9AccMethodHasDebugInfo;
1333
}
1334
1335
if (iterator.hasMethodParameters()) {
1336
modifiers |= J9AccMethodHasMethodParameters;
1337
}
1338
}
1339
1340
U_32 byteCodeSize = 0;
1341
if (iterator.isAbstract()) {
1342
/* Do nothing */
1343
} else if (iterator.isNative()) {
1344
byteCodeSize = computeNativeSignatureSize(_classFileOracle->getUTF8Data(iterator.getDescriptorIndex()));
1345
} else {
1346
byteCodeSize = iterator.getCodeLength();
1347
}
1348
1349
if (markAndCountOnly) {
1350
cursor->skip(sizeof(J9ROMMethod));
1351
} else {
1352
CheckSize _(cursor, sizeof(J9ROMMethod));
1353
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getNameIndex()), Cursor::SRP_TO_UTF8);
1354
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getDescriptorIndex()), Cursor::SRP_TO_UTF8);
1355
if (0 != extendedModifiers) {
1356
modifiers |= J9AccMethodHasExtendedModifiers;
1357
}
1358
cursor->writeU32(modifiers, Cursor::ROM_CLASS_MODIFIERS);
1359
cursor->writeU16(iterator.getMaxStack(), Cursor::GENERIC);
1360
cursor->writeU16(U_16(byteCodeSize), Cursor::GENERIC);
1361
cursor->writeU8(U_8(byteCodeSize >> 16), Cursor::GENERIC);
1362
cursor->writeU8(argCount, Cursor::GENERIC);
1363
cursor->writeU16(tempCount, Cursor::GENERIC);
1364
}
1365
1366
if (iterator.isAbstract()) {
1367
/* Do nothing */
1368
} else if (markAndCountOnly) {
1369
cursor->skip(byteCodeSize);
1370
} else if (iterator.isNative()) {
1371
writeNativeSignature(cursor, _classFileOracle->getUTF8Data(iterator.getDescriptorIndex()), byteCodeSize - 2);
1372
} else {
1373
UDATA count = cursor->getCount();
1374
writeByteCodes(cursor, &iterator);
1375
count = cursor->getCount() - count;
1376
Trc_BCU_Assert_Equals(count, byteCodeSize);
1377
}
1378
1379
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1380
if (0 != extendedModifiers) {
1381
cursor->writeU32(extendedModifiers, Cursor::ROM_CLASS_MODIFIERS);
1382
}
1383
1384
if (iterator.hasGenericSignature()) {
1385
if (markAndCountOnly) { // TODO check if this is a performance win
1386
cursor->skip(sizeof(J9SRP));
1387
} else {
1388
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);
1389
}
1390
}
1391
1392
if ((0 != iterator.getExceptionHandlersCount()) || (0 != iterator.getExceptionsThrownCount())) {
1393
/* Write exceptions info */
1394
cursor->writeU16(iterator.getExceptionHandlersCount(), Cursor::GENERIC);
1395
cursor->writeU16(iterator.getExceptionsThrownCount(), Cursor::GENERIC);
1396
UDATA size =
1397
UDATA(iterator.getExceptionHandlersCount()) * sizeof(J9ExceptionHandler) +
1398
UDATA(iterator.getExceptionsThrownCount()) * sizeof(J9SRP);
1399
CheckSize _(cursor, size);
1400
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1401
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeExceptionBlock(&iterator);
1402
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1403
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeExceptionBlock(&iterator);
1404
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1405
}
1406
1407
if (iterator.hasAnnotationsData()) {
1408
/*
1409
* u_32 length
1410
* length * u_8
1411
* pad to u_32 size
1412
*/
1413
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1414
_classFileOracle->methodAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
1415
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1416
}
1417
1418
if (iterator.hasParameterAnnotations()) {
1419
/*
1420
* u_32 length
1421
* length * u_8
1422
* pad to u_32 size
1423
*/
1424
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1425
_classFileOracle->parameterAnnotationsDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
1426
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1427
}
1428
1429
if (iterator.hasDefaultAnnotation()) {
1430
/*
1431
* u_32 length
1432
* length * u_8
1433
* pad to u_32 size
1434
*/
1435
AnnotationWriter annotationWriter(cursor, _constantPoolMap,_classFileOracle);
1436
AnnotationElementWriter annotationElementWriter(cursor, _constantPoolMap, _classFileOracle);
1437
_classFileOracle->defaultAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationElementWriter);
1438
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1439
}
1440
1441
if (iterator.hasMethodTypeAnnotations()) {
1442
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1443
_classFileOracle->methodTypeAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
1444
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1445
}
1446
1447
if (iterator.hasCodeTypeAnnotations()) {
1448
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1449
_classFileOracle->methodCodeTypeAnnotationDo(iterator.getIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
1450
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1451
}
1452
1453
bool existingDebugData = _context->romMethodHasDebugData();
1454
if (writeDebugInfo || existingDebugData) {
1455
/* writeMethodDebugInfo is called if there is debug data to write,
1456
* or if an existing method with debug data is being compared to.
1457
*/
1458
cursor->notifyDebugDataWriteStart();
1459
if (!_context->shouldWriteDebugDataInline()) {
1460
cursor->writeSRP(_srpKeyProducer->mapMethodIndexToMethodDebugInfoKey(iterator.getIndex()), Cursor::SRP_TO_DEBUG_DATA);
1461
}
1462
writeMethodDebugInfo(&iterator, lineNumberCursor, variableInfoCursor, markAndCountOnly, existingDebugData);
1463
cursor->notifyDebugDataWriteEnd();
1464
}
1465
1466
if ( iterator.hasStackMap() ) {
1467
/*
1468
* Write out Stack Map
1469
*
1470
* *** SUN format ***
1471
* u2 attribute_name_index
1472
* u4 attribute_length
1473
* u2 number_of_entries
1474
* stack_map_frame entries[number_of_entries]
1475
*
1476
* *** J9 format ***
1477
* u4 attribute_length (native endian)
1478
* u2 number_of_entries (big endian)
1479
* stack_map_frame entries[number_of_entries] (big endian)
1480
* padding for u4 alignment
1481
*
1482
*/
1483
1484
UDATA start = cursor->getCount();
1485
/* output the length of the stack map */
1486
cursor->writeU32(_methodNotes[iterator.getIndex()].stackMapSize, Cursor::GENERIC);
1487
/* output the number of frames */
1488
cursor->writeBigEndianU16(iterator.getStackMapFramesCount(), Cursor::GENERIC); /* TODO: don't write this stuff in BigEndian??? */
1489
1490
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1491
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeStackMap(&iterator);
1492
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1493
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeStackMap(&iterator);
1494
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1495
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1496
if (markAndCountOnly) {
1497
/* Following is adding PAD to stackmap size. First round is always markAndCountOnly.
1498
* This logic is very difficult to catch. Cause of the padded stackmapsize, we dont use padding in nextROMMethod() in mthutil.
1499
* Also I find this markAndCountOnly unnecessary and confusing for the following reasons
1500
* 1. It is used partially : See above, we dont use it for the first 6 bytes and we write them down.
1501
* It should be used properly, either always or never.
1502
* 2. Also when it is counting, it is a counting cursor and it actually do not write (see Cursor.hpp).
1503
* Therefore, markAndCountOnly flag is not needed at all and extra checks for it just makes it slower.
1504
*
1505
* */
1506
_methodNotes[iterator.getIndex()].stackMapSize = U_32(cursor->getCount() - start);
1507
}
1508
}
1509
1510
if (0 != iterator.hasMethodParameters()) {
1511
U_8 mthParamCount = iterator.getMethodParametersCount();
1512
UDATA size = UDATA(mthParamCount * sizeof(J9MethodParameter));
1513
if (true == markAndCountOnly) {
1514
cursor->skip(sizeof(U_8) + size);
1515
} else {
1516
cursor->writeU8(mthParamCount, Cursor::GENERIC);
1517
CheckSize _(cursor, size);
1518
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1519
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeMethodParameters(&iterator);
1520
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1521
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeMethodParameters(&iterator);
1522
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1523
}
1524
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1525
}
1526
1527
}
1528
}
1529
1530
class ROMClassWriter::ConstantPoolShapeDescriptionWriter : public ConstantPoolMap::ConstantPoolEntryTypeVisitor
1531
{
1532
public:
1533
ConstantPoolShapeDescriptionWriter(Cursor *cursor) :
1534
_cursor(cursor),
1535
_wordValue(0),
1536
_nibbleIndex(1) /* Account for zeroth entry */
1537
{
1538
}
1539
1540
void visitEntryType(U_32 entryType)
1541
{
1542
_wordValue |= entryType << (_nibbleIndex * J9_CP_BITS_PER_DESCRIPTION);
1543
++_nibbleIndex;
1544
if (0 == (_nibbleIndex % J9_CP_DESCRIPTIONS_PER_U32)) {
1545
_cursor->writeU32(_wordValue, Cursor::GENERIC);
1546
_nibbleIndex = 0;
1547
_wordValue = 0;
1548
}
1549
}
1550
1551
void flushAndPad()
1552
{
1553
/* Flush any remaining nibbles and pad */
1554
if (0 != (_nibbleIndex % J9_CP_DESCRIPTIONS_PER_U32)) {
1555
_cursor->writeU32(_wordValue, Cursor::GENERIC);
1556
}
1557
}
1558
1559
private:
1560
Cursor *_cursor;
1561
U_32 _wordValue;
1562
U_32 _nibbleIndex;
1563
};
1564
1565
void
1566
ROMClassWriter::writeConstantPoolShapeDescriptions(Cursor *cursor, bool markAndCountOnly)
1567
{
1568
cursor->mark(_cpDescriptionShapeSRPKey);
1569
UDATA size = ((UDATA(_constantPoolMap->getROMConstantPoolCount()) + J9_CP_DESCRIPTIONS_PER_U32 - 1) / J9_CP_DESCRIPTIONS_PER_U32) * sizeof(U_32);
1570
1571
if (markAndCountOnly) {
1572
cursor->skip(size);
1573
} else {
1574
CheckSize _(cursor, size);
1575
ConstantPoolShapeDescriptionWriter constantPoolShapeDescriptionWriter(cursor);
1576
_constantPoolMap->constantPoolEntryTypesDo(&constantPoolShapeDescriptionWriter);
1577
constantPoolShapeDescriptionWriter.flushAndPad();
1578
}
1579
}
1580
1581
void
1582
ROMClassWriter::writeAnnotationInfo(Cursor *cursor)
1583
{
1584
if (_classFileOracle->hasClassAnnotations()) {
1585
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1586
cursor->mark(_annotationInfoClassSRPKey);
1587
/*
1588
* u_32 length
1589
* length * u_8
1590
* pad to u_32 size
1591
*/
1592
_classFileOracle->classAnnotationsDo(&annotationWriter, &annotationWriter, &annotationWriter);
1593
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1594
}
1595
if (_classFileOracle->hasTypeAnnotations()) {
1596
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1597
cursor->mark(_typeAnnotationInfoSRPKey);
1598
_classFileOracle->classTypeAnnotationsDo(&annotationWriter, &annotationWriter, &annotationWriter);
1599
}
1600
}
1601
void ROMClassWriter::AnnotationElementWriter::visitNestedAnnotation(U_16 elementNameIndex, ClassFileOracle::NestedAnnotation *nestedAnnotation)
1602
{
1603
_cursor->writeU8('@', Cursor::GENERIC);
1604
1605
AnnotationWriter annotationWriter(_cursor, _constantPoolMap, _classFileOracle);
1606
nestedAnnotation->annotationDo(&annotationWriter, &annotationWriter, NULL);
1607
}
1608
1609
void
1610
ROMClassWriter::writeMethodDebugInfo(ClassFileOracle::MethodIterator *methodIterator, Cursor *lineNumberCursor, Cursor *variableInfoCursor, bool markAndCountOnly, bool existHasDebugInformation)
1611
{
1612
/*
1613
* Method Debug Information is stored in one of two ways:
1614
* 1) inline with the ROMMethod
1615
* 2) in two separate areas of the Shared Class Cache
1616
*
1617
* When the data is inline with the ROMMethod the lineNumberCursor and variableInfoCursor will be the same Cursor.
1618
*
1619
* The J9MethodDebugInfo header structure and the J9LineNumber entries are written to the lineNumberCursor, while
1620
* the J9VariableInfo entries are written to the variableInfoCursor.
1621
*
1622
* The data looks like:
1623
*
1624
* written to lineNumberCursor:
1625
* J9MethodDebugInfo
1626
* SRP to J9VariableInfo -OR- size of all Method Debug Info include Line Numbers and Variable Info
1627
*
1628
* if lineNumberCount fits in 16bit and lineNumbersInfoCompressedSize fits in 15bit
1629
* u32 lineNumberCount << 16 | lineNumbersInfoCompressedSize << 1 | 0
1630
* u32 variableInfoCount
1631
* else
1632
* u32 lineNumberCount | 1
1633
* u32 variableInfoCount
1634
* u32 lineNumbersInfoCompressedSize
1635
* end if
1636
* U_8 * compressed buffer of pcOffset and lineNumber
1637
*
1638
* written to variableInfoCursor:
1639
* Block of compressed data containing the 'index', 'startPC' and length [+ gen sig flag]
1640
* Followed by
1641
* SRP to name
1642
* SRP to signature
1643
* [SRP to generic signature]
1644
*/
1645
bool preserveLineNumbers = _context->shouldPreserveLineNumbers();
1646
bool preserveLocalVariablesInfo = _context->shouldPreserveLocalVariablesInfo();
1647
1648
if (preserveLineNumbers || preserveLocalVariablesInfo || existHasDebugInformation) {
1649
U_32 lineNumbersCount = (preserveLineNumbers ? methodIterator->getLineNumbersCount() : 0);
1650
U_32 localVariablesCount = (preserveLocalVariablesInfo ? methodIterator->getLocalVariablesCount() : 0);
1651
U_32 lineNumbersInfoCompressedSize = methodIterator->getLineNumbersInfoCompressedSize();
1652
1653
lineNumberCursor->mark(_srpKeyProducer->mapMethodIndexToMethodDebugInfoKey(methodIterator->getIndex()));
1654
1655
/* Write J9MethodDebugInfo */
1656
UDATA start = lineNumberCursor->getCount();
1657
if (!(_context->shouldWriteDebugDataInline())) {
1658
lineNumberCursor->writeSRP(_srpKeyProducer->mapMethodIndexToVariableInfoKey(methodIterator->getIndex()), Cursor::SRP_TO_LOCAL_VARIABLE_DATA);
1659
} else {
1660
if ( !markAndCountOnly && ((lineNumbersCount > 0) || (localVariablesCount > 0))) {
1661
/* Only check this assert if the class being created was found to have
1662
* debug data during the 'mark and count phase'. This should always be the
1663
* case if lineNumbersCount or localVariablesCount are non zero.
1664
*/
1665
Trc_BCU_Assert_False(_methodNotes[methodIterator->getIndex()].debugInfoSize == 0);
1666
}
1667
lineNumberCursor->writeU32(_methodNotes[methodIterator->getIndex()].debugInfoSize | 1, Cursor::METHOD_DEBUG_SIZE);
1668
}
1669
1670
/* Encode the lineNumbersCount with the lineNumbersInfoCompressedSize
1671
* a = number of bytes in the compressed line number table
1672
* b = lineNumberCount
1673
* c = escape bit (0: use a and b, 1: lineNumberCount uses 31 bit and number of bytes in the compressed line number table will be stored as the next U_32)
1674
* aaaaaaaa aaaaaaaa bbbbbbbb bbbbbbbc
1675
*
1676
* Note: If the lineNumberCount is 0, then check the existing rom class in the context for compressed data.
1677
* In the case of the comparing cursor this will ensure the correct number of bytes are advanced.
1678
*
1679
* Note 2: The call to getCount relies on getCount() getting an offset into the current method, and
1680
* not out of line debug data. See the implementation of ComparingCursor::getCount() for more info.
1681
*/
1682
if (((0 == lineNumbersCount) && (_context->romMethodHasLineNumberCountCompressed()))
1683
|| ((lineNumbersInfoCompressedSize < 0xFFFF) && (lineNumbersCount < 0x7FFF))){
1684
/* it fits, c = 0 */
1685
U_32 lineNumbersCountEncoded = (lineNumbersInfoCompressedSize << 16) | ((lineNumbersCount << 1) & 0xFFFE);
1686
lineNumberCursor->writeU32(lineNumbersCountEncoded, Cursor::LINE_NUMBER_DATA);
1687
lineNumberCursor->writeU32(localVariablesCount, Cursor::LOCAL_VARIABLE_COUNT);
1688
} else {
1689
/* it does not fit, c = 1 */
1690
lineNumberCursor->writeU32((lineNumbersCount << 1) | 1, Cursor::LINE_NUMBER_DATA);
1691
lineNumberCursor->writeU32(localVariablesCount, Cursor::LOCAL_VARIABLE_COUNT);
1692
lineNumberCursor->writeU32(lineNumbersInfoCompressedSize, Cursor::LINE_NUMBER_DATA);
1693
}
1694
1695
lineNumberCursor->writeData(methodIterator->getLineNumbersInfoCompressed(), methodIterator->getLineNumbersInfoCompressedSize(), Cursor::LINE_NUMBER_DATA);
1696
1697
if (0 != localVariablesCount) {
1698
U_8 buffer[13];
1699
UDATA bufferLength;
1700
variableInfoCursor->mark(_srpKeyProducer->mapMethodIndexToVariableInfoKey(methodIterator->getIndex()));
1701
U_32 count = 0;
1702
U_32 lastIndex = 0;
1703
U_32 lastStartPC = 0;
1704
U_32 lastLength = 0;
1705
for (ClassFileOracle::LocalVariablesIterator localVariablesIterator = methodIterator->getLocalVariablesIterator();
1706
localVariablesIterator.isNotDone();
1707
localVariablesIterator.next()) {
1708
I_32 index = localVariablesIterator.getIndex() - lastIndex;
1709
I_32 startPC = localVariablesIterator.getStartPC() - lastStartPC;
1710
1711
I_32 length = localVariablesIterator.getLength();
1712
if (localVariablesIterator.hasGenericSignature()) {
1713
length |= J9_ROMCLASS_OPTINFO_VARIABLE_TABLE_HAS_GENERIC;
1714
}
1715
length = length - lastLength;
1716
1717
bufferLength = compressLocalVariableTableEntry(index, startPC, length, buffer);
1718
1719
variableInfoCursor->writeData(buffer, bufferLength, Cursor::LOCAL_VARIABLE_DATA);
1720
1721
variableInfoCursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(localVariablesIterator.getNameIndex()), Cursor::LOCAL_VARIABLE_DATA_SRP_TO_UTF8);
1722
variableInfoCursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(localVariablesIterator.getDescriptorIndex()), Cursor::LOCAL_VARIABLE_DATA_SRP_TO_UTF8);
1723
if (localVariablesIterator.hasGenericSignature()) {
1724
variableInfoCursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(localVariablesIterator.getGenericSignatureIndex()), Cursor::LOCAL_VARIABLE_DATA_SRP_TO_UTF8);
1725
}
1726
1727
lastIndex = localVariablesIterator.getIndex();
1728
lastStartPC = localVariablesIterator.getStartPC();
1729
lastLength = localVariablesIterator.getLength();
1730
1731
++count;
1732
}
1733
Trc_BCU_Assert_Equals(count, localVariablesCount);
1734
}
1735
1736
/* Once done writing the 'variable table' the cursor is notified. This is done to
1737
* enable special cursors like the comparing cursor to update their internal
1738
* information
1739
*/
1740
variableInfoCursor->notifyVariableTableWriteEnd();
1741
1742
/* Both cursors have to be padded, because the low bit is used as a tag, if the
1743
* addressed are unaligned, the low bit may not be free */
1744
if (!(_context->shouldWriteDebugDataInline())) {
1745
/* When out of line, a 16bit alignment is required for the tag bit */
1746
lineNumberCursor->padToAlignment(sizeof(U_16), Cursor::LINE_NUMBER_DATA);
1747
variableInfoCursor->padToAlignment(sizeof(U_16), Cursor::LOCAL_VARIABLE_DATA);
1748
} else {
1749
/* When in line, a 32bit alignment is required for the next sections
1750
* after the debug info section. Both cursors lineNumberCursor and
1751
* variableInfoCursor are identical, only one needs to be padded */
1752
lineNumberCursor->padToAlignment(sizeof(U_32), Cursor::LINE_NUMBER_DATA);
1753
}
1754
1755
if (markAndCountOnly) {
1756
_methodNotes[methodIterator->getIndex()].debugInfoSize = U_32(lineNumberCursor->getCount() - start);
1757
}
1758
}
1759
}
1760
1761
void
1762
ROMClassWriter::writeSourceDebugExtension(Cursor *cursor)
1763
{
1764
if ((_classFileOracle->hasSourceDebugExtension() && _context->shouldPreserveSourceDebugExtension()) || (_context->romClassHasSourceDebugExtension())) {
1765
cursor->mark(_sourceDebugExtensionSRPKey);
1766
cursor->writeU32(_classFileOracle->getSourceDebugExtensionLength(), Cursor::SOURCE_DEBUG_EXT_LENGTH);
1767
cursor->writeData(_classFileOracle->getSourceDebugExtensionData(), _classFileOracle->getSourceDebugExtensionLength(), Cursor::SOURCE_DEBUG_EXT_DATA);
1768
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1769
}
1770
}
1771
1772
/*
1773
* Records in the ROM class has the following layout:
1774
* 4 bytes for the number of record components in the class
1775
* for each record component:
1776
* J9ROMRecordComponentShape
1777
* 4 bytes SRP to record component's generic signature if the component has a signature annotation.
1778
* 4 bytes length of annotation data in bytes, followed by annotation data. Omitted if there are no annotations.
1779
* 4 bytes length of type annotation data in bytes followed by type annotation data. Omitted if there are no type annotations.
1780
*
1781
* For example, if a record component has a generic signature annotation and no other annotations the record components shape will look like:
1782
* J9ROMRecordComponentShape
1783
* 4 bytes SRP
1784
*/
1785
void
1786
ROMClassWriter::writeRecordComponents(Cursor *cursor, bool markAndCountOnly)
1787
{
1788
if (! _classFileOracle->isRecord()) {
1789
return;
1790
}
1791
1792
cursor->mark(_recordInfoSRPKey);
1793
1794
/* number of record components */
1795
if (markAndCountOnly) {
1796
cursor->skip(sizeof(U_32));
1797
} else {
1798
cursor->writeU32(_classFileOracle->getRecordComponentCount(), Cursor::GENERIC);
1799
}
1800
1801
ClassFileOracle::RecordComponentIterator iterator = _classFileOracle->getRecordComponentIterator();
1802
while ( iterator.isNotDone() ) {
1803
if (markAndCountOnly) {
1804
cursor->skip(sizeof(J9ROMRecordComponentShape));
1805
} else {
1806
CheckSize _(cursor, sizeof(J9ROMRecordComponentShape));
1807
1808
/* record component name and descriptor */
1809
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getNameIndex()), Cursor::SRP_TO_UTF8);
1810
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getDescriptorIndex()), Cursor::SRP_TO_UTF8);
1811
1812
/* attribute flags */
1813
U_32 attributeFlags = 0;
1814
if (iterator.hasGenericSignature()) {
1815
attributeFlags |= J9RecordComponentFlagHasGenericSignature;
1816
}
1817
if (iterator.hasAnnotation()) {
1818
attributeFlags |= J9RecordComponentFlagHasAnnotations;
1819
}
1820
if (iterator.hasTypeAnnotation()) {
1821
attributeFlags |= J9RecordComponentFlagHasTypeAnnotations;
1822
}
1823
cursor->writeU32(attributeFlags, Cursor::GENERIC);
1824
}
1825
1826
/* write optional attributes */
1827
if (iterator.hasGenericSignature()) {
1828
if (markAndCountOnly) {
1829
cursor->skip(sizeof(J9SRP));
1830
} else {
1831
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(iterator.getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);
1832
}
1833
}
1834
if (iterator.hasAnnotation()) {
1835
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1836
_classFileOracle->recordComponentAnnotationDo(iterator.getRecordComponentIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
1837
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1838
}
1839
if (iterator.hasTypeAnnotation()) {
1840
AnnotationWriter annotationWriter(cursor, _constantPoolMap, _classFileOracle);
1841
_classFileOracle->recordComponentTypeAnnotationDo(iterator.getRecordComponentIndex(), &annotationWriter, &annotationWriter, &annotationWriter);
1842
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1843
}
1844
1845
iterator.next();
1846
}
1847
}
1848
1849
/*
1850
* PermittedSubclasses ROM class layout:
1851
* 4 bytes for number of classes (actually takes up two, but use 4 for alignment)
1852
* for number of classes:
1853
* 4 byte SRP to class name
1854
*/
1855
void
1856
ROMClassWriter::writePermittedSubclasses(Cursor *cursor, bool markAndCountOnly)
1857
{
1858
if (_classFileOracle->isSealed()) {
1859
cursor->mark(_permittedSubclassesInfoSRPKey);
1860
1861
U_16 classCount = _classFileOracle->getPermittedSubclassesClassCount();
1862
if (markAndCountOnly) {
1863
cursor->skip(sizeof(U_32));
1864
} else {
1865
cursor->writeU32(classCount, Cursor::GENERIC);
1866
}
1867
1868
for (U_16 index = 0; index < classCount; index++) {
1869
if (markAndCountOnly) {
1870
cursor->skip(sizeof(J9SRP));
1871
} else {
1872
U_16 classNameCpIndex = _classFileOracle->getPermittedSubclassesClassNameAtIndex(index);
1873
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(classNameCpIndex), Cursor::SRP_TO_UTF8);
1874
}
1875
}
1876
}
1877
}
1878
1879
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1880
void
1881
ROMClassWriter::writeInjectedInterfaces(Cursor *cursor, bool markAndCountOnly)
1882
{
1883
if (_interfaceInjectionInfo->numOfInterfaces > 0) {
1884
cursor->mark(_injectedInterfaceInfoSRPKey);
1885
1886
if (markAndCountOnly) {
1887
cursor->skip(sizeof(U_32));
1888
} else {
1889
cursor->writeU32(_interfaceInjectionInfo->numOfInterfaces, Cursor::GENERIC);
1890
}
1891
}
1892
}
1893
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1894
void
1895
ROMClassWriter::writeOptionalInfo(Cursor *cursor)
1896
{
1897
// TODO check if we care about alignment of optional info
1898
cursor->padToAlignment(sizeof(U_32), Cursor::GENERIC);
1899
1900
/*
1901
* TODO The following is written in storeOptionalData, but likely needs to be a part of something else
1902
*
1903
* J9EnclosingObject:
1904
* U_32 classRefCPIndex
1905
* SRP nameAndSignature
1906
*/
1907
if (_classFileOracle->hasEnclosingMethod()) {
1908
cursor->mark(_enclosingMethodSRPKey);
1909
cursor->writeU32(_constantPoolMap->getROMClassCPIndexForReference(_classFileOracle->getEnclosingMethodClassRefIndex()), Cursor::GENERIC);
1910
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getEnclosingMethodNameAndSignatureIndex()), Cursor::SRP_TO_NAME_AND_SIGNATURE);
1911
}
1912
1913
/*
1914
* OptionalInfo is made up of the following information:
1915
*
1916
* All entries are optional, present only if the appropriate data is available.
1917
*
1918
* SRP to source file name
1919
* SRP to generic signature
1920
* SRP to source debug extensions
1921
* SRP to annotation info
1922
* SRP to Method Debug Info
1923
* SRP to enclosing method
1924
* SRP to simple name
1925
* SRP to 'SRP' (self) if OPTINFO_VERIFY_EXCLUDE.. pretty much a flag, leaving an empty slot.
1926
* SRP to class annotations
1927
* SRP to class Type Annotations
1928
* SRP to record class component attributes
1929
* SRP to PermittedSubclasses attribute
1930
* SRP to injected interfaces info
1931
*/
1932
cursor->mark(_optionalInfoSRPKey);
1933
1934
if ((_classFileOracle->hasSourceFile() && _context->shouldPreserveSourceFileName())
1935
|| (_context->romClassHasSourceFileName())) {
1936
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getSourceFileIndex()), Cursor::OPTINFO_SOURCE_FILE_NAME);
1937
}
1938
1939
if (_classFileOracle->hasGenericSignature()) {
1940
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getGenericSignatureIndex()), Cursor::SRP_TO_UTF8);
1941
}
1942
1943
if ((_classFileOracle->hasSourceDebugExtension() && (_context->shouldPreserveSourceDebugExtension()))
1944
|| (_context->romClassHasSourceDebugExtension())) {
1945
cursor->writeSRP(_sourceDebugExtensionSRPKey, Cursor::SRP_TO_SOURCE_DEBUG_EXT);
1946
}
1947
1948
if (_classFileOracle->hasEnclosingMethod()) {
1949
cursor->writeSRP(_enclosingMethodSRPKey, Cursor::SRP_TO_GENERIC);
1950
}
1951
1952
if (_classFileOracle->hasSimpleName()) {
1953
cursor->writeSRP(_srpKeyProducer->mapCfrConstantPoolIndexToKey(_classFileOracle->getSimpleNameIndex()), Cursor::SRP_TO_UTF8);
1954
}
1955
1956
if (_classFileOracle->hasVerifyExcludeAttribute()) {
1957
cursor->writeU32(0, Cursor::GENERIC); /* This is required for getSRPPtr in util/optinfo.c to work (counts bits in romClass->optionalFlags) */
1958
}
1959
1960
if (_classFileOracle->hasClassAnnotations()) {
1961
cursor->writeSRP(_annotationInfoClassSRPKey, Cursor::SRP_TO_GENERIC);
1962
}
1963
if (_classFileOracle->hasTypeAnnotations()) {
1964
cursor->writeSRP(_typeAnnotationInfoSRPKey, Cursor::SRP_TO_GENERIC);
1965
}
1966
if (_classFileOracle->isRecord()) {
1967
cursor->writeSRP(_recordInfoSRPKey, Cursor::SRP_TO_GENERIC);
1968
}
1969
if (_classFileOracle->isSealed()) {
1970
cursor->writeSRP(_permittedSubclassesInfoSRPKey, Cursor::SRP_TO_GENERIC);
1971
}
1972
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1973
if (_interfaceInjectionInfo->numOfInterfaces > 0) {
1974
cursor->writeSRP(_injectedInterfaceInfoSRPKey, Cursor::SRP_TO_GENERIC);
1975
}
1976
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1977
}
1978
1979
void
1980
ROMClassWriter::writeCallSiteData(Cursor *cursor, bool markAndCountOnly)
1981
{
1982
if (_constantPoolMap->hasCallSites() || _classFileOracle->hasBootstrapMethods()) {
1983
cursor->mark(_callSiteDataSRPKey);
1984
}
1985
if (_constantPoolMap->hasCallSites()) {
1986
UDATA size = UDATA(_constantPoolMap->getCallSiteCount()) * (sizeof(J9SRP) + sizeof(U_16));
1987
CheckSize _(cursor, size);
1988
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1989
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeCallSiteData();
1990
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1991
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeCallSiteData();
1992
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1993
}
1994
if (_classFileOracle->hasBootstrapMethods()) {
1995
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1996
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0, _interfaceInjectionInfo).writeBootstrapMethods();
1997
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1998
Helper(cursor, false, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, 0).writeBootstrapMethods();
1999
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
2000
}
2001
}
2002
2003
#if defined(J9VM_OPT_METHOD_HANDLE)
2004
void
2005
ROMClassWriter::writeVarHandleMethodTypeLookupTable(Cursor *cursor, bool markAndCountOnly)
2006
{
2007
if (_constantPoolMap->hasVarHandleMethodRefs()) {
2008
cursor->mark(_varHandleMethodTypeLookupTableSRPKey);
2009
UDATA size = _constantPoolMap->getVarHandleMethodTypePaddedCount() * sizeof(U_16);
2010
CheckSize _(cursor, size);
2011
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2012
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeVarHandleMethodTypeLookupTable();
2013
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
2014
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeVarHandleMethodTypeLookupTable();
2015
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
2016
}
2017
}
2018
#endif /* defined(J9VM_OPT_METHOD_HANDLE) */
2019
2020
void
2021
ROMClassWriter::writeStaticSplitTable(Cursor *cursor, bool markAndCountOnly)
2022
{
2023
if (_constantPoolMap->hasStaticSplitTable()) {
2024
cursor->mark(_staticSplitTableSRPKey);
2025
UDATA size = UDATA(_constantPoolMap->getStaticSplitEntryCount()) * sizeof(U_16);
2026
CheckSize _(cursor, size);
2027
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2028
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeStaticSplitTable();
2029
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
2030
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeStaticSplitTable();
2031
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
2032
}
2033
}
2034
2035
void
2036
ROMClassWriter::writeSpecialSplitTable(Cursor *cursor, bool markAndCountOnly)
2037
{
2038
if (_constantPoolMap->hasSpecialSplitTable()) {
2039
cursor->mark(_specialSplitTableSRPKey);
2040
UDATA size = UDATA(_constantPoolMap->getSpecialSplitEntryCount()) * sizeof(U_16);
2041
CheckSize _(cursor, size);
2042
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2043
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size, _interfaceInjectionInfo).writeSpecialSplitTable();
2044
#else /* J9VM_OPT_VALHALLA_VALUE_TYPES */
2045
Helper(cursor, markAndCountOnly, _classFileOracle, _srpKeyProducer, _srpOffsetTable, _constantPoolMap, size).writeSpecialSplitTable();
2046
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
2047
}
2048
}
2049
2050
void
2051
ROMClassWriter::writeByteCodes(Cursor* cursor, ClassFileOracle::MethodIterator *methodIterator)
2052
{
2053
U_8 *code = methodIterator->getCode();
2054
2055
if (!methodIterator->isByteCodeFixupDone()) {
2056
ClassFileOracle::BytecodeFixupEntry *fixupTable = methodIterator->getByteCodeFixupTable();
2057
ClassFileOracle::BytecodeFixupEntry *end = fixupTable + methodIterator->getByteCodeFixupCount();
2058
2059
for (ClassFileOracle::BytecodeFixupEntry *entry = fixupTable; entry != end; ++entry) {
2060
U_16 *dest = (U_16 *) &code[entry->codeIndex];
2061
2062
switch(entry->type) {
2063
case ConstantPoolMap::LDC:
2064
code[entry->codeIndex] = U_8(_constantPoolMap->getROMClassCPIndex(entry->cpIndex));
2065
break;
2066
2067
case ConstantPoolMap::INVOKE_DYNAMIC:
2068
/* rewrite the invokedynamic index to be the callSiteIndex */
2069
*dest = _constantPoolMap->getCallSiteIndex(entry->cpIndex);
2070
break;
2071
2072
case ConstantPoolMap::INVOKE_STATIC:
2073
if (_constantPoolMap->isStaticSplit(entry->cpIndex)) {
2074
code[entry->codeIndex - 1] = JBinvokestaticsplit;
2075
*dest = _constantPoolMap->getStaticSplitTableIndex(entry->cpIndex);
2076
} else {
2077
*dest = _constantPoolMap->getROMClassCPIndex(entry->cpIndex, entry->type);
2078
}
2079
break;
2080
2081
case ConstantPoolMap::INVOKE_SPECIAL:
2082
if (_constantPoolMap->isSpecialSplit(entry->cpIndex)) {
2083
code[entry->codeIndex - 1] = JBinvokespecialsplit;
2084
*dest = _constantPoolMap->getSpecialSplitTableIndex(entry->cpIndex);
2085
} else {
2086
*dest = _constantPoolMap->getROMClassCPIndex(entry->cpIndex, entry->type);
2087
}
2088
break;
2089
2090
default:
2091
*dest = _constantPoolMap->getROMClassCPIndex(entry->cpIndex, entry->type);
2092
break;
2093
}
2094
}
2095
methodIterator->setByteCodeFixupDone();
2096
}
2097
2098
cursor->writeData(code, methodIterator->getCodeLength(), Cursor::BYTECODE);
2099
}
2100
2101
U_32
2102
ROMClassWriter::computeNativeSignatureSize(U_8 *methodDescriptor)
2103
{
2104
Cursor countingCursor(0, NULL, _context);
2105
writeNativeSignature(&countingCursor, methodDescriptor, 0);
2106
return U_32(countingCursor.getCount());
2107
}
2108
2109
void
2110
ROMClassWriter::writeNativeSignature(Cursor *cursor, U_8 *methodDescriptor, U_8 nativeArgCount)
2111
{
2112
/* mapping characters A..Z */
2113
static const U_8 nativeArgCharConversion[] = {
2114
0, PARAM_BYTE, PARAM_CHAR, PARAM_DOUBLE,
2115
0, PARAM_FLOAT, 0, 0,
2116
PARAM_INT, PARAM_LONG, 0, PARAM_OBJECT,
2117
0, 0, 0, 0,
2118
0, 0, PARAM_SHORT, 0,
2119
0, PARAM_VOID, 0, 0,
2120
0, PARAM_BOOLEAN};
2121
2122
UDATA index = 1;
2123
2124
cursor->writeU8(nativeArgCount, Cursor::GENERIC);
2125
2126
/* Parse and write return type */
2127
while (')' != methodDescriptor[index]) {
2128
++index;
2129
}
2130
++index;
2131
if ('[' == methodDescriptor[index]) {
2132
cursor->writeU8(PARAM_OBJECT, Cursor::GENERIC);
2133
} else {
2134
cursor->writeU8(nativeArgCharConversion[methodDescriptor[index] - 'A'], Cursor::GENERIC);
2135
}
2136
2137
index = 1;
2138
2139
/* Parse the signature inside the ()'s */
2140
while (')' != methodDescriptor[index]) {
2141
if ('[' == methodDescriptor[index]) {
2142
cursor->writeU8(PARAM_OBJECT, Cursor::GENERIC);
2143
while ('[' == methodDescriptor[index]) {
2144
++index;
2145
}
2146
} else {
2147
cursor->writeU8(nativeArgCharConversion[methodDescriptor[index] - 'A'], Cursor::GENERIC);
2148
}
2149
if ('L' == methodDescriptor[index]) {
2150
while (';' != methodDescriptor[index]) {
2151
++index;
2152
}
2153
}
2154
++index;
2155
}
2156
}
2157
2158