@@ -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,32 @@ 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+ if (J9_CLASSFILE_OR_ROMCLASS_SUPPORTS_STRICT_FIELDS (verifyData -> romClass )
924+ && (NULL != field ) && J9ROMFIELD_IS_STRICT (field -> modifiers )
916925 ) {
917- return (IDATA )FALSE;
926+ /* A strict final field cannot be set in the following cases:
927+ * - the initialization state is not early larval
928+ * - another instance initialization method has been called
929+ */
930+ if (J9_ARE_ALL_BITS_SET (field -> modifiers , J9AccFinal )) {
931+ if ((FALSE == liveStack -> uninitializedThis )
932+ || (TRUE == anotherInstanceInitCalled )
933+ ) {
934+ return (IDATA )FALSE;
935+ }
936+ }
937+
938+ if (isInitMethod && (TRUE == liveStack -> uninitializedThis )) {
939+ J9UTF8 * fieldName = J9ROMNAMEANDSIGNATURE_NAME (J9ROMFIELDREF_NAMEANDSIGNATURE (fieldRef ));
940+ J9StrictFieldEntry query = {0 };
941+ query .nameutf8 = fieldName ;
942+ J9StrictFieldEntry * entry = hashTableFind (verifyData -> strictFields , & query );
943+ if ((NULL != entry ) && (FALSE == entry -> isSet )) {
944+ Assert_RTV_true (verifyData -> strictFieldsUnsetCount > 0 );
945+ entry -> isSet = TRUE;
946+ verifyData -> strictFieldsUnsetCount -- ;
947+ }
948+ }
918949 }
919950#endif /* defined(J9VM_OPT_VALHALLA_STRICT_FIELDS) */
920951
@@ -1259,3 +1290,47 @@ findFieldFromCurrentRomClass(J9ROMClass *romClass, J9ROMFieldRef *field)
12591290
12601291 return currentField ;
12611292}
1293+ #if defined(J9VM_OPT_VALHALLA_STRICT_FIELDS )
1294+
1295+ void
1296+ createOrResetStrictFieldsList (J9BytecodeVerificationData * verifyData , BOOLEAN * addToStrictFieldTable )
1297+ {
1298+ if (* addToStrictFieldTable ) {
1299+ /* Fields only need to be added to the hash table once per class. */
1300+ * addToStrictFieldTable = FALSE;
1301+
1302+ /* Clear map entries from the last class. */
1303+ J9HashTableState hashTableState = {0 };
1304+ J9StrictFieldEntry * entry = (J9StrictFieldEntry * )hashTableStartDo (verifyData -> strictFields , & hashTableState );
1305+ while (NULL != entry ) {
1306+ hashTableDoRemove (& hashTableState );
1307+ entry = hashTableNextDo (& hashTableState );
1308+ }
1309+
1310+ /* Create strictFields map of all strict instance fields. */
1311+ J9ROMFieldWalkState fieldWalkState = {0 };
1312+ J9ROMFieldShape * field = romFieldsStartDo (verifyData -> romClass , & fieldWalkState );
1313+ while (NULL != field ) {
1314+ if (J9ROMFIELD_IS_STRICT (field -> modifiers ) && J9_ARE_NO_BITS_SET (field -> modifiers , J9AccStatic )) {
1315+ J9UTF8 * fieldName = J9ROMFIELDSHAPE_NAME (field );
1316+ J9StrictFieldEntry newEntry = {0 };
1317+ newEntry .nameutf8 = fieldName ;
1318+ newEntry .isSet = FALSE;
1319+ hashTableAdd (verifyData -> strictFields , & newEntry );
1320+ }
1321+ field = romFieldsNextDo (& fieldWalkState );
1322+ }
1323+ } else {
1324+ /* Reset strictFields map and counter to be reused by another <init> method
1325+ * by marking all isSet flags as false.
1326+ */
1327+ J9HashTableState hashTableState = {0 };
1328+ J9StrictFieldEntry * entry = (J9StrictFieldEntry * )hashTableStartDo (verifyData -> strictFields , & hashTableState );
1329+ while (NULL != entry ) {
1330+ entry -> isSet = FALSE;
1331+ entry = hashTableNextDo (& hashTableState );
1332+ }
1333+ }
1334+ verifyData -> strictFieldsUnsetCount = hashTableGetCount (verifyData -> strictFields );
1335+ }
1336+ #endif /* defined(J9VM_OPT_VALHALLA_STRICT_FIELDS) */
0 commit comments