Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcutil/ClassFileWriter.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
* ClassFileWriter.cpp
24
*/
25
26
/* Note: j9.h has to be included before bcnames.h to avoid conflict of
27
* J9InternalVMLabels->JBaload0getfield in j9generated.h with
28
* the macro JBaload0getfield in bcnames.h.
29
*/
30
#include "j9.h"
31
#include "bcnames.h"
32
#include "bcutil.h"
33
#include "cfr.h"
34
#include "cfreader.h"
35
#include "pcstack.h"
36
#include "rommeth.h"
37
#include "util_api.h"
38
39
#include "ClassFileWriter.hpp"
40
41
#define DECLARE_UTF8_ATTRIBUTE_NAME(instanceName, name) \
42
static const struct { \
43
U_16 length; \
44
U_8 data[sizeof(name)]; \
45
} instanceName = { sizeof(name) - 1, name }
46
47
DECLARE_UTF8_ATTRIBUTE_NAME(CONSTANT_VALUE, "ConstantValue");
48
DECLARE_UTF8_ATTRIBUTE_NAME(CODE, "Code");
49
DECLARE_UTF8_ATTRIBUTE_NAME(STACK_MAP_TABLE, "StackMapTable");
50
DECLARE_UTF8_ATTRIBUTE_NAME(EXCEPTIONS, "Exceptions");
51
DECLARE_UTF8_ATTRIBUTE_NAME(METHODPARAMETERS, "MethodParameters");
52
DECLARE_UTF8_ATTRIBUTE_NAME(INNER_CLASSES, "InnerClasses");
53
DECLARE_UTF8_ATTRIBUTE_NAME(ENCLOSING_METHOD, "EnclosingMethod");
54
DECLARE_UTF8_ATTRIBUTE_NAME(SIGNATURE, "Signature");
55
DECLARE_UTF8_ATTRIBUTE_NAME(SOURCE_FILE, "SourceFile");
56
DECLARE_UTF8_ATTRIBUTE_NAME(SOURCE_DEBUG_EXTENSION, "SourceDebugExtension");
57
DECLARE_UTF8_ATTRIBUTE_NAME(LINE_NUMBER_TABLE, "LineNumberTable");
58
DECLARE_UTF8_ATTRIBUTE_NAME(LOCAL_VARIABLE_TABLE, "LocalVariableTable");
59
DECLARE_UTF8_ATTRIBUTE_NAME(LOCAL_VARIABLE_TYPE_TABLE, "LocalVariableTypeTable");
60
DECLARE_UTF8_ATTRIBUTE_NAME(RUNTIME_VISIBLE_ANNOTATIONS, "RuntimeVisibleAnnotations");
61
DECLARE_UTF8_ATTRIBUTE_NAME(RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, "RuntimeVisibleParameterAnnotations");
62
DECLARE_UTF8_ATTRIBUTE_NAME(RUNTIME_VISIBLE_TYPE_ANNOTATIONS, "RuntimeVisibleTypeAnnotations");
63
DECLARE_UTF8_ATTRIBUTE_NAME(ANNOTATION_DEFAULT, "AnnotationDefault");
64
DECLARE_UTF8_ATTRIBUTE_NAME(BOOTSTRAP_METHODS, "BootstrapMethods");
65
DECLARE_UTF8_ATTRIBUTE_NAME(RECORD, "Record");
66
DECLARE_UTF8_ATTRIBUTE_NAME(PERMITTED_SUBCLASSES, "PermittedSubclasses");
67
#if JAVA_SPEC_VERSION >= 11
68
DECLARE_UTF8_ATTRIBUTE_NAME(NEST_MEMBERS, "NestMembers");
69
DECLARE_UTF8_ATTRIBUTE_NAME(NEST_HOST, "NestHost");
70
#endif /* JAVA_SPEC_VERSION >= 11 */
71
72
void
73
ClassFileWriter::analyzeROMClass()
74
{
75
_cpHashTable = hashTableNew(OMRPORT_FROM_J9PORT(_portLibrary), "ClassFileWriter::_cpHashTable", _romClass->classFileCPCount, sizeof(HashTableEntry), 0, 0, J9MEM_CATEGORY_JVMTI, hashFunction, equalFunction, NULL, NULL);
76
if (NULL == _cpHashTable) {
77
_buildResult = OutOfMemory;
78
return;
79
}
80
81
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
82
if (J9_ARE_ALL_BITS_SET(_romClass->optionalFlags, J9_ROMCLASS_OPTINFO_INJECTED_INTERFACE_INFO)) {
83
_numOfInjectedInterfaces = getNumberOfInjectedInterfaces(_romClass);
84
}
85
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
86
87
/* Walk ROM class adding hashtable entries for all referenced UTF8s and NASs, with index=0 */
88
analyzeConstantPool();
89
analyzeInterfaces();
90
analyzeFields();
91
analyzeMethods();
92
addClassEntry(J9ROMCLASS_CLASSNAME(_romClass), 0);
93
94
/* Super class name is NULL only for java/lang/Object */
95
if (NULL != J9ROMCLASS_SUPERCLASSNAME(_romClass)) {
96
addClassEntry(J9ROMCLASS_SUPERCLASSNAME(_romClass), 0);
97
}
98
99
if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccRecord)) {
100
analyzeRecordAttribute();
101
}
102
103
if (J9ROMCLASS_IS_SEALED(_romClass)) {
104
addEntry((void*) &PERMITTED_SUBCLASSES, 0, CFR_CONSTANT_Utf8);
105
106
U_32 *permittedSubclassesCountPtr = getNumberOfPermittedSubclassesPtr(_romClass);
107
for (U_32 i = 0; i < *permittedSubclassesCountPtr; i++) {
108
J9UTF8* permittedSubclassNameUtf8 = permittedSubclassesNameAtIndex(permittedSubclassesCountPtr, i);
109
addEntry(permittedSubclassNameUtf8, 0, CFR_CONSTANT_Utf8);
110
}
111
}
112
113
J9EnclosingObject * enclosingObject = getEnclosingMethodForROMClass(_javaVM, NULL, _romClass);
114
J9UTF8 * genericSignature = getGenericSignatureForROMClass(_javaVM, NULL, _romClass);
115
J9UTF8 * sourceFileName = getSourceFileNameForROMClass(_javaVM, NULL, _romClass);
116
J9SourceDebugExtension * sourceDebugExtension = getSourceDebugExtensionForROMClass(_javaVM, NULL, _romClass);
117
U_32 * annotationsData = getClassAnnotationsDataForROMClass(_romClass);
118
U_32 * typeAnnotationsData = getClassTypeAnnotationsDataForROMClass(_romClass);
119
J9UTF8 * outerClassName = J9ROMCLASS_OUTERCLASSNAME(_romClass);
120
J9UTF8 * simpleName = getSimpleNameForROMClass(_javaVM, NULL, _romClass);
121
#if JAVA_SPEC_VERSION >= 11
122
J9UTF8 *nestHost = J9ROMCLASS_NESTHOSTNAME(_romClass);
123
#endif /* JAVA_SPEC_VERSION >= 11 */
124
125
/* For a local class only InnerClasses.class[i].inner_name_index is preserved as simpleName in its J9ROMClass */
126
if ((0 != _romClass->innerClassCount)
127
|| (0 != _romClass->enclosedInnerClassCount)
128
|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)
129
) {
130
addEntry((void *) &INNER_CLASSES, 0, CFR_CONSTANT_Utf8);
131
132
if (NULL != outerClassName) {
133
addClassEntry(outerClassName, 0);
134
}
135
136
if (NULL != simpleName) {
137
addEntry(simpleName, 0, CFR_CONSTANT_Utf8);
138
}
139
140
J9SRP * innerClasses = (J9SRP *) J9ROMCLASS_INNERCLASSES(_romClass);
141
for (UDATA i = 0; i < _romClass->innerClassCount; i++, innerClasses++) {
142
J9UTF8 * className = NNSRP_PTR_GET(innerClasses, J9UTF8 *);
143
addClassEntry(className, 0);
144
}
145
J9SRP * enclosedInnerClasses = (J9SRP *) J9ROMCLASS_ENCLOSEDINNERCLASSES(_romClass);
146
for (UDATA i = 0; i < _romClass->enclosedInnerClassCount; i++, enclosedInnerClasses++) {
147
J9UTF8 * className = NNSRP_PTR_GET(enclosedInnerClasses, J9UTF8 *);
148
addClassEntry(className, 0);
149
}
150
}
151
152
#if JAVA_SPEC_VERSION >= 11
153
/* Class can not have both a nest members and nest host attribute */
154
if (0 != _romClass->nestMemberCount) {
155
U_16 nestMemberCount = _romClass->nestMemberCount;
156
J9SRP *nestMembers = (J9SRP *) J9ROMCLASS_NESTMEMBERS(_romClass);
157
158
addEntry((void *) &NEST_MEMBERS, 0, CFR_CONSTANT_Utf8);
159
for (U_16 i = 0; i < nestMemberCount; i++) {
160
J9UTF8 * className = NNSRP_GET(nestMembers[i], J9UTF8 *);
161
addClassEntry(className, 0);
162
}
163
} else if (NULL != nestHost) {
164
addEntry((void *) &NEST_HOST, 0, CFR_CONSTANT_Utf8);
165
addClassEntry(nestHost, 0);
166
}
167
#endif /* JAVA_SPEC_VERSION >= 11 */
168
169
if (NULL != enclosingObject) {
170
addEntry((void *) &ENCLOSING_METHOD, 0, CFR_CONSTANT_Utf8);
171
J9ROMNameAndSignature * nas = J9ENCLOSINGOBJECT_NAMEANDSIGNATURE(enclosingObject);
172
if (NULL != nas) {
173
addNASEntry(nas);
174
}
175
}
176
177
if (NULL != genericSignature) {
178
addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);
179
addEntry(genericSignature, 0, CFR_CONSTANT_Utf8);
180
}
181
182
if (NULL != sourceFileName) {
183
addEntry((void *) &SOURCE_FILE, 0, CFR_CONSTANT_Utf8);
184
addEntry(sourceFileName, 0, CFR_CONSTANT_Utf8);
185
}
186
187
if (NULL != sourceDebugExtension) {
188
addEntry((void *) &SOURCE_DEBUG_EXTENSION, 0, CFR_CONSTANT_Utf8);
189
}
190
191
if (NULL != annotationsData) {
192
addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
193
}
194
195
if (NULL != typeAnnotationsData) {
196
addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
197
}
198
199
if (0 != _romClass->bsmCount) {
200
addEntry((void *) &BOOTSTRAP_METHODS, 0, CFR_CONSTANT_Utf8);
201
202
U_32 bsmCount = _romClass->bsmCount;
203
U_32 callSiteCount = _romClass->callSiteCount;
204
J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);
205
U_16 * bsmIndices = (U_16 *) (callSiteData + callSiteCount);
206
U_16 * bsmData = bsmIndices + callSiteCount;
207
U_16 * bsmCursor = bsmData;
208
209
for (U_32 i = 0; i < bsmCount; i++) {
210
U_16 argCount = bsmCursor[1];
211
bsmCursor += argCount + 2;
212
}
213
_bsmAttributeLength = (U_32)((bsmCursor - bsmData + 1) * sizeof(U_16)); /* +1 to account for num_bootstrap_methods */
214
}
215
216
/* Walk callSiteData and add InvokeDynamic CP entries.
217
*
218
* InvokeDynamic entries in J9ROMClass are stored as CallSite data.
219
* For every call site that refers an InvokeDynamic entry, we store its J9ROMNameAndSignature and bootstrapMethodIndex.
220
* First the SRPs to J9ROMNameAndSignature for each callsite are stored.
221
* This is followed by the bootstrapMethodIndex for each callsite.
222
* So the CallSite data consists of a block of SRPs to J9ROMNameAndSignature, followed by a block of bootstrapMethodIndices.
223
*
224
* If there are multiple call sites referring to same InvokeDynamic CP entry,
225
* then the contents get duplicated as many times.
226
*
227
* Eg: Say there are two InvokeDynamic entries in .class
228
*
229
* InvokeDynamic1
230
* bootstrap_method_attr_index1
231
* name_and_type_index1
232
* InvokeDynamic2
233
* bootstrap_method_attr_index2
234
* name_and_type_index2
235
*
236
* If InvokeDynamic1 is referred twice and InvokeDynamic2 is referred thrice,
237
* CallSite data layout in J9ROMClass will be:
238
*
239
* index: 0 1 2 3 4 0 1 2 3 4
240
*
241
* | SRP to NAS1 | SRP to NAS1 | SRP to NAS2 | SRP to NAS2 | SRP to NAS2 | bsm1 | bsm1 | bsm2 | bsm2 | bsm2 |
242
*
243
* When adding an entry in _cpHashTable for an InvokeDynamic entry,
244
* address of its SRP to J9ROMNameAndSignature is used as key.
245
* However, we need to skip the duplicate entries.
246
* In above example, entries at index 1, 3 and 4 are duplicate and should be skipped.
247
* This is achieved by checking J9ROMNameAndSignature address of callSite being considered with the
248
* address of J9ROMNameAndSignature of the callSite last stored in _cpHashTable.
249
* If they are same, it indicates a duplicate entry and can be skipped.
250
*/
251
if (0 != _romClass->callSiteCount) {
252
J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);
253
U_16 const * bsmIndices = (U_16 *) (callSiteData + _romClass->callSiteCount);
254
J9ROMNameAndSignature * prevNAS = NULL;
255
U_16 prevIndex = (U_16)-1; /* set to invalid value */
256
257
for (UDATA i = 0; i < _romClass->callSiteCount; i++) {
258
J9ROMNameAndSignature * nas = SRP_PTR_GET(callSiteData + i, J9ROMNameAndSignature *);
259
U_16 index = bsmIndices[i];
260
if ((nas != prevNAS) || (index != prevIndex)) {
261
/* Both the index and the NAS need to be the same to be considered the same element */
262
addEntry(callSiteData + i, 0, CFR_CONSTANT_InvokeDynamic);
263
addNASEntry(nas);
264
prevNAS = nas;
265
prevIndex = index;
266
}
267
}
268
}
269
270
/* Walk the hashtable assigning indexes to all entries with index==0 */
271
272
/* romConstantPoolCount has only one slot for Long/Double CP entries,
273
* but they occupy two slots in .class constant pool.
274
*/
275
U_16 doubleSlotCount = _romClass->romConstantPoolCount - _romClass->ramConstantPoolCount;
276
_constantPoolCount = _romClass->romConstantPoolCount + doubleSlotCount;
277
J9HashTableState hashTableState;
278
HashTableEntry * entry = (HashTableEntry *) hashTableStartDo(_cpHashTable, &hashTableState);
279
while (NULL != entry) {
280
if (0 == entry->cpIndex) {
281
entry->cpIndex = _constantPoolCount;
282
_constantPoolCount += 1;
283
if ((CFR_CONSTANT_Long == entry->cpType) || (CFR_CONSTANT_Double == entry->cpType)) {
284
_constantPoolCount += 1;
285
}
286
}
287
entry = (HashTableEntry *) hashTableNextDo(&hashTableState);
288
}
289
}
290
291
void
292
ClassFileWriter::analyzeConstantPool()
293
{
294
/* Walk ROM CP adding hashtable entries for all
295
* J9CPTYPE_INT, J9CPTYPE_FLOAT, J9CPTYPE_LONG, J9CPTYPE_DOUBLE CP entries, with their index,
296
* and all referenced UTF8s & NASs
297
*/
298
U_16 cpCount = _romClass->romConstantPoolCount;
299
J9ROMConstantPoolItem * constantPool = J9_ROM_CP_FROM_ROM_CLASS(_romClass);
300
U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(_romClass);
301
302
for (U_16 i = 1; i < cpCount; i++) {
303
J9ROMConstantPoolItem * cpItem = constantPool + i;
304
switch (J9_CP_TYPE(cpShapeDescription, i)) {
305
case J9CPTYPE_CLASS:
306
addClassEntry(J9ROMCLASSREF_NAME((J9ROMClassRef *) cpItem), i);
307
break;
308
case J9CPTYPE_STRING:
309
addEntry(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem), 0, CFR_CONSTANT_Utf8);
310
break;
311
case J9CPTYPE_FIELD:
312
addNASEntry(J9ROMFIELDREF_NAMEANDSIGNATURE((J9ROMFieldRef *) cpItem));
313
break;
314
case J9CPTYPE_INSTANCE_METHOD:
315
case J9CPTYPE_STATIC_METHOD:
316
case J9CPTYPE_INTERFACE_METHOD:
317
case J9CPTYPE_INTERFACE_STATIC_METHOD:
318
case J9CPTYPE_INTERFACE_INSTANCE_METHOD:
319
case J9CPTYPE_HANDLE_METHOD:
320
addNASEntry(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) cpItem));
321
break;
322
case J9CPTYPE_METHOD_TYPE:
323
addEntry(J9ROMMETHODTYPEREF_SIGNATURE((J9ROMMethodTypeRef *) cpItem), 0, CFR_CONSTANT_Utf8);
324
break;
325
case J9CPTYPE_METHODHANDLE:
326
/* do nothing */
327
break;
328
case J9CPTYPE_INT:
329
addEntry(&((J9ROMSingleSlotConstantRef *) cpItem)->data, i, CFR_CONSTANT_Integer);
330
break;
331
case J9CPTYPE_FLOAT:
332
addEntry(&((J9ROMSingleSlotConstantRef *) cpItem)->data, i, CFR_CONSTANT_Float);
333
break;
334
case J9CPTYPE_LONG:
335
addEntry(&((J9ROMConstantRef *) cpItem)->slot1, i + (i - _romClass->ramConstantPoolCount), CFR_CONSTANT_Long);
336
break;
337
case J9CPTYPE_DOUBLE:
338
addEntry(&((J9ROMConstantRef *) cpItem)->slot1, i + (i - _romClass->ramConstantPoolCount), CFR_CONSTANT_Double);
339
break;
340
case J9CPTYPE_ANNOTATION_UTF8:
341
addEntry(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem), i, CFR_CONSTANT_Utf8);
342
break;
343
case J9CPTYPE_CONSTANT_DYNAMIC:
344
addNASEntry(J9ROMCONSTANTDYNAMICREF_NAMEANDSIGNATURE((J9ROMConstantDynamicRef *) cpItem));
345
break;
346
default:
347
Trc_BCU_Assert_ShouldNeverHappen();
348
break;
349
}
350
}
351
}
352
353
void
354
ClassFileWriter::analyzeInterfaces()
355
{
356
J9SRP * interfaceNames = J9ROMCLASS_INTERFACES(_romClass);
357
UDATA interfaceCount = _romClass->interfaceCount;
358
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
359
interfaceCount -= _numOfInjectedInterfaces;
360
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
361
for (UDATA i = 0; i < interfaceCount; i++) {
362
J9UTF8 * interfaceName = NNSRP_GET(interfaceNames[i], J9UTF8*);
363
addClassEntry(interfaceName, 0);
364
}
365
}
366
367
void
368
ClassFileWriter::analyzeFields()
369
{
370
J9ROMFieldWalkState fieldWalkState;
371
J9ROMFieldShape * fieldShape = romFieldsStartDo(_romClass, &fieldWalkState);
372
while (NULL != fieldShape) {
373
addEntry(J9ROMFIELDSHAPE_NAME(fieldShape), 0, CFR_CONSTANT_Utf8);
374
addEntry(J9ROMFIELDSHAPE_SIGNATURE(fieldShape), 0, CFR_CONSTANT_Utf8);
375
376
J9UTF8 * genericSignature = romFieldGenericSignature(fieldShape);
377
if (NULL != genericSignature) {
378
addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);
379
addEntry(genericSignature, 0, CFR_CONSTANT_Utf8);
380
}
381
if (J9FieldFlagHasFieldAnnotations & fieldShape->modifiers) {
382
addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
383
}
384
385
if (J9FieldFlagHasTypeAnnotations & fieldShape->modifiers) {
386
addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
387
}
388
389
if (J9FieldFlagConstant & fieldShape->modifiers) {
390
addEntry((void *) &CONSTANT_VALUE, 0, CFR_CONSTANT_Utf8);
391
392
if (0 == (J9FieldFlagObject & fieldShape->modifiers)) {
393
U_32 * value = romFieldInitialValueAddress(fieldShape);
394
U_8 cpType = 0;
395
switch (J9FieldTypeMask & fieldShape->modifiers) {
396
case J9FieldTypeDouble:
397
cpType = CFR_CONSTANT_Double;
398
break;
399
case J9FieldTypeLong:
400
cpType = CFR_CONSTANT_Long;
401
break;
402
case J9FieldTypeFloat:
403
cpType = CFR_CONSTANT_Float;
404
break;
405
default:
406
cpType = CFR_CONSTANT_Integer;
407
break;
408
}
409
addEntry(value, 0, cpType);
410
}
411
}
412
413
fieldShape = romFieldsNextDo(&fieldWalkState);
414
}
415
}
416
417
void
418
ClassFileWriter::analyzeMethods()
419
{
420
J9ROMMethod * method = J9ROMCLASS_ROMMETHODS(_romClass);
421
422
for (U_32 i = 0; i < _romClass->romMethodCount; i++) {
423
addEntry(J9ROMMETHOD_NAME(method), 0, CFR_CONSTANT_Utf8);
424
addEntry(J9ROMMETHOD_SIGNATURE(method), 0, CFR_CONSTANT_Utf8);
425
426
if (J9ROMMETHOD_HAS_GENERIC_SIGNATURE(method)) {
427
addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);
428
addEntry(J9_GENERIC_SIGNATURE_FROM_ROM_METHOD(method), 0, CFR_CONSTANT_Utf8);
429
}
430
if (0 == ((J9AccAbstract | J9AccNative) & method->modifiers)) {
431
addEntry((void *) &CODE, 0, CFR_CONSTANT_Utf8);
432
}
433
if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {
434
J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);
435
if (0 != exceptionInfo->throwCount) {
436
addEntry((void *) &EXCEPTIONS, 0, CFR_CONSTANT_Utf8);
437
438
U_8 * address = (U_8 *) (exceptionInfo + 1);
439
address += sizeof(J9ExceptionHandler) * exceptionInfo->catchCount;
440
J9SRP * throwNames = (J9SRP *) address;
441
442
for (U_16 i = 0; i < exceptionInfo->throwCount; i++) {
443
J9UTF8 * throwName = NNSRP_GET(throwNames[i], J9UTF8 *);
444
addClassEntry(throwName, 0);
445
}
446
}
447
}
448
if (J9ROMMETHOD_HAS_METHOD_PARAMETERS(method)) {
449
addEntry((void *) &METHODPARAMETERS, 0, CFR_CONSTANT_Utf8);
450
/*
451
J9MethodParametersData
452
__________________________
453
| U_8 methodParameterCount |
454
|__________________________|
455
|__________________________|
456
| J9MethodParameter |
457
|__________________________|
458
| J9MethodParameter | ===========> methodParameterCount * J9MethodParameter
459
|__________________________|
460
| . . . |
461
| . . . |
462
|__________________________|
463
464
struct J9MethodParameter
465
---------------------------------------
466
|J9SRP name (J9SRP -> J9UTF8) |
467
|U_16 flags |
468
---------------------------------------
469
*/
470
J9MethodParametersData * methodParametersData = methodParametersFromROMMethod(method);
471
J9MethodParameter * parameters = &methodParametersData->parameters;
472
for (U_8 i = 0; i < methodParametersData->parameterCount; i++) {
473
J9UTF8 * parameterNameUTF8 = SRP_GET(parameters[i].name, J9UTF8 *);
474
if (NULL != parameterNameUTF8) {
475
addEntry(parameterNameUTF8, 0, CFR_CONSTANT_Utf8);
476
}
477
}
478
}
479
if (J9ROMMETHOD_HAS_ANNOTATIONS_DATA(method)) {
480
addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
481
}
482
if (J9ROMMETHOD_HAS_PARAMETER_ANNOTATIONS(method)) {
483
addEntry((void *) &RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
484
}
485
U_32 extendedModifiers = getExtendedModifiersDataFromROMMethod(method);
486
if (J9ROMMETHOD_HAS_METHOD_TYPE_ANNOTATIONS(extendedModifiers) || J9ROMMETHOD_HAS_CODE_TYPE_ANNOTATIONS(extendedModifiers)) {
487
addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
488
}
489
if (J9ROMMETHOD_HAS_DEFAULT_ANNOTATION(method)) {
490
addEntry((void *) &ANNOTATION_DEFAULT, 0, CFR_CONSTANT_Utf8);
491
}
492
if (J9ROMMETHOD_HAS_STACK_MAP(method)) {
493
addEntry((void *) &STACK_MAP_TABLE, 0, CFR_CONSTANT_Utf8);
494
}
495
496
J9MethodDebugInfo* debugInfo = getMethodDebugInfoFromROMMethod(method);
497
if (NULL != debugInfo) {
498
if (0 != debugInfo->lineNumberCount) {
499
addEntry((void *) &LINE_NUMBER_TABLE, 0, CFR_CONSTANT_Utf8);
500
}
501
502
if (0 != debugInfo->varInfoCount) {
503
addEntry((void *) &LOCAL_VARIABLE_TABLE, 0, CFR_CONSTANT_Utf8);
504
505
J9VariableInfoWalkState state;
506
J9VariableInfoValues *values = NULL;
507
bool typeTable = false;
508
509
values = variableInfoStartDo(debugInfo, &state);
510
while(NULL != values) {
511
addEntry(values->name, 0, CFR_CONSTANT_Utf8);
512
addEntry(values->signature, 0, CFR_CONSTANT_Utf8);
513
514
if (NULL != values->genericSignature) {
515
/* If any of the values has 'genericSignature' non-null, then it has LocalVariableTypeTable */
516
typeTable = true;
517
addEntry(values->genericSignature, 0, CFR_CONSTANT_Utf8);
518
}
519
values = variableInfoNextDo(&state);
520
}
521
if (typeTable) {
522
addEntry((void *) &LOCAL_VARIABLE_TYPE_TABLE, 0, CFR_CONSTANT_Utf8);
523
}
524
}
525
}
526
method = nextROMMethod(method);
527
}
528
}
529
530
void
531
ClassFileWriter::analyzeRecordAttribute()
532
{
533
addEntry((void *) &RECORD, 0, CFR_CONSTANT_Utf8);
534
535
/* first 4 bytes contains number of record components */
536
U_32 numberOfRecords = getNumberOfRecordComponents(_romClass);
537
J9ROMRecordComponentShape* recordComponent = recordComponentStartDo(_romClass);
538
for (U_32 i = 0; i < numberOfRecords; i++) {
539
540
/* record component name and signature */
541
addEntry(J9ROMRECORDCOMPONENTSHAPE_NAME(recordComponent), 0, CFR_CONSTANT_Utf8);
542
addEntry(J9ROMRECORDCOMPONENTSHAPE_SIGNATURE(recordComponent), 0, CFR_CONSTANT_Utf8);
543
544
/* analyze attributes */
545
if (recordComponentHasSignature(recordComponent)) {
546
J9UTF8* genericSignature = getRecordComponentGenericSignature(recordComponent);
547
addEntry((void *) &SIGNATURE, 0, CFR_CONSTANT_Utf8);
548
addEntry(genericSignature, 0, CFR_CONSTANT_Utf8);
549
}
550
if (recordComponentHasAnnotations(recordComponent)) {
551
addEntry((void *) &RUNTIME_VISIBLE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
552
}
553
if (recordComponentHasTypeAnnotations(recordComponent)) {
554
addEntry((void *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, 0, CFR_CONSTANT_Utf8);
555
}
556
557
recordComponent = recordComponentNextDo(recordComponent);
558
}
559
}
560
561
void
562
ClassFileWriter::writeClassFile()
563
{
564
writeU32(CFR_MAGIC);
565
writeU16(_romClass->minorVersion);
566
writeU16(_romClass->majorVersion);
567
writeConstantPool();
568
writeU16(_romClass->modifiers & CFR_CLASS_ACCESS_MASK);
569
writeU16(indexForClass(J9ROMCLASS_CLASSNAME(_romClass)));
570
/* Super class name is NULL only for java/lang/Object */
571
if (NULL != J9ROMCLASS_SUPERCLASSNAME(_romClass)) {
572
writeU16(indexForClass(J9ROMCLASS_SUPERCLASSNAME(_romClass)));
573
} else {
574
writeU16(0);
575
}
576
writeInterfaces();
577
writeFields();
578
writeMethods();
579
writeAttributes();
580
}
581
582
void
583
ClassFileWriter::writeConstantPool()
584
{
585
U_16 cpCount = _romClass->romConstantPoolCount;
586
J9ROMConstantPoolItem * constantPool = J9_ROM_CP_FROM_ROM_CLASS(_romClass);
587
U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(_romClass);
588
589
writeU16(_constantPoolCount);
590
591
/* Expand all ROM CP entries into .class file CP entries */
592
for (U_16 i = 1; i < cpCount; i++) {
593
J9ROMConstantPoolItem * cpItem = constantPool + i;
594
595
switch (J9_CP_TYPE(cpShapeDescription, i)) {
596
case J9CPTYPE_CLASS:
597
writeU8(CFR_CONSTANT_Class);
598
writeU16(indexForUTF8(J9ROMCLASSREF_NAME((J9ROMClassRef *) cpItem)));
599
break;
600
case J9CPTYPE_STRING:
601
writeU8(CFR_CONSTANT_String);
602
writeU16(indexForUTF8(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)));
603
break;
604
case J9CPTYPE_FIELD:
605
writeU8(CFR_CONSTANT_Fieldref);
606
writeU16(U_16(((J9ROMFieldRef *) cpItem)->classRefCPIndex));
607
writeU16(indexForNAS(J9ROMFIELDREF_NAMEANDSIGNATURE((J9ROMFieldRef *) cpItem)));
608
break;
609
case J9CPTYPE_INSTANCE_METHOD:
610
case J9CPTYPE_STATIC_METHOD:
611
case J9CPTYPE_HANDLE_METHOD:
612
writeU8(CFR_CONSTANT_Methodref);
613
writeU16(U_16(((J9ROMMethodRef *) cpItem)->classRefCPIndex));
614
writeU16(indexForNAS(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) cpItem)));
615
break;
616
case J9CPTYPE_INTERFACE_METHOD:
617
case J9CPTYPE_INTERFACE_STATIC_METHOD:
618
case J9CPTYPE_INTERFACE_INSTANCE_METHOD:
619
writeU8(CFR_CONSTANT_InterfaceMethodref);
620
writeU16(U_16(((J9ROMMethodRef *) cpItem)->classRefCPIndex));
621
writeU16(indexForNAS(J9ROMMETHODREF_NAMEANDSIGNATURE((J9ROMMethodRef *) cpItem)));
622
break;
623
case J9CPTYPE_METHOD_TYPE:
624
writeU8(CFR_CONSTANT_MethodType);
625
writeU16(indexForUTF8(J9ROMMETHODTYPEREF_SIGNATURE((J9ROMMethodTypeRef *) cpItem)));
626
break;
627
case J9CPTYPE_METHODHANDLE:
628
writeU8(CFR_CONSTANT_MethodHandle);
629
writeU8(U_8(((J9ROMMethodHandleRef *) cpItem)->handleTypeAndCpType >> BCT_J9DescriptionCpTypeShift));
630
writeU16(U_16(((J9ROMMethodHandleRef *) cpItem)->methodOrFieldRefIndex));
631
break;
632
case J9CPTYPE_INT:
633
writeU8(CFR_CONSTANT_Integer);
634
writeU32(((J9ROMSingleSlotConstantRef *) cpItem)->data);
635
break;
636
case J9CPTYPE_FLOAT:
637
writeU8(CFR_CONSTANT_Float);
638
writeU32(((J9ROMSingleSlotConstantRef *) cpItem)->data);
639
break;
640
case J9CPTYPE_LONG:
641
writeU8(CFR_CONSTANT_Long);
642
#ifdef J9VM_ENV_LITTLE_ENDIAN
643
writeU32(((J9ROMConstantRef *) cpItem)->slot2);
644
writeU32(((J9ROMConstantRef *) cpItem)->slot1);
645
#else /* J9VM_ENV_LITTLE_ENDIAN */
646
writeU32(((J9ROMConstantRef *) cpItem)->slot1);
647
writeU32(((J9ROMConstantRef *) cpItem)->slot2);
648
#endif /* J9VM_ENV_LITTLE_ENDIAN */
649
break;
650
case J9CPTYPE_DOUBLE:
651
writeU8(CFR_CONSTANT_Double);
652
#ifdef J9VM_ENV_LITTLE_ENDIAN
653
writeU32(((J9ROMConstantRef *) cpItem)->slot2);
654
writeU32(((J9ROMConstantRef *) cpItem)->slot1);
655
#else /* J9VM_ENV_LITTLE_ENDIAN */
656
writeU32(((J9ROMConstantRef *) cpItem)->slot1);
657
writeU32(((J9ROMConstantRef *) cpItem)->slot2);
658
#endif /* J9VM_ENV_LITTLE_ENDIAN */
659
break;
660
case J9CPTYPE_ANNOTATION_UTF8:
661
writeU8(CFR_CONSTANT_Utf8);
662
writeU16(J9UTF8_LENGTH(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)));
663
writeData(J9UTF8_LENGTH(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)), J9UTF8_DATA(J9ROMSTRINGREF_UTF8DATA((J9ROMStringRef *) cpItem)));
664
break;
665
case J9CPTYPE_CONSTANT_DYNAMIC:
666
writeU8(CFR_CONSTANT_Dynamic);
667
writeU16(U_16((((J9ROMConstantDynamicRef *) cpItem)->bsmIndexAndCpType >> J9DescriptionCpTypeShift) & J9DescriptionCpBsmIndexMask));
668
writeU16(indexForNAS(J9ROMCONSTANTDYNAMICREF_NAMEANDSIGNATURE((J9ROMConstantDynamicRef *) cpItem)));
669
break;
670
default:
671
Trc_BCU_Assert_ShouldNeverHappen();
672
break;
673
}
674
}
675
676
U_16 doubleSlotCount = _romClass->romConstantPoolCount - _romClass->ramConstantPoolCount;
677
/* Walk the hashtable and write CP entries for all hashtable entries with index >= _romClass->romConstantPoolCount */
678
J9HashTableState hashTableState;
679
HashTableEntry * entry = (HashTableEntry *) hashTableStartDo(_cpHashTable, &hashTableState);
680
while (NULL != entry) {
681
if ((_romClass->romConstantPoolCount + doubleSlotCount) <= entry->cpIndex) {
682
writeU8(entry->cpType);
683
684
switch (entry->cpType) {
685
case CFR_CONSTANT_Utf8:
686
{
687
J9UTF8 * utf8 = (J9UTF8 *) entry->address;
688
/* If this is an anonClass, we must build the classData with the original name,
689
* not the anonClass name. There is only one copy of the className in the ROMClass,
690
* so replace the matching anonClassName reference with the originalClassName reference
691
*/
692
if (_isAnon) {
693
if (utf8 == _anonClassName) {
694
utf8 = _originalClassName;
695
}
696
}
697
writeU16(J9UTF8_LENGTH(utf8));
698
writeData(J9UTF8_LENGTH(utf8), J9UTF8_DATA(utf8));
699
break;
700
}
701
case CFR_CONSTANT_Class:
702
writeU16(indexForUTF8((J9UTF8 *) entry->address));
703
break;
704
case CFR_CONSTANT_Double: /* fall through */
705
case CFR_CONSTANT_Long:
706
#ifdef J9VM_ENV_LITTLE_ENDIAN
707
writeU32(((U_32 *) entry->address)[1]);
708
writeU32(((U_32 *) entry->address)[0]);
709
#else /* J9VM_ENV_LITTLE_ENDIAN */
710
writeU32(((U_32 *) entry->address)[0]);
711
writeU32(((U_32 *) entry->address)[1]);
712
#endif /* J9VM_ENV_LITTLE_ENDIAN */
713
break;
714
case CFR_CONSTANT_Float: /* fall through */
715
case CFR_CONSTANT_Integer:
716
writeU32(((U_32 *) entry->address)[0]);
717
break;
718
case CFR_CONSTANT_NameAndType: {
719
J9ROMNameAndSignature * nas = (J9ROMNameAndSignature *) entry->address;
720
writeU16(indexForUTF8(J9ROMNAMEANDSIGNATURE_NAME(nas)));
721
writeU16(indexForUTF8(J9ROMNAMEANDSIGNATURE_SIGNATURE(nas)));
722
break;
723
}
724
case CFR_CONSTANT_InvokeDynamic: {
725
J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);
726
U_16 * bsmIndices = (U_16 *) (callSiteData + _romClass->callSiteCount);
727
J9SRP * srp = (J9SRP *) entry->address;
728
UDATA index(srp - callSiteData);
729
U_16 bsmIndex = bsmIndices[index];
730
J9ROMNameAndSignature * nas = SRP_PTR_GET(srp, J9ROMNameAndSignature *);
731
732
writeU16(bsmIndex);
733
writeU16(indexForNAS(nas));
734
break;
735
}
736
default:
737
Trc_BCU_Assert_ShouldNeverHappen();
738
break;
739
}
740
}
741
entry = (HashTableEntry *) hashTableNextDo(&hashTableState);
742
}
743
}
744
745
void
746
ClassFileWriter::writeInterfaces()
747
{
748
J9SRP * interfaceNames = J9ROMCLASS_INTERFACES(_romClass);
749
UDATA interfaceCount = _romClass->interfaceCount;
750
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
751
interfaceCount -= _numOfInjectedInterfaces;
752
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
753
754
writeU16(U_16(interfaceCount));
755
for (UDATA i = 0; i < interfaceCount; i++) {
756
J9UTF8 * interfaceName = NNSRP_GET(interfaceNames[i], J9UTF8 *);
757
writeU16(indexForClass(interfaceName));
758
}
759
}
760
761
void
762
ClassFileWriter::writeField(J9ROMFieldShape * fieldShape)
763
{
764
J9UTF8 * name = J9ROMFIELDSHAPE_NAME(fieldShape);
765
J9UTF8 * signature = J9ROMFIELDSHAPE_SIGNATURE(fieldShape);
766
J9UTF8 * genericSignature = romFieldGenericSignature(fieldShape);
767
U_32 * annotationsData = getFieldAnnotationsDataFromROMField(fieldShape);
768
U_32 * typeAnnotationsData = getFieldTypeAnnotationsDataFromROMField(fieldShape);
769
U_16 attributesCount = 0;
770
771
if (J9FieldFlagConstant & fieldShape->modifiers) {
772
attributesCount += 1;
773
}
774
if (NULL != genericSignature) {
775
attributesCount += 1;
776
}
777
if (NULL != annotationsData) {
778
attributesCount += 1;
779
}
780
if (NULL != typeAnnotationsData) {
781
attributesCount += 1;
782
}
783
784
writeU16(U_16(fieldShape->modifiers & CFR_FIELD_ACCESS_MASK));
785
writeU16(indexForUTF8(name));
786
writeU16(indexForUTF8(signature));
787
writeU16(attributesCount);
788
789
if (J9FieldFlagConstant & fieldShape->modifiers) {
790
U_32 * value = romFieldInitialValueAddress(fieldShape);
791
U_16 index = 0;
792
if (J9FieldFlagObject & fieldShape->modifiers) {
793
index = *value;
794
} else {
795
switch (J9FieldTypeMask & fieldShape->modifiers) {
796
case J9FieldTypeDouble:
797
index = indexForDouble(value);
798
break;
799
case J9FieldTypeLong:
800
index = indexForLong(value);
801
break;
802
case J9FieldTypeFloat:
803
index = indexForFloat(value);
804
break;
805
default:
806
index = indexForInteger(value);
807
break;
808
}
809
}
810
writeAttributeHeader((J9UTF8 *) &CONSTANT_VALUE, 2);
811
writeU16(index);
812
}
813
if (NULL != genericSignature) {
814
writeSignatureAttribute(genericSignature);
815
}
816
if (NULL != annotationsData) {
817
writeAnnotationsAttribute(annotationsData);
818
}
819
if (NULL != typeAnnotationsData) {
820
writeTypeAnnotationsAttribute(typeAnnotationsData);
821
}
822
}
823
824
void
825
ClassFileWriter::writeFields()
826
{
827
writeU16(U_16(_romClass->romFieldCount));
828
829
J9ROMFieldWalkState state;
830
J9ROMFieldShape * fieldShape = romFieldsStartDo(_romClass, &state);
831
while (NULL != fieldShape) {
832
writeField(fieldShape);
833
fieldShape = romFieldsNextDo(&state);
834
}
835
}
836
837
void
838
ClassFileWriter::writeMethod(J9ROMMethod * method)
839
{
840
J9UTF8 * name = J9ROMMETHOD_NAME(method);
841
J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(method);
842
J9UTF8 * genericSignature = J9_GENERIC_SIGNATURE_FROM_ROM_METHOD(method);
843
U_32 * defaultAnnotationsData = getDefaultAnnotationDataFromROMMethod(method);
844
U_32 * parameterAnnotationsData = getParameterAnnotationsDataFromROMMethod(method);
845
U_32 * typeAnnotationsData = getMethodTypeAnnotationsDataFromROMMethod(method);
846
U_32 * annotationsData = getMethodAnnotationsDataFromROMMethod(method);
847
J9MethodParametersData * methodParametersData = getMethodParametersFromROMMethod(method);
848
849
U_16 attributesCount = 0;
850
851
/* native or abstract methods don't have Code attribute */
852
if (0 == ((J9AccAbstract | J9AccNative) & method->modifiers)) {
853
attributesCount += 1;
854
}
855
if (NULL != genericSignature) {
856
attributesCount += 1;
857
}
858
if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {
859
J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);
860
if (0 != exceptionInfo->throwCount) {
861
attributesCount += 1;
862
}
863
}
864
if (NULL != annotationsData) {
865
attributesCount += 1;
866
}
867
if (NULL != parameterAnnotationsData) {
868
attributesCount += 1;
869
}
870
if (NULL != typeAnnotationsData) {
871
attributesCount += 1;
872
}
873
if (NULL != defaultAnnotationsData) {
874
attributesCount += 1;
875
}
876
if (NULL != methodParametersData) {
877
attributesCount += 1;
878
}
879
880
writeU16(U_16(method->modifiers & CFR_METHOD_ACCESS_MASK));
881
writeU16(indexForUTF8(name));
882
writeU16(indexForUTF8(signature));
883
writeU16(attributesCount);
884
885
if (0 == ((J9AccAbstract | J9AccNative) & method->modifiers)) {
886
writeCodeAttribute(method);
887
}
888
if (NULL != genericSignature) {
889
writeSignatureAttribute(genericSignature);
890
}
891
if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {
892
J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);
893
if (0 != exceptionInfo->throwCount) {
894
U_8 * address = (U_8 *) (exceptionInfo + 1);
895
address += sizeof(J9ExceptionHandler) * exceptionInfo->catchCount;
896
J9SRP * throwNames = (J9SRP *) address;
897
898
writeAttributeHeader((J9UTF8 *) &EXCEPTIONS, sizeof(U_16) + (sizeof(U_16) * exceptionInfo->throwCount));
899
writeU16(exceptionInfo->throwCount);
900
for (U_16 i = 0; i < exceptionInfo->throwCount; i++) {
901
J9UTF8 * throwName = NNSRP_GET(throwNames[i], J9UTF8 *);
902
writeU16(indexForClass(throwName));
903
}
904
}
905
}
906
if (NULL != annotationsData) {
907
writeAnnotationsAttribute(annotationsData);
908
}
909
if (NULL != parameterAnnotationsData) {
910
writeParameterAnnotationsAttribute(parameterAnnotationsData);
911
}
912
if (NULL != defaultAnnotationsData) {
913
writeAnnotationDefaultAttribute(defaultAnnotationsData);
914
}
915
if (NULL != typeAnnotationsData) {
916
writeTypeAnnotationsAttribute(typeAnnotationsData);
917
}
918
919
if (NULL != methodParametersData) {
920
U_8 parameterCount = methodParametersData->parameterCount;
921
J9MethodParameter * parameters = &methodParametersData->parameters;
922
writeAttributeHeader((J9UTF8 *) &METHODPARAMETERS, sizeof(U_8) + ((sizeof(U_16)+sizeof(U_16)) * parameterCount));
923
924
writeU8(parameterCount);
925
for (U_8 i = 0; i < parameterCount; i++) {
926
U_16 utfIndex = 0;
927
J9UTF8 * parameterName = SRP_GET(parameters[i].name, J9UTF8 *);
928
if (NULL != parameterName) {
929
utfIndex = indexForUTF8(parameterName);
930
}
931
writeU16(utfIndex);
932
writeU16(parameters[i].flags);
933
}
934
}
935
}
936
937
void
938
ClassFileWriter::writeMethods()
939
{
940
writeU16(U_16(_romClass->romMethodCount));
941
J9ROMMethod * method = J9ROMCLASS_ROMMETHODS(_romClass);
942
for (U_32 i = 0; i < _romClass->romMethodCount; i++) {
943
writeMethod(method);
944
method = nextROMMethod(method);
945
}
946
}
947
948
void
949
ClassFileWriter::writeAttributes()
950
{
951
U_16 attributesCount = 0;
952
J9UTF8 * outerClassName = J9ROMCLASS_OUTERCLASSNAME(_romClass);
953
J9UTF8 * simpleName = getSimpleNameForROMClass(_javaVM, NULL, _romClass);
954
J9EnclosingObject * enclosingObject = getEnclosingMethodForROMClass(_javaVM, NULL, _romClass);
955
J9UTF8 * signature = getGenericSignatureForROMClass(_javaVM, NULL, _romClass);
956
J9UTF8 * sourceFileName = getSourceFileNameForROMClass(_javaVM, NULL, _romClass);
957
J9SourceDebugExtension * sourceDebugExtension = getSourceDebugExtensionForROMClass(_javaVM, NULL, _romClass);
958
U_32 * annotationsData = getClassAnnotationsDataForROMClass(_romClass);
959
U_32 * typeAnnotationsData = getClassTypeAnnotationsDataForROMClass(_romClass);
960
#if JAVA_SPEC_VERSION >= 11
961
J9UTF8 *nestHost = J9ROMCLASS_NESTHOSTNAME(_romClass);
962
U_16 nestMemberCount = _romClass->nestMemberCount;
963
#endif /* JAVA_SPEC_VERSION >= 11 */
964
965
if ((0 != _romClass->innerClassCount)
966
|| (0 != _romClass->enclosedInnerClassCount)
967
|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)
968
) {
969
attributesCount += 1;
970
}
971
if (NULL != enclosingObject) {
972
attributesCount += 1;
973
}
974
if (NULL != signature) {
975
attributesCount += 1;
976
}
977
if (NULL != sourceFileName) {
978
attributesCount += 1;
979
}
980
if (NULL != sourceDebugExtension) {
981
attributesCount += 1;
982
}
983
if (NULL != annotationsData) {
984
attributesCount += 1;
985
}
986
if (NULL != typeAnnotationsData) {
987
attributesCount += 1;
988
}
989
if (0 != _romClass->bsmCount) {
990
attributesCount += 1;
991
}
992
if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccRecord)) {
993
attributesCount += 1;
994
}
995
if (J9ROMCLASS_IS_SEALED(_romClass)) {
996
attributesCount += 1;
997
}
998
#if JAVA_SPEC_VERSION >= 11
999
/* Class can not have both a nest members and member of nest attribute */
1000
if ((0 != _romClass->nestMemberCount) || (NULL != nestHost)) {
1001
attributesCount += 1;
1002
}
1003
#endif /* JAVA_SPEC_VERSION >= 11 */
1004
writeU16(attributesCount);
1005
1006
if ((0 != _romClass->innerClassCount)
1007
|| (0 != _romClass->enclosedInnerClassCount)
1008
|| J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)
1009
) {
1010
U_16 innerClassesCount(_romClass->innerClassCount + _romClass->enclosedInnerClassCount);
1011
1012
if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {
1013
/* This is an inner class, so we have one extra inner class attribute to allocate/write */
1014
innerClassesCount++;
1015
}
1016
1017
/* Calculate and write size of inner class attributes */
1018
U_32 innerClassesSize = innerClassesCount * 4 * sizeof(U_16);
1019
innerClassesSize += sizeof(U_16); /* innerClassesCount */
1020
writeAttributeHeader((J9UTF8 *) &INNER_CLASSES, innerClassesSize);
1021
writeU16(innerClassesCount);
1022
1023
U_16 thisClassCPIndex = indexForClass(J9ROMCLASS_CLASSNAME(_romClass));
1024
1025
/* Write inner classes of this class */
1026
J9SRP * innerClasses = (J9SRP *) J9ROMCLASS_INNERCLASSES(_romClass);
1027
/* Write inner class entries for inner classes of this class */
1028
for (UDATA i = 0; i < _romClass->innerClassCount; i++, innerClasses++) {
1029
J9UTF8 * innerClassName = NNSRP_PTR_GET(innerClasses, J9UTF8 *);
1030
1031
writeU16(indexForClass(innerClassName));
1032
writeU16(thisClassCPIndex);
1033
1034
/* NOTE: innerClassAccessFlags and innerNameIndex are not preserved in the ROM class - technically incorrect, but this should only matter to compilers */
1035
writeU16(0); /* innerNameIndex */
1036
writeU16(0); /* innerClassAccessFlags */
1037
}
1038
1039
/* Write enclosed inner classes of this class */
1040
J9SRP * enclosedInnerClasses = (J9SRP *) J9ROMCLASS_ENCLOSEDINNERCLASSES(_romClass);
1041
/* Write the enclosed inner class entries for inner classes of this class */
1042
for (UDATA i = 0; i < _romClass->enclosedInnerClassCount; i++, enclosedInnerClasses++) {
1043
J9UTF8 * enclosedInnerClassName = NNSRP_PTR_GET(enclosedInnerClasses, J9UTF8 *);
1044
1045
writeU16(indexForClass(enclosedInnerClassName));
1046
/* NOTE: outerClassInfoIndex (these inner class are not the declared classes of this class),
1047
* innerNameIndex and innerClassAccessFlags are not preserved in the ROM class
1048
* - technically incorrect, but this should only matter to compilers.
1049
*/
1050
writeU16(0); /* outerClassInfoIndex */
1051
writeU16(0); /* innerNameIndex */
1052
writeU16(0); /* innerClassAccessFlags */
1053
}
1054
1055
if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccClassInnerClass)) {
1056
/* This is an inner class. Write an inner class attribute for itself. */
1057
writeU16(thisClassCPIndex);
1058
writeU16((NULL == outerClassName) ? 0 : indexForClass(outerClassName));
1059
writeU16((NULL == simpleName) ? 0 : indexForUTF8(simpleName));
1060
writeU16(_romClass->memberAccessFlags);
1061
}
1062
}
1063
1064
#if JAVA_SPEC_VERSION >= 11
1065
/* A class can only have one of the nest mate attributes */
1066
if (0 != nestMemberCount) {
1067
J9SRP *nestMembers = (J9SRP *) J9ROMCLASS_NESTMEMBERS(_romClass);
1068
U_32 nestMembersAttributeSize = (1 + nestMemberCount) * sizeof(U_16);
1069
writeAttributeHeader((J9UTF8 *) &NEST_MEMBERS, nestMembersAttributeSize);
1070
writeU16(nestMemberCount);
1071
1072
for (U_16 i = 0; i < nestMemberCount; i++) {
1073
J9UTF8 * nestMemberName = NNSRP_PTR_GET(nestMembers, J9UTF8 *);
1074
writeU16(indexForClass(nestMemberName));
1075
nestMembers += 1;
1076
}
1077
} else if (NULL != nestHost) {
1078
writeAttributeHeader((J9UTF8 *) &NEST_HOST, 2);
1079
writeU16(indexForClass(nestHost));
1080
}
1081
#endif /* JAVA_SPEC_VERSION >= 11 */
1082
1083
if (NULL != enclosingObject) {
1084
J9ROMNameAndSignature * nas = J9ENCLOSINGOBJECT_NAMEANDSIGNATURE(enclosingObject);
1085
1086
writeAttributeHeader((J9UTF8 *) &ENCLOSING_METHOD, 4);
1087
writeU16(U_16(enclosingObject->classRefCPIndex));
1088
writeU16(NULL == nas ? 0 : indexForNAS(nas));
1089
}
1090
1091
if (NULL != signature) {
1092
writeSignatureAttribute(signature);
1093
}
1094
1095
if (NULL != sourceFileName) {
1096
writeAttributeHeader((J9UTF8 *) &SOURCE_FILE, 2);
1097
writeU16(indexForUTF8(sourceFileName));
1098
}
1099
1100
if (NULL != sourceDebugExtension) {
1101
writeAttributeHeader((J9UTF8 *) &SOURCE_DEBUG_EXTENSION, sourceDebugExtension->size);
1102
writeData(sourceDebugExtension->size, sourceDebugExtension + 1);
1103
}
1104
1105
if (NULL != annotationsData) {
1106
writeAnnotationsAttribute(annotationsData);
1107
}
1108
1109
if (NULL != typeAnnotationsData) {
1110
writeTypeAnnotationsAttribute(typeAnnotationsData);
1111
}
1112
1113
if (0 != _romClass->bsmCount) {
1114
U_32 bsmCount = _romClass->bsmCount;
1115
U_32 callSiteCount = _romClass->callSiteCount;
1116
J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);
1117
U_16 * bsmIndices = (U_16 *) (callSiteData + callSiteCount);
1118
U_16 * bsmCursor = bsmIndices + callSiteCount;
1119
1120
writeAttributeHeader((J9UTF8 *) &BOOTSTRAP_METHODS, _bsmAttributeLength);
1121
writeU16(U_16(bsmCount)); /* num_bootstrap_methods */
1122
for (U_32 i = 0; i < bsmCount; i++) {
1123
writeU16(*bsmCursor); /* bootstrap_method_ref */
1124
bsmCursor += 1;
1125
U_16 argCount = *bsmCursor;
1126
writeU16(argCount); /* num_bootstrap_arguments */
1127
bsmCursor += 1;
1128
for (U_16 j = 0; j < argCount; j++) {
1129
U_16 cpIndex = *bsmCursor;
1130
1131
if (cpIndex >= _romClass->ramConstantPoolCount) {
1132
/* Adjust double slot entry index */
1133
cpIndex = cpIndex + (cpIndex - _romClass->ramConstantPoolCount);
1134
}
1135
writeU16(cpIndex);
1136
bsmCursor += 1;
1137
}
1138
}
1139
}
1140
1141
/* record attribute */
1142
if (J9_ARE_ANY_BITS_SET(_romClass->extraModifiers, J9AccRecord)) {
1143
writeRecordAttribute();
1144
}
1145
1146
/* write PermittedSubclasses attribute */
1147
if (J9ROMCLASS_IS_SEALED(_romClass)) {
1148
U_32 *permittedSubclassesCountPtr = getNumberOfPermittedSubclassesPtr(_romClass);
1149
writeAttributeHeader((J9UTF8 *) &PERMITTED_SUBCLASSES, sizeof(U_16) + (*permittedSubclassesCountPtr * sizeof(U_16)));
1150
1151
writeU16(*permittedSubclassesCountPtr);
1152
1153
for (U_32 i = 0; i < *permittedSubclassesCountPtr; i++) {
1154
J9UTF8* permittedSubclassNameUtf8 = permittedSubclassesNameAtIndex(permittedSubclassesCountPtr, i);
1155
1156
/* CONSTANT_Class_info index should be written. Find class entry that references the subclass name in constant pool. */
1157
J9HashTableState hashTableState;
1158
HashTableEntry * entry = (HashTableEntry *) hashTableStartDo(_cpHashTable, &hashTableState);
1159
while (NULL != entry) {
1160
if (CFR_CONSTANT_Class == entry->cpType) {
1161
J9UTF8* classNameCandidate = (J9UTF8*)entry->address;
1162
if (J9UTF8_EQUALS(classNameCandidate, permittedSubclassNameUtf8)) {
1163
writeU16(entry->cpIndex);
1164
break;
1165
}
1166
}
1167
entry = (HashTableEntry *) hashTableNextDo(&hashTableState);
1168
}
1169
}
1170
}
1171
}
1172
1173
void ClassFileWriter::writeRecordAttribute()
1174
{
1175
/* Write header - size calculation will be written specially at the end.
1176
* Write zero as a placeholder for length.
1177
*/
1178
writeU16(indexForUTF8((J9UTF8 *) &RECORD));
1179
U_8* recordAttributeLengthAddr = _classFileCursor;
1180
writeU32(0);
1181
U_8* startLengthCalculationAddr = _classFileCursor;
1182
1183
/* write number of record components (components_count).
1184
* Stored as U32 in the ROM class, U16 in class file.
1185
*/
1186
U_32 numberOfRecords = getNumberOfRecordComponents(_romClass);
1187
writeU16(numberOfRecords);
1188
1189
/* write record components */
1190
J9ROMRecordComponentShape* recordComponent = recordComponentStartDo(_romClass);
1191
for (U_32 i = 0; i < numberOfRecords; i++) {
1192
J9UTF8 * name = J9ROMRECORDCOMPONENTSHAPE_NAME(recordComponent);
1193
J9UTF8 * signature = J9ROMRECORDCOMPONENTSHAPE_SIGNATURE(recordComponent);
1194
J9UTF8 * genericSignature = getRecordComponentGenericSignature(recordComponent);
1195
U_32 * annotationsData = getRecordComponentAnnotationData(recordComponent);
1196
U_32 * typeAnnotationsData = getRecordComponentTypeAnnotationData(recordComponent);
1197
U_16 attributesCount = 0;
1198
1199
writeU16(indexForUTF8(name));
1200
writeU16(indexForUTF8(signature));
1201
1202
if (NULL != genericSignature) {
1203
attributesCount += 1;
1204
}
1205
if (NULL != annotationsData) {
1206
attributesCount += 1;
1207
}
1208
if (NULL != typeAnnotationsData) {
1209
attributesCount += 1;
1210
}
1211
writeU16(attributesCount);
1212
1213
if (NULL != genericSignature) {
1214
writeSignatureAttribute(genericSignature);
1215
}
1216
if (NULL != annotationsData) {
1217
writeAnnotationsAttribute(annotationsData);
1218
}
1219
if (NULL != typeAnnotationsData) {
1220
writeTypeAnnotationsAttribute(typeAnnotationsData);
1221
}
1222
1223
recordComponent = recordComponentNextDo(recordComponent);
1224
}
1225
1226
/* calculate and write record attribute length */
1227
U_8* endLengthCalculationAddr = _classFileCursor;
1228
writeU32At(U_32(endLengthCalculationAddr - startLengthCalculationAddr), recordAttributeLengthAddr);
1229
}
1230
1231
U_8
1232
ClassFileWriter::computeArgsCount(U_16 methodRefIndex)
1233
{
1234
J9ROMConstantPoolItem *constantPool = (J9ROMConstantPoolItem*) (_romClass + 1);
1235
J9ROMMethodRef *methodRef = (J9ROMMethodRef *)(constantPool + methodRefIndex);
1236
J9ROMNameAndSignature *nas = J9ROMMETHODREF_NAMEANDSIGNATURE(methodRef);
1237
J9UTF8 *sigUTF8 = J9ROMNAMEANDSIGNATURE_SIGNATURE(nas);
1238
U_16 count = J9UTF8_LENGTH(sigUTF8);
1239
U_8 *sig = J9UTF8_DATA(sigUTF8);
1240
U_8 argsCount = 1; /* interface method always has 'this' parameter */
1241
bool done = false;
1242
1243
for (U_16 index = 1; (index < count) && (!done); index++) { /* 1 to skip the opening '(' */
1244
switch (sig[index]) {
1245
case ')':
1246
done = true;
1247
break;
1248
case '[':
1249
/* skip all '['s */
1250
while ((index < count) && ('[' == sig[index])) {
1251
index += 1;
1252
}
1253
if ('L' != sig[index]) {
1254
break;
1255
}
1256
/* fall through */
1257
case 'L':
1258
index += 1;
1259
while ((index < count) && (';' != sig[index])) {
1260
index += 1;
1261
}
1262
break;
1263
case 'D':
1264
/* fall through */
1265
case 'J':
1266
argsCount += 1; /* double occupies 2 slots */
1267
break;
1268
default:
1269
/* any other primitive type */
1270
break;
1271
}
1272
if (!done) {
1273
argsCount += 1;
1274
}
1275
}
1276
1277
return argsCount;
1278
}
1279
1280
void
1281
ClassFileWriter::writeCodeAttribute(J9ROMMethod * method)
1282
{
1283
U_32 codeLength(J9_BYTECODE_SIZE_FROM_ROM_METHOD(method));
1284
U_8 * code(J9_BYTECODE_START_FROM_ROM_METHOD(method));
1285
U_16 attributesCount = 0;
1286
1287
writeU16(indexForUTF8((J9UTF8 *) &CODE));
1288
U_8 * attributeLenAddr = _classFileCursor;
1289
writeU32(0);
1290
1291
U_8 * start = _classFileCursor;
1292
writeU16(method->maxStack);
1293
writeU16(method->tempCount + method->argCount);
1294
writeU32(codeLength);
1295
1296
U_8 * bytecode = _classFileCursor;
1297
writeData(codeLength, code);
1298
rewriteBytecode(method, codeLength, bytecode);
1299
1300
if (J9ROMMETHOD_HAS_EXCEPTION_INFO(method)) {
1301
J9ExceptionInfo * exceptionInfo = J9_EXCEPTION_DATA_FROM_ROM_METHOD(method);
1302
J9ExceptionHandler * handlers = (J9ExceptionHandler *) (exceptionInfo + 1);
1303
1304
writeU16(exceptionInfo->catchCount);
1305
for (U_16 i = 0; i < exceptionInfo->catchCount; i++) {
1306
writeU16(U_16(handlers[i].startPC));
1307
writeU16(U_16(handlers[i].endPC));
1308
writeU16(U_16(handlers[i].handlerPC));
1309
writeU16(U_16(handlers[i].exceptionClassIndex));
1310
}
1311
} else {
1312
writeU16(0);
1313
}
1314
1315
U_8 * attributesCountAddr = _classFileCursor;
1316
writeU16(0);
1317
1318
if (J9ROMMETHOD_HAS_STACK_MAP(method)) {
1319
writeStackMapTableAttribute(method);
1320
attributesCount += 1;
1321
}
1322
1323
if (J9ROMMETHOD_HAS_CODE_TYPE_ANNOTATIONS(getExtendedModifiersDataFromROMMethod(method))) {
1324
U_32 * typeAnnotationsData = getCodeTypeAnnotationsDataFromROMMethod(method);
1325
writeTypeAnnotationsAttribute(typeAnnotationsData);
1326
attributesCount += 1;
1327
}
1328
1329
J9MethodDebugInfo* debugInfo = getMethodDebugInfoFromROMMethod(method);
1330
if (NULL != debugInfo) {
1331
U_16 lineNumberCount(getLineNumberCount(debugInfo));
1332
1333
if (0 != lineNumberCount) {
1334
writeAttributeHeader((J9UTF8 *) &LINE_NUMBER_TABLE, sizeof(U_16) + (lineNumberCount * sizeof(U_16) * 2));
1335
writeU16(lineNumberCount);
1336
1337
U_8 * lineNumberTable = getLineNumberTable(debugInfo);
1338
1339
J9LineNumber lineNumber;
1340
/* getNextLineNumberFromTable() expects initial values in lineNumber to be 0 */
1341
memset(&lineNumber, 0, sizeof(J9LineNumber));
1342
1343
for (U_16 i = 0; i < lineNumberCount; i++) {
1344
if (getNextLineNumberFromTable(&lineNumberTable, &lineNumber)) {
1345
writeU16(lineNumber.location);
1346
writeU16(lineNumber.lineNumber);
1347
} else {
1348
_buildResult = LineNumberTableDecompressFailed;
1349
return;
1350
}
1351
}
1352
attributesCount += 1;
1353
}
1354
1355
U_16 varInfoCount(debugInfo->varInfoCount);
1356
1357
if (0 != varInfoCount) {
1358
writeAttributeHeader((J9UTF8 *) &LOCAL_VARIABLE_TABLE, sizeof(U_16) + (sizeof(U_16) * 5 * varInfoCount));
1359
writeU16(varInfoCount);
1360
1361
J9VariableInfoWalkState state;
1362
J9VariableInfoValues * values = NULL;
1363
1364
U_16 varInfoWithSigCount = 0;
1365
1366
values = variableInfoStartDo(debugInfo, &state);
1367
while(NULL != values) {
1368
writeU16(values->startVisibility);
1369
writeU16(values->visibilityLength);
1370
writeU16(indexForUTF8(values->name));
1371
writeU16(indexForUTF8(values->signature));
1372
writeU16(values->slotNumber);
1373
if (NULL != values->genericSignature) {
1374
varInfoWithSigCount += 1;
1375
}
1376
values = variableInfoNextDo(&state);
1377
}
1378
attributesCount += 1;
1379
1380
if (0 != varInfoWithSigCount) {
1381
writeAttributeHeader((J9UTF8 *) &LOCAL_VARIABLE_TYPE_TABLE, sizeof(U_16) + (sizeof(U_16) * 5 * varInfoWithSigCount));
1382
writeU16(varInfoWithSigCount);
1383
1384
values = variableInfoStartDo(debugInfo, &state);
1385
1386
while(NULL != values) {
1387
if (NULL != values->genericSignature) {
1388
writeU16(values->startVisibility);
1389
writeU16(values->visibilityLength);
1390
writeU16(indexForUTF8(values->name));
1391
writeU16(indexForUTF8(values->genericSignature));
1392
writeU16(values->slotNumber);
1393
}
1394
values = variableInfoNextDo(&state);
1395
}
1396
attributesCount += 1;
1397
}
1398
}
1399
}
1400
1401
writeU16At(attributesCount, attributesCountAddr);
1402
1403
U_8 * end = _classFileCursor;
1404
writeU32At(U_32(end - start), attributeLenAddr);
1405
}
1406
1407
void
1408
ClassFileWriter::rewriteBytecode(J9ROMMethod * method, U_32 length, U_8 * code)
1409
{
1410
/*
1411
* This is derived from jvmtiGetBytecodes() in jvmtiMethod.c. It avoids CP index renumbering.
1412
* It should likely be replaced with a call to jvmtiGetBytecodes() once that function is fixed for CP unsplitting.
1413
*/
1414
U_32 index = 0;
1415
while (index < length) {
1416
U_8 bc = code[index];
1417
U_32 bytecodeSize = J9JavaInstructionSizeAndBranchActionTable[bc] & 7;
1418
1419
if (bytecodeSize == 0) {
1420
_buildResult = InvalidBytecodeSize;
1421
return;
1422
}
1423
1424
switch (bc) {
1425
case JBldc: /* do nothing */
1426
break;
1427
1428
case JBldc2dw: /* Fall-through */
1429
case JBldc2lw: {
1430
code[index] = CFR_BC_ldc2_w;
1431
U_16 cpIndex = *(U_16 *)(code + index + 1);
1432
U_32 * cpShapeDescription = J9ROMCLASS_CPSHAPEDESCRIPTION(_romClass);
1433
1434
if (J9CPTYPE_CONSTANT_DYNAMIC != J9_CP_TYPE(cpShapeDescription, cpIndex)) {
1435
/* Adjust index of double/long CP entry. Not necessary for Constant_Dynamic as
1436
* its already in the RAM CP while double/long are sorted to the end.
1437
*/
1438
cpIndex = cpIndex + (cpIndex - _romClass->ramConstantPoolCount);
1439
}
1440
writeU16At(cpIndex, code + index + 1);
1441
}
1442
break;
1443
1444
case JBnewdup:
1445
code[index] = JBnew;
1446
flip16bit(code + index + 1);
1447
break;
1448
1449
case JBinvokehandle:
1450
case JBinvokehandlegeneric:
1451
code[index] = CFR_BC_invokevirtual;
1452
flip16bit(code + index + 1);
1453
break;
1454
1455
case JBinvokedynamic: {
1456
UDATA i;
1457
U_16 callSiteIndex = *(U_16 *) (code + index + 1);
1458
J9SRP * callSiteData = (J9SRP *) J9ROMCLASS_CALLSITEDATA(_romClass);
1459
U_16 *bsmIndices = (U_16 *)(callSiteData + _romClass->callSiteCount);
1460
J9ROMNameAndSignature * nas = SRP_PTR_GET(callSiteData + callSiteIndex, J9ROMNameAndSignature *);
1461
U_16 bsmIndex = bsmIndices[callSiteIndex];
1462
1463
/* Scan the data to get the first entry which has same J9ROMNameAndSignature as the 'nas'.
1464
* See comments in ClassFileWriter::analyzeROMClass() for the explanation.
1465
*/
1466
for (i = 0; i < _romClass->callSiteCount; i++) {
1467
J9ROMNameAndSignature * tempNAS = SRP_PTR_GET(callSiteData + i, J9ROMNameAndSignature *);
1468
U_16 tempIndex = bsmIndices[i];
1469
if ((nas == tempNAS) && (bsmIndex == tempIndex)) {
1470
break;
1471
}
1472
}
1473
writeU16At(indexForInvokeDynamic(callSiteData + i), code + index + 1);
1474
index += 2; /* Advance past the extra nops */
1475
break;
1476
}
1477
1478
case JBinvokestaticsplit: {
1479
U_16 cpIndex = *(U_16 *) (code + index + 1);
1480
/* treat cpIndex as index into static split table */
1481
cpIndex = *(U_16 *)(J9ROMCLASS_STATICSPLITMETHODREFINDEXES(_romClass) + cpIndex);
1482
/* reset bytecode to non-split version */
1483
*(code + index) = CFR_BC_invokestatic;
1484
writeU16At(cpIndex, code + index + 1);
1485
break;
1486
}
1487
1488
case JBinvokespecialsplit: {
1489
U_16 cpIndex = *(U_16 *) (code + index + 1);
1490
/* treat cpIndex as index into special split table */
1491
cpIndex = *(U_16 *)(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(_romClass) + cpIndex);
1492
/* reset bytecode to non-split version */
1493
*(code + index) = CFR_BC_invokespecial;
1494
writeU16At(cpIndex, code + index + 1);
1495
break;
1496
}
1497
1498
case JBiloadw: /* Fall-through */
1499
case JBlloadw: /* Fall-through */
1500
case JBfloadw: /* Fall-through */
1501
case JBdloadw: /* Fall-through */
1502
case JBaloadw:
1503
bc = bc - JBiloadw + JBiload;
1504
readdWide:
1505
code[index + 0] = CFR_BC_wide;
1506
{
1507
U_8 tmp = code[index + 1];
1508
code[index + 1] = bc;
1509
#ifdef J9VM_ENV_LITTLE_ENDIAN
1510
/* code[index + 2] = code[index + 2]; */
1511
code[index + 3] = tmp;
1512
#else /* J9VM_ENV_LITTLE_ENDIAN */
1513
code[index + 3] = code[index + 2];
1514
code[index + 2] = tmp;
1515
#endif /* J9VM_ENV_LITTLE_ENDIAN */
1516
}
1517
break;
1518
1519
case JBistorew: /* Fall-through */
1520
case JBlstorew: /* Fall-through */
1521
case JBfstorew: /* Fall-through */
1522
case JBdstorew: /* Fall-through */
1523
case JBastorew:
1524
bc = bc - JBistorew + JBistore;
1525
goto readdWide;
1526
1527
case JBiincw:
1528
#ifdef J9VM_ENV_LITTLE_ENDIAN
1529
/* code[index + 4] = code[index + 4]; */
1530
code[index + 5] = code[index + 3];
1531
#else /* J9VM_ENV_LITTLE_ENDIAN */
1532
code[index + 5] = code[index + 4];
1533
code[index + 4] = code[index + 3];
1534
#endif /* J9VM_ENV_LITTLE_ENDIAN */
1535
bc = JBiinc;
1536
goto readdWide;
1537
1538
case JBgenericReturn: /* Fall-through */
1539
case JBreturnFromConstructor: /* Fall-through */
1540
case JBreturn0: /* Fall-through */
1541
case JBreturn1: /* Fall-through */
1542
case JBreturn2: /* Fall-through */
1543
case JBreturnB: /* Fall-through */
1544
case JBreturnC: /* Fall-through */
1545
case JBreturnS: /* Fall-through */
1546
case JBreturnZ: /* Fall-through */
1547
case JBsyncReturn0: /* Fall-through */
1548
case JBsyncReturn1: /* Fall-through */
1549
case JBsyncReturn2: {
1550
J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(method);
1551
U_8 * sigData = J9UTF8_DATA(signature);
1552
U_16 sigLength = J9UTF8_LENGTH(signature);
1553
1554
switch (sigData[sigLength - 2] == '[' ? ';' : sigData[sigLength - 1]) {
1555
case 'V':
1556
bc = CFR_BC_return;
1557
break;
1558
case 'J':
1559
bc = CFR_BC_lreturn;
1560
break;
1561
case 'D':
1562
bc = CFR_BC_dreturn;
1563
break;
1564
case 'F':
1565
bc = CFR_BC_freturn;
1566
break;
1567
case ';':
1568
bc = CFR_BC_areturn;
1569
break;
1570
default:
1571
bc = CFR_BC_ireturn;
1572
break;
1573
}
1574
code[index] = bc;
1575
break;
1576
}
1577
1578
case JBaload0getfield:
1579
code[index] = JBaload0;
1580
break;
1581
1582
case JBinvokeinterface2: {
1583
code[index + 0] = CFR_BC_invokeinterface;
1584
U_16 cpIndex = *(U_16 *)(code + index + 3);
1585
writeU16At(cpIndex, code + index + 1);
1586
code[index + 3] = computeArgsCount(cpIndex);
1587
code[index + 4] = 0;
1588
break;
1589
}
1590
1591
case JBlookupswitch: /* Fall-through */
1592
case JBtableswitch: {
1593
U_32 tempIndex = index + (4 - (index & 3));
1594
UDATA numEntries;
1595
1596
flip32bit(code + tempIndex);
1597
tempIndex += sizeof(U_32);
1598
1599
I_32 low = *((I_32 *) (code + tempIndex));
1600
1601
flip32bit(code + tempIndex);
1602
tempIndex += sizeof(U_32);
1603
1604
if (bc == JBtableswitch) {
1605
I_32 high = *((I_32 *) (code + tempIndex));
1606
1607
flip32bit(code + tempIndex);
1608
tempIndex += sizeof(U_32);
1609
numEntries = (UDATA) (high - low + 1);
1610
} else {
1611
numEntries = ((UDATA) low) * 2;
1612
}
1613
1614
while (0 != numEntries) {
1615
flip32bit(code + tempIndex);
1616
tempIndex += 4;
1617
numEntries -= 1;
1618
}
1619
1620
bytecodeSize = tempIndex - index;
1621
break;
1622
}
1623
1624
#ifdef J9VM_ENV_LITTLE_ENDIAN
1625
case JBgotow:
1626
flip32bit(code + index + 1);
1627
break;
1628
1629
case JBiinc:
1630
/* Size is 3 - avoid the default endian flip case */
1631
break;
1632
1633
default:
1634
/* Any bytecode of size 3 or more which does not have a single word parm first must be added to the switch */
1635
if (bytecodeSize >= 3) {
1636
flip16bit(code + index + 1);
1637
}
1638
break;
1639
#endif /* J9VM_ENV_LITTLE_ENDIAN */
1640
}
1641
1642
index += bytecodeSize;
1643
}
1644
}
1645
1646
void
1647
ClassFileWriter::writeVerificationTypeInfo(U_16 count, U_8 ** typeInfo)
1648
{
1649
U_8 * cursor = *typeInfo;
1650
1651
for (U_16 i = 0; i < count; i++) {
1652
U_8 tag;
1653
NEXT_U8(tag, cursor);
1654
1655
switch(tag) {
1656
case CFR_STACKMAP_TYPE_BYTE_ARRAY:
1657
case CFR_STACKMAP_TYPE_BOOL_ARRAY:
1658
case CFR_STACKMAP_TYPE_CHAR_ARRAY:
1659
case CFR_STACKMAP_TYPE_DOUBLE_ARRAY:
1660
case CFR_STACKMAP_TYPE_FLOAT_ARRAY:
1661
case CFR_STACKMAP_TYPE_INT_ARRAY:
1662
case CFR_STACKMAP_TYPE_LONG_ARRAY:
1663
case CFR_STACKMAP_TYPE_SHORT_ARRAY: {
1664
/* convert primitive array tag to corresponding class index in constant pool */
1665
U_8 typeInfoTagToPrimitiveArrayCharMap[] = { 'I', 'F', 'D', 'J', 'S', 'B', 'C', 'Z' };
1666
U_8 primitiveChar = typeInfoTagToPrimitiveArrayCharMap[tag - CFR_STACKMAP_TYPE_INT_ARRAY];
1667
/* An array cannot have more than 255 dimensions as per VM spec */
1668
U_8 classUTF8[2 + 255 + 1]; /* represents J9UTF8 for primitive class (size = length + arity + primitiveChar) */
1669
U_16 arity;
1670
1671
NEXT_U16(arity, cursor);
1672
arity += 1; /* actual arity is one more than stored in stack map table */
1673
*(U_16 *)classUTF8 = arity + 1; /* store UTF8 length = arity + one char for primitive type */
1674
memset((void *)(classUTF8 + 2), '[', arity);
1675
*(classUTF8 + 2 + arity) = primitiveChar;
1676
1677
/* There is no need to double-check the primitive type the in the constant pool in the case
1678
* of boolean arrays because CFR_STACKMAP_TYPE_BYTE_ARRAY is only used for byte arrays and
1679
* CFR_STACKMAP_TYPE_BOOL_ARRAY is used to represent boolean arrays.
1680
*/
1681
1682
writeU8(CFR_STACKMAP_TYPE_OBJECT);
1683
writeU16(indexForClass((J9UTF8 *)classUTF8));
1684
break;
1685
}
1686
1687
case CFR_STACKMAP_TYPE_OBJECT:
1688
case CFR_STACKMAP_TYPE_NEW_OBJECT: {
1689
U_16 data;
1690
NEXT_U16(data, cursor);
1691
1692
writeU8(tag);
1693
writeU16(data);
1694
break;
1695
}
1696
1697
default:
1698
writeU8(tag);
1699
break;
1700
}
1701
}
1702
1703
*typeInfo = cursor;
1704
}
1705
1706
void
1707
ClassFileWriter::writeStackMapTableAttribute(J9ROMMethod * romMethod)
1708
{
1709
U_16 numEntries = 0;
1710
U_8 * stackMap = (U_8 *)stackMapFromROMMethod(romMethod);
1711
1712
writeU16(indexForUTF8((J9UTF8 *) &STACK_MAP_TABLE));
1713
U_8 * attributeLenAddr = _classFileCursor;
1714
writeU32(0);
1715
1716
stackMap += sizeof(U_32); /* skip length */
1717
1718
U_8 * start = _classFileCursor;
1719
1720
NEXT_U16(numEntries, stackMap);
1721
writeU16(numEntries);
1722
1723
for (U_16 i = 0; i < numEntries; i++) {
1724
U_8 frameType;
1725
1726
NEXT_U8(frameType, stackMap);
1727
writeU8(frameType);
1728
1729
if (CFR_STACKMAP_SAME_LOCALS_1_STACK > frameType) { /* 0..63 */
1730
/* SAME frame - no extra data */
1731
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_END > frameType) { /* 64..127 */
1732
/*
1733
* SAME_LOCALS_1_STACK {
1734
* TypeInfo stackItems[1]
1735
* };
1736
*/
1737
writeVerificationTypeInfo(1, &stackMap);
1738
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED > frameType) { /* 128..246 */
1739
/* Reserved frame types - no extra data */
1740
Trc_BCU_Assert_ShouldNeverHappen();
1741
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED == frameType) { /* 247 */
1742
/*
1743
* SAME_LOCALS_1_STACK_EXTENDED {
1744
* U_16 offsetDelta
1745
* TypeInfo stackItems[1]
1746
* };
1747
*/
1748
U_16 offsetDelta;
1749
NEXT_U16(offsetDelta, stackMap);
1750
writeU16(offsetDelta);
1751
writeVerificationTypeInfo(1, &stackMap);
1752
} else if (CFR_STACKMAP_SAME_EXTENDED > frameType) { /* 248..250 */
1753
/*
1754
* CHOP {
1755
* U_16 offsetDelta
1756
* };
1757
*/
1758
U_16 offsetDelta;
1759
NEXT_U16(offsetDelta, stackMap);
1760
writeU16(offsetDelta);
1761
} else if (CFR_STACKMAP_SAME_EXTENDED == frameType) { /* 251 */
1762
/*
1763
* SAME_EXTENDED {
1764
* U_16 offsetDelta
1765
* };
1766
*/
1767
U_16 offsetDelta;
1768
NEXT_U16(offsetDelta, stackMap);
1769
writeU16(offsetDelta);
1770
} else if (CFR_STACKMAP_FULL > frameType) { /* 252..254 */
1771
/*
1772
* APPEND {
1773
* U_16 offsetDelta
1774
* TypeInfo locals[frameType - CFR_STACKMAP_APPEND_BASE]
1775
* };
1776
*/
1777
U_16 offsetDelta;
1778
NEXT_U16(offsetDelta, stackMap);
1779
writeU16(offsetDelta);
1780
writeVerificationTypeInfo(frameType - CFR_STACKMAP_APPEND_BASE, &stackMap);
1781
} else if (CFR_STACKMAP_FULL == frameType) { /* 255 */
1782
/*
1783
* FULL {
1784
* U_16 offsetDelta
1785
* U_16 localsCount
1786
* TypeInfo locals[localsCount]
1787
* U_16 stackItemsCount
1788
* TypeInfo stackItems[stackItemsCount]
1789
* };
1790
*/
1791
U_16 offsetDelta;
1792
/* u2 offset delta */
1793
NEXT_U16(offsetDelta, stackMap);
1794
writeU16(offsetDelta);
1795
/* handle locals */
1796
/* u2 number of locals */
1797
U_16 localsCount;
1798
NEXT_U16(localsCount, stackMap);
1799
writeU16(localsCount);
1800
/* verification_type_info locals[number of locals] */
1801
writeVerificationTypeInfo(localsCount, &stackMap);
1802
1803
/* handle stack */
1804
/* u2 number of stack items */
1805
U_16 stackItemsCount;
1806
NEXT_U16(stackItemsCount, stackMap);
1807
writeU16(stackItemsCount);
1808
/* verification_type_info stack[number of stack items] */
1809
writeVerificationTypeInfo(stackItemsCount, &stackMap);
1810
}
1811
}
1812
1813
writeU32At((U_32)(_classFileCursor - start), attributeLenAddr);
1814
}
1815
1816
void
1817
ClassFileWriter::writeSignatureAttribute(J9UTF8 * genericSignature)
1818
{
1819
writeAttributeHeader((J9UTF8 *) &SIGNATURE, 2);
1820
writeU16(indexForUTF8(genericSignature));
1821
}
1822
1823
void
1824
ClassFileWriter::writeAnnotationElement(U_8 **annotationElement)
1825
{
1826
U_8 *cursor = *annotationElement;
1827
U_8 tag;
1828
1829
NEXT_U8(tag, cursor);
1830
writeU8(tag);
1831
1832
switch(tag) {
1833
case 'e': {
1834
U_16 typeNameIndex, constNameIndex;
1835
1836
NEXT_U16(typeNameIndex, cursor);
1837
writeU16(typeNameIndex);
1838
NEXT_U16(constNameIndex, cursor);
1839
writeU16(constNameIndex);
1840
}
1841
break;
1842
case 'c': {
1843
U_16 classInfoIndex;
1844
1845
NEXT_U16(classInfoIndex, cursor);
1846
writeU16(classInfoIndex);
1847
}
1848
break;
1849
case '@':
1850
writeAnnotation(&cursor);
1851
break;
1852
case '[': {
1853
U_16 numValues;
1854
1855
NEXT_U16(numValues, cursor);
1856
writeU16(numValues);
1857
for (U_16 i = 0; i < numValues; i++) {
1858
writeAnnotationElement(&cursor);
1859
}
1860
}
1861
break;
1862
default: {
1863
U_16 constValueIndex;
1864
1865
NEXT_U16(constValueIndex, cursor);
1866
if (('D' == tag) || ('J' == tag)) {
1867
/* Adjust index of double/long CP entry */
1868
constValueIndex = constValueIndex + (constValueIndex - _romClass->ramConstantPoolCount);
1869
}
1870
writeU16(constValueIndex);
1871
}
1872
break;
1873
}
1874
*annotationElement = cursor;
1875
}
1876
1877
void
1878
ClassFileWriter::writeAnnotation(U_8 **annotation)
1879
{
1880
U_8 *cursor = *annotation;
1881
U_16 typeIndex;
1882
1883
NEXT_U16(typeIndex, cursor);
1884
writeU16(typeIndex);
1885
1886
U_16 numElements;
1887
NEXT_U16(numElements, cursor);
1888
writeU16(numElements);
1889
1890
for (U_16 i = 0; i < numElements; i++) {
1891
U_16 elementNameIndex;
1892
1893
NEXT_U16(elementNameIndex, cursor);
1894
writeU16(elementNameIndex);
1895
writeAnnotationElement(&cursor);
1896
}
1897
*annotation = cursor;
1898
}
1899
1900
void
1901
ClassFileWriter::writeAnnotationsAttribute(U_32 * annotationsData)
1902
{
1903
writeAttributeHeader((J9UTF8 *) &RUNTIME_VISIBLE_ANNOTATIONS, *annotationsData);
1904
if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {
1905
U_8 *data = (U_8 *)(annotationsData + 1);
1906
U_16 numAnnotations;
1907
1908
NEXT_U16(numAnnotations, data);
1909
writeU16(numAnnotations);
1910
1911
for (U_16 i = 0; i < numAnnotations; i++) {
1912
writeAnnotation(&data);
1913
}
1914
} else {
1915
writeData(*annotationsData, annotationsData + 1);
1916
}
1917
}
1918
1919
void
1920
ClassFileWriter::writeParameterAnnotationsAttribute(U_32 *parameterAnnotationsData)
1921
{
1922
writeAttributeHeader((J9UTF8 *) &RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, *parameterAnnotationsData);
1923
if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {
1924
U_8 *data = (U_8 *)(parameterAnnotationsData + 1);
1925
U_8 numParameters;
1926
1927
NEXT_U8(numParameters, data);
1928
writeU8(numParameters);
1929
1930
for (U_8 i = 0; i < numParameters; i++) {
1931
U_16 numAnnotations;
1932
1933
NEXT_U16(numAnnotations, data);
1934
writeU16(numAnnotations);
1935
1936
for (U_16 i = 0; i < numAnnotations; i++) {
1937
writeAnnotation(&data);
1938
}
1939
}
1940
} else {
1941
writeData(*parameterAnnotationsData, parameterAnnotationsData + 1);
1942
}
1943
}
1944
1945
void
1946
ClassFileWriter::writeTypeAnnotationsAttribute(U_32 *typeAnnotationsData)
1947
{
1948
writeAttributeHeader((J9UTF8 *) &RUNTIME_VISIBLE_TYPE_ANNOTATIONS, *typeAnnotationsData);
1949
if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {
1950
U_8 *data = (U_8 *)(typeAnnotationsData + 1);
1951
U_16 numAnnotations;
1952
NEXT_U16(numAnnotations, data);
1953
writeU16(numAnnotations);
1954
if (CFR_TARGET_TYPE_ErrorInAttribute == *data) {
1955
writeData(*typeAnnotationsData, typeAnnotationsData + 1); /* dump out the raw bytes */
1956
} else {
1957
for (U_16 i = 0; i < numAnnotations; i++) {
1958
U_8 u8Data = 0;
1959
U_16 u16Data = 0;
1960
1961
U_8 targetType;
1962
NEXT_U8(targetType, data);
1963
writeU8(targetType);
1964
switch (targetType) {
1965
case CFR_TARGET_TYPE_TypeParameterGenericClass:
1966
case CFR_TARGET_TYPE_TypeParameterGenericMethod:
1967
NEXT_U8(u8Data, data); /* typeParameterIndex */
1968
writeU8(u8Data);
1969
break;
1970
1971
case CFR_TARGET_TYPE_TypeInExtends:
1972
NEXT_U16(u16Data, data);
1973
writeU16(u16Data); /* supertypeIndex */
1974
break;
1975
1976
case CFR_TARGET_TYPE_TypeInBoundOfGenericClass:
1977
case CFR_TARGET_TYPE_TypeInBoundOfGenericMethod:
1978
NEXT_U8(u8Data, data);
1979
writeU8(u8Data); /* typeParameterIndex */
1980
NEXT_U8(u8Data, data);
1981
writeU8(u8Data); /* boundIndex */
1982
break;
1983
1984
case CFR_TARGET_TYPE_TypeInFieldDecl:
1985
case CFR_TARGET_TYPE_ReturnType:
1986
case CFR_TARGET_TYPE_ReceiverType: /* empty_target */
1987
break;
1988
1989
case CFR_TARGET_TYPE_TypeInFormalParam:
1990
NEXT_U8(u8Data, data);
1991
writeU8(u8Data); /* formalParameterIndex */
1992
break;
1993
1994
case CFR_TARGET_TYPE_TypeInThrows:
1995
NEXT_U16(u16Data, data);
1996
writeU16(u16Data); /* throwsTypeIndex */
1997
break;
1998
1999
case CFR_TARGET_TYPE_TypeInLocalVar:
2000
case CFR_TARGET_TYPE_TypeInResourceVar: {
2001
U_16 tableLength = 0;
2002
NEXT_U16(tableLength, data);
2003
writeU16(tableLength);
2004
for (U_32 ti=0; ti < tableLength; ++ti) {
2005
NEXT_U16(u16Data, data);
2006
writeU16(u16Data); /* startPC */
2007
NEXT_U16(u16Data, data);
2008
writeU16(u16Data); /* length */
2009
NEXT_U16(u16Data, data);
2010
writeU16(u16Data); /* index */
2011
}
2012
}
2013
break;
2014
case CFR_TARGET_TYPE_TypeInExceptionParam:
2015
NEXT_U16(u16Data, data);
2016
writeU16(u16Data); /* exceptiontableIndex */
2017
break;
2018
2019
case CFR_TARGET_TYPE_TypeInInstanceof:
2020
case CFR_TARGET_TYPE_TypeInNew:
2021
case CFR_TARGET_TYPE_TypeInMethodrefNew:
2022
case CFR_TARGET_TYPE_TypeInMethodrefIdentifier:
2023
NEXT_U16(u16Data, data);
2024
writeU16(u16Data); /* offset */
2025
break;
2026
2027
case CFR_TARGET_TYPE_TypeInCast:
2028
case CFR_TARGET_TYPE_TypeForGenericConstructorInNew:
2029
case CFR_TARGET_TYPE_TypeForGenericMethodInvocation:
2030
case CFR_TARGET_TYPE_TypeForGenericConstructorInMethodRef:
2031
case CFR_TARGET_TYPE_TypeForGenericMethodInvocationInMethodRef:
2032
NEXT_U16(u16Data, data);
2033
writeU16(u16Data); /* offset */
2034
NEXT_U8(u8Data, data);
2035
writeU8(u8Data); /* typeArgumentIndex */
2036
break;
2037
2038
default:
2039
break;
2040
}
2041
U_8 pathLength;
2042
NEXT_U8(pathLength, data);
2043
writeU8(pathLength);
2044
for (U_8 pathIndex = 0; pathIndex < pathLength; ++pathIndex) {
2045
NEXT_U8(u8Data, data);
2046
writeU8(u8Data); /* typePathKind */
2047
NEXT_U8(u8Data, data);
2048
writeU8(u8Data); /* typeArgumentIndex */
2049
}
2050
writeAnnotation(&data);
2051
}
2052
}
2053
} else {
2054
writeData(*typeAnnotationsData, typeAnnotationsData + 1);
2055
}
2056
}
2057
2058
2059
void
2060
ClassFileWriter::writeAnnotationDefaultAttribute(U_32 *annotationsDefaultData)
2061
{
2062
writeAttributeHeader((J9UTF8 *) &ANNOTATION_DEFAULT, *annotationsDefaultData);
2063
if (J9ROMCLASS_ANNOTATION_REFERS_DOUBLE_SLOT_ENTRY(_romClass)) {
2064
U_8 *cursor = (U_8 *)(annotationsDefaultData+1);
2065
2066
writeAnnotationElement(&cursor);
2067
} else {
2068
writeData(*annotationsDefaultData, annotationsDefaultData + 1);
2069
}
2070
}
2071
2072
void
2073
ClassFileWriter::writeAttributeHeader(J9UTF8 * name, U_32 length)
2074
{
2075
writeU16(indexForUTF8(name));
2076
writeU32(length);
2077
}
2078
2079