@@ -888,14 +888,27 @@ j9bcv_createVerifyErrorString(J9PortLibrary * portLib, J9BytecodeVerificationDat
888888/*
889889 * Validates field access compatibility
890890 *
891+ * Update strictFields map for putfield
892+ * bytecode of strict final fields.
893+ *
891894 * returns TRUE if class are compatible
892895 * returns FALSE it not compatible
893896 * reasonCode (set by isClassCompatibleByName) is:
894897 * BCV_ERR_INSUFFICIENT_MEMORY :in OOM error case
895898 */
896899IDATA
897- isFieldAccessCompatible (J9BytecodeVerificationData * verifyData , J9ROMFieldRef * fieldRef , UDATA bytecode , UDATA receiver , IDATA * reasonCode )
898- {
900+ isFieldAccessCompatible (
901+ J9BytecodeVerificationData * verifyData ,
902+ J9ROMFieldRef * fieldRef ,
903+ UDATA bytecode ,
904+ UDATA receiver ,
905+ IDATA * reasonCode
906+ #if defined(J9VM_OPT_VALHALLA_STRICT_FIELDS )
907+ ,
908+ BOOLEAN isInitMethod ,
909+ BOOLEAN anotherInstanceInitCalled
910+ #endif /* defined(J9VM_OPT_VALHALLA_STRICT_FIELDS) */
911+ ) {
899912 J9ROMClass * romClass = verifyData -> romClass ;
900913 J9ROMConstantPoolItem * constantPool = (J9ROMConstantPoolItem * )(romClass + 1 );
901914 J9UTF8 * utf8string = J9ROMCLASSREF_NAME ((J9ROMClassRef * )& constantPool [fieldRef -> classRefCPIndex ]);
@@ -907,14 +920,31 @@ isFieldAccessCompatible(J9BytecodeVerificationData *verifyData, J9ROMFieldRef *f
907920 J9ROMFieldShape * field = findFieldFromCurrentRomClass (romClass , fieldRef );
908921
909922#if defined(J9VM_OPT_VALHALLA_STRICT_FIELDS )
910- /* A field declared by the current class with ACC_FINAL and ACC_STRICT flags
911- * can't be set unless the initialization state is early larval.
912- */
913- if ((NULL != field )
914- && J9ROMFIELD_IS_STRICT_FINAL (romClass , field -> modifiers )
915- && (FALSE == liveStack -> uninitializedThis )
923+ /* TODO Update the class version check if strict fields is released before value types. */
924+ if (J9_IS_CLASSFILE_OR_ROMCLASS_VALUETYPE_VERSION (verifyData -> romClass )
925+ && (NULL != field ) && J9ROMFIELD_IS_STRICT (field -> modifiers )
916926 ) {
917- return (IDATA )FALSE;
927+ /* A strict final field cannot be set in the following cases:
928+ * - the initialization state is not early larval
929+ * - another instance initialization method has been called
930+ */
931+ if (J9_ARE_ALL_BITS_SET (field -> modifiers , J9AccFinal )
932+ && ((FALSE == liveStack -> uninitializedThis ) || (TRUE == anotherInstanceInitCalled ))
933+ ) {
934+ return (IDATA )FALSE;
935+ }
936+
937+ if (isInitMethod && (TRUE == liveStack -> uninitializedThis )) {
938+ J9UTF8 * fieldName = J9ROMNAMEANDSIGNATURE_NAME (J9ROMFIELDREF_NAMEANDSIGNATURE (fieldRef ));
939+ J9StrictFieldEntry query = {0 };
940+ query .name = J9UTF8_DATA (fieldName );
941+ query .nameLength = J9UTF8_LENGTH (fieldName );
942+ J9StrictFieldEntry * entry = hashTableFind (verifyData -> strictFields , & query );
943+ if ((NULL != entry ) && (FALSE == entry -> isSet )) {
944+ entry -> isSet = TRUE;
945+ verifyData -> strictFieldsUnsetCount -- ;
946+ }
947+ }
918948 }
919949#endif /* defined(J9VM_OPT_VALHALLA_STRICT_FIELDS) */
920950
@@ -1259,3 +1289,46 @@ findFieldFromCurrentRomClass(J9ROMClass *romClass, J9ROMFieldRef *field)
12591289
12601290 return currentField ;
12611291}
1292+ #if defined(J9VM_OPT_VALHALLA_STRICT_FIELDS )
1293+
1294+ void
1295+ createOrResetStrictFieldsList (J9BytecodeVerificationData * verifyData , BOOLEAN * initMethodFound ) {
1296+ if (* initMethodFound ) {
1297+ * initMethodFound = FALSE;
1298+
1299+ /* Clear map entries from the last class. */
1300+ J9HashTableState hashTableState = {0 };
1301+ J9StrictFieldEntry * entry = (J9StrictFieldEntry * )hashTableStartDo (verifyData -> strictFields , & hashTableState );
1302+ while (NULL != entry ) {
1303+ hashTableDoRemove (& hashTableState );
1304+ entry = hashTableNextDo (& hashTableState );
1305+ }
1306+
1307+ /* Create strictFields map of all strict instance fields. */
1308+ J9ROMFieldWalkState fieldWalkState = {0 };
1309+ J9ROMFieldShape * field = romFieldsStartDo (verifyData -> romClass , & fieldWalkState );
1310+ while (NULL != field ) {
1311+ if (J9ROMFIELD_IS_STRICT (field -> modifiers ) && J9_ARE_NO_BITS_SET (field -> modifiers , J9AccStatic )) {
1312+ J9UTF8 * fieldName = J9ROMFIELDSHAPE_NAME (field );
1313+ J9StrictFieldEntry newEntry = {0 };
1314+ newEntry .name = J9UTF8_DATA (fieldName );
1315+ newEntry .nameLength = J9UTF8_LENGTH (fieldName );
1316+ newEntry .isSet = FALSE;
1317+ hashTableAdd (verifyData -> strictFields , & newEntry );
1318+ }
1319+ field = romFieldsNextDo (& fieldWalkState );
1320+ }
1321+ } else {
1322+ /* Reset strictFields map and counter to be reused by another <init> method
1323+ * by marking all isSet flags as false.
1324+ */
1325+ J9HashTableState hashTableState = {0 };
1326+ J9StrictFieldEntry * entry = (J9StrictFieldEntry * )hashTableStartDo (verifyData -> strictFields , & hashTableState );
1327+ while (NULL != entry ) {
1328+ entry -> isSet = FALSE;
1329+ entry = hashTableNextDo (& hashTableState );
1330+ }
1331+ }
1332+ verifyData -> strictFieldsUnsetCount = hashTableGetCount (verifyData -> strictFields );
1333+ }
1334+ #endif /* defined(J9VM_OPT_VALHALLA_STRICT_FIELDS) */
0 commit comments