@@ -192,8 +192,12 @@ ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *c
192
192
_needsStaticConstantInit(false ),
193
193
_isRecord(false ),
194
194
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
195
+ _hasIdentityInterface (false ),
195
196
_isIdentityInterfaceNeeded(false ),
196
197
_isValueType(false ),
198
+ _hasNonStaticSynchronizedMethod(false ),
199
+ _hasNonStaticFields(false ),
200
+ _hasNonEmptyConstructor(false ),
197
201
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
198
202
_recordComponentCount (0 ),
199
203
_permittedSubclassesAttribute(NULL ),
@@ -226,6 +230,17 @@ ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *c
226
230
_buildResult = _constantPoolMap->getBuildResult ();
227
231
return ;
228
232
}
233
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
234
+ if (J9_ARE_ALL_BITS_SET (_classFile->accessFlags , CFR_ACC_VALUE_TYPE)
235
+ || J9_ARE_NO_BITS_SET (_classFile->accessFlags , CFR_ACC_ABSTRACT | CFR_ACC_INTERFACE)
236
+ ) {
237
+ /* *
238
+ * We care about whether there is a non-empty constructor only for non-value type abstract classes.
239
+ * Simply set _hasNonEmptyConstructor to true for value types, or concrete classes.
240
+ */
241
+ _hasNonEmptyConstructor = true ;
242
+ }
243
+ #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
229
244
230
245
/* analyze class file */
231
246
@@ -252,7 +267,12 @@ ClassFileOracle::ClassFileOracle(BufferManager *bufferManager, J9CfrClassFile *c
252
267
if (OK == _buildResult) {
253
268
walkFields ();
254
269
}
255
-
270
+
271
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
272
+ if (OK == _buildResult) {
273
+ checkAndRecordIsIdentityInterfaceNeeded ();
274
+ }
275
+ #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
256
276
if (OK == _buildResult) {
257
277
_constantPoolMap->computeConstantPoolMapAndSizes ();
258
278
if (!constantPoolMap->isOK ()) {
@@ -338,6 +358,9 @@ ClassFileOracle::walkFields()
338
358
*/
339
359
_hasFinalFields = true ;
340
360
}
361
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
362
+ _hasNonStaticFields = true ;
363
+ #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
341
364
}
342
365
343
366
for (U_16 attributeIndex = 0 ; (OK == _buildResult) && (attributeIndex < field->attributesCount ); ++attributeIndex) {
@@ -732,16 +755,45 @@ ClassFileOracle::walkInterfaces()
732
755
if (J9_ARE_ALL_BITS_SET (_classFile->accessFlags , CFR_ACC_VALUE_TYPE)) {
733
756
_isValueType = true ;
734
757
}
735
- if (!isValueType ()
736
- && !interfaceVisitor.wasIdentityInterfaceSeen ()
737
- && (getSuperClassNameIndex () != 0 ) /* j.l.Object has no superClass */
738
- && (J9_ARE_NO_BITS_SET (_classFile->accessFlags , CFR_ACC_ABSTRACT | CFR_ACC_INTERFACE))
739
- ) {
740
- _isIdentityInterfaceNeeded = true ;
741
- }
758
+ _hasIdentityInterface = interfaceVisitor.wasIdentityInterfaceSeen ();
742
759
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
743
760
}
744
761
762
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
763
+ void
764
+ ClassFileOracle::checkAndRecordIsIdentityInterfaceNeeded ()
765
+ {
766
+ if (isValueType ()) {
767
+ if (_hasIdentityInterface
768
+ || J9_ARE_ANY_BITS_SET (_classFile->accessFlags , CFR_ACC_ABSTRACT | CFR_ACC_INTERFACE)
769
+ || _hasNonStaticSynchronizedMethod
770
+ ) {
771
+ _buildResult = InvalidValueType;
772
+ }
773
+ } else {
774
+ if (!_hasIdentityInterface
775
+ && (getSuperClassNameIndex () != 0 ) /* j.l.Object has no superClass */
776
+ ) {
777
+ if (J9_ARE_NO_BITS_SET (_classFile->accessFlags , CFR_ACC_ABSTRACT | CFR_ACC_INTERFACE)) {
778
+ /* For concrete classes, IdentityInterface is needed. */
779
+ _isIdentityInterfaceNeeded = true ;
780
+ } else {
781
+ /* *
782
+ * For abstract classes, IdentityInterface is needed only when it has non-static fields,
783
+ * non-static synchronized method or non-empty constructor.
784
+ */
785
+ if ((_hasNonStaticFields)
786
+ || (_hasNonStaticSynchronizedMethod)
787
+ || (_hasNonEmptyConstructor)
788
+ ) {
789
+ _isIdentityInterfaceNeeded = true ;
790
+ }
791
+ }
792
+ }
793
+ }
794
+ }
795
+ #endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
796
+
745
797
void
746
798
ClassFileOracle::walkMethods ()
747
799
{
@@ -777,6 +829,17 @@ ClassFileOracle::walkMethods()
777
829
if (methodIsObjectConstructor (methodIndex)) {
778
830
_methodsInfo[methodIndex].modifiers |= J9AccMethodObjectConstructor;
779
831
}
832
+
833
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
834
+ if (!_hasNonEmptyConstructor) {
835
+ if (methodIsConstructor (methodIndex)) {
836
+ /* Do not record constructor forwarded to its superclass. */
837
+ if (J9_ARE_NO_BITS_SET (_methodsInfo[methodIndex].modifiers , J9AccForwarderMethod)) {
838
+ _hasNonEmptyConstructor = true ;
839
+ }
840
+ }
841
+ }
842
+ #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
780
843
781
844
/* does the method belong in vtables? */
782
845
if (methodIsVirtual (methodIndex)) {
@@ -796,6 +859,11 @@ ClassFileOracle::walkMethods()
796
859
_hasEmptyFinalizeMethod = true ;
797
860
}
798
861
}
862
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
863
+ if (!_hasNonStaticSynchronizedMethod) {
864
+ _hasNonStaticSynchronizedMethod = methodIsNonStaticSynchronized (methodIndex);
865
+ }
866
+ #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
799
867
800
868
computeSendSlotCount (methodIndex);
801
869
@@ -2175,6 +2243,29 @@ ClassFileOracle::methodIsObjectConstructor(U_16 methodIndex)
2175
2243
return false ;
2176
2244
}
2177
2245
2246
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2247
+ /* *
2248
+ * Determine if a method is constructor of a non-Value Type (Value Type constructors are static).
2249
+ *
2250
+ * @param methodIndex[in] the method index
2251
+ *
2252
+ * @returns true if the method is a constructor of a non-Value Type, false if not.
2253
+ */
2254
+ bool
2255
+ ClassFileOracle::methodIsConstructor (U_16 methodIndex)
2256
+ {
2257
+ ROMCLASS_VERBOSE_PHASE_HOT (_context, MethodIsConstructor);
2258
+
2259
+ if (J9_ARE_NO_BITS_SET (_classFile->methods [methodIndex].accessFlags , (CFR_ACC_ABSTRACT | CFR_ACC_STATIC | CFR_ACC_SYNCHRONIZED))
2260
+ && (' <' == getUTF8Data (_classFile->methods [methodIndex].nameIndex )[0 ])
2261
+ ) {
2262
+ return true ;
2263
+ }
2264
+
2265
+ return false ;
2266
+ }
2267
+ #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
2268
+
2178
2269
/* *
2179
2270
* Determine if a method is <clinit>.
2180
2271
*
@@ -2419,6 +2510,20 @@ ClassFileOracle::methodIsNonStaticNonAbstract(U_16 methodIndex)
2419
2510
return J9_ARE_NO_BITS_SET (_classFile->methods [methodIndex].accessFlags , (CFR_ACC_STATIC | CFR_ACC_ABSTRACT));
2420
2511
}
2421
2512
2513
+ #if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
2514
+ bool
2515
+ ClassFileOracle::methodIsNonStaticSynchronized (U_16 methodIndex)
2516
+ {
2517
+ ROMCLASS_VERBOSE_PHASE_HOT (_context, MethodIsNonStaticSynchronized);
2518
+ if (J9_ARE_NO_BITS_SET (_classFile->methods [methodIndex].accessFlags , CFR_ACC_STATIC)
2519
+ && J9_ARE_ALL_BITS_SET (_classFile->methods [methodIndex].accessFlags , CFR_ACC_SYNCHRONIZED)
2520
+ ) {
2521
+ return true ;
2522
+ }
2523
+ return false ;
2524
+ }
2525
+ #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
2526
+
2422
2527
/* *
2423
2528
* Method to determine if an invokevirtual instruction should be re-written to be an
2424
2529
* invokehandle or invokehandlegeneric bytecode. Modifications as follows:
0 commit comments