Replace SnapshotStateObserver.invalidated with ArraySet

Using ArraySet here removes iterator allocation for frequent state invalidations (e.g. on scroll)

Fixes: 224584836
Test: SnapshotStateObserverBenchmark#notifyChanges (lower alloc count)

Change-Id: I4809ae362fd88e1aef7c49c726e3fe9638a3d597
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
index 6b31b4e..6bfd57c 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/collection/IdentityArraySet.kt
@@ -91,9 +91,7 @@
      * Remove all values from the set.
      */
     fun clear() {
-        for (i in 0 until size) {
-            values[i] = null
-        }
+        values.fill(null)
 
         size = 0
     }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
index 2e0396c..b7f31f9 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/snapshots/SnapshotStateObserver.kt
@@ -21,6 +21,7 @@
 import androidx.compose.runtime.TestOnly
 import androidx.compose.runtime.collection.IdentityArrayIntMap
 import androidx.compose.runtime.collection.IdentityArrayMap
+import androidx.compose.runtime.collection.IdentityArraySet
 import androidx.compose.runtime.collection.IdentityScopeMap
 import androidx.compose.runtime.collection.mutableVectorOf
 import androidx.compose.runtime.observeDerivedStateRecalculations
@@ -261,7 +262,7 @@
         /**
          * Scopes that were invalidated during previous apply step.
          */
-        private val invalidated = hashSetOf<Any>()
+        private val invalidated = IdentityArraySet<Any>()
 
         // derived state handling
 
@@ -417,7 +418,7 @@
                         // Invalidate only if currentValue is different than observed on read
                         if (!policy.equivalent(derivedState.currentValue, previousValue)) {
                             valueToScopes.forEachScopeOf(derivedState) { scope ->
-                                invalidated += scope
+                                invalidated.add(scope)
                                 hasValues = true
                             }
                         }
@@ -425,7 +426,7 @@
                 }
 
                 valueToScopes.forEachScopeOf(value) { scope ->
-                    invalidated += scope
+                    invalidated.add(scope)
                     hasValues = true
                 }
             }
@@ -436,7 +437,7 @@
          * Call [onChanged] for previously invalidated scopes.
          */
         fun notifyInvalidatedScopes() {
-            invalidated.forEach(onChanged)
+            invalidated.fastForEach(onChanged)
             invalidated.clear()
         }
     }