Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/bcutil/ClassFileOracle.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2001, 2022 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
/*
23
* ClassFileOracle.cpp
24
*/
25
26
#include "ClassFileOracle.hpp"
27
#include "BufferManager.hpp"
28
#include "ConstantPoolMap.hpp"
29
#include "ROMClassCreationContext.hpp"
30
#include "ROMClassVerbosePhase.hpp"
31
32
33
#include "j9port.h"
34
#include "jbcmap.h"
35
#include "ut_j9bcu.h"
36
#include "util_api.h"
37
#include "j9protos.h"
38
39
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
40
#define VALUE_TYPES_MAJOR_VERSION 55
41
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
42
43
/* The array entries must be in same order as the enums in ClassFileOracle.hpp */
44
ClassFileOracle::KnownAnnotation ClassFileOracle::_knownAnnotations[] = {
45
#define FRAMEITERATORSKIP_SIGNATURE "Ljava/lang/invoke/MethodHandle$FrameIteratorSkip;"
46
{FRAMEITERATORSKIP_SIGNATURE, sizeof(FRAMEITERATORSKIP_SIGNATURE)},
47
#undef FRAMEITERATORSKIP_SIGNATURE
48
#define SUN_REFLECT_CALLERSENSITIVE_SIGNATURE "Lsun/reflect/CallerSensitive;"
49
{SUN_REFLECT_CALLERSENSITIVE_SIGNATURE, sizeof(SUN_REFLECT_CALLERSENSITIVE_SIGNATURE)},
50
#undef SUN_REFLECT_CALLERSENSITIVE_SIGNATURE
51
#define JDK_INTERNAL_REFLECT_CALLERSENSITIVE_SIGNATURE "Ljdk/internal/reflect/CallerSensitive;"
52
{JDK_INTERNAL_REFLECT_CALLERSENSITIVE_SIGNATURE, sizeof(JDK_INTERNAL_REFLECT_CALLERSENSITIVE_SIGNATURE)},
53
#undef JDK_INTERNAL_REFLECT_CALLERSENSITIVE_SIGNATURE
54
#if JAVA_SPEC_VERSION >= 18
55
#define JDK_INTERNAL_REFLECT_CALLERSENSITIVEADAPTER_SIGNATURE "Ljdk/internal/reflect/CallerSensitiveAdapter;"
56
{JDK_INTERNAL_REFLECT_CALLERSENSITIVEADAPTER_SIGNATURE, sizeof(JDK_INTERNAL_REFLECT_CALLERSENSITIVEADAPTER_SIGNATURE)},
57
#undef JDK_INTERNAL_REFLECT_CALLERSENSITIVEADAPTER_SIGNATURE
58
#endif /* JAVA_SPEC_VERSION >= 18 */
59
#define JAVA8_CONTENDED_SIGNATURE "Lsun/misc/Contended;" /* TODO remove this if VM does not support Java 8 */
60
{JAVA8_CONTENDED_SIGNATURE, sizeof(JAVA8_CONTENDED_SIGNATURE)},
61
#undef JAVA8_CONTENDED_SIGNATURE
62
#define CONTENDED_SIGNATURE "Ljdk/internal/vm/annotation/Contended;"
63
{CONTENDED_SIGNATURE, sizeof(CONTENDED_SIGNATURE)},
64
#undef CONTENDED_SIGNATURE
65
{J9_UNMODIFIABLE_CLASS_ANNOTATION, sizeof(J9_UNMODIFIABLE_CLASS_ANNOTATION)},
66
#define VALUEBASED_SIGNATURE "Ljdk/internal/ValueBased;"
67
{VALUEBASED_SIGNATURE, sizeof(VALUEBASED_SIGNATURE)},
68
#undef VALUEBASED_SIGNATURE
69
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
70
#if JAVA_SPEC_VERSION >= 16
71
#define HIDDEN_SIGNATURE "Ljdk/internal/vm/annotation/Hidden;"
72
#else /* JAVA_SPEC_VERSION >= 16 */
73
#define HIDDEN_SIGNATURE "Ljava/lang/invoke/LambdaForm$Hidden;"
74
#endif /* JAVA_SPEC_VERSION >= 16 */
75
{HIDDEN_SIGNATURE, sizeof(HIDDEN_SIGNATURE)},
76
#undef HIDDEN_SIGNATURE
77
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
78
#if JAVA_SPEC_VERSION >= 16
79
#define SCOPED_SIGNATURE "Ljdk/internal/misc/ScopedMemoryAccess$Scoped;"
80
{SCOPED_SIGNATURE, sizeof(SCOPED_SIGNATURE)},
81
#undef SCOPED_SIGNATURE
82
#endif /* JAVA_SPEC_VERSION >= 16 */
83
{0, 0}
84
};
85
86
bool
87
ClassFileOracle::containsKnownAnnotation(UDATA knownAnnotationSet, UDATA knownAnnotation)
88
{
89
UDATA knownAnnotationBit = (UDATA) 1 << knownAnnotation;
90
return (knownAnnotationSet & knownAnnotationBit) == knownAnnotationBit;
91
}
92
93
UDATA
94
ClassFileOracle::addAnnotationBit(UDATA annotationBits, UDATA knownAnnotation)
95
{
96
UDATA knownAnnotationBit = (UDATA) 1 << knownAnnotation;
97
return annotationBits |= knownAnnotationBit;
98
}
99
100
U_16
101
ClassFileOracle::LocalVariablesIterator::getGenericSignatureIndex()
102
{
103
Trc_BCU_Assert_NotEquals(NULL, _localVariableTable);
104
Trc_BCU_Assert_NotEquals(NULL, _localVariablesInfo[_index].localVariableTypeTableAttribute);
105
106
/* If the localVariableTable and localVariableTypeTable are in the same order, return the signatureIndex */
107
J9CfrLocalVariableTypeTableEntry* localVariableTypeTable = _localVariablesInfo[_index].localVariableTypeTableAttribute->localVariableTypeTable;
108
if ((_localVariableTableIndex < _localVariablesInfo[_index].localVariableTypeTableAttribute->localVariableTypeTableLength)
109
&& (_localVariableTable[_localVariableTableIndex].index == localVariableTypeTable[_localVariableTableIndex].index)
110
&& (_localVariableTable[_localVariableTableIndex].startPC == localVariableTypeTable[_localVariableTableIndex].startPC)
111
&& (_localVariableTable[_localVariableTableIndex].length == localVariableTypeTable[_localVariableTableIndex].length)) {
112
return localVariableTypeTable[_localVariableTableIndex].signatureIndex;
113
}
114
115
/* Scan for matching localVariableTypeTable entry */
116
for (U_16 localVariableTypeTableIndex = 0;
117
localVariableTypeTableIndex < _localVariablesInfo[_index].localVariableTypeTableAttribute->localVariableTypeTableLength;
118
++localVariableTypeTableIndex) {
119
if ((_localVariableTable[_localVariableTableIndex].index == localVariableTypeTable[localVariableTypeTableIndex].index)
120
&& (_localVariableTable[_localVariableTableIndex].startPC == localVariableTypeTable[localVariableTypeTableIndex].startPC)
121
&& (_localVariableTable[_localVariableTableIndex].length == localVariableTypeTable[localVariableTypeTableIndex].length)) {
122
return localVariableTypeTable[localVariableTypeTableIndex].signatureIndex;
123
}
124
}
125
126
Trc_BCU_Assert_ShouldNeverHappen();
127
return 0;
128
}
129
130
bool
131
ClassFileOracle::LocalVariablesIterator::hasGenericSignature()
132
{
133
Trc_BCU_Assert_NotEquals(NULL, _localVariableTable);
134
135
/* Check if the current local variable isn't generic */
136
if (NULL == _localVariablesInfo[_index].localVariableTypeTableAttribute) {
137
return false;
138
}
139
140
/* Check if the localVariableTable and localVariableTypeTable are in the same order */
141
J9CfrLocalVariableTypeTableEntry* localVariableTypeTable = _localVariablesInfo[_index].localVariableTypeTableAttribute->localVariableTypeTable;
142
if ((_localVariableTableIndex < _localVariablesInfo[_index].localVariableTypeTableAttribute->localVariableTypeTableLength)
143
&& (_localVariableTable[_localVariableTableIndex].index == localVariableTypeTable[_localVariableTableIndex].index)
144
&& (_localVariableTable[_localVariableTableIndex].startPC == localVariableTypeTable[_localVariableTableIndex].startPC)
145
&& (_localVariableTable[_localVariableTableIndex].length == localVariableTypeTable[_localVariableTableIndex].length)) {
146
return true;
147
}
148
149
/* Scan for matching localVariableTypeTable entry */
150
for (U_16 localVariableTypeTableIndex = 0;
151
localVariableTypeTableIndex < _localVariablesInfo[_index].localVariableTypeTableAttribute->localVariableTypeTableLength;
152
++localVariableTypeTableIndex) {
153
if ((_localVariableTable[_localVariableTableIndex].index == localVariableTypeTable[localVariableTypeTableIndex].index)
154
&& (_localVariableTable[_localVariableTableIndex].startPC == localVariableTypeTable[localVariableTypeTableIndex].startPC)
155
&& (_localVariableTable[_localVariableTableIndex].length == localVariableTypeTable[localVariableTypeTableIndex].length)) {
156
return true;
157
}
158
}
159
return false;
160
}
161
162
ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *classFile, ConstantPoolMap *constantPoolMap,
163
U_8 * verifyExcludeAttribute, U_8 * romBuilderClassFileBuffer, ROMClassCreationContext *context) :
164
_buildResult(OK),
165
_bufferManager(bufferManager),
166
_classFile(classFile),
167
_constantPoolMap(constantPoolMap),
168
_verifyExcludeAttribute(verifyExcludeAttribute),
169
_romBuilderClassFileBuffer(romBuilderClassFileBuffer),
170
_context(context),
171
_singleScalarStaticCount(0),
172
_objectStaticCount(0),
173
_doubleScalarStaticCount(0),
174
_memberAccessFlags(0),
175
_innerClassCount(0),
176
_enclosedInnerClassCount(0),
177
#if JAVA_SPEC_VERSION >= 11
178
_nestMembersCount(0),
179
_nestHost(0),
180
#endif /* JAVA_SPEC_VERSION >= 11 */
181
_maxBranchCount(1), /* This is required to support buffer size calculations for stackmap support code */
182
_outerClassNameIndex(0),
183
_simpleNameIndex(0),
184
_hasEmptyFinalizeMethod(false),
185
_hasFinalFields(false),
186
_hasNonStaticNonAbstractMethods(false),
187
_hasFinalizeMethod(false),
188
_isCloneable(false),
189
_isSerializable(false),
190
_isSynthetic(false),
191
_hasVerifyExcludeAttribute(false),
192
_hasFrameIteratorSkipAnnotation(false),
193
_hasClinit(false),
194
_annotationRefersDoubleSlotEntry(false),
195
_fieldsInfo(NULL),
196
_methodsInfo(NULL),
197
_recordComponentsInfo(NULL),
198
_genericSignature(NULL),
199
_enclosingMethod(NULL),
200
_sourceFile(NULL),
201
_sourceDebugExtension(NULL),
202
_annotationsAttribute(NULL),
203
_typeAnnotationsAttribute(NULL),
204
_innerClasses(NULL),
205
_bootstrapMethodsAttribute(NULL),
206
#if JAVA_SPEC_VERSION >= 11
207
_nestMembers(NULL),
208
#endif /* JAVA_SPEC_VERSION >= 11 */
209
_isClassContended(false),
210
_isClassUnmodifiable(context->isClassUnmodifiable()),
211
_isInnerClass(false),
212
_needsStaticConstantInit(false),
213
_isRecord(false),
214
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
215
_hasIdentityInterface(false),
216
_isIdentityInterfaceNeeded(false),
217
_isValueType(false),
218
_hasNonStaticSynchronizedMethod(false),
219
_hasNonStaticFields(false),
220
_hasNonEmptyConstructor(false),
221
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
222
_recordComponentCount(0),
223
_permittedSubclassesAttribute(NULL),
224
_isSealed(false),
225
_isClassValueBased(false)
226
{
227
Trc_BCU_Assert_NotEquals( classFile, NULL );
228
229
ROMClassVerbosePhase v(_context, ClassFileAnalysis, &_buildResult);
230
231
232
/* Quick check against expected class name */
233
_buildResult = _context->checkClassName(getUTF8Data(getClassNameIndex()), getUTF8Length(getClassNameIndex()));
234
if (OK != _buildResult) {
235
return;
236
}
237
238
_fieldsInfo = (FieldInfo *) _bufferManager->alloc(getFieldsCount() * sizeof(FieldInfo));
239
_methodsInfo = (MethodInfo *) _bufferManager->alloc(getMethodsCount() * sizeof(MethodInfo));
240
if ( (NULL == _fieldsInfo) || (NULL == _methodsInfo) ) {
241
Trc_BCU_ClassFileOracle_OutOfMemory((U_32)getUTF8Length(getClassNameIndex()), getUTF8Data(getClassNameIndex()));
242
_buildResult = OutOfMemory;
243
return;
244
}
245
memset(_fieldsInfo, 0, getFieldsCount() * sizeof(FieldInfo));
246
memset(_methodsInfo, 0, getMethodsCount() * sizeof(MethodInfo));
247
248
_constantPoolMap->setClassFileOracleAndInitialize(this);
249
if ( !constantPoolMap->isOK() ) {
250
_buildResult = _constantPoolMap->getBuildResult();
251
return;
252
}
253
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
254
if (J9_ARE_ALL_BITS_SET(_classFile->accessFlags, CFR_ACC_VALUE_TYPE)
255
|| J9_ARE_NO_BITS_SET(_classFile->accessFlags, CFR_ACC_ABSTRACT | CFR_ACC_INTERFACE)
256
) {
257
/**
258
* We care about whether there is a non-empty constructor only for non-value type abstract classes.
259
* Simply set _hasNonEmptyConstructor to true for value types, or concrete classes.
260
*/
261
_hasNonEmptyConstructor = true;
262
}
263
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
264
265
/* analyze class file */
266
267
if (OK == _buildResult) {
268
walkHeader();
269
}
270
if (OK == _buildResult) {
271
walkAttributes();
272
}
273
274
if (_context->isClassHidden()) {
275
checkHiddenClass();
276
}
277
278
if (OK == _buildResult) {
279
walkInterfaces();
280
}
281
282
283
if (OK == _buildResult) {
284
walkMethods();
285
}
286
287
if (OK == _buildResult) {
288
walkFields();
289
}
290
291
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
292
if (OK == _buildResult) {
293
checkAndRecordIsIdentityInterfaceNeeded();
294
}
295
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
296
if (OK == _buildResult) {
297
_constantPoolMap->computeConstantPoolMapAndSizes();
298
if (!constantPoolMap->isOK()) {
299
_buildResult = _constantPoolMap->getBuildResult();
300
} else {
301
#if defined(J9VM_OPT_METHOD_HANDLE)
302
/* computeConstantPoolMapAndSizes must complete successfully before calling findVarHandleMethodRefs */
303
_constantPoolMap->findVarHandleMethodRefs();
304
if (!constantPoolMap->isOK()) {
305
_buildResult = _constantPoolMap->getBuildResult();
306
}
307
#endif /* defined(J9VM_OPT_METHOD_HANDLE) */
308
}
309
}
310
311
}
312
313
ClassFileOracle::~ClassFileOracle()
314
{
315
if (NULL != _methodsInfo && OutOfMemory != _buildResult) {
316
for (U_16 methodIndex = 0; methodIndex < _classFile->methodsCount; ++methodIndex) {
317
_bufferManager->free(_methodsInfo[methodIndex].stackMapFramesInfo);
318
_bufferManager->free(_methodsInfo[methodIndex].localVariablesInfo);
319
_bufferManager->free(_methodsInfo[methodIndex].lineNumbersInfoCompressed);
320
}
321
}
322
_bufferManager->free(_methodsInfo);
323
_bufferManager->free(_fieldsInfo);
324
325
}
326
327
void
328
ClassFileOracle::walkHeader()
329
{
330
ROMClassVerbosePhase v(_context, ClassFileHeaderAnalysis);
331
332
markConstantUTF8AsReferenced(getClassNameIndex());
333
U_16 superClassNameIndex = getSuperClassNameIndex();
334
if (0 != superClassNameIndex) { /* java/lang/Object has no super class */
335
markConstantUTF8AsReferenced(superClassNameIndex);
336
}
337
}
338
339
void
340
ClassFileOracle::walkFields()
341
{
342
ROMClassVerbosePhase v(_context, ClassFileFieldsAnalysis);
343
344
345
U_16 fieldsCount = getFieldsCount();
346
347
/* CMVC 197718 : After the first compliance offense is detected, if we do not stop, annotations on subsequent fields
348
* will not be parsed, resulting in all subsequent valid fields to be noted as not having proper @Length annotation, hence overwriting
349
* the good error message. Checking (OK == _buildResult) in for-loop condition achieves the desired error handling behavior.
350
*/
351
for (U_16 fieldIndex = 0; (OK == _buildResult) && (fieldIndex < fieldsCount); fieldIndex++) {
352
J9CfrField *field = &_classFile->fields[fieldIndex];
353
U_8 fieldChar = _classFile->constantPool[field->descriptorIndex].bytes[0];
354
bool isStatic = (0 != (field->accessFlags & CFR_ACC_STATIC));
355
356
357
markConstantUTF8AsReferenced(field->nameIndex);
358
markConstantUTF8AsReferenced(field->descriptorIndex);
359
360
if (isStatic) {
361
if (NULL != field->constantValueAttribute) {
362
_needsStaticConstantInit = true;
363
U_16 constantValueIndex = field->constantValueAttribute->constantValueIndex;
364
if (CFR_CONSTANT_String == _classFile->constantPool[constantValueIndex].tag) {
365
markStringAsReferenced(constantValueIndex);
366
}
367
}
368
if ((IS_REF_OR_VAL_SIGNATURE(fieldChar))
369
|| ('[' == fieldChar)
370
) {
371
_objectStaticCount++;
372
} else if (('D' == fieldChar) || ('J' == fieldChar)) {
373
_doubleScalarStaticCount++;
374
} else {
375
_singleScalarStaticCount++;
376
}
377
} else {
378
if (0 != (field->accessFlags & CFR_ACC_FINAL)) {
379
/* if the class has any final instance fields, mark it so that we can generate
380
* the appropriate memory barriers when its constructors run. See
381
* JBreturnFromConstructor
382
*/
383
_hasFinalFields = true;
384
}
385
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
386
_hasNonStaticFields = true;
387
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
388
}
389
390
for (U_16 attributeIndex = 0; (OK == _buildResult) && (attributeIndex < field->attributesCount); ++attributeIndex) {
391
J9CfrAttribute * attrib = field->attributes[attributeIndex];
392
switch (attrib->tag) {
393
case CFR_ATTRIBUTE_Signature: {
394
J9CfrAttributeSignature *signature = (J9CfrAttributeSignature *) attrib;
395
markConstantUTF8AsReferenced(signature->signatureIndex);
396
_fieldsInfo[fieldIndex].hasGenericSignature = true;
397
_fieldsInfo[fieldIndex].genericSignatureIndex = signature->signatureIndex;
398
break;
399
}
400
case CFR_ATTRIBUTE_Synthetic:
401
_fieldsInfo[fieldIndex].isSynthetic = true;
402
break;
403
case CFR_ATTRIBUTE_RuntimeVisibleAnnotations: {
404
J9CfrAttributeRuntimeVisibleAnnotations *attribAnnotations = (J9CfrAttributeRuntimeVisibleAnnotations *)attrib;
405
UDATA knownAnnotations = 0;
406
if ((NULL != _context->javaVM()) && (J9_ARE_ALL_BITS_SET(_context->javaVM()->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_ALLOW_CONTENDED_FIELDS)) &&
407
(_context->isBootstrapLoader() || (J9_ARE_ALL_BITS_SET(_context->javaVM()->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_ALLOW_APPLICATION_CONTENDED_FIELDS)))) {
408
knownAnnotations = addAnnotationBit(knownAnnotations, CONTENDED_ANNOTATION);
409
knownAnnotations = addAnnotationBit(knownAnnotations, JAVA8_CONTENDED_ANNOTATION);
410
}
411
if (0 == attribAnnotations->rawDataLength) {
412
UDATA foundAnnotations = walkAnnotations(attribAnnotations->numberOfAnnotations, attribAnnotations->annotations, knownAnnotations);
413
414
415
if (containsKnownAnnotation(foundAnnotations, CONTENDED_ANNOTATION) || containsKnownAnnotation(foundAnnotations, JAVA8_CONTENDED_ANNOTATION)) {
416
_fieldsInfo[fieldIndex].isFieldContended = true;
417
}
418
}
419
_fieldsInfo[fieldIndex].annotationsAttribute = attribAnnotations;
420
break;
421
}
422
case CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations: {
423
J9CfrAttributeRuntimeVisibleTypeAnnotations *typeAnnotations = (J9CfrAttributeRuntimeVisibleTypeAnnotations *)attrib;
424
if (0 == typeAnnotations->rawDataLength) { /* rawDataLength non-zero in case of error in the attribute */
425
walkTypeAnnotations(typeAnnotations->numberOfAnnotations, typeAnnotations->typeAnnotations);
426
}
427
_fieldsInfo[fieldIndex].typeAnnotationsAttribute = typeAnnotations;
428
break;
429
}
430
case CFR_ATTRIBUTE_ConstantValue:
431
/* Fall through */
432
case CFR_ATTRIBUTE_Deprecated:
433
/* Do nothing */
434
break;
435
default:
436
Trc_BCU_ClassFileOracle_walkFields_UnknownAttribute((U_32)attrib->tag, (U_32)getUTF8Length(attrib->nameIndex), getUTF8Data(attrib->nameIndex), attrib->length);
437
break;
438
}
439
}
440
441
}
442
443
}
444
445
void
446
ClassFileOracle::walkAttributes()
447
{
448
ROMClassVerbosePhase v(_context, ClassFileAttributesAnalysis);
449
450
for (U_16 attributeIndex = 0; attributeIndex < _classFile->attributesCount; attributeIndex++) {
451
J9CfrAttribute *attrib = _classFile->attributes[attributeIndex];
452
switch (attrib->tag) {
453
case CFR_ATTRIBUTE_InnerClasses: {
454
J9CfrAttributeInnerClasses *classes = (J9CfrAttributeInnerClasses*)attrib;
455
U_16 thisClassUTF8 = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, _classFile->thisClass);
456
for (U_16 classIndex = 0; classIndex < classes->numberOfClasses; classIndex++) {
457
J9CfrClassesEntry *entry = &(classes->classes[classIndex]);
458
U_16 outerClassUTF8 = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, entry->outerClassInfoIndex);
459
U_16 innerClassUTF8 = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, entry->innerClassInfoIndex);
460
461
/* In some cases, there might be two entries for the same class.
462
* But the UTF8 classname entry will be only one.
463
* Therefore comparing the UTF8 will find the matches, while comparing the class entries will not
464
*/
465
if (outerClassUTF8 == thisClassUTF8) {
466
/* Member class - mark the class' name. */
467
markClassNameAsReferenced(entry->innerClassInfoIndex);
468
_innerClassCount += 1;
469
} else if (innerClassUTF8 == thisClassUTF8) {
470
_isInnerClass = true;
471
_memberAccessFlags = entry->innerClassAccessFlags;
472
/* We are an inner class - a member? */
473
if (entry->outerClassInfoIndex != 0) {
474
/* We are a member class - mark the outer class name. */
475
markClassNameAsReferenced(entry->outerClassInfoIndex);
476
_outerClassNameIndex = outerClassUTF8;
477
}
478
if (entry->innerNameIndex != 0) {
479
/* mark the simple class name of member, local, and anonymous classes */
480
markConstantUTF8AsReferenced(entry->innerNameIndex);
481
_simpleNameIndex = entry->innerNameIndex;
482
}
483
} else {
484
/* Count all entries in the InnerClass attribute (except the inner class itself) so as
485
* to check the InnerClass attribute between the inner classes and the enclosing class.
486
* See getDeclaringClass() for details.
487
*/
488
markClassNameAsReferenced(entry->innerClassInfoIndex);
489
_enclosedInnerClassCount += 1;
490
}
491
}
492
Trc_BCU_Assert_Equals(NULL, _innerClasses);
493
_innerClasses = classes;
494
break;
495
}
496
case CFR_ATTRIBUTE_Signature:
497
_genericSignature = (J9CfrAttributeSignature *)attrib;
498
markConstantUTF8AsReferenced(_genericSignature->signatureIndex);
499
break;
500
case CFR_ATTRIBUTE_EnclosingMethod:
501
_enclosingMethod = (J9CfrAttributeEnclosingMethod *)attrib;
502
markClassAsReferenced(_enclosingMethod->classIndex);
503
if (0 != _enclosingMethod->methodIndex) {
504
markNameAndDescriptorAsReferenced(_enclosingMethod->methodIndex);
505
}
506
break;
507
case CFR_ATTRIBUTE_Synthetic:
508
_isSynthetic = true;
509
break;
510
case CFR_ATTRIBUTE_SourceFile:
511
if (!hasSourceFile() && _context->shouldPreserveSourceFileName()) {
512
_sourceFile = (J9CfrAttributeSourceFile *)attrib;
513
markConstantUTF8AsReferenced(_sourceFile->sourceFileIndex);
514
}
515
break;
516
case CFR_ATTRIBUTE_SourceDebugExtension:
517
if (!hasSourceDebugExtension()) {
518
_sourceDebugExtension = (J9CfrAttributeUnknown *)attrib;
519
}
520
break;
521
case CFR_ATTRIBUTE_RuntimeVisibleAnnotations: {
522
UDATA knownAnnotations = 0;
523
if ((NULL != _context->javaVM()) && J9_ARE_ALL_BITS_SET(_context->javaVM()->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_ALLOW_CONTENDED_FIELDS) &&
524
(_context->isBootstrapLoader() || (J9_ARE_ALL_BITS_SET(_context->javaVM()->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_ALLOW_APPLICATION_CONTENDED_FIELDS)))) {
525
knownAnnotations = addAnnotationBit(knownAnnotations, CONTENDED_ANNOTATION);
526
knownAnnotations = addAnnotationBit(knownAnnotations, JAVA8_CONTENDED_ANNOTATION);
527
}
528
knownAnnotations = addAnnotationBit(knownAnnotations, UNMODIFIABLE_ANNOTATION);
529
knownAnnotations = addAnnotationBit(knownAnnotations, VALUEBASED_ANNOTATION);
530
_annotationsAttribute = (J9CfrAttributeRuntimeVisibleAnnotations *)attrib;
531
if (0 == _annotationsAttribute->rawDataLength) {
532
UDATA foundAnnotations = walkAnnotations(_annotationsAttribute->numberOfAnnotations, _annotationsAttribute->annotations, knownAnnotations);
533
if (containsKnownAnnotation(foundAnnotations, CONTENDED_ANNOTATION) || containsKnownAnnotation(foundAnnotations, JAVA8_CONTENDED_ANNOTATION)) {
534
_isClassContended = true;
535
}
536
if (containsKnownAnnotation(foundAnnotations, UNMODIFIABLE_ANNOTATION)) {
537
_isClassUnmodifiable = true;
538
}
539
if (containsKnownAnnotation(foundAnnotations, VALUEBASED_ANNOTATION)) {
540
_isClassValueBased = true;
541
}
542
}
543
break;
544
}
545
case CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations: {
546
J9CfrAttributeRuntimeVisibleTypeAnnotations *typeAnnotations = (J9CfrAttributeRuntimeVisibleTypeAnnotations *)attrib;
547
if (0 == typeAnnotations->rawDataLength) { /* rawDataLength non-zero in case of error in the attribute */
548
walkTypeAnnotations(typeAnnotations->numberOfAnnotations, typeAnnotations->typeAnnotations);
549
}
550
_typeAnnotationsAttribute = typeAnnotations;
551
break;
552
}
553
case CFR_ATTRIBUTE_BootstrapMethods: {
554
_bootstrapMethodsAttribute = (J9CfrAttributeBootstrapMethods *)attrib;
555
for (U_16 methodIndex = 0; methodIndex < _bootstrapMethodsAttribute->numberOfBootstrapMethods; methodIndex++) {
556
J9CfrBootstrapMethod *bootstrapMethod = _bootstrapMethodsAttribute->bootstrapMethods + methodIndex;
557
markMethodHandleAsReferenced(bootstrapMethod->bootstrapMethodIndex);
558
for (U_16 argumentIndex = 0; argumentIndex < bootstrapMethod->numberOfBootstrapArguments; argumentIndex++) {
559
U_16 argCpIndex = bootstrapMethod->bootstrapArguments[argumentIndex];
560
markConstantBasedOnCpType(argCpIndex, false);
561
}
562
}
563
break;
564
}
565
case CFR_ATTRIBUTE_Record: {
566
_isRecord = true;
567
walkRecordComponents((J9CfrAttributeRecord *)attrib);
568
break;
569
}
570
case CFR_ATTRIBUTE_PermittedSubclasses: {
571
/* PermittedSubclasses verification is for Java version >= 15 */
572
if ((_classFile->majorVersion > 59)
573
|| ((59 == _classFile->majorVersion) && (65535 == _classFile->minorVersion))
574
) {
575
_isSealed = true;
576
_permittedSubclassesAttribute = (J9CfrAttributePermittedSubclasses *)attrib;
577
for (U_16 numberOfClasses = 0; numberOfClasses < _permittedSubclassesAttribute->numberOfClasses; numberOfClasses++) {
578
U_16 classCpIndex = _permittedSubclassesAttribute->classes[numberOfClasses];
579
markClassAsReferenced(classCpIndex);
580
}
581
}
582
break;
583
}
584
#if JAVA_SPEC_VERSION >= 11
585
case CFR_ATTRIBUTE_NestMembers:
586
/* ignore CFR_ATTRIBUTE_NestMembers for hidden classes, as the nest members never know the name of hidden classes */
587
if (!_context->isClassHidden()) {
588
_nestMembers = (J9CfrAttributeNestMembers *)attrib;
589
_nestMembersCount = _nestMembers->numberOfClasses;
590
/* The classRefs are never resolved & therefore do not need to
591
* be kept in the constant pool.
592
*/
593
for (U_16 i = 0; i < _nestMembersCount; i++) {
594
U_16 classNameIndex = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, _nestMembers->classes[i]);
595
markConstantUTF8AsReferenced(classNameIndex);
596
}
597
}
598
break;
599
600
case CFR_ATTRIBUTE_NestHost: {
601
/* Ignore CFR_ATTRIBUTE_NestHost for hidden classes, as the nest host of a hidden class is not decided by CFR_ATTRIBUTE_NestHost.
602
* The nesthost of a hidden class is its host class if ClassOption.NESTMATE is used or itself if ClassOption.NESTMATE is not used. */
603
if (!_context->isClassHidden()) {
604
U_16 hostClassIndex = ((J9CfrAttributeNestHost *)attrib)->hostClassIndex;
605
_nestHost = UTF8_INDEX_FROM_CLASS_INDEX(_classFile->constantPool, hostClassIndex);
606
markConstantUTF8AsReferenced(_nestHost);
607
}
608
break;
609
}
610
#endif /* JAVA_SPEC_VERSION >= 11 */
611
default:
612
Trc_BCU_ClassFileOracle_walkAttributes_UnknownAttribute((U_32)attrib->tag, (U_32)getUTF8Length(attrib->nameIndex), getUTF8Data(attrib->nameIndex), attrib->length);
613
break;
614
}
615
if (!_hasVerifyExcludeAttribute && (NULL != _verifyExcludeAttribute)) {
616
U_8 *found = (U_8 *) strstr((const char *)_verifyExcludeAttribute, (const char *)getUTF8Data(attrib->nameIndex));
617
if ((NULL != found)
618
&& ((found == _verifyExcludeAttribute) || (';' == (*(found - 1))))
619
&& (('\0' == found[getUTF8Length(attrib->nameIndex)]) || (';' == found[getUTF8Length(attrib->nameIndex)]))) {
620
_hasVerifyExcludeAttribute = true;
621
}
622
}
623
}
624
}
625
626
void
627
ClassFileOracle::checkHiddenClass()
628
{
629
ROMClassVerbosePhase v(_context, ClassFileAttributesAnalysis);
630
/* Hidden Class cannot be a record or enum. */
631
U_16 superClassNameIndex = getSuperClassNameIndex();
632
bool isEnum = false;
633
634
/**
635
* See test case jdk/java/lang/invoke/defineHiddenClass/BasicTest.emptyHiddenClass().
636
* A normal Enum cannot be defined as a hidden class. But an empty enum class that does not
637
* define constants of its type can still be defined as a hidden class.
638
* So when setting isEnum, add a check for field count.
639
*/
640
if (0 != superClassNameIndex) {
641
isEnum = J9_ARE_ALL_BITS_SET(_classFile->accessFlags, CFR_ACC_ENUM) &&
642
J9UTF8_DATA_EQUALS(getUTF8Data(superClassNameIndex), getUTF8Length(superClassNameIndex), "java/lang/Enum", LITERAL_STRLEN("java/lang/Enum")) &&
643
(getFieldsCount() > 0);
644
}
645
if (_isRecord || isEnum) {
646
PORT_ACCESS_FROM_PORT(_context->portLibrary());
647
char msg[] = "Hidden Class cannot be a record or enum";
648
UDATA len = sizeof(msg);
649
char *error = (char *) j9mem_allocate_memory(len, J9MEM_CATEGORY_CLASSES);
650
if (NULL != error) {
651
strcpy(error, msg);
652
_context->recordCFRError((U_8*)error);
653
}
654
_buildResult = InvalidClassType;
655
}
656
}
657
658
void
659
ClassFileOracle::walkRecordComponents(J9CfrAttributeRecord *attrib)
660
{
661
ROMClassVerbosePhase v(_context, ClassFileAttributesRecordAnalysis);
662
663
if (0 == attrib->numberOfRecordComponents) {
664
return;
665
}
666
667
_recordComponentCount = attrib->numberOfRecordComponents;
668
669
_recordComponentsInfo = (RecordComponentInfo *) _bufferManager->alloc(_recordComponentCount * sizeof(RecordComponentInfo));
670
if (NULL == _recordComponentsInfo) {
671
Trc_BCU_ClassFileOracle_OutOfMemory((U_32)getUTF8Length(getClassNameIndex()), getUTF8Data(getClassNameIndex()));
672
_buildResult = OutOfMemory;
673
return;
674
}
675
memset(_recordComponentsInfo, 0, _recordComponentCount * sizeof(RecordComponentInfo));
676
677
for (U_16 i = 0; i < _recordComponentCount; i++) {
678
J9CfrRecordComponent* recordComponent = &attrib->recordComponents[i];
679
680
markConstantUTF8AsReferenced(recordComponent->nameIndex);
681
_recordComponentsInfo[i].nameIndex = recordComponent->nameIndex;
682
markConstantUTF8AsReferenced(recordComponent->descriptorIndex);
683
_recordComponentsInfo[i].descriptorIndex = recordComponent->descriptorIndex;
684
685
/* track record component attributes */
686
for (U_16 j = 0; j < recordComponent->attributesCount; j++) {
687
J9CfrAttribute* recordComponentAttr = recordComponent->attributes[j];
688
switch(recordComponentAttr->tag) {
689
case CFR_ATTRIBUTE_Signature: {
690
J9CfrAttributeSignature *signature = (J9CfrAttributeSignature *) recordComponentAttr;
691
markConstantUTF8AsReferenced(signature->signatureIndex);
692
_recordComponentsInfo[i].hasGenericSignature = true;
693
_recordComponentsInfo[i].genericSignatureIndex = signature->signatureIndex;
694
break;
695
}
696
case CFR_ATTRIBUTE_RuntimeVisibleAnnotations: {
697
J9CfrAttributeRuntimeVisibleAnnotations *recordComponentAnnotations = (J9CfrAttributeRuntimeVisibleAnnotations *)recordComponentAttr;
698
if (0 == recordComponentAnnotations->rawDataLength) {
699
walkAnnotations(recordComponentAnnotations->numberOfAnnotations, recordComponentAnnotations->annotations, 0);
700
}
701
_recordComponentsInfo[i].annotationsAttribute = recordComponentAnnotations;
702
break;
703
}
704
case CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations: {
705
J9CfrAttributeRuntimeVisibleTypeAnnotations *recordComponentTypeAnnotations = (J9CfrAttributeRuntimeVisibleTypeAnnotations *)recordComponentAttr;
706
if (0 == recordComponentTypeAnnotations->rawDataLength) {
707
walkTypeAnnotations(recordComponentTypeAnnotations->numberOfAnnotations, recordComponentTypeAnnotations->typeAnnotations);
708
}
709
_recordComponentsInfo[i].typeAnnotationsAttribute = recordComponentTypeAnnotations;
710
break;
711
}
712
default:
713
Trc_BCU_ClassFileOracle_walkRecordComponents_UnknownAttribute((U_32)attrib->tag, (U_32)getUTF8Length(attrib->nameIndex), getUTF8Data(attrib->nameIndex), attrib->length);
714
break;
715
}
716
}
717
}
718
}
719
720
class ClassFileOracle::InterfaceVisitor : public ClassFileOracle::ConstantPoolIndexVisitor
721
{
722
public:
723
InterfaceVisitor(ClassFileOracle *classFileOracle, ConstantPoolMap *constantPoolMap) :
724
_classFileOracle(classFileOracle),
725
_constantPoolMap(constantPoolMap),
726
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
727
_wasIdentityInterfaceSeen(false),
728
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
729
_wasCloneableSeen(false),
730
_wasSerializableSeen(false)
731
{
732
}
733
734
void visitConstantPoolIndex(U_16 cpIndex)
735
{
736
_constantPoolMap->markConstantUTF8AsReferenced(cpIndex);
737
#define CLONEABLE_NAME "java/lang/Cloneable"
738
if( _classFileOracle->isUTF8AtIndexEqualToString(cpIndex, CLONEABLE_NAME, sizeof(CLONEABLE_NAME)) ) {
739
_wasCloneableSeen = true;
740
}
741
#undef CLONEABLE_NAME
742
743
#define SERIALIZABLE_NAME "java/io/Serializable"
744
if( _classFileOracle->isUTF8AtIndexEqualToString(cpIndex, SERIALIZABLE_NAME, sizeof(SERIALIZABLE_NAME)) ) {
745
_wasSerializableSeen = true;
746
}
747
#undef SERIALIZABLE_NAME
748
749
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
750
if( _classFileOracle->isUTF8AtIndexEqualToString(cpIndex, IDENTITY_OBJECT_NAME, sizeof(IDENTITY_OBJECT_NAME)) ) {
751
_wasIdentityInterfaceSeen = true;
752
}
753
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
754
}
755
756
bool wasCloneableSeen() const { return _wasCloneableSeen; }
757
bool wasSerializableSeen() const { return _wasSerializableSeen; }
758
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
759
bool wasIdentityInterfaceSeen() const { return _wasIdentityInterfaceSeen; }
760
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
761
762
private:
763
ClassFileOracle *_classFileOracle;
764
ConstantPoolMap *_constantPoolMap;
765
bool _wasCloneableSeen;
766
bool _wasSerializableSeen;
767
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
768
bool _wasIdentityInterfaceSeen;
769
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
770
};
771
772
void
773
ClassFileOracle::walkInterfaces()
774
{
775
ROMClassVerbosePhase v(_context, ClassFileInterfacesAnalysis);
776
777
InterfaceVisitor interfaceVisitor(this, _constantPoolMap);
778
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
779
interfacesDo(&interfaceVisitor, 0);
780
#else
781
interfacesDo(&interfaceVisitor);
782
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
783
_isCloneable = interfaceVisitor.wasCloneableSeen();
784
_isSerializable = interfaceVisitor.wasSerializableSeen();
785
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
786
if (J9_ARE_ALL_BITS_SET(_classFile->accessFlags, CFR_ACC_VALUE_TYPE)) {
787
_isValueType = true;
788
}
789
_hasIdentityInterface = interfaceVisitor.wasIdentityInterfaceSeen();
790
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
791
}
792
793
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
794
void
795
ClassFileOracle::checkAndRecordIsIdentityInterfaceNeeded()
796
{
797
if (isValueType()) {
798
if (_hasIdentityInterface
799
|| J9_ARE_ANY_BITS_SET(_classFile->accessFlags, CFR_ACC_ABSTRACT | CFR_ACC_INTERFACE)
800
|| _hasNonStaticSynchronizedMethod
801
) {
802
_buildResult = InvalidValueType;
803
}
804
} else {
805
if (!_hasIdentityInterface
806
&& (getSuperClassNameIndex() != 0) /* j.l.Object has no superClass */
807
) {
808
if (J9_ARE_NO_BITS_SET(_classFile->accessFlags, CFR_ACC_ABSTRACT | CFR_ACC_INTERFACE)) {
809
/* For concrete classes, IdentityInterface is needed. */
810
_isIdentityInterfaceNeeded = true;
811
} else {
812
/**
813
* For abstract classes, IdentityInterface is needed only when it has non-static fields,
814
* non-static synchronized method or non-empty constructor.
815
*/
816
if ((_hasNonStaticFields)
817
|| (_hasNonStaticSynchronizedMethod)
818
|| (_hasNonEmptyConstructor)
819
) {
820
_isIdentityInterfaceNeeded = true;
821
}
822
}
823
}
824
}
825
}
826
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
827
828
void
829
ClassFileOracle::walkMethods()
830
{
831
ROMClassVerbosePhase v(_context, ClassFileMethodsAnalysis);
832
833
U_16 methodsCount = getMethodsCount();
834
/* We check (OK == _buildResult) because walkMethodCodeAttribute() may fail to alloc the bytecode fixup table. */
835
for (U_16 methodIndex = 0; (methodIndex < methodsCount) && (OK == _buildResult); ++methodIndex) {
836
U_16 nameIndex = _classFile->methods[methodIndex].nameIndex;
837
U_16 descIndex = _classFile->methods[methodIndex].descriptorIndex;
838
markConstantUTF8AsReferenced(nameIndex);
839
markConstantUTF8AsReferenced(descIndex);
840
841
842
walkMethodAttributes(methodIndex);
843
844
_methodsInfo[methodIndex].modifiers |= _classFile->methods[methodIndex].accessFlags;
845
846
/* Is this an empty method, a getter, a forwarder or <clinit>?
847
* Note that <clinit> is checked after empty, so we will consider
848
* classes with an empty <clinit> to not have one.
849
*/
850
if (methodIsEmpty(methodIndex)) {
851
_methodsInfo[methodIndex].modifiers |= J9AccEmptyMethod;
852
} else if (methodIsForwarder(methodIndex)) {
853
_methodsInfo[methodIndex].modifiers |= J9AccForwarderMethod;
854
} else if (methodIsGetter(methodIndex)) {
855
_methodsInfo[methodIndex].modifiers |= J9AccGetterMethod;
856
} else if (methodIsClinit(methodIndex)) {
857
_hasClinit = true;
858
}
859
860
if (methodIsObjectConstructor(methodIndex)) {
861
_methodsInfo[methodIndex].modifiers |= J9AccMethodObjectConstructor;
862
}
863
864
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
865
if (!_hasNonEmptyConstructor) {
866
if (methodIsConstructor(methodIndex)) {
867
/* Do not record constructor forwarded to its superclass. */
868
if (J9_ARE_NO_BITS_SET(_methodsInfo[methodIndex].modifiers, J9AccForwarderMethod)) {
869
_hasNonEmptyConstructor = true;
870
}
871
}
872
}
873
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
874
875
/* does the method belong in vtables? */
876
if (methodIsVirtual(methodIndex)) {
877
_methodsInfo[methodIndex].modifiers |= J9AccMethodVTable;
878
}
879
880
/* Does this class contain non-static, non-abstract methods? */
881
if (!_hasNonStaticNonAbstractMethods) {
882
_hasNonStaticNonAbstractMethods = methodIsNonStaticNonAbstract(methodIndex);
883
}
884
885
/* Look for an instance selector whose name is finalize()V */
886
if (methodIsFinalize(methodIndex, 0 != (_methodsInfo[methodIndex].modifiers & J9AccForwarderMethod))) {
887
_hasFinalizeMethod = true;
888
/* If finalize() is empty, mark this class so it does not inherit CFR_ACC_FINALIZE_NEEDED from its superclass */
889
if (0 != (_methodsInfo[methodIndex].modifiers & J9AccEmptyMethod)) {
890
_hasEmptyFinalizeMethod = true;
891
}
892
}
893
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
894
if (!_hasNonStaticSynchronizedMethod) {
895
_hasNonStaticSynchronizedMethod = methodIsNonStaticSynchronized(methodIndex);
896
}
897
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
898
899
computeSendSlotCount(methodIndex);
900
901
walkMethodThrownExceptions(methodIndex);
902
walkMethodCodeAttribute(methodIndex);
903
walkMethodMethodParametersAttribute(methodIndex);
904
}
905
906
}
907
908
void
909
ClassFileOracle::walkMethodAttributes(U_16 methodIndex)
910
{
911
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileMethodAttributesAnalysis);
912
913
for (U_16 methodAttrIndex = 0; (methodAttrIndex < _classFile->methods[methodIndex].attributesCount) && (OK == _buildResult); ++methodAttrIndex){
914
J9CfrAttribute *attrib = _classFile->methods[methodIndex].attributes[methodAttrIndex];
915
switch (attrib->tag) {
916
case CFR_ATTRIBUTE_Synthetic:
917
_methodsInfo[methodIndex].modifiers |= J9AccSynthetic;
918
break;
919
case CFR_ATTRIBUTE_Signature: {
920
J9CfrAttributeSignature *signature = (J9CfrAttributeSignature *) attrib;
921
markConstantUTF8AsReferenced(signature->signatureIndex);
922
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasGenericSignature;
923
_methodsInfo[methodIndex].genericSignatureIndex = signature->signatureIndex;
924
break;
925
}
926
case CFR_ATTRIBUTE_RuntimeVisibleAnnotations: {
927
UDATA knownAnnotations = 0;
928
knownAnnotations = addAnnotationBit(knownAnnotations, FRAMEITERATORSKIP_ANNOTATION);
929
knownAnnotations = addAnnotationBit(knownAnnotations, SUN_REFLECT_CALLERSENSITIVE_ANNOTATION);
930
knownAnnotations = addAnnotationBit(knownAnnotations, JDK_INTERNAL_REFLECT_CALLERSENSITIVE_ANNOTATION);
931
#if JAVA_SPEC_VERSION >= 18
932
knownAnnotations = addAnnotationBit(knownAnnotations, JDK_INTERNAL_REFLECT_CALLERSENSITIVEADAPTER_ANNOTATION);
933
#endif /* JAVA_SPEC_VERSION >= 18*/
934
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
935
knownAnnotations = addAnnotationBit(knownAnnotations, HIDDEN_ANNOTATION);
936
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
937
#if JAVA_SPEC_VERSION >= 16
938
knownAnnotations = addAnnotationBit(knownAnnotations, SCOPED_ANNOTATION);
939
#endif /* JAVA_SPEC_VERSION >= 16*/
940
941
J9CfrAttributeRuntimeVisibleAnnotations *attribAnnotations = (J9CfrAttributeRuntimeVisibleAnnotations *)attrib;
942
if (0 == attribAnnotations->rawDataLength) { /* rawDataLength non-zero in case of error in the attribute */
943
UDATA foundAnnotations = walkAnnotations(attribAnnotations->numberOfAnnotations, attribAnnotations->annotations, knownAnnotations);
944
if (containsKnownAnnotation(foundAnnotations, SUN_REFLECT_CALLERSENSITIVE_ANNOTATION)
945
|| containsKnownAnnotation(foundAnnotations, JDK_INTERNAL_REFLECT_CALLERSENSITIVE_ANNOTATION)
946
#if JAVA_SPEC_VERSION >= 18
947
|| containsKnownAnnotation(foundAnnotations, JDK_INTERNAL_REFLECT_CALLERSENSITIVEADAPTER_ANNOTATION)
948
#endif /* JAVA_SPEC_VERSION >= 18*/
949
) {
950
_methodsInfo[methodIndex].modifiers |= J9AccMethodCallerSensitive;
951
}
952
if (_context->isBootstrapLoader()) {
953
/* Only check for FrameIteratorSkip annotation on bootstrap classes */
954
if (containsKnownAnnotation(foundAnnotations, FRAMEITERATORSKIP_ANNOTATION)) {
955
_methodsInfo[methodIndex].modifiers |= J9AccMethodFrameIteratorSkip;
956
}
957
}
958
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
959
if (containsKnownAnnotation(foundAnnotations, HIDDEN_ANNOTATION)) {
960
/* J9AccMethodFrameIteratorSkip is reused for Hidden Annotation when OpenJDK MH is enabled
961
* Hidden annotation is used by OpenJDK to tag LambdaForm generated methods which is similar
962
* to the thunkArchetype methods as they both need to be skipped during stackwalk when
963
* verifying the caller
964
*/
965
_methodsInfo[methodIndex].modifiers |= J9AccMethodFrameIteratorSkip;
966
}
967
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
968
#if JAVA_SPEC_VERSION >= 16
969
if (containsKnownAnnotation(foundAnnotations, SCOPED_ANNOTATION)) {
970
/* J9AccMethodHasExtendedModifiers in the modifiers is set when the ROM class is written */
971
_methodsInfo[methodIndex].extendedModifiers |= CFR_METHOD_EXT_HAS_SCOPED_ANNOTATION;
972
}
973
#endif /* JAVA_SPEC_VERSION >= 16*/
974
}
975
_methodsInfo[methodIndex].annotationsAttribute = attribAnnotations;
976
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasMethodAnnotations;
977
break;
978
}
979
case CFR_ATTRIBUTE_RuntimeVisibleParameterAnnotations: {
980
J9CfrAttributeRuntimeVisibleParameterAnnotations *attribParameterAnnotations = (J9CfrAttributeRuntimeVisibleParameterAnnotations *)attrib;
981
for (U_8 parameterAnnotationIndex = 0;
982
(parameterAnnotationIndex < attribParameterAnnotations->numberOfParameters) && (OK == _buildResult);
983
++parameterAnnotationIndex) {
984
walkAnnotations(
985
attribParameterAnnotations->parameterAnnotations[parameterAnnotationIndex].numberOfAnnotations,
986
attribParameterAnnotations->parameterAnnotations[parameterAnnotationIndex].annotations,
987
0);
988
}
989
_methodsInfo[methodIndex].parameterAnnotationsAttribute = attribParameterAnnotations;
990
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasParameterAnnotations;
991
break;
992
}
993
case CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations: {
994
J9CfrAttributeRuntimeVisibleTypeAnnotations *typeAnnotations = (J9CfrAttributeRuntimeVisibleTypeAnnotations *)attrib;
995
if (0 == typeAnnotations->rawDataLength) { /* rawDataLength non-zero in case of error in the attribute */
996
walkTypeAnnotations(typeAnnotations->numberOfAnnotations, typeAnnotations->typeAnnotations);
997
}
998
_methodsInfo[methodIndex].methodTypeAnnotationsAttribute = typeAnnotations;
999
/* J9AccMethodHasExtendedModifiers in the modifiers is set when the ROM class is written */
1000
_methodsInfo[methodIndex].extendedModifiers |= CFR_METHOD_EXT_HAS_METHOD_TYPE_ANNOTATIONS;
1001
break;
1002
}
1003
case CFR_ATTRIBUTE_AnnotationDefault:
1004
walkAnnotationElement(((J9CfrAttributeAnnotationDefault *)attrib)->defaultValue);
1005
_methodsInfo[methodIndex].defaultAnnotationAttribute = (J9CfrAttributeAnnotationDefault *)attrib;
1006
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasDefaultAnnotation;
1007
break;
1008
case CFR_ATTRIBUTE_MethodParameters:
1009
/* Fall through */
1010
case CFR_ATTRIBUTE_Code:
1011
/* Fall through */
1012
case CFR_ATTRIBUTE_Exceptions:
1013
/* Fall through */
1014
case CFR_ATTRIBUTE_Deprecated:
1015
/* Do nothing */
1016
break;
1017
default:
1018
Trc_BCU_ClassFileOracle_walkMethods_UnknownAttribute((U_32)attrib->tag, (U_32)getUTF8Length(attrib->nameIndex), getUTF8Data(attrib->nameIndex), attrib->length);
1019
break;
1020
}
1021
}
1022
}
1023
1024
UDATA
1025
ClassFileOracle::walkAnnotations(U_16 annotationsCount, J9CfrAnnotation *annotations, UDATA knownAnnotations)
1026
{
1027
ROMClassVerbosePhase v(_context, ClassFileAnnotationsAnalysis);
1028
UDATA foundAnnotations = 0;
1029
1030
if (0 == knownAnnotations) {
1031
for (U_16 annotationsIndex = 0; (annotationsIndex < annotationsCount) &&(OK == _buildResult); ++annotationsIndex) {
1032
markConstantAsUsedByAnnotation(annotations[annotationsIndex].typeIndex);
1033
const U_16 elementValuePairsCount = annotations[annotationsIndex].numberOfElementValuePairs;
1034
for (U_16 elementValuePairsIndex = 0; (elementValuePairsIndex < elementValuePairsCount) && (OK == _buildResult); ++elementValuePairsIndex) {
1035
markConstantAsUsedByAnnotation(annotations[annotationsIndex].elementValuePairs[elementValuePairsIndex].elementNameIndex);
1036
walkAnnotationElement(annotations[annotationsIndex].elementValuePairs[elementValuePairsIndex].value);
1037
}
1038
}
1039
} else {
1040
for (U_16 annotationsIndex = 0; (annotationsIndex < annotationsCount) && (OK == _buildResult); ++annotationsIndex) {
1041
markConstantAsUsedByAnnotation(annotations[annotationsIndex].typeIndex);
1042
for (UDATA knownAnnotationIndex = 0; knownAnnotationIndex < KNOWN_ANNOTATION_COUNT; ++knownAnnotationIndex) {
1043
if (containsKnownAnnotation(knownAnnotations, knownAnnotationIndex) && isUTF8AtIndexEqualToString(annotations[annotationsIndex].typeIndex, _knownAnnotations[knownAnnotationIndex].name, _knownAnnotations[knownAnnotationIndex].size)) {
1044
foundAnnotations = addAnnotationBit(foundAnnotations, knownAnnotationIndex);
1045
}
1046
}
1047
const U_16 elementValuePairsCount = annotations[annotationsIndex].numberOfElementValuePairs;
1048
for (U_16 elementValuePairsIndex = 0; (elementValuePairsIndex < elementValuePairsCount) && (OK == _buildResult); ++elementValuePairsIndex) {
1049
markConstantAsUsedByAnnotation(annotations[annotationsIndex].elementValuePairs[elementValuePairsIndex].elementNameIndex);
1050
walkAnnotationElement(annotations[annotationsIndex].elementValuePairs[elementValuePairsIndex].value);
1051
}
1052
}
1053
}
1054
return foundAnnotations;
1055
}
1056
1057
void
1058
ClassFileOracle::walkTypeAnnotations(U_16 annotationsCount, J9CfrTypeAnnotation *typeAnnotations) {
1059
for (U_16 typeAnnotationIndex = 0; typeAnnotationIndex < annotationsCount; ++ typeAnnotationIndex) {
1060
J9CfrAnnotation *annotation = &(typeAnnotations[typeAnnotationIndex].annotation);
1061
/* type_index in an annotation must refer to a CONSTANT_UTF8_info structure. */
1062
if (getCPTag(annotation->typeIndex) == CFR_CONSTANT_Utf8) {
1063
markConstantAsUsedByAnnotation(annotation->typeIndex);
1064
const U_16 elementValuePairsCount = annotation->numberOfElementValuePairs;
1065
for (U_16 elementValuePairsIndex = 0;
1066
(elementValuePairsIndex < elementValuePairsCount) && (OK == _buildResult); ++elementValuePairsIndex) {
1067
markConstantAsUsedByAnnotation(annotation->elementValuePairs[elementValuePairsIndex].elementNameIndex);
1068
walkAnnotationElement(annotation->elementValuePairs[elementValuePairsIndex].value);
1069
}
1070
} else {
1071
/*
1072
* UTF-8 entries and method entries use the same set of marking labels when
1073
* preparing to build the ROM class, but
1074
* the label value meanings differ depending on the type of the entry.
1075
* Thus we cannot mark a non-UTF-8 entry with a label used for UTF-8 as that label
1076
* value will be (mis)interpreted according to the type of the entry.
1077
*
1078
* In this case, force the typeIndex to a null value.
1079
* This will cause the parser to throw
1080
* an error if the VM or application tries to retrieve the annotation.
1081
*/
1082
annotation->typeIndex = 0;
1083
}
1084
}
1085
}
1086
1087
void
1088
ClassFileOracle::walkAnnotationElement(J9CfrAnnotationElement * annotationElement)
1089
{
1090
ROMClassVerbosePhase v(_context, ClassFileAnnotationElementAnalysis);
1091
1092
switch (annotationElement->tag) {
1093
case 'e':
1094
markConstantAsUsedByAnnotation(((J9CfrAnnotationElementEnum *)annotationElement)->typeNameIndex);
1095
markConstantAsUsedByAnnotation(((J9CfrAnnotationElementEnum *)annotationElement)->constNameIndex);
1096
break;
1097
case 'c':
1098
markConstantAsUsedByAnnotation(((J9CfrAnnotationElementClass *)annotationElement)->classInfoIndex);
1099
break;
1100
case '@':
1101
walkAnnotations(1, &(((J9CfrAnnotationElementAnnotation *)annotationElement)->annotationValue), 0);
1102
break;
1103
case '[': {
1104
J9CfrAnnotationElementArray *array = (J9CfrAnnotationElementArray *)annotationElement;
1105
for (U_16 valuesIndex = 0; (valuesIndex < array->numberOfValues) && (OK == _buildResult); ++valuesIndex) {
1106
walkAnnotationElement(array->values[valuesIndex]);
1107
}
1108
break;
1109
}
1110
1111
case 'D': /* fall thru */
1112
case 'J':
1113
_annotationRefersDoubleSlotEntry = true;
1114
/* fall thru */
1115
case 'B': /* fall thru */
1116
case 'C': /* fall thru */
1117
case 'F': /* fall thru */
1118
case 'I': /* fall thru */
1119
case 'S': /* fall thru */
1120
case 'Z': /* fall thru */
1121
/* Fall through - in Java 7, the annotation data is preserved in class file format, including referenced constant pool entries */
1122
case 's':
1123
markConstantAsUsedByAnnotation(((J9CfrAnnotationElementPrimitive *)annotationElement)->constValueIndex);
1124
break;
1125
default:
1126
Trc_BCU_ClassFileOracle_walkAnnotationElement_UnknownTag((U_32)annotationElement->tag);
1127
_buildResult = UnknownAnnotation;
1128
break;
1129
}
1130
}
1131
1132
void
1133
ClassFileOracle::computeSendSlotCount(U_16 methodIndex)
1134
{
1135
ROMCLASS_VERBOSE_PHASE_HOT(_context, ComputeSendSlotCount);
1136
1137
U_16 descriptorIndex = _classFile->methods[methodIndex].descriptorIndex;
1138
U_16 count = getUTF8Length(descriptorIndex);
1139
U_8 * bytes = getUTF8Data(descriptorIndex);
1140
U_8 sendSlotCount = 0;
1141
1142
for (U_16 index = 1; index < count; ++index) { /* 1 to skip the opening '(' */
1143
switch (bytes[index]) {
1144
case ')':
1145
_methodsInfo[methodIndex].sendSlotCount = sendSlotCount;
1146
return;
1147
case '[':
1148
/* skip all '['s */
1149
while ((index < count) && ('[' == bytes[index])) {
1150
++index;
1151
}
1152
if ((index >= count)
1153
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1154
|| (('L' != bytes[index]) && ('Q' != bytes[index]))
1155
#else
1156
|| ('L' != bytes[index])
1157
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1158
) {
1159
break;
1160
}
1161
/* fall through */
1162
case 'L':
1163
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
1164
case 'Q':
1165
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
1166
++index;
1167
while ((index < count) && (';' != bytes[index])) {
1168
++index;
1169
}
1170
break;
1171
case 'D':
1172
++sendSlotCount; /* double requires an extra send slot */
1173
break;
1174
case 'J':
1175
++sendSlotCount; /* long requires an extra send slot */
1176
break;
1177
default:
1178
/* any other primitive type */
1179
break;
1180
}
1181
++sendSlotCount;
1182
}
1183
}
1184
1185
void
1186
ClassFileOracle::walkMethodThrownExceptions(U_16 methodIndex)
1187
{
1188
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileMethodThrownExceptionsAnalysis);
1189
1190
J9CfrAttributeExceptions *exceptions = _classFile->methods[methodIndex].exceptionsAttribute;
1191
if (NULL != exceptions) {
1192
U_16 exceptionsThrownCount = 0;
1193
U_16 exceptionsCount = exceptions->numberOfExceptions;
1194
1195
for (U_16 exceptionIndex = 0; exceptionIndex < exceptionsCount; ++exceptionIndex) {
1196
U_16 cpIndex = exceptions->exceptionIndexTable[exceptionIndex];
1197
if (0 != cpIndex) {
1198
markClassNameAsReferenced(cpIndex);
1199
++exceptionsThrownCount;
1200
1201
}
1202
}
1203
1204
if (exceptionsThrownCount > 0) {
1205
_methodsInfo[methodIndex].exceptionsThrownCount = exceptionsThrownCount;
1206
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasExceptionInfo;
1207
}
1208
}
1209
}
1210
1211
void
1212
ClassFileOracle::walkMethodCodeAttribute(U_16 methodIndex)
1213
{
1214
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileMethodCodeAttributeAnalysis);
1215
1216
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
1217
if (NULL != codeAttribute) {
1218
walkMethodCodeAttributeAttributes(methodIndex);
1219
walkMethodCodeAttributeCaughtExceptions(methodIndex);
1220
walkMethodCodeAttributeCode(methodIndex);
1221
1222
if (0 != codeAttribute->exceptionTableLength) {
1223
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasExceptionInfo;
1224
}
1225
}
1226
}
1227
1228
void
1229
ClassFileOracle::walkMethodMethodParametersAttribute(U_16 methodIndex)
1230
{
1231
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileMethodMethodParametersAttributeAnalysis);
1232
1233
J9CfrAttributeMethodParameters *methodParametersAttribute = _classFile->methods[methodIndex].methodParametersAttribute;
1234
1235
if (NULL != methodParametersAttribute) {
1236
for (U_8 methodParamsIndex = 0;
1237
(methodParamsIndex < methodParametersAttribute->numberOfMethodParameters) && (OK == _buildResult);
1238
++methodParamsIndex)
1239
{
1240
U_16 utfIndex = methodParametersAttribute->methodParametersIndexTable[methodParamsIndex];
1241
if (J9_ARE_ANY_BITS_SET(methodParametersAttribute->flags[methodParamsIndex], ~CFR_ATTRIBUTE_METHOD_PARAMETERS_MASK)) {
1242
/* only CFR_ACC_FINAL | CFR_ACC_SYNTHETIC | CFR_ACC_MANDATED should be set */
1243
_methodsInfo[methodIndex].extendedModifiers |= CFR_METHOD_EXT_INVALID_CP_ENTRY;
1244
}
1245
if (0 != utfIndex) {
1246
bool cpEntryOkay = false;
1247
if (utfIndex <= _classFile->constantPoolCount) {
1248
UDATA cpTag = getCPTag(utfIndex);
1249
if (CFR_CONSTANT_Utf8 == cpTag) {
1250
markConstantUTF8AsReferenced(utfIndex);
1251
cpEntryOkay = true;
1252
}
1253
}
1254
if (!cpEntryOkay) {
1255
/* Mark the method as having bad methodParameters */
1256
methodParametersAttribute->methodParametersIndexTable[methodParamsIndex] = 0;
1257
_methodsInfo[methodIndex].extendedModifiers |= CFR_METHOD_EXT_INVALID_CP_ENTRY;
1258
Trc_BCU_MalformedMethodParameterAttribute(methodIndex);
1259
}
1260
}
1261
}
1262
/* PR 97987 keep parameters object to detect mismatch between parameters attribute and actual argument count */
1263
_methodsInfo[methodIndex].methodParametersAttribute = methodParametersAttribute;
1264
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasMethodParameters;
1265
}
1266
1267
}
1268
1269
void
1270
ClassFileOracle::throwGenericErrorWithCustomMsg(UDATA code, UDATA offset)
1271
{
1272
_buildResult = OutOfMemory;
1273
PORT_ACCESS_FROM_PORT(_context->portLibrary());
1274
U_8* errorMsg = (U_8 *)j9mem_allocate_memory(sizeof(J9CfrError), J9MEM_CATEGORY_CLASSES);
1275
if (NULL != errorMsg) {
1276
_buildResult = GenericErrorCustomMsg;
1277
buildError((J9CfrError*)errorMsg, code, GenericErrorCustomMsg, offset);
1278
J9TranslationBufferSet* dlb = _context->javaVM()->dynamicLoadBuffers;
1279
/* avoid leaking memory if classFileError was not previously null. Do not free
1280
* memory if _classFileBuffer from ROMClassBuilder is using the same address. */
1281
if ((NULL != dlb->classFileError) && (_romBuilderClassFileBuffer != dlb->classFileError)) {
1282
j9mem_free_memory(dlb->classFileError);
1283
}
1284
dlb->classFileError = errorMsg;
1285
}
1286
}
1287
1288
void
1289
ClassFileOracle::walkMethodCodeAttributeAttributes(U_16 methodIndex)
1290
{
1291
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileMethodCodeAttributeAttributesAnalysis);
1292
1293
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
1294
U_32 lineNumbersCount = 0;
1295
1296
Trc_BCU_Assert_NotEquals(NULL, codeAttribute);
1297
1298
U_16 attributesCount = codeAttribute->attributesCount;
1299
for (U_16 attributeIndex = 0; (attributeIndex < attributesCount) && (OK == _buildResult); ++attributeIndex) {
1300
J9CfrAttribute *attribute = codeAttribute->attributes[attributeIndex];
1301
1302
switch (attribute->tag) {
1303
case CFR_ATTRIBUTE_StackMapTable: {
1304
/*
1305
* Stack map table frames are variable sized and look like:
1306
* StackMapTableFrame {
1307
* U_8 frameType
1308
* ... rest
1309
* };
1310
*
1311
* frameType is a tag distinguishing 256 different types of frame that fall into 8 categories:
1312
* SAME
1313
* SAME_LOCALS_1_STACK
1314
* Reserved
1315
* SAME_LOCALS_1_STACK_EXTENDED
1316
* CHOP
1317
* SAME_EXTENDED
1318
* APPEND
1319
* FULL
1320
*
1321
* Each of these types is described in more detail below.
1322
*
1323
* Some frame types contain 1 or more TypeInfo entries. TypeInfo is a variable-length data type TODO add doc?
1324
*
1325
* stackMap->numberOfEntries is the number of StackMapFrames in stackMap->entries.
1326
* stackMap->entries is a byte buffer containing the variable length StackMapFrames.
1327
*
1328
* framePointer is used to step through stackMap->entries.
1329
* entryIndex is used to determine when we've read all the StackMapFrames.
1330
*/
1331
1332
J9CfrAttributeStackMap * stackMap = (J9CfrAttributeStackMap *) attribute;
1333
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasStackMap;
1334
1335
Trc_BCU_Assert_Equals(NULL, _methodsInfo[methodIndex].stackMapFramesInfo);
1336
_methodsInfo[methodIndex].stackMapFramesInfo = (StackMapFrameInfo *) _bufferManager->alloc(stackMap->numberOfEntries * sizeof(StackMapFrameInfo));
1337
if (NULL == _methodsInfo[methodIndex].stackMapFramesInfo) {
1338
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_OutOfMemory(stackMap->numberOfEntries * sizeof(StackMapFrameInfo));
1339
_buildResult = OutOfMemory;
1340
break;
1341
}
1342
memset(_methodsInfo[methodIndex].stackMapFramesInfo, 0, stackMap->numberOfEntries * sizeof(StackMapFrameInfo));
1343
_methodsInfo[methodIndex].stackMapFramesCount = U_16(stackMap->numberOfEntries);
1344
1345
StackMapFrameInfo *stackMapFramesInfo = _methodsInfo[methodIndex].stackMapFramesInfo;
1346
U_8 *framePointer = stackMap->entries;
1347
U_16 entryCount = U_16(stackMap->numberOfEntries);
1348
for(U_16 entryIndex = 0; entryIndex < entryCount; ++entryIndex) {
1349
NEXT_U8(stackMapFramesInfo[entryIndex].frameType, framePointer);
1350
1351
if (CFR_STACKMAP_SAME_LOCALS_1_STACK > stackMapFramesInfo[entryIndex].frameType) { /* 0..63 */
1352
/* SAME frame - no extra data */
1353
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_END > stackMapFramesInfo[entryIndex].frameType) { /* 64..127 */
1354
/*
1355
* SAME_LOCALS_1_STACK {
1356
* TypeInfo stackItems[1]
1357
* };
1358
*/
1359
stackMapFramesInfo[entryIndex].stackItemsCount = 1;
1360
stackMapFramesInfo[entryIndex].stackItemsTypeInfo = framePointer;
1361
framePointer = walkStackMapSlots(framePointer, stackMapFramesInfo[entryIndex].stackItemsCount);
1362
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED > stackMapFramesInfo[entryIndex].frameType) { /* 128..246 */
1363
/* Reserved frame types - no extra data */
1364
Trc_BCU_Assert_ShouldNeverHappen();
1365
} else if (CFR_STACKMAP_SAME_LOCALS_1_STACK_EXTENDED == stackMapFramesInfo[entryIndex].frameType) { /* 247 */
1366
/*
1367
* SAME_LOCALS_1_STACK_EXTENDED {
1368
* U_16 offsetDelta
1369
* TypeInfo stackItems[1]
1370
* };
1371
*/
1372
NEXT_U16(stackMapFramesInfo[entryIndex].offsetDelta, framePointer); /* Extract offsetDelta */
1373
stackMapFramesInfo[entryIndex].stackItemsCount = 1;
1374
stackMapFramesInfo[entryIndex].stackItemsTypeInfo = framePointer;
1375
framePointer = walkStackMapSlots(framePointer, stackMapFramesInfo[entryIndex].stackItemsCount);
1376
} else if (CFR_STACKMAP_SAME_EXTENDED > stackMapFramesInfo[entryIndex].frameType) { /* 248..250 */
1377
/*
1378
* CHOP {
1379
* U_16 offsetDelta
1380
* };
1381
*/
1382
NEXT_U16(stackMapFramesInfo[entryIndex].offsetDelta, framePointer); /* Extract offsetDelta */
1383
} else if (CFR_STACKMAP_SAME_EXTENDED == stackMapFramesInfo[entryIndex].frameType) { /* 251 */
1384
/*
1385
* SAME_EXTENDED {
1386
* U_16 offsetDelta
1387
* };
1388
*/
1389
NEXT_U16(stackMapFramesInfo[entryIndex].offsetDelta, framePointer); /* Extract offsetDelta */
1390
} else if (CFR_STACKMAP_FULL > stackMapFramesInfo[entryIndex].frameType) { /* 252..254 */
1391
/*
1392
* APPEND {
1393
* U_16 offsetDelta
1394
* TypeInfo locals[frameType - CFR_STACKMAP_APPEND_BASE]
1395
* };
1396
*/
1397
NEXT_U16(stackMapFramesInfo[entryIndex].offsetDelta, framePointer); /* Extract offsetDelta */
1398
stackMapFramesInfo[entryIndex].localsCount = stackMapFramesInfo[entryIndex].frameType - CFR_STACKMAP_APPEND_BASE;
1399
stackMapFramesInfo[entryIndex].localsTypeInfo = framePointer;
1400
framePointer = walkStackMapSlots(framePointer, stackMapFramesInfo[entryIndex].localsCount);
1401
} else if (CFR_STACKMAP_FULL == stackMapFramesInfo[entryIndex].frameType) { /* 255 */
1402
/*
1403
* FULL {
1404
* U_16 offsetDelta
1405
* U_16 localsCount
1406
* TypeInfo locals[localsCount]
1407
* U_16 stackItemsCount
1408
* TypeInfo stackItems[stackItemsCount]
1409
* };
1410
*/
1411
NEXT_U16(stackMapFramesInfo[entryIndex].offsetDelta, framePointer); /* Extract offsetDelta */
1412
NEXT_U16(stackMapFramesInfo[entryIndex].localsCount, framePointer); /* Extract localsCount */
1413
stackMapFramesInfo[entryIndex].localsTypeInfo = framePointer;
1414
framePointer = walkStackMapSlots(framePointer, stackMapFramesInfo[entryIndex].localsCount);
1415
NEXT_U16(stackMapFramesInfo[entryIndex].stackItemsCount, framePointer); /* Extract stackItemsCount */
1416
stackMapFramesInfo[entryIndex].stackItemsTypeInfo = framePointer;
1417
framePointer = walkStackMapSlots(framePointer, stackMapFramesInfo[entryIndex].stackItemsCount);
1418
}
1419
}
1420
break;
1421
}
1422
case CFR_ATTRIBUTE_LineNumberTable:
1423
if (_context->shouldPreserveLineNumbers()) {
1424
J9CfrAttributeLineNumberTable *lineNumberTable = (J9CfrAttributeLineNumberTable *) attribute;
1425
lineNumbersCount += lineNumberTable->lineNumberTableLength;
1426
}
1427
break;
1428
case CFR_ATTRIBUTE_LocalVariableTable:
1429
if (_context->shouldPreserveLocalVariablesInfo()) {
1430
/* There can be at most one entry per local variable, so we allocate the full table up-front and index by local variable index */
1431
if (NULL == _methodsInfo[methodIndex].localVariablesInfo) {
1432
_methodsInfo[methodIndex].localVariablesInfo = (LocalVariableInfo *) _bufferManager->alloc(codeAttribute->maxLocals * sizeof(LocalVariableInfo));
1433
if (NULL == _methodsInfo[methodIndex].localVariablesInfo) {
1434
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_OutOfMemory(codeAttribute->maxLocals * sizeof(LocalVariableInfo));
1435
_buildResult = OutOfMemory;
1436
break;
1437
}
1438
memset(_methodsInfo[methodIndex].localVariablesInfo, 0, codeAttribute->maxLocals * sizeof(LocalVariableInfo));
1439
}
1440
1441
J9CfrAttributeLocalVariableTable *localVariableTableAttribute = (J9CfrAttributeLocalVariableTable *) attribute;
1442
_methodsInfo[methodIndex].localVariablesCount += localVariableTableAttribute->localVariableTableLength;
1443
if (0 != localVariableTableAttribute->localVariableTableLength) {
1444
for (U_16 localVariableTableIndex = 0; localVariableTableIndex < localVariableTableAttribute->localVariableTableLength; ++localVariableTableIndex) {
1445
U_16 index = localVariableTableAttribute->localVariableTable[localVariableTableIndex].index;
1446
if (codeAttribute->maxLocals <= index) {
1447
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_LocalVariableTableIndexOutOfBounds(
1448
index, codeAttribute->maxLocals, (U_32)getUTF8Length(_classFile->methods[methodIndex].nameIndex), getUTF8Data(_classFile->methods[methodIndex].nameIndex));
1449
1450
throwGenericErrorWithCustomMsg(J9NLS_CFR_LVT_INDEX_OUTOFRANGE__ID, index);
1451
break;
1452
} else if (NULL == _methodsInfo[methodIndex].localVariablesInfo[index].localVariableTableAttribute) {
1453
_methodsInfo[methodIndex].localVariablesInfo[index].localVariableTableAttribute = localVariableTableAttribute;
1454
} else if (localVariableTableAttribute != _methodsInfo[methodIndex].localVariablesInfo[index].localVariableTableAttribute) {
1455
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_DuplicateLocalVariableTable(
1456
(U_32)getUTF8Length(_classFile->methods[methodIndex].nameIndex), getUTF8Data(_classFile->methods[methodIndex].nameIndex),
1457
localVariableTableAttribute, _methodsInfo[methodIndex].localVariablesInfo[index].localVariableTableAttribute);
1458
_buildResult = GenericError;
1459
break;
1460
}
1461
markConstantUTF8AsReferenced(localVariableTableAttribute->localVariableTable[localVariableTableIndex].nameIndex);
1462
markConstantUTF8AsReferenced(localVariableTableAttribute->localVariableTable[localVariableTableIndex].descriptorIndex);
1463
}
1464
}
1465
}
1466
break;
1467
case CFR_ATTRIBUTE_LocalVariableTypeTable:
1468
if (_context->shouldPreserveLocalVariablesInfo()) {
1469
/* There can be at most one entry per local variable, so we allocate the full table up-front and index by local variable index */
1470
if (NULL == _methodsInfo[methodIndex].localVariablesInfo) {
1471
_methodsInfo[methodIndex].localVariablesInfo = (LocalVariableInfo *) _bufferManager->alloc(codeAttribute->maxLocals * sizeof(LocalVariableInfo));
1472
if (NULL == _methodsInfo[methodIndex].localVariablesInfo) {
1473
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_OutOfMemory(codeAttribute->maxLocals * sizeof(LocalVariableInfo));
1474
_buildResult = OutOfMemory;
1475
break;
1476
}
1477
memset(_methodsInfo[methodIndex].localVariablesInfo, 0, codeAttribute->maxLocals * sizeof(LocalVariableInfo));
1478
}
1479
1480
J9CfrAttributeLocalVariableTypeTable *localVariableTypeTableAttribute = (J9CfrAttributeLocalVariableTypeTable *) attribute;
1481
if (0 != localVariableTypeTableAttribute->localVariableTypeTableLength) {
1482
for (U_16 localVariableTypeTableIndex = 0; localVariableTypeTableIndex < localVariableTypeTableAttribute->localVariableTypeTableLength; ++localVariableTypeTableIndex) {
1483
J9CfrLocalVariableTypeTableEntry *lvttEntry = &(localVariableTypeTableAttribute->localVariableTypeTable[localVariableTypeTableIndex]);
1484
const U_16 index = lvttEntry->index;
1485
if (codeAttribute->maxLocals <= index) {
1486
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_LocalVariableTypeTableIndexOutOfBounds(
1487
index, codeAttribute->maxLocals, (U_32)getUTF8Length(_classFile->methods[methodIndex].nameIndex), getUTF8Data(_classFile->methods[methodIndex].nameIndex));
1488
throwGenericErrorWithCustomMsg(J9NLS_CFR_LVTT_INDEX_OUTOFRANGE__ID, index);
1489
break;
1490
} else if (NULL == _methodsInfo[methodIndex].localVariablesInfo[index].localVariableTypeTableAttribute) {
1491
_methodsInfo[methodIndex].localVariablesInfo[index].localVariableTypeTableAttribute = localVariableTypeTableAttribute;
1492
} else if (localVariableTypeTableAttribute != _methodsInfo[methodIndex].localVariablesInfo[index].localVariableTypeTableAttribute) {
1493
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_DuplicateLocalVariableTypeTable(
1494
(U_32)getUTF8Length(_classFile->methods[methodIndex].nameIndex), getUTF8Data(_classFile->methods[methodIndex].nameIndex),
1495
localVariableTypeTableAttribute, _methodsInfo[methodIndex].localVariablesInfo[index].localVariableTypeTableAttribute);
1496
_buildResult = GenericError;
1497
break;
1498
}
1499
1500
/* 4.7.14: There may be no more than one LocalVariableTypeTable attribute per local variable in the attributes table of a Code attribute.
1501
* The entry is unique with its startPC, length, and index. */
1502
for (U_16 localVariableTypeTableCompareIndex = 0; localVariableTypeTableCompareIndex < localVariableTypeTableIndex; ++localVariableTypeTableCompareIndex) {
1503
J9CfrLocalVariableTypeTableEntry *lvttCompareEntry = &(localVariableTypeTableAttribute->localVariableTypeTable[localVariableTypeTableCompareIndex]);
1504
if ((lvttEntry->startPC == lvttCompareEntry->startPC)
1505
&& (lvttEntry->length == lvttCompareEntry->length)
1506
&& (lvttEntry->nameIndex == lvttCompareEntry->nameIndex)
1507
&& (lvttEntry->signatureIndex == lvttCompareEntry->signatureIndex)
1508
&& (index == lvttCompareEntry->index)
1509
) {
1510
throwGenericErrorWithCustomMsg(J9NLS_CFR_LVTT_DUPLICATE__ID, index);
1511
break;
1512
}
1513
}
1514
markConstantUTF8AsReferenced(localVariableTypeTableAttribute->localVariableTypeTable[localVariableTypeTableIndex].signatureIndex);
1515
}
1516
}
1517
}
1518
break;
1519
case CFR_ATTRIBUTE_RuntimeVisibleTypeAnnotations: {
1520
J9CfrAttributeRuntimeVisibleTypeAnnotations *typeAnnotations = (J9CfrAttributeRuntimeVisibleTypeAnnotations *)attribute;
1521
if (0 == typeAnnotations->rawDataLength) { /* rawDataLength non-zero in case of error in the attribute */
1522
walkTypeAnnotations(typeAnnotations->numberOfAnnotations, typeAnnotations->typeAnnotations);
1523
}
1524
_methodsInfo[methodIndex].codeTypeAnnotationsAttribute = typeAnnotations;
1525
/* J9AccMethodHasExtendedModifiers in the modifiers is set when the ROM class is written */
1526
_methodsInfo[methodIndex].extendedModifiers |= CFR_METHOD_EXT_HAS_CODE_TYPE_ANNOTATIONS;
1527
break;
1528
}
1529
default:
1530
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_UnknownAttribute((U_32)attribute->tag, (U_32)getUTF8Length(attribute->nameIndex), getUTF8Data(attribute->nameIndex), attribute->length);
1531
break;
1532
}
1533
}
1534
1535
/* Verify that each LVTT entry has a matching local variable. Since there is no guaranteed order
1536
* for code attributes, this check must be performed after all attributes are processed.
1537
*
1538
* According to the JVM spec: "Each entry in the local_variable_type_table array ...
1539
* indicates the index into the local variable array of the current frame at which
1540
* that local variable can be found."
1541
*
1542
* While multiple LocalVariableTypeTable attributes may exist according to the spec, upon observation
1543
* it is the common case for 'javac' to generate only one attribute per method. To take advantage of this
1544
* I tracked the last LVTT attribute that has been verified so the second loop search is not repeated.
1545
* Because of this for most cases the second loop will only be executed once.
1546
*
1547
* It is also common to see LVT and LVTT entries in the same order though the spec makes no ordering guaruntees.
1548
* To take advantage of this each search for an LVT match starts from the index where the previous match was
1549
* found saving iterations.
1550
*
1551
* With these two optimizations the common runtime for this verification step should be:
1552
* maxLocals + localVariableTypeTableLength + localVariableTableLength
1553
*/
1554
if (_context->shouldPreserveLocalVariablesInfo() && (NULL != _methodsInfo[methodIndex].localVariablesInfo)) {
1555
J9CfrAttributeLocalVariableTypeTable *lastLVTTAttribute = NULL; /* track last processed LVTT attribute */
1556
1557
for (UDATA varIndex = 0; varIndex < codeAttribute->maxLocals; varIndex++) {
1558
J9CfrAttributeLocalVariableTable *localVariableTableAttribute = _methodsInfo[methodIndex].localVariablesInfo[varIndex].localVariableTableAttribute;
1559
J9CfrAttributeLocalVariableTypeTable *localVariableTypeTableAttribute = _methodsInfo[methodIndex].localVariablesInfo[varIndex].localVariableTypeTableAttribute;
1560
1561
/* This may occur if the variable type does not require signature information, or if there is no entry for this variable. */
1562
if ((NULL == localVariableTypeTableAttribute) || (NULL == localVariableTableAttribute)) {
1563
continue;
1564
}
1565
1566
/* if LVTT has been processed previously, skip to the next variable */
1567
if (NULL == lastLVTTAttribute) {
1568
lastLVTTAttribute = localVariableTypeTableAttribute;
1569
} else if (localVariableTypeTableAttribute == lastLVTTAttribute) {
1570
continue;
1571
}
1572
1573
/* Verify that each entry in the LocalVariableTypeTable has a match */
1574
U_16 lvtIndex = 0; /* start at the index of the last LVT match since LVT and LVTTs are likely in the same order. */
1575
for (U_16 lvttIndex = 0; lvttIndex < localVariableTypeTableAttribute->localVariableTypeTableLength; lvttIndex++) {
1576
J9CfrLocalVariableTypeTableEntry *lvttEntry = &(localVariableTypeTableAttribute->localVariableTypeTable[lvttIndex]);
1577
UDATA foundMatch = FALSE;
1578
1579
/* Search for match in LVT attribute with matching index. */
1580
for (U_16 lvtCount = 0; lvtCount < localVariableTableAttribute->localVariableTableLength; lvtCount++) {
1581
J9CfrLocalVariableTableEntry *lvtEntry = &(localVariableTableAttribute->localVariableTable[lvtIndex]);
1582
1583
/* Update index for next iteration, rolling over to 0 if necessary. */
1584
lvtIndex = (lvtIndex + 1) % localVariableTableAttribute->localVariableTableLength;
1585
1586
if ((lvttEntry->startPC == lvtEntry->startPC)
1587
&& (lvttEntry->length == lvtEntry->length)
1588
&& (lvttEntry->nameIndex == lvtEntry->nameIndex)
1589
&& (lvttEntry->index == lvtEntry->index)
1590
) {
1591
foundMatch = TRUE;
1592
break;
1593
}
1594
}
1595
1596
/* throw error if there is no variable match. */
1597
if (!foundMatch) {
1598
throwGenericErrorWithCustomMsg(J9NLS_CFR_LVTT_DOES_NOT_MATCH_LVT__ID, lvttIndex);
1599
}
1600
}
1601
}
1602
}
1603
1604
if ((OK == _buildResult) && (0 != lineNumbersCount)) {
1605
ROMCLASS_VERBOSE_PHASE_HOT(_context, CompressLineNumbers);
1606
compressLineNumberTable(methodIndex, lineNumbersCount);
1607
}
1608
}
1609
1610
int
1611
ClassFileOracle::compareLineNumbers(const void *left, const void *right)
1612
{
1613
J9CfrLineNumberTableEntry *leftNumber = (J9CfrLineNumberTableEntry *)left;
1614
J9CfrLineNumberTableEntry *rightNumber = (J9CfrLineNumberTableEntry *)right;
1615
1616
return int(leftNumber->startPC - rightNumber->startPC);
1617
}
1618
1619
void
1620
ClassFileOracle::compressLineNumberTable(U_16 methodIndex, U_32 lineNumbersCount)
1621
{
1622
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
1623
U_16 attributesCount = codeAttribute->attributesCount;
1624
MethodInfo *method = &(_methodsInfo[methodIndex]);
1625
1626
/* maximum possible size of compressed data, compressLineNumbers may use a maximum
1627
* of 5 bytes for compressed data, the maximum memory needed will be of 5 bytes per line number.
1628
*/
1629
U_8 *lineNumbersInfoCompressed = (U_8*)(_bufferManager->alloc(lineNumbersCount * 5));
1630
U_8 *lineNumbersInfoCompressedInitial = lineNumbersInfoCompressed;
1631
if (NULL == lineNumbersInfoCompressed) {
1632
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_OutOfMemory(lineNumbersCount * 5);
1633
_buildResult = OutOfMemory;
1634
} else {
1635
J9CfrLineNumberTableEntry * lastLineNumberTableEntry = NULL;
1636
1637
for (U_16 attributeIndex = 0; attributeIndex < attributesCount; ++attributeIndex) {
1638
J9CfrAttribute *attribute = codeAttribute->attributes[attributeIndex];
1639
if (CFR_ATTRIBUTE_LineNumberTable == attribute->tag) {
1640
J9CfrAttributeLineNumberTable *lineNumberTable = (J9CfrAttributeLineNumberTable *) attribute;
1641
if (!compressLineNumbers(lineNumberTable->lineNumberTable, lineNumberTable->lineNumberTableLength, lastLineNumberTableEntry, &lineNumbersInfoCompressed)) {
1642
/* the line numbers are not sorted, sort them */
1643
sortAndCompressLineNumberTable(methodIndex, lineNumbersCount, lineNumbersInfoCompressedInitial);
1644
return;
1645
}
1646
lastLineNumberTableEntry = &lineNumberTable->lineNumberTable[lineNumberTable->lineNumberTableLength - 1];
1647
}
1648
}
1649
method->lineNumbersInfoCompressed = lineNumbersInfoCompressedInitial;
1650
method->lineNumbersCount = lineNumbersCount;
1651
method->lineNumbersInfoCompressedSize = (U_32)(lineNumbersInfoCompressed - lineNumbersInfoCompressedInitial);
1652
1653
/* Reclaim the rest of the buffer lineNumbersInfoCompressed */
1654
_bufferManager->reclaim(lineNumbersInfoCompressedInitial, method->lineNumbersInfoCompressedSize);
1655
}
1656
}
1657
1658
void
1659
ClassFileOracle::sortAndCompressLineNumberTable(U_16 methodIndex, U_32 lineNumbersCount, U_8 *lineNumbersInfoCompressedInitial)
1660
{
1661
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
1662
U_16 attributesCount = codeAttribute->attributesCount;
1663
MethodInfo *method = &(_methodsInfo[methodIndex]);
1664
1665
U_8 *lineNumbersInfoCompressed;
1666
UDATA lineNumbersInfoSize = lineNumbersCount * sizeof (J9CfrLineNumberTableEntry);
1667
J9CfrLineNumberTableEntry *lineNumbersInfo = (J9CfrLineNumberTableEntry*)(_bufferManager->alloc(lineNumbersInfoSize));
1668
lineNumbersInfoCompressed = lineNumbersInfoCompressedInitial;
1669
if (NULL == lineNumbersInfo) {
1670
Trc_BCU_ClassFileOracle_walkMethodCodeAttributeAttributes_OutOfMemory(lineNumbersInfoSize);
1671
_buildResult = OutOfMemory;
1672
} else {
1673
sortLineNumberTable(methodIndex, lineNumbersInfo);
1674
1675
/* Compress the line numbers */
1676
if (!compressLineNumbers(lineNumbersInfo, lineNumbersCount, NULL, &lineNumbersInfoCompressed)) {
1677
/* The pcOffset should be sorted by now */
1678
Trc_BCU_Assert_ShouldNeverHappen();
1679
}
1680
1681
method->lineNumbersInfoCompressed = lineNumbersInfoCompressedInitial;
1682
method->lineNumbersCount = lineNumbersCount;
1683
method->lineNumbersInfoCompressedSize = (U_32)(lineNumbersInfoCompressed - lineNumbersInfoCompressedInitial);
1684
_bufferManager->reclaim(lineNumbersInfo, lineNumbersInfoSize);
1685
}
1686
}
1687
void
1688
ClassFileOracle::sortLineNumberTable(U_16 methodIndex, J9CfrLineNumberTableEntry *lineNumbersInfo) {
1689
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
1690
U_16 attributesCount = codeAttribute->attributesCount;
1691
1692
U_32 lineNumbersIndex = 0;
1693
U_32 lastPC = 0;
1694
/* Used by ROMClassBuilder to not sort the line if they were already sorted */
1695
BOOLEAN sorted = TRUE;
1696
for (U_16 attributeIndex = 0; attributeIndex < attributesCount; ++attributeIndex) {
1697
J9CfrAttribute *attribute = codeAttribute->attributes[attributeIndex];
1698
1699
if (CFR_ATTRIBUTE_LineNumberTable == attribute->tag) {
1700
J9CfrAttributeLineNumberTable *lineNumberTable = (J9CfrAttributeLineNumberTable *) attribute;
1701
for (U_16 lineNumberTableIndex = 0; lineNumberTableIndex < lineNumberTable->lineNumberTableLength; ++lineNumberTableIndex) {
1702
if (lineNumberTable->lineNumberTable[lineNumberTableIndex].startPC < lastPC) {
1703
sorted = FALSE;
1704
}
1705
lastPC = lineNumbersInfo[lineNumbersIndex].startPC = lineNumberTable->lineNumberTable[lineNumberTableIndex].startPC;
1706
lineNumbersInfo[lineNumbersIndex].lineNumber = lineNumberTable->lineNumberTable[lineNumberTableIndex].lineNumber;
1707
++lineNumbersIndex;
1708
}
1709
}
1710
}
1711
1712
if (!sorted) {
1713
/* Sort the line numbers */
1714
J9_SORT(lineNumbersInfo, lineNumbersIndex, sizeof(J9CfrLineNumberTableEntry), &ClassFileOracle::compareLineNumbers);
1715
}
1716
}
1717
1718
void
1719
ClassFileOracle::walkMethodCodeAttributeCaughtExceptions(U_16 methodIndex)
1720
{
1721
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileMethodCodeAttributeCaughtExceptionsAnalysis);
1722
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
1723
1724
Trc_BCU_Assert_NotEquals(NULL, codeAttribute);
1725
1726
for (U_16 exceptionTableIndex = 0; exceptionTableIndex < codeAttribute->exceptionTableLength; ++exceptionTableIndex) {
1727
U_16 cpIndex = codeAttribute->exceptionTable[exceptionTableIndex].catchType;
1728
if (0 != cpIndex) {
1729
markClassAsReferenced(cpIndex);
1730
}
1731
}
1732
}
1733
1734
void
1735
ClassFileOracle::addBytecodeFixupEntry(BytecodeFixupEntry *entry, U_32 codeIndex, U_16 cpIndex, U_8 type)
1736
{
1737
entry->codeIndex = codeIndex;
1738
entry->cpIndex = cpIndex;
1739
entry->type = type;
1740
}
1741
1742
const U_8 PARAM_VOID = 0;
1743
const U_8 PARAM_BOOLEAN = 1;
1744
const U_8 PARAM_BYTE = 2;
1745
const U_8 PARAM_CHAR = 3;
1746
const U_8 PARAM_SHORT = 4;
1747
const U_8 PARAM_FLOAT = 5;
1748
const U_8 PARAM_INT = 6;
1749
const U_8 PARAM_DOUBLE = 7;
1750
const U_8 PARAM_LONG = 8;
1751
const U_8 PARAM_OBJECT = 9;
1752
1753
#define PARAM_U8() code[codeIndex + 1]
1754
#define PARAM_U16() (U_16(code[codeIndex + 1]) << 8) | U_16(code[codeIndex + 2])
1755
#define PARAM_I16() I_16(PARAM_U16())
1756
1757
#if defined(J9VM_ENV_LITTLE_ENDIAN)
1758
1759
/*
1760
* Swaps the I_32 in-place, returning it.
1761
*/
1762
static VMINLINE I_32
1763
swapI32(U_8 *code, U_32 codeIndex)
1764
{
1765
I_32 *dest = (I_32 *)&code[codeIndex];
1766
I_32 value = I_32(U_32(code[codeIndex] << 24) | U_32(code[codeIndex + 1] << 16) | U_32(code[codeIndex + 2] << 8) | U_32(code[codeIndex + 3]));
1767
*dest = value;
1768
return value;
1769
}
1770
1771
#define SWAP_I32_GET(index) swapI32(code, index)
1772
#define SWAP_I32(index) SWAP_I32_GET(index)
1773
#else
1774
/*
1775
* We use separate macros here because the compiler is not guaranteed to optimize out the pointer
1776
* dereference (as doing so may result in a change of program behaviour in the compiler's view -
1777
* for example a GPF may not happen).
1778
*/
1779
#define SWAP_I32_GET(index) *(I_32*)&code[index]
1780
#define SWAP_I32(index)
1781
#endif
1782
1783
void
1784
ClassFileOracle::walkMethodCodeAttributeCode(U_16 methodIndex)
1785
{
1786
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileMethodCodeAttributeCodeAnalysis);
1787
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
1788
1789
static const U_8 returnArgCharConversion[] = {
1790
0, PARAM_INT, PARAM_INT, PARAM_DOUBLE,
1791
0, PARAM_FLOAT, 0, 0,
1792
PARAM_INT, PARAM_LONG, 0, PARAM_OBJECT,
1793
0, 0, 0, 0,
1794
0, 0, PARAM_INT, 0,
1795
0, PARAM_VOID, 0, 0,
1796
0, PARAM_INT
1797
};
1798
1799
static const U_8 returnBytecodeConversion[] = {
1800
PARAM_INT, /* ireturn */
1801
PARAM_LONG, /* lreturn */
1802
PARAM_FLOAT, /* freturn */
1803
PARAM_DOUBLE, /* dreturn */
1804
PARAM_OBJECT, /* areturn */
1805
PARAM_VOID /* return */
1806
};
1807
1808
Trc_BCU_Assert_NotEquals(NULL, codeAttribute);
1809
1810
U_32 step = 0;
1811
U_16 cpIndex = 0;
1812
U_32 branchCount = 1;
1813
1814
U_16 methodDescriptorIndex = _classFile->methods[methodIndex].descriptorIndex;
1815
U_8 *methodDescriptorData = getUTF8Data(methodDescriptorIndex);
1816
U_16 methodDescriptorLength = getUTF8Length(methodDescriptorIndex);
1817
U_8 returnType = methodDescriptorData[methodDescriptorLength - 1];
1818
if (( returnType == ';') || (methodDescriptorData[methodDescriptorLength - 2] == '[')) {
1819
returnType = PARAM_OBJECT;
1820
} else {
1821
returnType = returnArgCharConversion[returnType - 'A'];
1822
}
1823
1824
/* In the worst case scenario, all bytecodes are LDCs and thus half the bytes will need fixup entries. */
1825
UDATA maxFixupTableSize = (codeAttribute->codeLength / 2) * sizeof(BytecodeFixupEntry);
1826
BytecodeFixupEntry *fixupTable = (BytecodeFixupEntry *) _bufferManager->alloc(maxFixupTableSize);
1827
if (NULL == fixupTable) {
1828
_buildResult = OutOfMemory;
1829
return;
1830
}
1831
BytecodeFixupEntry *entry = fixupTable;
1832
1833
U_8 *code = codeAttribute->code;
1834
for (U_32 codeIndex = 0; codeIndex < codeAttribute->codeLength; codeIndex += step) { /* NOTE codeIndex is modified below for CFR_BC_tableswitch and CFR_BC_lookupswitch */
1835
1836
U_8 sunInstruction = code[codeIndex];
1837
1838
step = sunJavaInstructionSizeTable[sunInstruction];
1839
1840
/* Unknown bytecodes should have been detected by the static verifier. */
1841
Trc_BCU_Assert_SupportedByteCode(sunInstruction);
1842
1843
/* TODO: A lot of cases in this switch are very similar, can we use a lookup table to match them faster? */
1844
switch (sunInstruction) {
1845
case CFR_BC_ireturn:
1846
case CFR_BC_freturn:
1847
case CFR_BC_areturn:
1848
case CFR_BC_lreturn:
1849
case CFR_BC_dreturn:
1850
case CFR_BC_return:
1851
if (returnType == returnBytecodeConversion[sunInstruction - CFR_BC_ireturn]) {
1852
code[codeIndex] = JBgenericReturn;
1853
} else if (returnType == PARAM_VOID) {
1854
code[codeIndex] = JBreturn1;
1855
} else {
1856
code[codeIndex] = JBreturn0;
1857
}
1858
break;
1859
1860
case CFR_BC_aload_0:
1861
if (CFR_BC_getfield == code[codeIndex + 1]) {
1862
code[codeIndex] = JBaload0getfield;
1863
}
1864
break;
1865
1866
case CFR_BC_ldc:
1867
cpIndex = PARAM_U8();
1868
if (isConstantInteger0(cpIndex)) {
1869
/* Don't allow constant int of 0, use iconst_0 - for string/class resolution later */
1870
code[codeIndex] = JBnop;
1871
code[codeIndex + 1] = JBiconst0;
1872
} else if (isConstantFloat0(cpIndex)) {
1873
/* Don't allow constant float of 0, use fconst_0 - for string/class resolution later */
1874
code[codeIndex] = JBnop;
1875
code[codeIndex + 1] = JBfconst0;
1876
} else {
1877
markConstantAsUsedByLDC(U_8(cpIndex));
1878
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::LDC);
1879
markConstantBasedOnCpType(cpIndex, true);
1880
}
1881
break;
1882
1883
case CFR_BC_wide: {
1884
U_8 nextInstruction = code[codeIndex + 1];
1885
/* byteswap and move up the U_16 local variable index */
1886
#if !defined(J9VM_ENV_LITTLE_ENDIAN)
1887
code[codeIndex + 1] = code[codeIndex + 2];
1888
code[codeIndex + 2] = code[codeIndex + 3];
1889
#else
1890
code[codeIndex + 1] = code[codeIndex + 3];
1891
/* Don't need to do: code[codeIndex + 2] = code[codeIndex + 2]; */
1892
#endif
1893
if (CFR_BC_iinc == nextInstruction) {
1894
code[codeIndex + 0] = JBiincw;
1895
/* byteswap and move up the U_16 increment */
1896
#if !defined(J9VM_ENV_LITTLE_ENDIAN)
1897
code[codeIndex + 3] = code[codeIndex + 4];
1898
code[codeIndex + 4] = code[codeIndex + 5];
1899
#else
1900
code[codeIndex + 3] = code[codeIndex + 5];
1901
/* Don't need to do: code[codeIndex + 4] = code[codeIndex + 4]; */
1902
#endif
1903
code[codeIndex + 5] = JBnop;
1904
} else {
1905
if (CFR_BC_istore <= nextInstruction) {
1906
/* Stores - assumes JB?storew in same order as CFR_BC_?store */
1907
code[codeIndex + 0] = (nextInstruction - CFR_BC_istore) + JBistorew;
1908
} else {
1909
/* Loads - assumes JB?loadw in same order as CFR_BC_?load */
1910
code[codeIndex + 0] = (nextInstruction - CFR_BC_iload) + JBiloadw;
1911
}
1912
code[codeIndex + 3] = JBnop;
1913
}
1914
/* Wide instruction are twice as wide as the original instructions */
1915
step = sunJavaInstructionSizeTable[nextInstruction] * 2;
1916
break;
1917
}
1918
1919
case CFR_BC_ldc_w:
1920
cpIndex = PARAM_U16();
1921
if (isConstantInteger0(cpIndex)) {
1922
/* Don't allow constant int of 0, use iconst_0 - for string/class resolution later */
1923
code[codeIndex + 0] = JBnop;
1924
code[codeIndex + 1] = JBiconst0;
1925
code[codeIndex + 2] = JBnop;
1926
} else if (isConstantFloat0(cpIndex)) {
1927
/* Don't allow constant float of 0, use fconst_0 - for string/class resolution later */
1928
code[codeIndex + 0] = JBnop;
1929
code[codeIndex + 1] = JBfconst0;
1930
code[codeIndex + 2] = JBnop;
1931
} else {
1932
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::REFERENCED);
1933
markConstantBasedOnCpType(cpIndex, true);
1934
}
1935
break;
1936
1937
case CFR_BC_ldc2_w:
1938
cpIndex = PARAM_U16();
1939
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::LDC2W);
1940
1941
if (isConstantLong(cpIndex)) {
1942
code[codeIndex + 0] = JBldc2lw;
1943
markConstantAsUsedByLDC2W(cpIndex);
1944
} else if (isConstantDouble(cpIndex)) {
1945
code[codeIndex + 0] = JBldc2dw;
1946
markConstantAsUsedByLDC2W(cpIndex);
1947
} else if (isConstantDynamic(cpIndex)) {
1948
code[codeIndex + 0] = constantDynamicType(cpIndex);
1949
markConstantDynamicAsReferenced(cpIndex);
1950
} else {
1951
Trc_BCU_Assert_ShouldNeverHappen();
1952
}
1953
break;
1954
1955
case CFR_BC_tableswitch: {
1956
codeIndex += 4 - (codeIndex & 3); /* step past instruction + pad */
1957
SWAP_I32(codeIndex);
1958
codeIndex += sizeof(I_32); /* default offset */
1959
I_32 low = SWAP_I32_GET(codeIndex);
1960
codeIndex += sizeof(I_32);
1961
I_32 high = SWAP_I32_GET(codeIndex);
1962
codeIndex += sizeof(I_32);
1963
I_32 noffsets = high - low + 1;
1964
#if defined(J9VM_ENV_LITTLE_ENDIAN)
1965
for (U_32 offsetsCount = high - low + 1; 0 != offsetsCount; --offsetsCount) {
1966
SWAP_I32(codeIndex);
1967
codeIndex += sizeof(I_32);
1968
}
1969
#else
1970
codeIndex += noffsets * sizeof(I_32);
1971
#endif
1972
step = 0; /* codeIndex increment has been handled already */
1973
branchCount += noffsets + 1;
1974
break;
1975
}
1976
1977
case CFR_BC_lookupswitch: {
1978
codeIndex += 4 - (codeIndex & 3); /* step past instruction + pad */
1979
SWAP_I32(codeIndex);
1980
codeIndex += sizeof(I_32); /* default offset */
1981
I_32 npairs = SWAP_I32_GET(codeIndex);
1982
codeIndex += sizeof(I_32);
1983
#if defined(J9VM_ENV_LITTLE_ENDIAN)
1984
for (I_32 count = npairs; 0 != count; --count) {
1985
SWAP_I32(codeIndex);
1986
codeIndex += sizeof(I_32);
1987
SWAP_I32(codeIndex);
1988
codeIndex += sizeof(I_32);
1989
}
1990
#else
1991
codeIndex += npairs * 2 * sizeof(I_32);
1992
#endif
1993
step = 0; /* codeIndex increment has been handled already */
1994
branchCount += npairs + 1;
1995
break;
1996
}
1997
1998
case CFR_BC_invokevirtual:
1999
UDATA methodHandleInvocation;
2000
cpIndex = PARAM_U16();
2001
2002
methodHandleInvocation = shouldConvertInvokeVirtualToMethodHandleBytecodeForMethodRef(cpIndex);
2003
if (methodHandleInvocation == CFR_BC_invokehandlegeneric) {
2004
code[codeIndex + 0] = CFR_BC_invokehandlegeneric;
2005
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INVOKE_HANDLEGENERIC);
2006
markMethodRefAsUsedByInvokeHandleGeneric(cpIndex);
2007
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasMethodHandleInvokes;
2008
} else if (methodHandleInvocation == CFR_BC_invokehandle) {
2009
code[codeIndex + 0] = CFR_BC_invokehandle;
2010
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INVOKE_HANDLEEXACT);
2011
markMethodRefAsUsedByInvokeHandle(cpIndex);
2012
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasMethodHandleInvokes;
2013
} else if (shouldConvertInvokeVirtualToInvokeSpecialForMethodRef(cpIndex)) {
2014
code[codeIndex + 0] = CFR_BC_invokespecial;
2015
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INVOKE_SPECIAL);
2016
markMethodRefAsUsedByInvokeSpecial(cpIndex);
2017
} else {
2018
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INVOKE_VIRTUAL);
2019
markMethodRefAsUsedByInvokeVirtual(cpIndex);
2020
}
2021
break;
2022
2023
case CFR_BC_invokeinterface:
2024
cpIndex = PARAM_U16();
2025
markMethodRefAsUsedByInvokeInterface(cpIndex);
2026
addBytecodeFixupEntry(entry++, codeIndex + 3, cpIndex, ConstantPoolMap::INVOKE_INTERFACE);
2027
code[codeIndex + 0] = JBinvokeinterface2;
2028
code[codeIndex + 1] = JBnop;
2029
code[codeIndex + 2] = JBinvokeinterface;
2030
break;
2031
2032
case CFR_BC_invokedynamic:
2033
cpIndex = PARAM_U16();
2034
markInvokeDynamicInfoAsUsedByInvokeDynamic(cpIndex);
2035
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INVOKE_DYNAMIC);
2036
// TODO slam in JBnop2 to code[codeIndex + 3]?
2037
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasMethodHandleInvokes;
2038
break;
2039
2040
case CFR_BC_putfield:
2041
cpIndex = PARAM_U16();
2042
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::PUT_FIELD);
2043
markFieldRefAsUsedByPutField(cpIndex);
2044
break;
2045
case CFR_BC_invokespecial:
2046
cpIndex = PARAM_U16();
2047
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INVOKE_SPECIAL);
2048
markMethodRefAsUsedByInvokeSpecial(cpIndex);
2049
break;
2050
case CFR_BC_putstatic:
2051
cpIndex = PARAM_U16();
2052
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::PUT_STATIC);
2053
markFieldRefAsUsedByPutStatic(cpIndex);
2054
break;
2055
case CFR_BC_getfield:
2056
cpIndex = PARAM_U16();
2057
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::GET_FIELD);
2058
markFieldRefAsUsedByGetField(cpIndex);
2059
break;
2060
case CFR_BC_invokestatic:
2061
cpIndex = PARAM_U16();
2062
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INVOKE_STATIC);
2063
markMethodRefAsUsedByInvokeStatic(cpIndex);
2064
break;
2065
case CFR_BC_getstatic:
2066
cpIndex = PARAM_U16();
2067
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::GET_STATIC);
2068
markFieldRefAsUsedByGetStatic(cpIndex);
2069
break;
2070
case CFR_BC_new:
2071
cpIndex = PARAM_U16();
2072
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::NEW);
2073
markClassAsUsedByNew(cpIndex);
2074
if (CFR_BC_dup == code[codeIndex + 3]) {
2075
code[codeIndex] = JBnewdup;
2076
}
2077
break;
2078
case CFR_BC_anewarray:
2079
cpIndex = PARAM_U16();
2080
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::ANEW_ARRAY);
2081
markClassAsUsedByANewArray(cpIndex);
2082
break;
2083
case CFR_BC_multianewarray:
2084
cpIndex = PARAM_U16();
2085
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::MULTI_ANEW_ARRAY);
2086
markClassAsUsedByMultiANewArray(cpIndex);
2087
break;
2088
case CFR_BC_checkcast:
2089
cpIndex = PARAM_U16();
2090
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::CHECK_CAST);
2091
markClassAsUsedByCheckCast(cpIndex);
2092
break;
2093
case CFR_BC_instanceof:
2094
cpIndex = PARAM_U16();
2095
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::INSTANCE_OF);
2096
markClassAsUsedByInstanceOf(cpIndex);
2097
break;
2098
2099
#if defined(J9VM_ENV_LITTLE_ENDIAN)
2100
case CFR_BC_sipush: {
2101
/* byteswap U_16 */
2102
U_8 temp = code[codeIndex + 1];
2103
code[codeIndex + 1] = code[codeIndex + 2];
2104
code[codeIndex + 2] = temp;
2105
break;
2106
}
2107
#endif
2108
2109
case CFR_BC_ifeq:
2110
/* Fall through */
2111
case CFR_BC_ifne:
2112
/* Fall through */
2113
case CFR_BC_iflt:
2114
/* Fall through */
2115
case CFR_BC_ifge:
2116
/* Fall through */
2117
case CFR_BC_ifgt:
2118
/* Fall through */
2119
case CFR_BC_ifle:
2120
/* Fall through */
2121
case CFR_BC_if_icmplt:
2122
/* Fall through */
2123
case CFR_BC_if_icmpge:
2124
/* Fall through */
2125
case CFR_BC_if_icmpgt:
2126
/* Fall through */
2127
case CFR_BC_if_icmple:
2128
/* Fall through */
2129
case CFR_BC_if_icmpeq:
2130
/* Fall through */
2131
case CFR_BC_if_icmpne:
2132
/* Fall through */
2133
case CFR_BC_if_acmpeq:
2134
/* Fall through */
2135
case CFR_BC_if_acmpne:
2136
/* Fall through */
2137
case CFR_BC_ifnull:
2138
/* Fall through */
2139
case CFR_BC_ifnonnull:
2140
++branchCount;
2141
/* Fall through */
2142
2143
case CFR_BC_goto: {
2144
#if defined(J9VM_ENV_LITTLE_ENDIAN)
2145
U_8 temp = code[codeIndex + 1];
2146
code[codeIndex + 1] = code[codeIndex + 2];
2147
code[codeIndex + 2] = temp;
2148
#endif
2149
if (0 == (_methodsInfo[methodIndex].modifiers & J9AccMethodHasBackwardBranches)) {
2150
I_32 offset = I_32(*(I_16*)&code[codeIndex + 1]);
2151
if (offset <= 0) {
2152
/* The branch wasn't positive, so mark the method as containing backward branches. */
2153
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasBackwardBranches;
2154
}
2155
}
2156
break;
2157
}
2158
2159
case CFR_BC_goto_w: {
2160
SWAP_I32(codeIndex + 1);
2161
if (0 == (_methodsInfo[methodIndex].modifiers & J9AccMethodHasBackwardBranches)) {
2162
I_32 offset = *(I_32*)&code[codeIndex + 1];
2163
if (offset <= 0) {
2164
/* The branch wasn't positive, so mark the method as containing backward branches. */
2165
_methodsInfo[methodIndex].modifiers |= J9AccMethodHasBackwardBranches;
2166
}
2167
}
2168
break;
2169
}
2170
2171
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2172
case CFR_BC_aconst_init:
2173
if (_classFile->majorVersion >= VALUE_TYPES_MAJOR_VERSION) {
2174
cpIndex = PARAM_U16();
2175
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::ACONST_INIT);
2176
markClassAsUsedByAconst_init(cpIndex);
2177
}
2178
break;
2179
case CFR_BC_withfield:
2180
if (_classFile->majorVersion >= VALUE_TYPES_MAJOR_VERSION) {
2181
cpIndex = PARAM_U16();
2182
addBytecodeFixupEntry(entry++, codeIndex + 1, cpIndex, ConstantPoolMap::WITH_FIELD);
2183
markFieldRefAsUsedByWithField(cpIndex);
2184
}
2185
break;
2186
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
2187
2188
default:
2189
/* Do nothing */
2190
break;
2191
}
2192
}
2193
2194
branchCount += _classFile->methods[methodIndex].codeAttribute->exceptionTableLength;
2195
if (_maxBranchCount < branchCount) {
2196
_maxBranchCount = branchCount;
2197
}
2198
2199
/* Let the buffer manager reclaim the unused part of the fixup table. */
2200
UDATA actualFixupTableSize = UDATA(entry) - UDATA(fixupTable);
2201
_bufferManager->reclaim(fixupTable, actualFixupTableSize);
2202
_methodsInfo[methodIndex].byteCodeFixupTable = fixupTable;
2203
_methodsInfo[methodIndex].byteCodeFixupCount = U_32(actualFixupTableSize / sizeof(BytecodeFixupEntry));
2204
_methodsInfo[methodIndex].isByteCodeFixupDone = false;
2205
}
2206
#undef SWAP_I32
2207
#undef SWAP_I32_GET
2208
#undef PARAM_I16
2209
#undef PARAM_U16
2210
#undef PARAM_U8
2211
2212
U_8 *
2213
ClassFileOracle::walkStackMapSlots(U_8 *framePointer, U_16 typeInfoCount)
2214
{
2215
ROMCLASS_VERBOSE_PHASE_HOT(_context, ClassFileStackMapSlotsAnalysis);
2216
U_8 typeInfoType;
2217
U_16 cpIndex;
2218
U_16 offset;
2219
2220
/*
2221
* Type info entries are variable sized and distinguished by a 8-bit type tag.
2222
* Most entry types contain only the tag. The exceptions are described below.
2223
*/
2224
for(U_16 typeInfoIndex = 0; typeInfoIndex < typeInfoCount; ++typeInfoIndex) {
2225
NEXT_U8(typeInfoType, framePointer); /* Extract typeInfoType */
2226
switch (typeInfoType) {
2227
case CFR_STACKMAP_TYPE_OBJECT:
2228
/*
2229
* OBJECT {
2230
* U_8 type
2231
* U_16 cpIndex
2232
* };
2233
*/
2234
NEXT_U16(cpIndex, framePointer); /* Extract cpIndex */
2235
markClassAsReferenced(cpIndex);
2236
break;
2237
case CFR_STACKMAP_TYPE_NEW_OBJECT:
2238
/*
2239
* NEW_OBJECT {
2240
* U_8 type
2241
* U_16 offset
2242
* };
2243
*/
2244
NEXT_U16(offset, framePointer); /* Extract offset */
2245
break;
2246
default:
2247
/* do nothing */
2248
break;
2249
}
2250
}
2251
2252
return framePointer;
2253
}
2254
2255
bool
2256
ClassFileOracle::methodIsFinalize(U_16 methodIndex, bool isForwarder)
2257
{
2258
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsFinalize);
2259
2260
#define FINALIZE_NAME "finalize"
2261
#define FINALIZE_SIG "()V"
2262
if (
2263
(0 == (_classFile->methods[methodIndex].accessFlags & CFR_ACC_STATIC))
2264
&& isUTF8AtIndexEqualToString(_classFile->methods[methodIndex].descriptorIndex, FINALIZE_SIG, sizeof(FINALIZE_SIG))
2265
&& isUTF8AtIndexEqualToString(_classFile->methods[methodIndex].nameIndex, FINALIZE_NAME, sizeof(FINALIZE_NAME))
2266
) {
2267
return true;
2268
}
2269
#undef FINALIZE_NAME
2270
#undef FINALIZE_SIG
2271
2272
return false;
2273
}
2274
2275
2276
2277
bool
2278
ClassFileOracle::methodIsEmpty(U_16 methodIndex)
2279
{
2280
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsEmpty);
2281
if (0 == (_classFile->methods[methodIndex].accessFlags & (CFR_ACC_ABSTRACT | CFR_ACC_NATIVE | CFR_ACC_SYNCHRONIZED))) {
2282
U_8 instruction = _classFile->methods[methodIndex].codeAttribute->code[0];
2283
if ((CFR_BC_ireturn <= instruction) && (instruction <= CFR_BC_return)) {
2284
return true;
2285
}
2286
}
2287
return false;
2288
}
2289
2290
bool
2291
ClassFileOracle::methodIsObjectConstructor(U_16 methodIndex)
2292
{
2293
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsObjectConstructor);
2294
2295
if ((0 == _classFile->superClass) &&
2296
(0 == (_classFile->methods[methodIndex].accessFlags & (CFR_ACC_ABSTRACT | CFR_ACC_STATIC | CFR_ACC_PRIVATE | CFR_ACC_SYNCHRONIZED))) &&
2297
('<' == getUTF8Data(_classFile->methods[methodIndex].nameIndex)[0]))
2298
{
2299
return true;
2300
}
2301
2302
return false;
2303
}
2304
2305
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2306
/**
2307
* Determine if a method is constructor of a non-Value Type (Value Type constructors are static).
2308
*
2309
* @param methodIndex[in] the method index
2310
*
2311
* @returns true if the method is a constructor of a non-Value Type, false if not.
2312
*/
2313
bool
2314
ClassFileOracle::methodIsConstructor(U_16 methodIndex)
2315
{
2316
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsConstructor);
2317
2318
if (J9_ARE_NO_BITS_SET(_classFile->methods[methodIndex].accessFlags, (CFR_ACC_ABSTRACT | CFR_ACC_STATIC | CFR_ACC_SYNCHRONIZED))
2319
&& ('<' == getUTF8Data(_classFile->methods[methodIndex].nameIndex)[0])
2320
) {
2321
return true;
2322
}
2323
2324
return false;
2325
}
2326
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
2327
2328
/**
2329
* Determine if a method is <clinit>.
2330
*
2331
* @param methodIndex[in] the method index
2332
*
2333
* @returns true if the method is <clinit>, false if not
2334
*/
2335
bool
2336
ClassFileOracle::methodIsClinit(U_16 methodIndex)
2337
{
2338
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsClinit);
2339
2340
/* Use a quick check - assume any static method starting with < is <clinit>.
2341
* This can not be harmful, as the worst thing that happens is we would lose
2342
* the performance optimization on questionable class files.
2343
*/
2344
if ((_classFile->methods[methodIndex].accessFlags & CFR_ACC_STATIC) &&
2345
('<' == getUTF8Data(_classFile->methods[methodIndex].nameIndex)[0]))
2346
{
2347
return true;
2348
}
2349
2350
return false;
2351
}
2352
2353
/* answers non-zero if this method simply forwards to its superclass.
2354
A forwarder method is not synchronized.
2355
Forwarder methods must have return type void (because right now we only care if it forwards to an empty method)
2356
*/
2357
2358
bool
2359
ClassFileOracle::methodIsForwarder(U_16 methodIndex)
2360
{
2361
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsForwarder);
2362
if (_classFile->methods[methodIndex].accessFlags & (CFR_ACC_ABSTRACT | CFR_ACC_NATIVE | CFR_ACC_SYNCHRONIZED | CFR_ACC_STATIC)) {
2363
return false;
2364
}
2365
2366
/* Must return void */
2367
U_16 signatureIndex = _classFile->methods[methodIndex].descriptorIndex;
2368
U_8 *signatureData = getUTF8Data(signatureIndex);
2369
U_16 signatureLength = getUTF8Length(signatureIndex);
2370
if ((signatureData[signatureLength - 1]) != 'V') {
2371
return false;
2372
}
2373
2374
J9CfrAttributeCode *codeAttribute = _classFile->methods[methodIndex].codeAttribute;
2375
2376
/* ensure that there are no exception handlers */
2377
if (codeAttribute->exceptionTableLength > 0) {
2378
return false;
2379
}
2380
2381
/* check that there are no temps */
2382
U_8 argCount = _methodsInfo[methodIndex].sendSlotCount;
2383
++argCount; /* not static */
2384
U_16 tempCount = codeAttribute->maxLocals;
2385
if (tempCount >= argCount) {
2386
tempCount -= argCount;
2387
} else {
2388
Trc_BCU_Assert_Equals(0, tempCount);
2389
}
2390
2391
if (0 != tempCount) {
2392
return false;
2393
}
2394
2395
IDATA thisArg = 0;
2396
U_8 *code = codeAttribute->code;
2397
for (U_32 codeIndex = 0; ;codeIndex++) {
2398
switch (code[codeIndex]) {
2399
case CFR_BC_aload_0:
2400
if (thisArg++ != 0) {
2401
return false;
2402
}
2403
break;
2404
case CFR_BC_iload_1:
2405
case CFR_BC_fload_1:
2406
case CFR_BC_aload_1:
2407
if (thisArg++ != 1) {
2408
return false;
2409
}
2410
break;
2411
case CFR_BC_dload_1:
2412
case CFR_BC_lload_1:
2413
if (thisArg != 1) {
2414
return false;
2415
}
2416
thisArg += 2;
2417
break;
2418
case CFR_BC_iload_2:
2419
case CFR_BC_fload_2:
2420
case CFR_BC_aload_2:
2421
if (thisArg++ != 2) {
2422
return false;
2423
}
2424
break;
2425
case CFR_BC_dload_2:
2426
case CFR_BC_lload_2:
2427
if (thisArg != 2) {
2428
return false;
2429
}
2430
thisArg += 2;
2431
break;
2432
case CFR_BC_iload_3:
2433
case CFR_BC_fload_3:
2434
case CFR_BC_aload_3:
2435
if (thisArg++ != 3) {
2436
return false;
2437
}
2438
break;
2439
case CFR_BC_dload_3:
2440
case CFR_BC_lload_3:
2441
if (thisArg != 3) {
2442
return false;
2443
}
2444
thisArg += 2;
2445
break;
2446
case CFR_BC_iload:
2447
case CFR_BC_fload:
2448
case CFR_BC_aload:
2449
if (thisArg++ != code[++codeIndex]) {
2450
return false;
2451
}
2452
break;
2453
case CFR_BC_dload:
2454
case CFR_BC_lload:
2455
if (thisArg != code[++codeIndex]) {
2456
return false;
2457
}
2458
thisArg += 2;
2459
break;
2460
case CFR_BC_invokespecial: {
2461
if (thisArg++ != argCount) {
2462
/* we haven't pushed all of our arguments */
2463
return false;
2464
}
2465
#define PARAM_U16() (U_16(code[codeIndex + 1]) << 8) | U_16(code[codeIndex + 2])
2466
J9CfrConstantPoolInfo *methodRef = (J9CfrConstantPoolInfo *) &_classFile->constantPool[PARAM_U16()];
2467
#undef PARAM_U16
2468
2469
/* use identity comparisons for name and sig for simplicity. Since they came from the same
2470
class file they're almost certainly identical,and if not we just run a bit slower */
2471
2472
/* check that this is a super send */
2473
if ( methodRef->slot1 != _classFile->superClass ) {
2474
return false;
2475
}
2476
J9CfrConstantPoolInfo *nas = (J9CfrConstantPoolInfo *) &_classFile->constantPool[methodRef->slot2];
2477
if ( !isUTF8AtIndexEqualToString(nas->slot1, (const char *)getUTF8Data(_classFile->methods[methodIndex].nameIndex), getUTF8Length(_classFile->methods[methodIndex].nameIndex)+1)) {
2478
return false;
2479
}
2480
if ( !isUTF8AtIndexEqualToString(nas->slot2, (const char *)getUTF8Data(_classFile->methods[methodIndex].descriptorIndex), getUTF8Length(_classFile->methods[methodIndex].descriptorIndex)+1)) {
2481
return false;
2482
}
2483
2484
/* check that the next instruction is a void return */
2485
if (CFR_BC_return == code[codeIndex+3]) {
2486
return true;
2487
}
2488
2489
/* fall through */
2490
}
2491
default:
2492
return false;
2493
}
2494
}
2495
2496
/* can't get here, but add a return false just in case */
2497
return false;
2498
}
2499
2500
2501
2502
bool
2503
ClassFileOracle::methodIsGetter (U_16 methodIndex)
2504
{
2505
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsGetter);
2506
2507
2508
if (0 != (_classFile->methods[methodIndex].accessFlags & (CFR_ACC_ABSTRACT | CFR_ACC_NATIVE | CFR_ACC_SYNCHRONIZED | CFR_ACC_STATIC))) {
2509
return false;
2510
}
2511
2512
/* ensure that there are no exception handlers */
2513
if (0 != _classFile->methods[methodIndex].codeAttribute->exceptionTableLength) {
2514
return false;
2515
}
2516
2517
/* ensure that there's exactly one argument (the receiver) */
2518
if (')' != getUTF8Data(_classFile->methods[methodIndex].descriptorIndex)[1]) {
2519
return false;
2520
}
2521
2522
/* this exact bytecode sequence */
2523
/* JBaload0getfield means JBgetfield follows
2524
* NOTEs:
2525
* - JBaload0getfield is actually CFR_BC_aload_0 followed by CFR_BC_getfield in Sun bytecodes
2526
* - JBgenericReturn is any one of the return bytecodes CFR_BC_*return */
2527
U_8* sunBytecodes = _classFile->methods[methodIndex].codeAttribute->code;
2528
if ((CFR_BC_aload_0 == sunBytecodes[0]) && (CFR_BC_getfield == sunBytecodes[1]) && (CFR_BC_ireturn <= sunBytecodes[4]) && (sunBytecodes[4] <= CFR_BC_return)) {
2529
return true;
2530
}
2531
2532
return false;
2533
}
2534
2535
bool
2536
ClassFileOracle::methodIsVirtual(U_16 methodIndex)
2537
{
2538
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsVirtual);
2539
2540
/* static and private methods are never virtual */
2541
if (0 != (_classFile->methods[methodIndex].accessFlags & (CFR_ACC_STATIC | CFR_ACC_PRIVATE))) {
2542
return false;
2543
}
2544
2545
/* <init> (and <clinit>) are not virtual */
2546
if ('<' == getUTF8Data(_classFile->methods[methodIndex].nameIndex)[0]) {
2547
return false;
2548
}
2549
2550
if (0 == _classFile->superClass) { // TODO is this the same as J9ROMCLASS_SUPERCLASSNAME(romClass) == NULL???
2551
/* check for the final methods in object */
2552
if (methodIsFinalInObject (
2553
getUTF8Length(_classFile->methods[methodIndex].nameIndex),
2554
getUTF8Data(_classFile->methods[methodIndex].nameIndex),
2555
getUTF8Length(_classFile->methods[methodIndex].descriptorIndex),
2556
getUTF8Data(_classFile->methods[methodIndex].descriptorIndex)
2557
)) {
2558
return false;
2559
}
2560
}
2561
return true;
2562
}
2563
2564
bool
2565
ClassFileOracle::methodIsNonStaticNonAbstract(U_16 methodIndex)
2566
{
2567
ROMCLASS_VERBOSE_PHASE_HOT(_context, IsMethodNonStaticNonAbstract);
2568
2569
return J9_ARE_NO_BITS_SET(_classFile->methods[methodIndex].accessFlags, (CFR_ACC_STATIC | CFR_ACC_ABSTRACT));
2570
}
2571
2572
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2573
bool
2574
ClassFileOracle::methodIsNonStaticSynchronized(U_16 methodIndex)
2575
{
2576
ROMCLASS_VERBOSE_PHASE_HOT(_context, MethodIsNonStaticSynchronized);
2577
if (J9_ARE_NO_BITS_SET(_classFile->methods[methodIndex].accessFlags, CFR_ACC_STATIC)
2578
&& J9_ARE_ALL_BITS_SET(_classFile->methods[methodIndex].accessFlags, CFR_ACC_SYNCHRONIZED)
2579
) {
2580
return true;
2581
}
2582
return false;
2583
}
2584
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
2585
2586
/**
2587
* Method to determine if an invokevirtual instruction should be re-written to be an
2588
* invokehandle or invokehandlegeneric bytecode. Modifications as follows:
2589
* invokevirtual MethodHandle.invokeExact(any signature) --> invokehandle
2590
* invokevirtual MethodHandle.invoke(any signature) --> invokehandlegeneric
2591
*
2592
* @param methodRefCPIndex - the constantpool index used in the invokevirtual bytecode
2593
* @return the invoke* bytecode to be used if it needs to be rewritten or 0
2594
* ie: One of: CFR_BC_invokehandlegeneric, CFR_BC_invokehandle, 0
2595
*/
2596
UDATA
2597
ClassFileOracle::shouldConvertInvokeVirtualToMethodHandleBytecodeForMethodRef(U_16 methodRefCPIndex)
2598
{
2599
J9CfrConstantPoolInfo *methodInfo = &_classFile->constantPool[methodRefCPIndex];
2600
J9CfrConstantPoolInfo *targetClassName = &_classFile->constantPool[ _classFile->constantPool[methodInfo->slot1].slot1 ];
2601
J9CfrConstantPoolInfo *nas = &_classFile->constantPool[methodInfo->slot2];
2602
J9CfrConstantPoolInfo *name = &_classFile->constantPool[nas->slot1];
2603
UDATA result = 0;
2604
2605
/* Invoking against java.lang.invoke.MethodHandle. */
2606
if (J9UTF8_LITERAL_EQUALS(targetClassName->bytes, targetClassName->slot1, "java/lang/invoke/MethodHandle")) {
2607
if (J9UTF8_LITERAL_EQUALS(name->bytes, name->slot1, "invokeExact")) {
2608
/* MethodHandle.invokeExact */
2609
result = CFR_BC_invokehandle;
2610
} else if (J9UTF8_LITERAL_EQUALS(name->bytes, name->slot1, "invoke")) {
2611
/* MethodHandle.invoke */
2612
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
2613
result = CFR_BC_invokehandle;
2614
#else /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
2615
result = CFR_BC_invokehandlegeneric;
2616
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
2617
}
2618
}
2619
2620
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
2621
/* Invoking against java.lang.invoke.VarHandle. */
2622
if (J9UTF8_LITERAL_EQUALS(targetClassName->bytes, targetClassName->slot1, "java/lang/invoke/VarHandle")
2623
&& VM_VMHelpers::isPolymorphicVarHandleMethod((const U_8 *)name->bytes, name->slot1)
2624
) {
2625
result = CFR_BC_invokehandle;
2626
}
2627
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
2628
2629
return result;
2630
}
2631
2632
bool
2633
ClassFileOracle::shouldConvertInvokeVirtualToInvokeSpecialForMethodRef(U_16 methodRefCPIndex)
2634
{
2635
ROMCLASS_VERBOSE_PHASE_HOT(_context, ShouldConvertInvokeVirtualToInvokeSpecial);
2636
2637
J9CfrConstantPoolInfo *methodInfo = &_classFile->constantPool[methodRefCPIndex];
2638
J9CfrConstantPoolInfo *className = &_classFile->constantPool[ _classFile->constantPool[_classFile->thisClass].slot1 ];
2639
J9CfrConstantPoolInfo *targetClassName = &_classFile->constantPool[ _classFile->constantPool[methodInfo->slot1].slot1 ];
2640
J9CfrConstantPoolInfo *nas = &_classFile->constantPool[methodInfo->slot2];
2641
J9CfrConstantPoolInfo *name = &_classFile->constantPool[nas->slot1];
2642
J9CfrConstantPoolInfo *sig = &_classFile->constantPool[nas->slot2];
2643
2644
/* check for wait, notify, notifyAll and getClass first */
2645
if (methodIsFinalInObject(name->slot1, name->bytes, sig->slot1, sig->bytes)) {
2646
return true;
2647
}
2648
2649
/* Interfaces are allowed to call methods in java.lang.Object but other invokevirtual must fail */
2650
if (J9_ARE_ANY_BITS_SET(_classFile->accessFlags, CFR_ACC_INTERFACE)) {
2651
return false;
2652
}
2653
2654
/* check for private methods (this is unlikely to be generated by a working compiler,
2655
* but it is legal, so check for the case and force it to be an invokespecial)
2656
*/
2657
// TODO this hurts performance significantly - can we get away with not doing this? E.g. does it inflate vtables? Does the JIT do "the right thing"?
2658
if (J9UTF8_DATA_EQUALS(className->bytes, className->slot1, targetClassName->bytes, targetClassName->slot1)) {
2659
for (UDATA methodIndex = 0; methodIndex < _classFile->methodsCount; methodIndex++) {
2660
J9CfrMethod* method = &_classFile->methods[methodIndex];
2661
J9CfrConstantPoolInfo *aName = &_classFile->constantPool[method->nameIndex];
2662
J9CfrConstantPoolInfo *aSig = &_classFile->constantPool[method->descriptorIndex];
2663
if ((aName->slot1 == name->slot1)
2664
&& (aSig->slot1 == sig->slot1)
2665
&& (0 == memcmp(aName->bytes, name->bytes, name->slot1))
2666
&& (0 == memcmp(aSig->bytes, sig->bytes, sig->slot1))
2667
) {
2668
/* we found the method -- is it private or final? */
2669
return (method->accessFlags & (CFR_ACC_PRIVATE | CFR_ACC_FINAL)) != 0;
2670
}
2671
}
2672
}
2673
return false;
2674
}
2675
2676
void
2677
ClassFileOracle::markClassAsReferenced(U_16 classCPIndex)
2678
{
2679
Trc_BCU_Assert_Equals(CFR_CONSTANT_Class, _classFile->constantPool[classCPIndex].tag);
2680
2681
markConstantAsReferenced(classCPIndex); /* Mark class */
2682
markClassNameAsReferenced(classCPIndex);
2683
}
2684
2685
void
2686
ClassFileOracle::markClassNameAsReferenced(U_16 classCPIndex)
2687
{
2688
Trc_BCU_Assert_Equals(CFR_CONSTANT_Class, _classFile->constantPool[classCPIndex].tag);
2689
2690
markConstantUTF8AsReferenced(_classFile->constantPool[classCPIndex].slot1); /* Mark class name UTF8 */
2691
}
2692
2693
void
2694
ClassFileOracle::markStringAsReferenced(U_16 cpIndex)
2695
{
2696
Trc_BCU_Assert_Equals(CFR_CONSTANT_String, _classFile->constantPool[cpIndex].tag);
2697
2698
markConstantAsReferenced(cpIndex); /* Mark string */
2699
markConstantUTF8AsReferenced(_classFile->constantPool[cpIndex].slot1); /* Mark UTF8 */
2700
}
2701
2702
void
2703
ClassFileOracle::markMethodTypeAsReferenced(U_16 cpIndex)
2704
{
2705
Trc_BCU_Assert_Equals(CFR_CONSTANT_MethodType, _classFile->constantPool[cpIndex].tag);
2706
2707
markConstantAsReferenced(cpIndex); /* Mark MethodType */
2708
markConstantUTF8AsReferenced(_classFile->constantPool[cpIndex].slot1); /* Mark UTF8 */
2709
}
2710
2711
void
2712
ClassFileOracle::markMethodHandleAsReferenced(U_16 cpIndex)
2713
{
2714
2715
Trc_BCU_Assert_Equals(CFR_CONSTANT_MethodHandle, _classFile->constantPool[cpIndex].tag);
2716
2717
markConstantAsReferenced(cpIndex); /* Mark MethodHandle */
2718
2719
switch(_classFile->constantPool[cpIndex].slot1) {
2720
case MH_REF_GETFIELD:
2721
markFieldRefAsUsedByGetField(_classFile->constantPool[cpIndex].slot2);
2722
break;
2723
case MH_REF_GETSTATIC:
2724
markFieldRefAsUsedByGetStatic(_classFile->constantPool[cpIndex].slot2);
2725
break;
2726
case MH_REF_PUTFIELD:
2727
markFieldRefAsUsedByPutField(_classFile->constantPool[cpIndex].slot2);
2728
break;
2729
case MH_REF_PUTSTATIC:
2730
markFieldRefAsUsedByPutStatic(_classFile->constantPool[cpIndex].slot2);
2731
break;
2732
case MH_REF_INVOKEVIRTUAL:
2733
markMethodRefAsUsedByInvokeVirtual(_classFile->constantPool[cpIndex].slot2);
2734
break;
2735
case MH_REF_INVOKESTATIC:
2736
markMethodRefAsUsedByInvokeStatic(_classFile->constantPool[cpIndex].slot2);
2737
break;
2738
case MH_REF_INVOKESPECIAL:
2739
case MH_REF_NEWINVOKESPECIAL:
2740
markMethodRefAsUsedByInvokeSpecial(_classFile->constantPool[cpIndex].slot2);
2741
break;
2742
case MH_REF_INVOKEINTERFACE:
2743
markMethodRefAsUsedByInvokeInterface(_classFile->constantPool[cpIndex].slot2);
2744
break;
2745
}
2746
}
2747
2748
void
2749
ClassFileOracle::markNameAndDescriptorAsReferenced(U_16 nasCPIndex)
2750
{
2751
Trc_BCU_Assert_Equals(CFR_CONSTANT_NameAndType, _classFile->constantPool[nasCPIndex].tag);
2752
2753
markConstantNameAndTypeAsReferenced(nasCPIndex); /* Mark name-and-signature */
2754
markConstantUTF8AsReferenced(_classFile->constantPool[nasCPIndex].slot1); /* Mark name UTF8 */
2755
markConstantUTF8AsReferenced(_classFile->constantPool[nasCPIndex].slot2); /* Mark descriptor UTF8 */
2756
}
2757
2758
void
2759
ClassFileOracle::markFieldRefAsReferenced(U_16 cpIndex)
2760
{
2761
Trc_BCU_Assert_Equals(CFR_CONSTANT_Fieldref, _classFile->constantPool[cpIndex].tag);
2762
2763
// TODO markConstantAsReferenced(cpIndex); -- this breaks the iteration strategy in ROMClassBuilder
2764
markClassAsReferenced(_classFile->constantPool[cpIndex].slot1);
2765
markNameAndDescriptorAsReferenced(_classFile->constantPool[cpIndex].slot2);
2766
}
2767
2768
void
2769
ClassFileOracle::markMethodRefAsReferenced(U_16 cpIndex)
2770
{
2771
Trc_BCU_Assert_True((CFR_CONSTANT_Methodref == _classFile->constantPool[cpIndex].tag) || (CFR_CONSTANT_InterfaceMethodref == _classFile->constantPool[cpIndex].tag));
2772
2773
// TODO markConstantAsReferenced(cpIndex); -- this breaks the iteration strategy in ROMClassBuilder
2774
markClassAsReferenced(_classFile->constantPool[cpIndex].slot1);
2775
markNameAndDescriptorAsReferenced(_classFile->constantPool[cpIndex].slot2);
2776
}
2777
2778
/* Mark the parts of a MethodRef used for a MethodTypeRef - just the signature of the methodref's nas.
2779
* The invokehandle/invokehandlegeneric instruction will only ever preserve the signature.
2780
*/
2781
void
2782
ClassFileOracle::markMethodRefForMHInvocationAsReferenced(U_16 cpIndex)
2783
{
2784
markMethodRefAsReferenced(cpIndex);
2785
}
2786
2787
void
2788
ClassFileOracle::markConstantAsReferenced(U_16 cpIndex)
2789
{
2790
if (0 != cpIndex) { /* Never, never, never mark constantPool[0] referenced */
2791
_constantPoolMap->markConstantAsReferenced(cpIndex);
2792
}
2793
}
2794
2795
void
2796
ClassFileOracle::markConstantUTF8AsReferenced(U_16 cpIndex)
2797
{
2798
if (0 != cpIndex) { /* Never, never, never mark constantPool[0] referenced */
2799
_constantPoolMap->markConstantUTF8AsReferenced(cpIndex);
2800
}
2801
}
2802
2803
void
2804
ClassFileOracle::markConstantNameAndTypeAsReferenced(U_16 cpIndex)
2805
{
2806
if (0 != cpIndex) { /* Never, never, never mark constantPool[0] referenced */
2807
_constantPoolMap->markConstantNameAndTypeAsReferenced(cpIndex);
2808
}
2809
}
2810
2811
void
2812
ClassFileOracle::markConstantDynamicAsReferenced(U_16 cpIndex)
2813
{
2814
markNameAndDescriptorAsReferenced(_classFile->constantPool[cpIndex].slot2);
2815
if (0 != cpIndex) { /* Never, never, never mark constantPool[0] referenced */
2816
_constantPoolMap->markConstantAsReferenced(cpIndex);
2817
}
2818
}
2819
2820
void
2821
ClassFileOracle::markConstantAsUsedByAnnotation(U_16 cpIndex)
2822
{
2823
UDATA cpTag = getCPTag(cpIndex);
2824
2825
if ((CFR_CONSTANT_Double == cpTag) || (CFR_CONSTANT_Long == cpTag)) {
2826
_constantPoolMap->markConstantAsReferencedDoubleSlot(cpIndex);
2827
} else if (CFR_CONSTANT_Utf8 == cpTag) {
2828
markConstantUTF8AsReferenced(cpIndex); /* Mark descriptor UTF8 */
2829
/* Is not equivalent to markConstantAsReferenced(), as that does something else for UTF8s. */
2830
_constantPoolMap->markConstantAsUsedByAnnotationUTF8(cpIndex);
2831
} else {
2832
markConstantAsReferenced(cpIndex);
2833
}
2834
}
2835
2836
void
2837
ClassFileOracle::markConstantAsUsedByLDC(U_8 cpIndex)
2838
{
2839
_constantPoolMap->markConstantAsUsedByLDC(cpIndex);
2840
}
2841
2842
void
2843
ClassFileOracle::markConstantAsUsedByLDC2W(U_16 cpIndex)
2844
{
2845
_constantPoolMap->markConstantAsReferencedDoubleSlot(cpIndex);
2846
}
2847
2848
void
2849
ClassFileOracle::markClassAsUsedByInstanceOf(U_16 classCPIndex)
2850
{
2851
markClassAsReferenced(classCPIndex);
2852
_constantPoolMap->markClassAsUsedByInstanceOf(classCPIndex);
2853
}
2854
2855
void
2856
ClassFileOracle::markClassAsUsedByCheckCast(U_16 classCPIndex)
2857
{
2858
markClassAsReferenced(classCPIndex);
2859
_constantPoolMap->markClassAsUsedByCheckCast(classCPIndex);
2860
}
2861
2862
void
2863
ClassFileOracle::markClassAsUsedByMultiANewArray(U_16 classCPIndex)
2864
{
2865
markClassAsReferenced(classCPIndex);
2866
_constantPoolMap->markClassAsUsedByMultiANewArray(classCPIndex);
2867
}
2868
2869
void
2870
ClassFileOracle::markClassAsUsedByANewArray(U_16 classCPIndex)
2871
{
2872
markClassAsReferenced(classCPIndex);
2873
_constantPoolMap->markClassAsUsedByANewArray(classCPIndex);
2874
}
2875
2876
void
2877
ClassFileOracle::markClassAsUsedByNew(U_16 classCPIndex)
2878
{
2879
markClassAsReferenced(classCPIndex);
2880
_constantPoolMap->markClassAsUsedByNew(classCPIndex);
2881
}
2882
2883
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2884
void
2885
ClassFileOracle::markClassAsUsedByAconst_init(U_16 classCPIndex)
2886
{
2887
markClassAsReferenced(classCPIndex);
2888
_constantPoolMap->markClassAsUsedByAconst_init(classCPIndex);
2889
}
2890
2891
void
2892
ClassFileOracle::markFieldRefAsUsedByWithField(U_16 fieldRefCPIndex)
2893
{
2894
markFieldRefAsReferenced(fieldRefCPIndex);
2895
_constantPoolMap->markFieldRefAsUsedByWithField(fieldRefCPIndex);
2896
}
2897
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
2898
2899
void
2900
ClassFileOracle::markFieldRefAsUsedByGetStatic(U_16 fieldRefCPIndex)
2901
{
2902
markFieldRefAsReferenced(fieldRefCPIndex);
2903
_constantPoolMap->markFieldRefAsUsedByGetStatic(fieldRefCPIndex);
2904
}
2905
2906
void
2907
ClassFileOracle::markFieldRefAsUsedByPutStatic(U_16 fieldRefCPIndex)
2908
{
2909
markFieldRefAsReferenced(fieldRefCPIndex);
2910
_constantPoolMap->markFieldRefAsUsedByPutStatic(fieldRefCPIndex);
2911
}
2912
2913
void
2914
ClassFileOracle::markFieldRefAsUsedByGetField(U_16 fieldRefCPIndex)
2915
{
2916
markFieldRefAsReferenced(fieldRefCPIndex);
2917
_constantPoolMap->markFieldRefAsUsedByGetField(fieldRefCPIndex);
2918
}
2919
2920
void
2921
ClassFileOracle::markFieldRefAsUsedByPutField(U_16 fieldRefCPIndex)
2922
{
2923
markFieldRefAsReferenced(fieldRefCPIndex);
2924
_constantPoolMap->markFieldRefAsUsedByPutField(fieldRefCPIndex);
2925
}
2926
2927
void
2928
ClassFileOracle::markMethodRefAsUsedByInvokeVirtual(U_16 methodRefCPIndex)
2929
{
2930
markMethodRefAsReferenced(methodRefCPIndex);
2931
_constantPoolMap->markMethodRefAsUsedByInvokeVirtual(methodRefCPIndex);
2932
}
2933
2934
void
2935
ClassFileOracle::markMethodRefAsUsedByInvokeSpecial(U_16 methodRefCPIndex)
2936
{
2937
markMethodRefAsReferenced(methodRefCPIndex);
2938
_constantPoolMap->markMethodRefAsUsedByInvokeSpecial(methodRefCPIndex);
2939
}
2940
2941
void
2942
ClassFileOracle::markMethodRefAsUsedByInvokeStatic(U_16 methodRefCPIndex)
2943
{
2944
markMethodRefAsReferenced(methodRefCPIndex);
2945
_constantPoolMap->markMethodRefAsUsedByInvokeStatic(methodRefCPIndex);
2946
}
2947
2948
void
2949
ClassFileOracle::markMethodRefAsUsedByInvokeInterface(U_16 methodRefCPIndex)
2950
{
2951
markMethodRefAsReferenced(methodRefCPIndex);
2952
_constantPoolMap->markMethodRefAsUsedByInvokeInterface(methodRefCPIndex);
2953
}
2954
2955
void
2956
ClassFileOracle::markMethodRefAsUsedByInvokeHandle(U_16 methodRefCPIndex)
2957
{
2958
markMethodRefForMHInvocationAsReferenced(methodRefCPIndex);
2959
_constantPoolMap->markMethodRefAsUsedByInvokeHandle(methodRefCPIndex);
2960
}
2961
2962
void
2963
ClassFileOracle::markMethodRefAsUsedByInvokeHandleGeneric(U_16 methodRefCPIndex)
2964
{
2965
markMethodRefForMHInvocationAsReferenced(methodRefCPIndex);
2966
_constantPoolMap->markMethodRefAsUsedByInvokeHandleGeneric(methodRefCPIndex);
2967
}
2968
2969
void
2970
ClassFileOracle::markInvokeDynamicInfoAsUsedByInvokeDynamic(U_16 cpIndex)
2971
{
2972
Trc_BCU_Assert_Equals(CFR_CONSTANT_InvokeDynamic, _classFile->constantPool[cpIndex].tag);
2973
2974
U_16 bsmIndex = _classFile->constantPool[cpIndex].slot1;
2975
if ((NULL == _bootstrapMethodsAttribute) || (bsmIndex >= _bootstrapMethodsAttribute->numberOfBootstrapMethods)) {
2976
_buildResult = GenericError;
2977
return;
2978
}
2979
2980
markNameAndDescriptorAsReferenced(_classFile->constantPool[cpIndex].slot2);
2981
_constantPoolMap->markInvokeDynamicInfoAsUsedByInvokeDynamic(cpIndex);
2982
}
2983
2984
void
2985
ClassFileOracle::markConstantBasedOnCpType(U_16 cpIndex, bool assertNotDoubleOrLong)
2986
{
2987
switch(getCPTag(cpIndex)) {
2988
case CFR_CONSTANT_String:
2989
markStringAsReferenced(cpIndex);
2990
break;
2991
case CFR_CONSTANT_Class:
2992
markClassAsReferenced(cpIndex);
2993
break;
2994
case CFR_CONSTANT_Integer:
2995
case CFR_CONSTANT_Float:
2996
markConstantAsReferenced(cpIndex);
2997
break;
2998
case CFR_CONSTANT_MethodHandle:
2999
markMethodHandleAsReferenced(cpIndex);
3000
break;
3001
case CFR_CONSTANT_MethodType:
3002
markMethodTypeAsReferenced(cpIndex);
3003
break;
3004
case CFR_CONSTANT_Double:
3005
case CFR_CONSTANT_Long:
3006
if (assertNotDoubleOrLong) {
3007
Trc_BCU_Assert_ShouldNeverHappen();
3008
break;
3009
}
3010
_constantPoolMap->markConstantAsReferencedDoubleSlot(cpIndex);
3011
break;
3012
case CFR_CONSTANT_Dynamic:
3013
markConstantDynamicAsReferenced(cpIndex);
3014
break;
3015
default:
3016
Trc_BCU_Assert_ShouldNeverHappen();
3017
}
3018
}
3019
3020