Merge "Add CompositionData to replace SlotTable for tooling API usage" into androidx-master-dev
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractCodegenSignatureTest.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractCodegenSignatureTest.kt
index 7e58ce0..c21c5e6 100644
--- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractCodegenSignatureTest.kt
+++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/AbstractCodegenSignatureTest.kt
@@ -126,7 +126,6 @@
                 fun makeComposer(): Composer<*> {
                     val container = LinearLayout(__context!!)
                     return Composer(
-                        SlotTable(),
                         UiApplier(container),
                         Recomposer.current()
                     )
diff --git a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt
index 1d8e90e..b544ab1 100644
--- a/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt
+++ b/compose/foundation/foundation/src/test/kotlin/androidx/compose/foundation/gestures/SuspendingGestureTestUtil.kt
@@ -23,7 +23,6 @@
 import androidx.compose.runtime.InternalComposeApi
 import androidx.compose.runtime.Providers
 import androidx.compose.runtime.Recomposer
-import androidx.compose.runtime.SlotTable
 import androidx.compose.runtime.currentComposer
 import androidx.compose.runtime.dispatch.MonotonicFrameClock
 import androidx.compose.runtime.withRunningRecomposer
@@ -302,7 +301,6 @@
         block: @Composable () -> Unit
     ): Composer<Unit> {
         return Composer(
-            SlotTable(),
             EmptyApplier(),
             recomposer
         ).apply {
@@ -312,7 +310,7 @@
                 fn(this, 0)
             }
             applyChanges()
-            slotTable.verifyWellFormed()
+            verifyConsistent()
         }
     }
 
diff --git a/compose/runtime/runtime/api/current.txt b/compose/runtime/runtime/api/current.txt
index 34986e5..ebe4b82 100644
--- a/compose/runtime/runtime/api/current.txt
+++ b/compose/runtime/runtime/api/current.txt
@@ -34,13 +34,6 @@
     method public static <T> androidx.compose.runtime.ProvidableAmbient<T> staticAmbientOf(optional kotlin.jvm.functions.Function0<? extends T>? defaultFactory);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class Anchor {
-    method public boolean getValid();
-    method public int toIndexFor(androidx.compose.runtime.SlotTable slots);
-    method public int toIndexFor(androidx.compose.runtime.SlotWriter writer);
-    property public final boolean valid;
-  }
-
   public interface Applier<N> {
     method public void clear();
     method public void down(N? node);
@@ -85,7 +78,7 @@
   }
 
   public final class Composer<N> {
-    ctor public Composer(androidx.compose.runtime.SlotTable slotTable, @kotlin.PublishedApi androidx.compose.runtime.Applier<N> applier, androidx.compose.runtime.CompositionReference parentReference);
+    ctor public Composer(@kotlin.PublishedApi androidx.compose.runtime.Applier<N> applier, androidx.compose.runtime.CompositionReference parentReference);
     method @androidx.compose.runtime.InternalComposeApi public void applyChanges();
     method @androidx.compose.runtime.ComposeCompilerApi public inline <T> T! cache(boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
     method @androidx.compose.runtime.ComposeCompilerApi public boolean changed(Object? value);
@@ -105,10 +98,10 @@
     method @androidx.compose.runtime.ComposeCompilerApi public void endReplaceableGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.ScopeUpdateScope? endRestartGroup();
     method @org.jetbrains.annotations.TestOnly public kotlin.coroutines.CoroutineContext getApplyCoroutineContext();
+    method public androidx.compose.runtime.CompositionData getCompositionData();
     method public int getCurrentCompoundKeyHash();
     method public boolean getDefaultsInvalid();
     method public boolean getSkipping();
-    method public androidx.compose.runtime.SlotTable getSlotTable();
     method @androidx.compose.runtime.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
     method @androidx.compose.runtime.InternalComposeApi public boolean recompose();
     method @androidx.compose.runtime.InternalComposeApi public void recordModificationsOf(java.util.Set<?> values);
@@ -123,11 +116,12 @@
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startRestartGroup(int key);
     method @androidx.compose.runtime.ComposeCompilerApi public void startRestartGroup(int key, String? sourceInformation);
+    method @androidx.compose.runtime.InternalComposeApi public void verifyConsistent();
     property @org.jetbrains.annotations.TestOnly public final kotlin.coroutines.CoroutineContext applyCoroutineContext;
+    property public final androidx.compose.runtime.CompositionData compositionData;
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean skipping;
-    property public final androidx.compose.runtime.SlotTable slotTable;
   }
 
   public final class ComposerKt {
@@ -140,6 +134,24 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
+  public interface CompositionData {
+    method public Iterable<androidx.compose.runtime.CompositionGroup> getCompositionGroups();
+    method public boolean isEmpty();
+    property public abstract Iterable<androidx.compose.runtime.CompositionGroup> compositionGroups;
+    property public abstract boolean isEmpty;
+  }
+
+  public interface CompositionGroup extends androidx.compose.runtime.CompositionData {
+    method public Iterable<java.lang.Object> getData();
+    method public Object getKey();
+    method public Object? getNode();
+    method public String? getSourceInfo();
+    property public abstract Iterable<java.lang.Object> data;
+    property public abstract Object key;
+    property public abstract Object? node;
+    property public abstract String? sourceInfo;
+  }
+
   public final class CompositionKt {
     method @androidx.compose.runtime.ExperimentalComposeApi public static androidx.compose.runtime.Composition compositionFor(Object key, androidx.compose.runtime.Applier<?> applier, androidx.compose.runtime.CompositionReference parent, optional kotlin.jvm.functions.Function0<kotlin.Unit> onCreated);
   }
@@ -341,150 +353,10 @@
     method public inline void update(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.Updater<T>,kotlin.Unit> block);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class SlotReader {
-    ctor public SlotReader(androidx.compose.runtime.SlotTable table);
-    method public androidx.compose.runtime.Anchor anchor(optional int index);
-    method public void beginEmpty();
-    method public void close();
-    method public void endEmpty();
-    method public void endGroup();
-    method public java.util.List<androidx.compose.runtime.KeyInfo> extractKeys();
-    method public Object? get(int index);
-    method public int getCurrentEnd();
-    method public int getCurrentGroup();
-    method public Object! getGroupAux();
-    method public int getGroupEnd();
-    method public int getGroupKey();
-    method public Object! getGroupNode();
-    method public Object! getGroupObjectKey();
-    method public int getGroupSize();
-    method public int getGroupSlotCount();
-    method public int getGroupSlotIndex();
-    method public boolean getInEmpty();
-    method public int getNodeCount();
-    method public int getParent();
-    method public int getParentNodes();
-    method public int getSize();
-    method public int getSlot();
-    method public Object? groupAux(int index);
-    method public int groupEnd(int index);
-    method public Object? groupGet(int index);
-    method public int groupKey(int index);
-    method public int groupKey(androidx.compose.runtime.Anchor anchor);
-    method public Object? groupObjectKey(int index);
-    method public int groupSize(int index);
-    method public boolean hasObjectKey(int index);
-    method public boolean isGroupEnd();
-    method public boolean isNode();
-    method public boolean isNode(int index);
-    method public Object? next();
-    method public Object? node(int index);
-    method public int nodeCount(int index);
-    method public int parent(int index);
-    method public int parentOf(int index);
-    method public void reposition(int index);
-    method public void restoreParent(int index);
-    method public int skipGroup();
-    method public void skipToGroupEnd();
-    method public void startGroup();
-    method public void startNode();
-    property public final int currentEnd;
-    property public final int currentGroup;
-    property public final Object! groupAux;
-    property public final int groupEnd;
-    property public final int groupKey;
-    property public final Object! groupNode;
-    property public final Object! groupObjectKey;
-    property public final int groupSize;
-    property public final int groupSlotCount;
-    property public final int groupSlotIndex;
-    property public final boolean inEmpty;
-    property public final boolean isGroupEnd;
-    property public final boolean isNode;
-    property public final int nodeCount;
-    property public final int parent;
-    property public final int parentNodes;
-    property public final int size;
-    property public final int slot;
-  }
-
-  @androidx.compose.runtime.InternalComposeApi public final class SlotTable {
-    ctor public SlotTable();
-    method public int anchorIndex(androidx.compose.runtime.Anchor anchor);
-    method public String asString();
-    method public int[] getGroups();
-    method public int getGroupsSize();
-    method public Object![] getSlots();
-    method public int getSlotsSize();
-    method public boolean isEmpty();
-    method public androidx.compose.runtime.SlotReader openReader();
-    method public androidx.compose.runtime.SlotWriter openWriter();
-    method public boolean ownsAnchor(androidx.compose.runtime.Anchor anchor);
-    method public inline <T> T! read(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.SlotReader,? extends T> block);
-    method public void verifyWellFormed();
-    method public inline <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.SlotWriter,? extends T> block);
-    property public final int[] groups;
-    property public final int groupsSize;
-    property public final boolean isEmpty;
-    property public final Object![] slots;
-    property public final int slotsSize;
-  }
-
   public final class SlotTableKt {
     method public static java.util.List<java.lang.Integer> slice(int[], Iterable<java.lang.Integer> indices);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class SlotWriter {
-    method public void advanceBy(int amount);
-    method public androidx.compose.runtime.Anchor anchor(optional int index);
-    method public int anchorIndex(androidx.compose.runtime.Anchor anchor);
-    method public void beginInsert();
-    method public void close();
-    method public int endGroup();
-    method public void endInsert();
-    method public void ensureStarted(int index);
-    method public void ensureStarted(androidx.compose.runtime.Anchor anchor);
-    method public boolean getClosed();
-    method public int getCurrentGroup();
-    method public int getParent();
-    method public Object? groupAux(int index);
-    method public int groupKey(int index);
-    method public Object? groupObjectKey(int index);
-    method public int groupSize(int index);
-    method public java.util.Iterator<java.lang.Object> groupSlots();
-    method public String groupsAsString();
-    method public boolean isGroupEnd();
-    method public boolean isNode();
-    method public java.util.List<androidx.compose.runtime.Anchor> moveFrom(androidx.compose.runtime.SlotTable table, int index);
-    method public void moveGroup(int offset);
-    method public Object? node(int index);
-    method public int parent(int index);
-    method public int parent(androidx.compose.runtime.Anchor anchor);
-    method public boolean removeGroup();
-    method public void seek(androidx.compose.runtime.Anchor anchor);
-    method public void set(Object? value);
-    method public Object? set(int index, Object? value);
-    method public Object? skip();
-    method public int skipGroup();
-    method public void skipToGroupEnd();
-    method public void startData(int key, Object? objectKey, Object? aux);
-    method public void startData(int key, Object? aux);
-    method public void startGroup();
-    method public void startGroup(int key);
-    method public void startGroup(int key, Object? dataKey);
-    method public void startNode(Object? key);
-    method public void startNode(Object? key, Object? node);
-    method public Object? update(Object? value);
-    method public void updateAux(Object? value);
-    method public void updateNode(Object? value);
-    method public void updateParentNode(Object? value);
-    property public final boolean closed;
-    property public final int currentGroup;
-    property public final boolean isGroupEnd;
-    property public final boolean isNode;
-    property public final int parent;
-  }
-
   public interface SnapshotMutationPolicy<T> {
     method public boolean equivalent(T? a, T? b);
     method @androidx.compose.runtime.ExperimentalComposeApi public default T? merge(T? previous, T? current, T? applied);
@@ -879,7 +751,7 @@
 package androidx.compose.runtime.tooling {
 
   public final class InspectionTablesKt {
-    method public static androidx.compose.runtime.ProvidableAmbient<java.util.Set<androidx.compose.runtime.SlotTable>> getInspectionTables();
+    method public static androidx.compose.runtime.ProvidableAmbient<java.util.Set<androidx.compose.runtime.CompositionData>> getInspectionTables();
   }
 
 }
diff --git a/compose/runtime/runtime/api/public_plus_experimental_current.txt b/compose/runtime/runtime/api/public_plus_experimental_current.txt
index 34986e5..ebe4b82 100644
--- a/compose/runtime/runtime/api/public_plus_experimental_current.txt
+++ b/compose/runtime/runtime/api/public_plus_experimental_current.txt
@@ -34,13 +34,6 @@
     method public static <T> androidx.compose.runtime.ProvidableAmbient<T> staticAmbientOf(optional kotlin.jvm.functions.Function0<? extends T>? defaultFactory);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class Anchor {
-    method public boolean getValid();
-    method public int toIndexFor(androidx.compose.runtime.SlotTable slots);
-    method public int toIndexFor(androidx.compose.runtime.SlotWriter writer);
-    property public final boolean valid;
-  }
-
   public interface Applier<N> {
     method public void clear();
     method public void down(N? node);
@@ -85,7 +78,7 @@
   }
 
   public final class Composer<N> {
-    ctor public Composer(androidx.compose.runtime.SlotTable slotTable, @kotlin.PublishedApi androidx.compose.runtime.Applier<N> applier, androidx.compose.runtime.CompositionReference parentReference);
+    ctor public Composer(@kotlin.PublishedApi androidx.compose.runtime.Applier<N> applier, androidx.compose.runtime.CompositionReference parentReference);
     method @androidx.compose.runtime.InternalComposeApi public void applyChanges();
     method @androidx.compose.runtime.ComposeCompilerApi public inline <T> T! cache(boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
     method @androidx.compose.runtime.ComposeCompilerApi public boolean changed(Object? value);
@@ -105,10 +98,10 @@
     method @androidx.compose.runtime.ComposeCompilerApi public void endReplaceableGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.ScopeUpdateScope? endRestartGroup();
     method @org.jetbrains.annotations.TestOnly public kotlin.coroutines.CoroutineContext getApplyCoroutineContext();
+    method public androidx.compose.runtime.CompositionData getCompositionData();
     method public int getCurrentCompoundKeyHash();
     method public boolean getDefaultsInvalid();
     method public boolean getSkipping();
-    method public androidx.compose.runtime.SlotTable getSlotTable();
     method @androidx.compose.runtime.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
     method @androidx.compose.runtime.InternalComposeApi public boolean recompose();
     method @androidx.compose.runtime.InternalComposeApi public void recordModificationsOf(java.util.Set<?> values);
@@ -123,11 +116,12 @@
     method @androidx.compose.runtime.ComposeCompilerApi public void startReplaceableGroup(int key, String? sourceInformation);
     method @androidx.compose.runtime.ComposeCompilerApi public void startRestartGroup(int key);
     method @androidx.compose.runtime.ComposeCompilerApi public void startRestartGroup(int key, String? sourceInformation);
+    method @androidx.compose.runtime.InternalComposeApi public void verifyConsistent();
     property @org.jetbrains.annotations.TestOnly public final kotlin.coroutines.CoroutineContext applyCoroutineContext;
+    property public final androidx.compose.runtime.CompositionData compositionData;
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean skipping;
-    property public final androidx.compose.runtime.SlotTable slotTable;
   }
 
   public final class ComposerKt {
@@ -140,6 +134,24 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
+  public interface CompositionData {
+    method public Iterable<androidx.compose.runtime.CompositionGroup> getCompositionGroups();
+    method public boolean isEmpty();
+    property public abstract Iterable<androidx.compose.runtime.CompositionGroup> compositionGroups;
+    property public abstract boolean isEmpty;
+  }
+
+  public interface CompositionGroup extends androidx.compose.runtime.CompositionData {
+    method public Iterable<java.lang.Object> getData();
+    method public Object getKey();
+    method public Object? getNode();
+    method public String? getSourceInfo();
+    property public abstract Iterable<java.lang.Object> data;
+    property public abstract Object key;
+    property public abstract Object? node;
+    property public abstract String? sourceInfo;
+  }
+
   public final class CompositionKt {
     method @androidx.compose.runtime.ExperimentalComposeApi public static androidx.compose.runtime.Composition compositionFor(Object key, androidx.compose.runtime.Applier<?> applier, androidx.compose.runtime.CompositionReference parent, optional kotlin.jvm.functions.Function0<kotlin.Unit> onCreated);
   }
@@ -341,150 +353,10 @@
     method public inline void update(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.Updater<T>,kotlin.Unit> block);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class SlotReader {
-    ctor public SlotReader(androidx.compose.runtime.SlotTable table);
-    method public androidx.compose.runtime.Anchor anchor(optional int index);
-    method public void beginEmpty();
-    method public void close();
-    method public void endEmpty();
-    method public void endGroup();
-    method public java.util.List<androidx.compose.runtime.KeyInfo> extractKeys();
-    method public Object? get(int index);
-    method public int getCurrentEnd();
-    method public int getCurrentGroup();
-    method public Object! getGroupAux();
-    method public int getGroupEnd();
-    method public int getGroupKey();
-    method public Object! getGroupNode();
-    method public Object! getGroupObjectKey();
-    method public int getGroupSize();
-    method public int getGroupSlotCount();
-    method public int getGroupSlotIndex();
-    method public boolean getInEmpty();
-    method public int getNodeCount();
-    method public int getParent();
-    method public int getParentNodes();
-    method public int getSize();
-    method public int getSlot();
-    method public Object? groupAux(int index);
-    method public int groupEnd(int index);
-    method public Object? groupGet(int index);
-    method public int groupKey(int index);
-    method public int groupKey(androidx.compose.runtime.Anchor anchor);
-    method public Object? groupObjectKey(int index);
-    method public int groupSize(int index);
-    method public boolean hasObjectKey(int index);
-    method public boolean isGroupEnd();
-    method public boolean isNode();
-    method public boolean isNode(int index);
-    method public Object? next();
-    method public Object? node(int index);
-    method public int nodeCount(int index);
-    method public int parent(int index);
-    method public int parentOf(int index);
-    method public void reposition(int index);
-    method public void restoreParent(int index);
-    method public int skipGroup();
-    method public void skipToGroupEnd();
-    method public void startGroup();
-    method public void startNode();
-    property public final int currentEnd;
-    property public final int currentGroup;
-    property public final Object! groupAux;
-    property public final int groupEnd;
-    property public final int groupKey;
-    property public final Object! groupNode;
-    property public final Object! groupObjectKey;
-    property public final int groupSize;
-    property public final int groupSlotCount;
-    property public final int groupSlotIndex;
-    property public final boolean inEmpty;
-    property public final boolean isGroupEnd;
-    property public final boolean isNode;
-    property public final int nodeCount;
-    property public final int parent;
-    property public final int parentNodes;
-    property public final int size;
-    property public final int slot;
-  }
-
-  @androidx.compose.runtime.InternalComposeApi public final class SlotTable {
-    ctor public SlotTable();
-    method public int anchorIndex(androidx.compose.runtime.Anchor anchor);
-    method public String asString();
-    method public int[] getGroups();
-    method public int getGroupsSize();
-    method public Object![] getSlots();
-    method public int getSlotsSize();
-    method public boolean isEmpty();
-    method public androidx.compose.runtime.SlotReader openReader();
-    method public androidx.compose.runtime.SlotWriter openWriter();
-    method public boolean ownsAnchor(androidx.compose.runtime.Anchor anchor);
-    method public inline <T> T! read(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.SlotReader,? extends T> block);
-    method public void verifyWellFormed();
-    method public inline <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.SlotWriter,? extends T> block);
-    property public final int[] groups;
-    property public final int groupsSize;
-    property public final boolean isEmpty;
-    property public final Object![] slots;
-    property public final int slotsSize;
-  }
-
   public final class SlotTableKt {
     method public static java.util.List<java.lang.Integer> slice(int[], Iterable<java.lang.Integer> indices);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class SlotWriter {
-    method public void advanceBy(int amount);
-    method public androidx.compose.runtime.Anchor anchor(optional int index);
-    method public int anchorIndex(androidx.compose.runtime.Anchor anchor);
-    method public void beginInsert();
-    method public void close();
-    method public int endGroup();
-    method public void endInsert();
-    method public void ensureStarted(int index);
-    method public void ensureStarted(androidx.compose.runtime.Anchor anchor);
-    method public boolean getClosed();
-    method public int getCurrentGroup();
-    method public int getParent();
-    method public Object? groupAux(int index);
-    method public int groupKey(int index);
-    method public Object? groupObjectKey(int index);
-    method public int groupSize(int index);
-    method public java.util.Iterator<java.lang.Object> groupSlots();
-    method public String groupsAsString();
-    method public boolean isGroupEnd();
-    method public boolean isNode();
-    method public java.util.List<androidx.compose.runtime.Anchor> moveFrom(androidx.compose.runtime.SlotTable table, int index);
-    method public void moveGroup(int offset);
-    method public Object? node(int index);
-    method public int parent(int index);
-    method public int parent(androidx.compose.runtime.Anchor anchor);
-    method public boolean removeGroup();
-    method public void seek(androidx.compose.runtime.Anchor anchor);
-    method public void set(Object? value);
-    method public Object? set(int index, Object? value);
-    method public Object? skip();
-    method public int skipGroup();
-    method public void skipToGroupEnd();
-    method public void startData(int key, Object? objectKey, Object? aux);
-    method public void startData(int key, Object? aux);
-    method public void startGroup();
-    method public void startGroup(int key);
-    method public void startGroup(int key, Object? dataKey);
-    method public void startNode(Object? key);
-    method public void startNode(Object? key, Object? node);
-    method public Object? update(Object? value);
-    method public void updateAux(Object? value);
-    method public void updateNode(Object? value);
-    method public void updateParentNode(Object? value);
-    property public final boolean closed;
-    property public final int currentGroup;
-    property public final boolean isGroupEnd;
-    property public final boolean isNode;
-    property public final int parent;
-  }
-
   public interface SnapshotMutationPolicy<T> {
     method public boolean equivalent(T? a, T? b);
     method @androidx.compose.runtime.ExperimentalComposeApi public default T? merge(T? previous, T? current, T? applied);
@@ -879,7 +751,7 @@
 package androidx.compose.runtime.tooling {
 
   public final class InspectionTablesKt {
-    method public static androidx.compose.runtime.ProvidableAmbient<java.util.Set<androidx.compose.runtime.SlotTable>> getInspectionTables();
+    method public static androidx.compose.runtime.ProvidableAmbient<java.util.Set<androidx.compose.runtime.CompositionData>> getInspectionTables();
   }
 
 }
diff --git a/compose/runtime/runtime/api/restricted_current.txt b/compose/runtime/runtime/api/restricted_current.txt
index c0658ef..f0c99aa 100644
--- a/compose/runtime/runtime/api/restricted_current.txt
+++ b/compose/runtime/runtime/api/restricted_current.txt
@@ -34,13 +34,6 @@
     method public static <T> androidx.compose.runtime.ProvidableAmbient<T> staticAmbientOf(optional kotlin.jvm.functions.Function0<? extends T>? defaultFactory);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class Anchor {
-    method public boolean getValid();
-    method public int toIndexFor(androidx.compose.runtime.SlotTable slots);
-    method public int toIndexFor(androidx.compose.runtime.SlotWriter writer);
-    property public final boolean valid;
-  }
-
   public interface Applier<N> {
     method public void clear();
     method public void down(N? node);
@@ -85,7 +78,7 @@
   }
 
   public final class Composer<N> {
-    ctor public Composer(androidx.compose.runtime.SlotTable slotTable, @kotlin.PublishedApi androidx.compose.runtime.Applier<N> applier, androidx.compose.runtime.CompositionReference parentReference);
+    ctor public Composer(@kotlin.PublishedApi androidx.compose.runtime.Applier<N> applier, androidx.compose.runtime.CompositionReference parentReference);
     method @androidx.compose.runtime.InternalComposeApi public void applyChanges();
     method @androidx.compose.runtime.ComposeCompilerApi public inline <T> T! cache(boolean invalid, kotlin.jvm.functions.Function0<? extends T> block);
     method @androidx.compose.runtime.ComposeCompilerApi public boolean changed(Object? value);
@@ -108,10 +101,10 @@
     method @androidx.compose.runtime.ComposeCompilerApi public void endReplaceableGroup();
     method @androidx.compose.runtime.ComposeCompilerApi public androidx.compose.runtime.ScopeUpdateScope? endRestartGroup();
     method @org.jetbrains.annotations.TestOnly public kotlin.coroutines.CoroutineContext getApplyCoroutineContext();
+    method public androidx.compose.runtime.CompositionData getCompositionData();
     method public int getCurrentCompoundKeyHash();
     method public boolean getDefaultsInvalid();
     method public boolean getSkipping();
-    method public androidx.compose.runtime.SlotTable getSlotTable();
     method @androidx.compose.runtime.ComposeCompilerApi public Object joinKey(Object? left, Object? right);
     method @kotlin.PublishedApi internal Object? nextSlot();
     method @androidx.compose.runtime.InternalComposeApi public boolean recompose();
@@ -130,11 +123,12 @@
     method @androidx.compose.runtime.ComposeCompilerApi public void startRestartGroup(int key, String? sourceInformation);
     method @kotlin.PublishedApi internal void updateValue(Object? value);
     method @kotlin.PublishedApi internal N! useNode();
+    method @androidx.compose.runtime.InternalComposeApi public void verifyConsistent();
     property @org.jetbrains.annotations.TestOnly public final kotlin.coroutines.CoroutineContext applyCoroutineContext;
+    property public final androidx.compose.runtime.CompositionData compositionData;
     property public final int currentCompoundKeyHash;
     property public final boolean defaultsInvalid;
     property public final boolean skipping;
-    property public final androidx.compose.runtime.SlotTable slotTable;
     field @kotlin.PublishedApi internal boolean inserting;
   }
 
@@ -160,6 +154,24 @@
     method public void setContent(kotlin.jvm.functions.Function0<kotlin.Unit> content);
   }
 
+  public interface CompositionData {
+    method public Iterable<androidx.compose.runtime.CompositionGroup> getCompositionGroups();
+    method public boolean isEmpty();
+    property public abstract Iterable<androidx.compose.runtime.CompositionGroup> compositionGroups;
+    property public abstract boolean isEmpty;
+  }
+
+  public interface CompositionGroup extends androidx.compose.runtime.CompositionData {
+    method public Iterable<java.lang.Object> getData();
+    method public Object getKey();
+    method public Object? getNode();
+    method public String? getSourceInfo();
+    property public abstract Iterable<java.lang.Object> data;
+    property public abstract Object key;
+    property public abstract Object? node;
+    property public abstract String? sourceInfo;
+  }
+
   public final class CompositionKt {
     method @androidx.compose.runtime.ExperimentalComposeApi public static androidx.compose.runtime.Composition compositionFor(Object key, androidx.compose.runtime.Applier<?> applier, androidx.compose.runtime.CompositionReference parent, optional kotlin.jvm.functions.Function0<kotlin.Unit> onCreated);
   }
@@ -374,151 +386,11 @@
     method public inline void update(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.Updater<T>,kotlin.Unit> block);
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class SlotReader {
-    ctor public SlotReader(androidx.compose.runtime.SlotTable table);
-    method public androidx.compose.runtime.Anchor anchor(optional int index);
-    method public void beginEmpty();
-    method public void close();
-    method public void endEmpty();
-    method public void endGroup();
-    method public java.util.List<androidx.compose.runtime.KeyInfo> extractKeys();
-    method public Object? get(int index);
-    method public int getCurrentEnd();
-    method public int getCurrentGroup();
-    method public Object! getGroupAux();
-    method public int getGroupEnd();
-    method public int getGroupKey();
-    method public Object! getGroupNode();
-    method public Object! getGroupObjectKey();
-    method public int getGroupSize();
-    method public int getGroupSlotCount();
-    method public int getGroupSlotIndex();
-    method public boolean getInEmpty();
-    method public int getNodeCount();
-    method public int getParent();
-    method public int getParentNodes();
-    method public int getSize();
-    method public int getSlot();
-    method public Object? groupAux(int index);
-    method public int groupEnd(int index);
-    method public Object? groupGet(int index);
-    method public int groupKey(int index);
-    method public int groupKey(androidx.compose.runtime.Anchor anchor);
-    method public Object? groupObjectKey(int index);
-    method public int groupSize(int index);
-    method public boolean hasObjectKey(int index);
-    method public boolean isGroupEnd();
-    method public boolean isNode();
-    method public boolean isNode(int index);
-    method public Object? next();
-    method public Object? node(int index);
-    method public int nodeCount(int index);
-    method public int parent(int index);
-    method public int parentOf(int index);
-    method public void reposition(int index);
-    method public void restoreParent(int index);
-    method public int skipGroup();
-    method public void skipToGroupEnd();
-    method public void startGroup();
-    method public void startNode();
-    property public final int currentEnd;
-    property public final int currentGroup;
-    property public final Object! groupAux;
-    property public final int groupEnd;
-    property public final int groupKey;
-    property public final Object! groupNode;
-    property public final Object! groupObjectKey;
-    property public final int groupSize;
-    property public final int groupSlotCount;
-    property public final int groupSlotIndex;
-    property public final boolean inEmpty;
-    property public final boolean isGroupEnd;
-    property public final boolean isNode;
-    property public final int nodeCount;
-    property public final int parent;
-    property public final int parentNodes;
-    property public final int size;
-    property public final int slot;
-  }
-
-  @androidx.compose.runtime.InternalComposeApi public final class SlotTable {
-    ctor public SlotTable();
-    method public int anchorIndex(androidx.compose.runtime.Anchor anchor);
-    method public String asString();
-    method public int[] getGroups();
-    method public int getGroupsSize();
-    method public Object![] getSlots();
-    method public int getSlotsSize();
-    method public boolean isEmpty();
-    method public androidx.compose.runtime.SlotReader openReader();
-    method public androidx.compose.runtime.SlotWriter openWriter();
-    method public boolean ownsAnchor(androidx.compose.runtime.Anchor anchor);
-    method public inline <T> T! read(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.SlotReader,? extends T> block);
-    method public void verifyWellFormed();
-    method public inline <T> T! write(kotlin.jvm.functions.Function1<? super androidx.compose.runtime.SlotWriter,? extends T> block);
-    property public final int[] groups;
-    property public final int groupsSize;
-    property public final boolean isEmpty;
-    property public final Object![] slots;
-    property public final int slotsSize;
-  }
-
   public final class SlotTableKt {
     method public static java.util.List<java.lang.Integer> slice(int[], Iterable<java.lang.Integer> indices);
     field @kotlin.PublishedApi internal static final Object EMPTY;
   }
 
-  @androidx.compose.runtime.InternalComposeApi public final class SlotWriter {
-    method public void advanceBy(int amount);
-    method public androidx.compose.runtime.Anchor anchor(optional int index);
-    method public int anchorIndex(androidx.compose.runtime.Anchor anchor);
-    method public void beginInsert();
-    method public void close();
-    method public int endGroup();
-    method public void endInsert();
-    method public void ensureStarted(int index);
-    method public void ensureStarted(androidx.compose.runtime.Anchor anchor);
-    method public boolean getClosed();
-    method public int getCurrentGroup();
-    method public int getParent();
-    method public Object? groupAux(int index);
-    method public int groupKey(int index);
-    method public Object? groupObjectKey(int index);
-    method public int groupSize(int index);
-    method public java.util.Iterator<java.lang.Object> groupSlots();
-    method public String groupsAsString();
-    method public boolean isGroupEnd();
-    method public boolean isNode();
-    method public java.util.List<androidx.compose.runtime.Anchor> moveFrom(androidx.compose.runtime.SlotTable table, int index);
-    method public void moveGroup(int offset);
-    method public Object? node(int index);
-    method public int parent(int index);
-    method public int parent(androidx.compose.runtime.Anchor anchor);
-    method public boolean removeGroup();
-    method public void seek(androidx.compose.runtime.Anchor anchor);
-    method public void set(Object? value);
-    method public Object? set(int index, Object? value);
-    method public Object? skip();
-    method public int skipGroup();
-    method public void skipToGroupEnd();
-    method public void startData(int key, Object? objectKey, Object? aux);
-    method public void startData(int key, Object? aux);
-    method public void startGroup();
-    method public void startGroup(int key);
-    method public void startGroup(int key, Object? dataKey);
-    method public void startNode(Object? key);
-    method public void startNode(Object? key, Object? node);
-    method public Object? update(Object? value);
-    method public void updateAux(Object? value);
-    method public void updateNode(Object? value);
-    method public void updateParentNode(Object? value);
-    property public final boolean closed;
-    property public final int currentGroup;
-    property public final boolean isGroupEnd;
-    property public final boolean isNode;
-    property public final int parent;
-  }
-
   public interface SnapshotMutationPolicy<T> {
     method public boolean equivalent(T? a, T? b);
     method @androidx.compose.runtime.ExperimentalComposeApi public default T? merge(T? previous, T? current, T? applied);
@@ -927,7 +799,7 @@
 package androidx.compose.runtime.tooling {
 
   public final class InspectionTablesKt {
-    method public static androidx.compose.runtime.ProvidableAmbient<java.util.Set<androidx.compose.runtime.SlotTable>> getInspectionTables();
+    method public static androidx.compose.runtime.ProvidableAmbient<java.util.Set<androidx.compose.runtime.CompositionData>> getInspectionTables();
   }
 
 }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
index e39d965..f6d3736 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composer.kt
@@ -351,11 +351,6 @@
  */
 class Composer<N>(
     /**
-     * Backing storage for the composition
-     */
-    val slotTable: SlotTable,
-
-    /**
      * An adapter that applies changes to the tree using the Applier abstraction.
      */
     @PublishedApi internal val applier: Applier<N>,
@@ -365,6 +360,7 @@
      */
     private val parentReference: CompositionReference
 ) {
+    private val slotTable: SlotTable = SlotTable()
     private val changes = mutableListOf<Change<N>>()
     private val lifecycleObservers = HashMap<
         CompositionLifecycleObserverHolder,
@@ -675,6 +671,31 @@
     }
 
     /**
+     * Throw a diagnostic exception if the internal tracking tables are inconsistent.
+     */
+    @InternalComposeApi
+    fun verifyConsistent() {
+        if (!isComposing) {
+            slotTable.verifyWellFormed()
+            insertTable.verifyWellFormed()
+            validateRecomposeScopeAnchors(slotTable)
+        }
+    }
+
+    private fun validateRecomposeScopeAnchors(slotTable: SlotTable) {
+        val scopes = slotTable.slots.map { it as? RecomposeScope }.filterNotNull()
+        for (scope in scopes) {
+            scope.anchor?.let { anchor ->
+                check(scope in slotTable.slotsOf(anchor.toIndexFor(slotTable))) {
+                    val dataIndex = slotTable.slots.indexOf(scope)
+                    "Misaligned anchor $anchor in scope $scope encountered, scope found at " +
+                        "$dataIndex"
+                }
+            }
+        }
+    }
+
+    /**
      * Record that the objects in [values] have been modified. This invalidates any recomposes
      * scopes  that were current when [recordReadOf] was called with an instance in [values].
      *
@@ -1147,6 +1168,9 @@
         }
     }
 
+    @InternalComposeApi
+    val compositionData: CompositionData get() = slotTable
+
     /**
      * Schedule a side effect to run when we apply composition changes.
      */
@@ -2448,7 +2472,7 @@
         override val collectingKeySources: Boolean,
         override val collectingParameterInformation: Boolean
     ) : CompositionReference() {
-        var inspectionTables: MutableSet<MutableSet<SlotTable>>? = null
+        var inspectionTables: MutableSet<MutableSet<CompositionData>>? = null
         val composers = mutableSetOf<Composer<*>>()
 
         fun dispose() {
@@ -2518,9 +2542,9 @@
             return ambientScopeAt(scope.anchor?.toIndexFor(slotTable) ?: 0)
         }
 
-        override fun recordInspectionTable(table: MutableSet<SlotTable>) {
+        override fun recordInspectionTable(table: MutableSet<CompositionData>) {
             (
-                inspectionTables ?: HashSet<MutableSet<SlotTable>>().also {
+                inspectionTables ?: HashSet<MutableSet<CompositionData>>().also {
                     inspectionTables = it
                 }
                 ).add(table)
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
index 458e047..15b94e6 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Composition.kt
@@ -73,7 +73,7 @@
 ): Composition = Compositions.findOrCreate(key) {
     CompositionImpl(
         parent,
-        composerFactory = { slots, rcmpsr -> Composer(slots, applier, rcmpsr) },
+        composerFactory = { parent -> Composer(applier, parent) },
         onDispose = { Compositions.onDisposed(key) }
     ).also {
         onCreated()
@@ -87,11 +87,10 @@
  */
 private class CompositionImpl(
     private val parent: CompositionReference,
-    composerFactory: (SlotTable, CompositionReference) -> Composer<*>,
+    composerFactory: (CompositionReference) -> Composer<*>,
     private val onDispose: () -> Unit
 ) : Composition {
-    private val slotTable: SlotTable = SlotTable()
-    private val composer: Composer<*> = composerFactory(slotTable, parent).also {
+    private val composer: Composer<*> = composerFactory(parent).also {
         parent.registerComposer(it)
     }
 
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionData.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionData.kt
new file mode 100644
index 0000000..53aa673
--- /dev/null
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionData.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+/**
+ * A [CompositionData] is the data tracked by the composer during composition.
+ *
+ * This interface is not intended to be used directly and is provided to allow the tools API to
+ * have access to data tracked during composition. The tools API should be used instead which
+ * provides a more usable interpretation of the slot table.
+ */
+interface CompositionData {
+    /**
+     * Iterate the composition data in the group.  The composition data is structured as a tree of
+     * values that corresponds to the call graph of the functions that produced the tree.
+     * Interspersed are groups that represents the nodes themselves.
+     */
+    val compositionGroups: Iterable<CompositionGroup>
+
+    /**
+     * Returns true if no composition data has been collected. This occurs when the first
+     * composition into this composition data has not completed yet or, if it is a group, it
+     * doesn't contain any child groups.
+     */
+    val isEmpty: Boolean
+}
+
+/**
+ * [CompositionGroup] is a group of data slots tracked independently by composition. These groups
+ * correspond to flow control branches (such as if statements and function calls) as well as
+ * emitting of a node to the tree.
+ *
+ * This interface is not intended to be used directly and is provided to allow the tools API to
+ * have access to data tracked during composition. The tools API should be used instead which
+ * provides a more usable interpretation of the slot table.
+ */
+interface CompositionGroup : CompositionData {
+    /**
+     * A value used to identify the group within its siblings and is typically a compiler
+     * generated integer but can be an object if the [key] composable is used.
+     */
+    val key: Any
+
+    /**
+     * Information recorded by the compiler to help tooling identify the source that generated
+     * the group. The format of this string is internal and is interpreted by the tools API which
+     * translates this information into source file name and offsets.
+     */
+    val sourceInfo: String?
+
+    /**
+     * If the group represents a node this returns a non-null value which is the node that was
+     * emitted for the group.
+     */
+    val node: Any?
+
+    /**
+     * The data stored in the slot table for this group. This information includes the values
+     * stored for parameters that are checked for change, any value passed as a parameter for
+     * [remember] and the last value returned by [remember], etc.
+     */
+    val data: Iterable<Any?>
+}
\ No newline at end of file
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionReference.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionReference.kt
index 26940dd..cdcb110 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionReference.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/CompositionReference.kt
@@ -41,7 +41,7 @@
     internal abstract fun composeInitial(composer: Composer<*>, composable: @Composable () -> Unit)
     internal abstract fun invalidate(composer: Composer<*>)
 
-    internal open fun recordInspectionTable(table: MutableSet<SlotTable>) {}
+    internal open fun recordInspectionTable(table: MutableSet<CompositionData>) {}
     internal open fun registerComposer(composer: Composer<*>) {
         registerComposerWithRoot(composer)
     }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
index 03bdc3d..7f5560c 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/Recomposer.kt
@@ -437,7 +437,7 @@
     internal override val collectingParameterInformation: Boolean
         get() = false
 
-    internal override fun recordInspectionTable(table: MutableSet<SlotTable>) {
+    internal override fun recordInspectionTable(table: MutableSet<CompositionData>) {
         // TODO: The root recomposer might be a better place to set up inspection
         // than the current configuration with an ambient
     }
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
index b1f49c7..14e4ca6 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/SlotTable.kt
@@ -73,8 +73,7 @@
 
 // The public API refers only to Index values. Address values are internal.
 
-@InternalComposeApi
-class SlotTable {
+internal class SlotTable : CompositionData, Iterable<CompositionGroup> {
     /**
      * An array to store group information that is stored as groups of [Group_Fields_Size]
      * elements of the array. The [groups] array can be thought of as an array of an inline
@@ -113,7 +112,14 @@
     /**
      * Tracks whether there is an active writer.
      */
-    private var writer = false
+    internal var writer = false
+        private set
+
+    /**
+     * An internal version that is incremented whenever a writer is created. This is used to
+     * detect when an iterator created by [CompositionData] is invalid.
+     */
+    internal var version = 0
 
     /**
      * A list of currently active anchors.
@@ -123,7 +129,7 @@
     /**
      * Returns true if the slot table is empty
      */
-    val isEmpty get() = groupsSize == 0
+    override val isEmpty get() = groupsSize == 0
 
     /**
      * Read the slot table in [block]. Any number of readers can be created but a slot table cannot
@@ -178,6 +184,7 @@
         check(!writer) { "Cannot start a writer when another writer is pending" }
         check(readers <= 0) { "Cannot start a writer when a reader is pending" }
         writer = true
+        version++
         return SlotWriter(this)
     }
 
@@ -438,6 +445,11 @@
         val end = if (group + 1 < groupsSize) groups.dataAnchor(group + 1) else slots.size
         return slots.toList().subList(start, end)
     }
+
+    override val compositionGroups: Iterable<CompositionGroup> get() = this
+
+    override fun iterator(): Iterator<CompositionGroup> =
+        GroupIterator(this, 0, groupsSize)
 }
 
 /**
@@ -448,8 +460,7 @@
  * instead of the [SlotTable] as the anchor index could have shifted due to operations performed
  * on the writer.
  */
-@InternalComposeApi
-class Anchor internal constructor(loc: Int) {
+internal class Anchor(loc: Int) {
     internal var location: Int = loc
     val valid get() = location != Int.MIN_VALUE
     fun toIndexFor(slots: SlotTable) = slots.anchorIndex(this)
@@ -459,8 +470,7 @@
 /**
  * A reader of a slot table. See [SlotTable]
  */
-@InternalComposeApi
-class SlotReader(
+internal class SlotReader(
     /**
      * The table for whom this is a reader.
      */
@@ -890,8 +900,7 @@
 /**
  * The writer for a slot table. See [SlotTable] for details.
  */
-@InternalComposeApi
-class SlotWriter internal constructor(
+internal class SlotWriter(
     /**
      * The [SlotTable] for whom this is writer.
      */
@@ -2350,6 +2359,79 @@
         if (index > parentAnchorPivot) index else size + index - parentAnchorPivot
 }
 
+private class GroupIterator(
+    val table: SlotTable,
+    start: Int,
+    val end: Int
+) : Iterator<CompositionGroup> {
+    private var index = start
+    private val version = table.version
+
+    init {
+        if (table.writer) throw ConcurrentModificationException()
+    }
+
+    override fun hasNext() = index < end
+
+    override fun next(): CompositionGroup {
+        validateRead()
+        val group = index
+        index += table.groups.groupSize(group)
+        return object : CompositionGroup, Iterable<CompositionGroup> {
+            override val isEmpty: Boolean get() = table.groups.groupSize(group) == 0
+
+            override val key: Any
+                get() = if (table.groups.hasObjectKey(group))
+                    table.slots[table.groups.objectKeyIndex(group)]!!
+                else table.groups.key(group)
+
+            override val sourceInfo: String?
+                get() = if (table.groups.hasAux(group))
+                    table.slots[table.groups.auxIndex(group)] as? String
+                else null
+
+            override val node: Any?
+                get() = if (table.groups.isNode(group))
+                    table.slots[table.groups.nodeIndex(group)] else
+                    null
+
+            override val data: Iterable<Any?> get() {
+                val start = table.groups.dataAnchor(group)
+                val end = if (group + 1 < table.groupsSize)
+                    table.groups.dataAnchor(group + 1) else table.slotsSize
+                return object : Iterable<Any?>, Iterator<Any?> {
+                    var index = start
+                    override fun iterator(): Iterator<Any?> = this
+                    override fun hasNext(): Boolean = index < end
+                    override fun next(): Any? =
+                        (
+                            if (index >= 0 && index < table.slots.size)
+                                table.slots[index]
+                            else null
+                            ).also { index++ }
+                }
+            }
+
+            override val compositionGroups: Iterable<CompositionGroup> get() = this
+
+            override fun iterator(): Iterator<CompositionGroup> {
+                validateRead()
+                return GroupIterator(
+                    table,
+                    group + 1,
+                    group + table.groups.groupSize(group)
+                )
+            }
+        }
+    }
+
+    private fun validateRead() {
+        if (table.version != version) {
+            throw ConcurrentModificationException()
+        }
+    }
+}
+
 // Parent -1 is reserved to be the root parent index so the anchor must pivot on -2.
 private const val parentAnchorPivot = -2
 
@@ -2539,7 +2621,6 @@
 /**
  * This is inlined here instead to avoid allocating a lambda for the compare when this is used.
  */
-@OptIn(InternalComposeApi::class)
 private fun ArrayList<Anchor>.search(location: Int, effectiveSize: Int): Int {
     var low = 0
     var high = size - 1
diff --git a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/InspectionTables.kt b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/InspectionTables.kt
index 6a1b9db..e8e35cc 100644
--- a/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/InspectionTables.kt
+++ b/compose/runtime/runtime/src/commonMain/kotlin/androidx/compose/runtime/tooling/InspectionTables.kt
@@ -16,12 +16,12 @@
 
 package androidx.compose.runtime.tooling
 
+import androidx.compose.runtime.CompositionData
 import androidx.compose.runtime.InternalComposeApi
-import androidx.compose.runtime.SlotTable
 import androidx.compose.runtime.staticAmbientOf
 
 /**
  * A set of slot tables that where produced when in inspection mode.
  */
 @InternalComposeApi
-val InspectionTables = staticAmbientOf<MutableSet<SlotTable>?> { null }
+val InspectionTables = staticAmbientOf<MutableSet<CompositionData>?> { null }
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/CompositionDataTests.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/CompositionDataTests.kt
new file mode 100644
index 0000000..20ee054
--- /dev/null
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/CompositionDataTests.kt
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.compose.runtime
+
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+@OptIn(InternalComposeApi::class)
+class CompositionDataTests {
+
+    @Test
+    fun canGetCompositionDataFromSlotTable() {
+        val slots = SlotTable()
+        val compositionData = slots as CompositionData
+        assertTrue(compositionData.compositionGroups.toList().isEmpty())
+    }
+
+    @Test
+    fun canIterateASlotTable() {
+        val slots = SlotTable().also {
+            it.write { writer ->
+                writer.insert {
+                    writer.group(1) {
+                        for (i in 1..5) {
+                            writer.group(i * 10) {
+                                for (j in 1..i) {
+                                    writer.update(i * 100 + j)
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        slots.verifyWellFormed()
+
+        val list = mutableListOf<Int>()
+        fun iterate(compositionData: CompositionData) {
+            for (group in compositionData.compositionGroups) {
+                list.add(group.key as Int)
+                for (data in group.data) {
+                    list.add(data as Int)
+                }
+                iterate(group)
+            }
+        }
+
+        iterate(slots)
+
+        assertEquals(
+            listOf(
+                1, 10, 101,
+                20, 201, 202,
+                30, 301, 302, 303,
+                40, 401, 402, 403, 404,
+                50, 501, 502, 503, 504, 505
+            ),
+            list
+        )
+    }
+
+    @Test
+    fun canFindNodes() {
+        val data = List(26) { 'A' + it }
+        val slots = SlotTable().also {
+            it.write { writer ->
+                writer.insert {
+                    writer.group(0) {
+                        fun emit(a: List<Char>) {
+                            if (a.isNotEmpty()) {
+                                writer.group(1) {
+                                    val mid = (a.size - 1) / 2 + 1
+                                    writer.nodeGroup(10, a[0])
+                                    if (mid > 1)
+                                        emit(a.subList(1, mid))
+                                    if (mid < a.size)
+                                        emit(a.subList(mid, a.size))
+                                }
+                            }
+                        }
+
+                        emit(data)
+                    }
+                }
+            }
+        }
+
+        val collected = mutableListOf<Char>()
+
+        fun collect(data: CompositionData) {
+            for (group in data.compositionGroups) {
+                if (group.node != null) {
+                    collected.add(group.node as Char)
+                }
+                collect(group)
+            }
+        }
+
+        collect(slots)
+
+        assertEquals(data, collected)
+    }
+
+    @Test
+    fun canFindSourceInfo() {
+        val slots = SlotTable().also {
+            var data = 0
+            it.write { writer ->
+                writer.insert {
+                    writer.group(0) {
+                        fun emit(depth: Int) {
+                            if (depth == 0) {
+                                writer.startData(100, aux = "$data")
+                                data++
+                                writer.endGroup()
+                            } else {
+                                if (depth == 2) {
+                                    writer.startData(depth * 1000, aux = "$data")
+                                    data++
+                                } else writer.startGroup(depth)
+                                emit(depth - 1)
+                                emit(depth - 1)
+                                writer.endGroup()
+                            }
+                        }
+                        emit(5)
+                    }
+                }
+            }
+        }
+
+        val collected = mutableListOf<String>()
+
+        fun collect(data: CompositionData) {
+            for (group in data.compositionGroups) {
+                val sourceInfo = group.sourceInfo
+                if (sourceInfo != null) {
+                    collected.add(sourceInfo)
+                }
+                collect(group)
+            }
+        }
+
+        collect(slots)
+
+        assertEquals(List(40) { "$it" }, collected)
+    }
+
+    @Test(expected = ConcurrentModificationException::class)
+    fun writeDuringIterationCausesException() {
+        val slots = SlotTable().also {
+            it.write { writer ->
+                writer.insert {
+                    writer.group(0) {
+                        repeat(10) { index ->
+                            writer.group(100 + index) { }
+                        }
+                    }
+                }
+            }
+        }
+
+        fun insertAGroup() {
+            slots.write { writer ->
+                writer.group {
+                    repeat(3) { writer.group { } }
+                    writer.insert {
+                        writer.group(200) { }
+                    }
+                    writer.skipToGroupEnd()
+                }
+            }
+        }
+
+        val groups = slots.compositionGroups.iterator()
+        insertAGroup()
+
+        // Expect this to cause an exception
+        groups.next()
+    }
+
+    @Test(expected = ConcurrentModificationException::class)
+    fun iterationDuringWriteCausesException() {
+        val slots = SlotTable().also {
+            it.write { writer ->
+                writer.insert {
+                    writer.group(0) {
+                        repeat(10) { index ->
+                            writer.group(100 + index) { }
+                        }
+                    }
+                }
+            }
+        }
+
+        slots.write { writer ->
+            writer.group {
+                repeat(3) { writer.group { } }
+                writer.insert {
+                    writer.group(200) { }
+                }
+                writer.skipToGroupEnd()
+
+                // Expect this to throw an exception
+                slots.compositionGroups.first()
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/CompositionTests.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/CompositionTests.kt
index fde53a01..84a2b9f 100644
--- a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/CompositionTests.kt
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/CompositionTests.kt
@@ -321,7 +321,7 @@
             repeat(of = chars) { c -> textOf(c) }
         }
 
-        fun MockViewValidator.validatechars(chars: Iterable<Char>) {
+        fun MockViewValidator.validateChars(chars: Iterable<Char>) {
             repeat(of = chars) { c -> textOf(c) }
         }
 
@@ -333,9 +333,9 @@
         }
 
         result.validate {
-            validatechars(chars)
-            validatechars(chars)
-            validatechars(chars)
+            validateChars(chars)
+            validateChars(chars)
+            validateChars(chars)
         }
 
         chars = listOf('a', 'b', 'x', 'c')
@@ -343,9 +343,9 @@
         result.expectChanges()
 
         result.validate {
-            validatechars(chars)
-            validatechars(chars)
-            validatechars(chars)
+            validateChars(chars)
+            validateChars(chars)
+            validateChars(chars)
         }
     }
 
@@ -567,7 +567,7 @@
     }
 
     @Test
-    fun testComponentWithVarCtorParameter() {
+    fun testComponentWithVarConstructorParameter() {
         @Composable fun MockComposeScope.One(first: Int) {
             text("$first")
         }
@@ -601,7 +601,7 @@
     }
 
     @Test
-    fun testComponentWithValCtorParameter() {
+    fun testComponentWithValConstructorParameter() {
         @Composable fun MockComposeScope.One(first: Int) {
             text("$first")
         }
@@ -2516,7 +2516,7 @@
     @Test
     fun testComposableLambdaSubcompositionInvalidation() = runBlockingTest {
         localRecomposerTest { recomposer ->
-            val composer = Composer(SlotTable(), EmptyApplier(), recomposer)
+            val composer = Composer(EmptyApplier(), recomposer)
             try {
                 var rootState by mutableStateOf(false)
                 val composedResults = mutableListOf<Boolean>()
@@ -2544,7 +2544,7 @@
     @Test
     fun testCompositionReferenceIsRemembered() = runBlockingTest {
         localRecomposerTest { recomposer ->
-            val composer = Composer(SlotTable(), EmptyApplier(), recomposer)
+            val composer = Composer(EmptyApplier(), recomposer)
             try {
                 lateinit var invalidator: () -> Unit
                 val parentReferences = mutableListOf<CompositionReference>()
@@ -2569,7 +2569,7 @@
     @Test
     fun testParentCompositionRecomposesFirst() = runBlockingTest {
         localRecomposerTest { recomposer ->
-            val composer = Composer(SlotTable(), EmptyApplier(), recomposer)
+            val composer = Composer(EmptyApplier(), recomposer)
             val results = mutableListOf<String>()
             try {
                 var firstState by mutableStateOf("firstInitial")
@@ -2606,7 +2606,7 @@
     val parentRef = compositionReference()
     val currentContent by rememberUpdatedState(content)
     DisposableEffect(parentRef) {
-        val subcomposer = Composer(SlotTable(), EmptyApplier(), parentRef)
+        val subcomposer = Composer(EmptyApplier(), parentRef)
         parentRef.composeInitial(subcomposer) {
             currentContent()
         }
@@ -2671,8 +2671,7 @@
         assertTrue(changes, "Expected changes")
         composer.applyChanges()
         Snapshot.notifyObjectsInitialized()
-        composer.slotTable.verifyWellFormed()
-        composer.insertTable.verifyWellFormed()
+        composer.verifyConsistent()
     }
 
     fun recompose(): Boolean = doCompose(composer) { composer.recompose() }
@@ -2708,6 +2707,9 @@
     }
 }
 
+/**
+ * Composer the given block.
+ */
 @OptIn(InternalComposeApi::class, ExperimentalComposeApi::class)
 private fun compose(
     block: @Composable MockComposeScope.() -> Unit
@@ -2727,7 +2729,6 @@
             scope.launch(clock) { runRecomposeAndApplyChanges() }
         }
         Composer(
-            SlotTable(),
             ViewApplier(root),
             recomposer
         )
@@ -2741,26 +2742,11 @@
         Snapshot.notifyObjectsInitialized()
         composer.applyChanges()
     }
-    composer.slotTable.verifyWellFormed()
-    validateRecomposeScopeAnchors(composer.slotTable)
+    composer.verifyConsistent()
 
     return CompositionResult(composer, root)
 }
 
-@OptIn(InternalComposeApi::class)
-fun validateRecomposeScopeAnchors(slotTable: SlotTable) {
-    val scopes = slotTable.slots.map { it as? RecomposeScope }.filterNotNull()
-    for (scope in scopes) {
-        scope.anchor?.let { anchor ->
-            check(scope in slotTable.slotsOf(anchor.toIndexFor(slotTable))) {
-                val dataIndex = slotTable.slots.indexOf(scope)
-                "Misaligned anchor $anchor in scope $scope encountered, scope found at " +
-                    "$dataIndex"
-            }
-        }
-    }
-}
-
 // Contact test data
 private val bob = Contact("Bob Smith", email = "bob@smith.com")
 private val jon = Contact(name = "Jon Alberton", email = "jon@alberton.com")
diff --git a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt
index 5910f88..d6d2f38 100644
--- a/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt
+++ b/compose/runtime/runtime/src/test/kotlin/androidx/compose/runtime/SlotTableTests.kt
@@ -3070,34 +3070,34 @@
 }
 
 @OptIn(InternalComposeApi::class)
-private inline fun SlotWriter.group(block: () -> Unit) {
+internal inline fun SlotWriter.group(block: () -> Unit) {
     startGroup()
     block()
     endGroup()
 }
 
 @OptIn(InternalComposeApi::class)
-private inline fun SlotWriter.group(key: Int, block: () -> Unit) {
+internal inline fun SlotWriter.group(key: Int, block: () -> Unit) {
     startGroup(key)
     block()
     endGroup()
 }
 
 @OptIn(InternalComposeApi::class)
-private inline fun SlotWriter.nodeGroup(key: Int, node: Any, block: () -> Unit = { }) {
+internal inline fun SlotWriter.nodeGroup(key: Int, node: Any, block: () -> Unit = { }) {
     startNode(key, node)
     block()
     endGroup()
 }
 @OptIn(InternalComposeApi::class)
-private inline fun SlotWriter.insert(block: () -> Unit) {
+internal inline fun SlotWriter.insert(block: () -> Unit) {
     beginInsert()
     block()
     endInsert()
 }
 
 @OptIn(InternalComposeApi::class)
-private inline fun SlotReader.group(key: Int, block: () -> Unit) {
+internal inline fun SlotReader.group(key: Int, block: () -> Unit) {
     assertEquals(key, groupKey)
     startGroup()
     block()
@@ -3105,7 +3105,7 @@
 }
 
 @OptIn(InternalComposeApi::class)
-private inline fun SlotReader.group(block: () -> Unit) {
+internal inline fun SlotReader.group(block: () -> Unit) {
     startGroup()
     block()
     endGroup()
@@ -3124,7 +3124,7 @@
 private const val elementKey = 100
 
 @OptIn(InternalComposeApi::class)
-fun testSlotsNumbered(): SlotTable {
+private fun testSlotsNumbered(): SlotTable {
     val slotTable = SlotTable()
     slotTable.write { writer ->
         writer.beginInsert()
@@ -3141,7 +3141,7 @@
 
 // Creates 0 until 10 items each with 10 elements numbered 0...n with 0..n slots
 @OptIn(InternalComposeApi::class)
-fun testItems(): SlotTable {
+private fun testItems(): SlotTable {
     val slots = SlotTable()
     slots.write { writer ->
         writer.beginInsert()
@@ -3178,7 +3178,7 @@
 }
 
 @OptIn(InternalComposeApi::class)
-fun validateItems(slots: SlotTable) {
+private fun validateItems(slots: SlotTable) {
     slots.read { reader ->
         check(reader.groupKey == treeRoot) { "Invalid root key" }
         reader.startGroup()
@@ -3229,7 +3229,7 @@
 }
 
 @OptIn(InternalComposeApi::class)
-fun narrowTrees(): Pair<SlotTable, List<Anchor>> {
+private fun narrowTrees(): Pair<SlotTable, List<Anchor>> {
     val slots = SlotTable()
     val anchors = mutableListOf<Anchor>()
     slots.write { writer ->
@@ -3278,13 +3278,13 @@
 }
 
 @OptIn(InternalComposeApi::class)
-fun SlotReader.expectGroup(key: Int): Int {
+private fun SlotReader.expectGroup(key: Int): Int {
     assertEquals(key, groupKey)
     return skipGroup()
 }
 
 @OptIn(InternalComposeApi::class)
-fun SlotReader.expectGroup(
+private fun SlotReader.expectGroup(
     key: Int,
     block: () -> Unit
 ) {
@@ -3295,12 +3295,12 @@
 }
 
 @OptIn(InternalComposeApi::class)
-fun SlotReader.expectData(value: Any) {
+private fun SlotReader.expectData(value: Any) {
     assertEquals(value, next())
 }
 
 @OptIn(InternalComposeApi::class)
-fun SlotReader.expectGroup(
+private fun SlotReader.expectGroup(
     key: Int,
     objectKey: Any?,
     block: () -> Unit = { skipToGroupEnd() }
diff --git a/compose/ui/ui-tooling/api/current.txt b/compose/ui/ui-tooling/api/current.txt
index ca0c914..2d94392 100644
--- a/compose/ui/ui-tooling/api/current.txt
+++ b/compose/ui/ui-tooling/api/current.txt
@@ -74,7 +74,7 @@
   }
 
   public final class SlotTreeKt {
-    method public static androidx.compose.ui.tooling.Group asTree(androidx.compose.runtime.SlotTable);
+    method public static androidx.compose.ui.tooling.Group asTree(androidx.compose.runtime.CompositionData);
     method public static String? getPosition(androidx.compose.ui.tooling.Group);
   }
 
diff --git a/compose/ui/ui-tooling/api/public_plus_experimental_current.txt b/compose/ui/ui-tooling/api/public_plus_experimental_current.txt
index ca0c914..2d94392 100644
--- a/compose/ui/ui-tooling/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui-tooling/api/public_plus_experimental_current.txt
@@ -74,7 +74,7 @@
   }
 
   public final class SlotTreeKt {
-    method public static androidx.compose.ui.tooling.Group asTree(androidx.compose.runtime.SlotTable);
+    method public static androidx.compose.ui.tooling.Group asTree(androidx.compose.runtime.CompositionData);
     method public static String? getPosition(androidx.compose.ui.tooling.Group);
   }
 
diff --git a/compose/ui/ui-tooling/api/restricted_current.txt b/compose/ui/ui-tooling/api/restricted_current.txt
index ca0c914..2d94392 100644
--- a/compose/ui/ui-tooling/api/restricted_current.txt
+++ b/compose/ui/ui-tooling/api/restricted_current.txt
@@ -74,7 +74,7 @@
   }
 
   public final class SlotTreeKt {
-    method public static androidx.compose.ui.tooling.Group asTree(androidx.compose.runtime.SlotTable);
+    method public static androidx.compose.ui.tooling.Group asTree(androidx.compose.runtime.CompositionData);
     method public static String? getPosition(androidx.compose.ui.tooling.Group);
   }
 
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/BoundsTest.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/BoundsTest.kt
index 5317df3..30d1dd4 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/BoundsTest.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/BoundsTest.kt
@@ -55,7 +55,7 @@
 
     @Test
     fun testBounds() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         show {
             Inspectable(slotTableRecord) {
                 Box {
@@ -98,7 +98,7 @@
 
     @Test
     fun testBoundWithConstraints() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         show {
             Inspectable(slotTableRecord) {
                 WithConstraints {
@@ -131,7 +131,7 @@
     @Test
     @LargeTest
     fun testDisposeWithComposeTables() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         var value by mutableStateOf(0)
         var latch = CountDownLatch(1)
         show {
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/InspectableTests.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/InspectableTests.kt
index 7f1b213..a1ea937 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/InspectableTests.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/InspectableTests.kt
@@ -25,7 +25,6 @@
 import androidx.compose.material.Text
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.InternalComposeApi
-import androidx.compose.runtime.SlotTable
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.drawBehind
 import androidx.compose.ui.graphics.Color
@@ -50,7 +49,7 @@
 class InspectableTests : ToolingTest() {
     @Test
     fun simpleInspection() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         show {
             Inspectable(slotTableRecord) {
                 Column {
@@ -77,7 +76,7 @@
 
     @Test
     fun parametersTest() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         fun unknown(i: Int) = i
 
         show {
@@ -116,8 +115,8 @@
 
         val tree = slotTableRecord.store.first().asTree()
         val list = tree.asList()
-        val parameters = list.filter {
-            it.parameters.isNotEmpty() && it.location.let {
+        val parameters = list.filter { group ->
+            group.parameters.isNotEmpty() && group.location.let {
                 it != null && it.sourceFile == "InspectableTests.kt"
             }
         }
@@ -295,7 +294,7 @@
     fun inInspectionMode() {
         var displayed = false
         show {
-            Inspectable(SlotTableRecord.create()) {
+            Inspectable(CompositionDataRecord.create()) {
                 Column {
                     InInspectionModeOnly {
                         Box(Modifier.preferredSize(100.dp).background(color = Color(0xFF)))
@@ -326,7 +325,7 @@
     @InternalComposeApi
     @Test // regression test for b/161839910
     fun textParametersAreCorrect() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         show {
             Inspectable(slotTableRecord) {
                 Text("Test")
@@ -334,8 +333,8 @@
         }
         val tree = slotTableRecord.store.first().asTree()
         val list = tree.asList()
-        val parameters = list.filter {
-            it.parameters.isNotEmpty() && it.location.let {
+        val parameters = list.filter { group ->
+            group.parameters.isNotEmpty() && group.location.let {
                 it != null && it.sourceFile == "InspectableTests.kt"
             }
         }
@@ -431,14 +430,3 @@
     }
     return result
 }
-
-internal fun SlotTableRecord.findGroupForFile(fileName: String) =
-    store.map { it.findGroupForFile(fileName) }.filterNotNull().firstOrNull()
-
-@OptIn(InternalComposeApi::class)
-fun SlotTable.findGroupForFile(fileName: String) = asTree().findGroupForFile(fileName)
-fun Group.findGroupForFile(fileName: String): Group? {
-    val position = position
-    if (position != null && position.contains(fileName)) return this
-    return children.map { it.findGroupForFile(fileName) }.filterNotNull().firstOrNull()
-}
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ModifierInfoTest.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ModifierInfoTest.kt
index 6a7348f..a5070a6 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ModifierInfoTest.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ModifierInfoTest.kt
@@ -44,7 +44,7 @@
 
     @Test
     fun testBounds() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         show {
             Inspectable(slotTableRecord) {
                 with(AmbientDensity.current) {
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ToolingTest.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ToolingTest.kt
index d3d094f..f8c34a2 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ToolingTest.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/ToolingTest.kt
@@ -21,8 +21,7 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.InternalComposeApi
-import androidx.compose.runtime.SlotTable
+import androidx.compose.runtime.CompositionData
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.R
 import androidx.compose.ui.layout.onGloballyPositioned
@@ -73,12 +72,11 @@
         activityTestRule.onUiThread { }
     }
 
-    @OptIn(InternalComposeApi::class)
-    internal fun showAndRecord(content: @Composable () -> Unit): MutableSet<SlotTable>? {
+    internal fun showAndRecord(content: @Composable () -> Unit): MutableSet<CompositionData>? {
 
         positionedLatch = CountDownLatch(1)
-        val map: MutableSet<SlotTable> = Collections.newSetFromMap(
-            WeakHashMap<SlotTable, Boolean>()
+        val map: MutableSet<CompositionData> = Collections.newSetFromMap(
+            WeakHashMap<CompositionData, Boolean>()
         )
         activityTestRule.onUiThread {
             ViewRootForTest.onViewCreatedCallback = {
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/InlineClassConverterTest.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/InlineClassConverterTest.kt
index 1491a4c..6a035f6 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/InlineClassConverterTest.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/InlineClassConverterTest.kt
@@ -21,7 +21,7 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.tooling.Group
 import androidx.compose.ui.tooling.Inspectable
-import androidx.compose.ui.tooling.SlotTableRecord
+import androidx.compose.ui.tooling.CompositionDataRecord
 import androidx.compose.ui.tooling.ToolingTest
 import androidx.compose.ui.tooling.asTree
 import androidx.compose.ui.unit.Dp
@@ -38,7 +38,7 @@
 
     @Test
     fun parameterValueTest() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         show {
             Inspectable(slotTableRecord) {
                 Surface {
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt
index 4ecf4eb..89c3db5 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTreeTest.kt
@@ -39,7 +39,7 @@
 import androidx.compose.ui.tooling.Group
 import androidx.compose.ui.tooling.Inspectable
 import androidx.compose.ui.tooling.R
-import androidx.compose.ui.tooling.SlotTableRecord
+import androidx.compose.ui.tooling.CompositionDataRecord
 import androidx.compose.ui.tooling.ToolingTest
 import androidx.compose.ui.tooling.asTree
 import androidx.compose.ui.tooling.position
@@ -76,7 +76,7 @@
     @Ignore("Manual test")
     @Test
     fun buildTree() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
 
         show {
             Inspectable(slotTableRecord) {
@@ -388,7 +388,7 @@
 
     @Test
     fun testStitchTreeFromModelDrawerLayout() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
 
         show {
             Inspectable(slotTableRecord) {
@@ -442,7 +442,7 @@
 
     @Test
     fun testSpacer() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
 
         show {
             Inspectable(slotTableRecord) {
@@ -466,7 +466,7 @@
 
     @Test // regression test b/174855322
     fun testBasicText() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
 
         view.setTag(R.id.inspection_slot_table_set, slotTableRecord.store)
         show {
@@ -492,7 +492,7 @@
     @Test
     @Ignore("b/174152464")
     fun testTextId() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
 
         show {
             Inspectable(slotTableRecord) {
@@ -664,7 +664,7 @@
             else -> value?.toString() ?: "null"
         }
 
-    private fun dumpSlotTableSet(slotTableRecord: SlotTableRecord) {
+    private fun dumpSlotTableSet(slotTableRecord: CompositionDataRecord) {
         @Suppress("ConstantConditionIf")
         if (!DEBUG) {
             return
diff --git a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/OffsetInformationTest.kt b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/OffsetInformationTest.kt
index 96c833c..7c85542 100644
--- a/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/OffsetInformationTest.kt
+++ b/compose/ui/ui-tooling/src/androidTest/java/androidx/compose/ui/tooling/inspector/OffsetInformationTest.kt
@@ -18,7 +18,7 @@
 
 import androidx.compose.ui.tooling.Group
 import androidx.compose.ui.tooling.Inspectable
-import androidx.compose.ui.tooling.SlotTableRecord
+import androidx.compose.ui.tooling.CompositionDataRecord
 import androidx.compose.ui.tooling.ToolingTest
 import androidx.compose.ui.tooling.asTree
 import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -32,7 +32,7 @@
 class OffsetInformationTest : ToolingTest() {
     @Test
     fun testOffset() {
-        val slotTableRecord = SlotTableRecord.create()
+        val slotTableRecord = CompositionDataRecord.create()
         show {
             Inspectable(slotTableRecord) {
                 OffsetData()
diff --git a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/Inspectable.kt b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/Inspectable.kt
index 1f1b9d2..b0d5680 100644
--- a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/Inspectable.kt
+++ b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/Inspectable.kt
@@ -17,9 +17,9 @@
 package androidx.compose.ui.tooling
 
 import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionData
 import androidx.compose.runtime.InternalComposeApi
 import androidx.compose.runtime.Providers
-import androidx.compose.runtime.SlotTable
 import androidx.compose.runtime.currentComposer
 import androidx.compose.runtime.tooling.InspectionTables
 import androidx.compose.ui.platform.InspectionMode
@@ -27,20 +27,19 @@
 import java.util.WeakHashMap
 
 /**
- * Storage for the preview generated [SlotTable]s.
+ * Storage for the preview generated [CompositionData]s.
  */
-internal interface SlotTableRecord {
-    @OptIn(InternalComposeApi::class)
-    val store: Set<SlotTable>
+internal interface CompositionDataRecord {
+    val store: Set<CompositionData>
 
     companion object {
-        fun create(): SlotTableRecord = SlotTableRecordImpl()
+        fun create(): CompositionDataRecord = CompositionDataRecordImpl()
     }
 }
 
-private class SlotTableRecordImpl : SlotTableRecord {
+private class CompositionDataRecordImpl : CompositionDataRecord {
     @OptIn(InternalComposeApi::class)
-    override val store: MutableSet<SlotTable> =
+    override val store: MutableSet<CompositionData> =
         Collections.newSetFromMap(WeakHashMap())
 }
 
@@ -48,20 +47,21 @@
  * A wrapper for compositions in inspection mode. The composition inside the Inspectable component
  * is in inspection mode.
  *
- * @param slotTableRecord [SlotTableRecord] to record the SlotTable used in the composition of [content]
+ * @param compositionDataRecord [CompositionDataRecord] to record the SlotTable used in the
+ * composition of [content]
  *
  * @suppress
  */
 @Composable
 @OptIn(InternalComposeApi::class)
 internal fun Inspectable(
-    slotTableRecord: SlotTableRecord,
+    compositionDataRecord: CompositionDataRecord,
     content: @Composable () -> Unit
 ) {
     currentComposer.collectKeySourceInformation()
     currentComposer.collectParameterInformation()
-    val store = (slotTableRecord as SlotTableRecordImpl).store
-    store.add(currentComposer.slotTable)
+    val store = (compositionDataRecord as CompositionDataRecordImpl).store
+    store.add(currentComposer.compositionData)
     Providers(
         InspectionMode provides true,
         InspectionTables provides store,
diff --git a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/SlotTree.kt b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/SlotTree.kt
index 265bcfc..f38aa50 100644
--- a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/SlotTree.kt
+++ b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/SlotTree.kt
@@ -14,14 +14,10 @@
  * limitations under the License.
  */
 
-@file:OptIn(InternalComposeApi::class)
-
 package androidx.compose.ui.tooling
 
-import androidx.compose.runtime.InternalComposeApi
-import androidx.compose.runtime.SlotReader
-import androidx.compose.runtime.SlotTable
-import androidx.compose.runtime.keySourceInfoOf
+import androidx.compose.runtime.CompositionData
+import androidx.compose.runtime.CompositionGroup
 import androidx.compose.ui.layout.globalPosition
 import androidx.compose.ui.layout.LayoutInfo
 import androidx.compose.ui.layout.ModifierInfo
@@ -160,9 +156,6 @@
  */
 data class JoinedKey(val left: Any?, val right: Any?)
 
-@OptIn(InternalComposeApi::class)
-private fun convertKey(key: Int): Any? = keySourceInfoOf(key)
-
 internal val emptyBox = IntBounds(0, 0, 0, 0)
 
 private val tokenizer = Regex("(\\d+)|([,])|([*])|([:])|L|(P\\([^)]*\\))|(C(\\(([^)]*)\\))?)|@")
@@ -432,28 +425,15 @@
 /**
  * Iterate the slot table and extract a group tree that corresponds to the content of the table.
  */
-@OptIn(InternalComposeApi::class)
-private fun SlotReader.getGroup(parentContext: SourceInformationContext?): Group {
-    val key = convertKey(groupKey)
-    val groupData = groupAux
-    val context = if (groupData != null && groupData is String) {
-        sourceInformationContextOf(groupData, parentContext)
-    } else null
-    val nodeGroup = isNode
-    val end = currentGroup + groupSize
-    val node = if (nodeGroup) groupNode else null
+private fun CompositionGroup.getGroup(parentContext: SourceInformationContext?): Group {
+    val key = key
+    val context = sourceInfo?.let { sourceInformationContextOf(it, parentContext) }
+    val node = node
     val data = mutableListOf<Any?>()
     val children = mutableListOf<Group>()
-    for (index in 0 until groupSlotCount) {
-        data.add(groupGet(index))
-    }
-
-    reposition(currentGroup + 1)
-
-    // A group ends with a list of groups
-    while (currentGroup < end) {
-        children.add(getGroup(context))
-    }
+    data.addAll(this.data)
+    for (child in compositionGroups)
+        children.add(child.getGroup(context))
 
     val modifierInfo = if (node is LayoutInfo) {
         node.getModifierInfo()
@@ -468,9 +448,9 @@
             if (children.isEmpty()) emptyBox else
                 children.map { g -> g.box }.reduce { acc, box -> box.union(acc) }
     }
-    return if (nodeGroup) NodeGroup(
+    return if (node != null) NodeGroup(
         key,
-        node as Any,
+        node,
         box,
         data,
         modifierInfo,
@@ -513,8 +493,7 @@
  * Return a group tree for for the slot table that represents the entire content of the slot
  * table.
  */
-@OptIn(InternalComposeApi::class)
-fun SlotTable.asTree(): Group = read { it.getGroup(null) }
+fun CompositionData.asTree(): Group = compositionGroups.first().getGroup(null)
 
 internal fun IntBounds.union(other: IntBounds): IntBounds {
     if (this == emptyBox) return other else if (other == emptyBox) return this
@@ -547,62 +526,61 @@
     context: SourceInformationContext?
 ): List<ParameterInformation> {
     if (data.isNotEmpty()) {
-        val recomposeScope = data[0]
+        val recomposeScope = data.firstOrNull {
+            it != null && it.javaClass.name.endsWith(recomposeScopeNameSuffix)
+        }
         if (recomposeScope != null) {
-            val scopeClass = recomposeScope.javaClass
-            if (scopeClass.name.endsWith(recomposeScopeNameSuffix)) {
-                try {
-                    val blockField = scopeClass.accessibleField("block")
-                    if (blockField != null) {
-                        val block = blockField.get(recomposeScope)
-                        if (block != null) {
-                            val blockClass = block.javaClass
-                            val defaultsField = blockClass.accessibleField(defaultFieldName)
-                            val changedField = blockClass.accessibleField(changedFieldName)
-                            val default =
-                                if (defaultsField != null) defaultsField.get(block) as Int else 0
-                            val changed =
-                                if (changedField != null) changedField.get(block) as Int else 0
-                            val fields = blockClass.declaredFields
-                                .filter {
-                                    it.name.startsWith(parameterPrefix) &&
-                                        !it.name.startsWith(internalFieldPrefix) &&
-                                        !it.name.startsWith(jacocoDataField)
-                                }.sortedBy { it.name }
-                            val parameters = mutableListOf<ParameterInformation>()
-                            val parametersMetadata = context?.parameters ?: emptyList()
-                            repeat(fields.size) { index ->
-                                val metadata = if (index < parametersMetadata.size)
-                                    parametersMetadata[index] else Parameter(index)
-                                if (metadata.sortedIndex >= fields.size) return@repeat
-                                val field = fields[metadata.sortedIndex]
-                                field.isAccessible = true
-                                val value = field.get(block)
-                                val fromDefault = (1 shl index) and default != 0
-                                val changedOffset = index * BITS_PER_SLOT + 1
-                                val parameterChanged = (
-                                    (SLOT_MASK shl changedOffset) and changed
-                                    ) shr changedOffset
-                                val static = parameterChanged and STATIC_BITS == STATIC_BITS
-                                val compared = parameterChanged and STATIC_BITS == 0
-                                val stable = parameterChanged and STABLE_BITS == 0
-                                parameters.add(
-                                    ParameterInformation(
-                                        name = field.name.substring(1),
-                                        value = value,
-                                        fromDefault = fromDefault,
-                                        static = static,
-                                        compared = compared && !fromDefault,
-                                        inlineClass = metadata.inlineClass,
-                                        stable = stable
-                                    )
+            try {
+                val blockField = recomposeScope.javaClass.accessibleField("block")
+                if (blockField != null) {
+                    val block = blockField.get(recomposeScope)
+                    if (block != null) {
+                        val blockClass = block.javaClass
+                        val defaultsField = blockClass.accessibleField(defaultFieldName)
+                        val changedField = blockClass.accessibleField(changedFieldName)
+                        val default =
+                            if (defaultsField != null) defaultsField.get(block) as Int else 0
+                        val changed =
+                            if (changedField != null) changedField.get(block) as Int else 0
+                        val fields = blockClass.declaredFields
+                            .filter {
+                                it.name.startsWith(parameterPrefix) &&
+                                    !it.name.startsWith(internalFieldPrefix) &&
+                                    !it.name.startsWith(jacocoDataField)
+                            }.sortedBy { it.name }
+                        val parameters = mutableListOf<ParameterInformation>()
+                        val parametersMetadata = context?.parameters ?: emptyList()
+                        repeat(fields.size) { index ->
+                            val metadata = if (index < parametersMetadata.size)
+                                parametersMetadata[index] else Parameter(index)
+                            if (metadata.sortedIndex >= fields.size) return@repeat
+                            val field = fields[metadata.sortedIndex]
+                            field.isAccessible = true
+                            val value = field.get(block)
+                            val fromDefault = (1 shl index) and default != 0
+                            val changedOffset = index * BITS_PER_SLOT + 1
+                            val parameterChanged = (
+                                (SLOT_MASK shl changedOffset) and changed
+                                ) shr changedOffset
+                            val static = parameterChanged and STATIC_BITS == STATIC_BITS
+                            val compared = parameterChanged and STATIC_BITS == 0
+                            val stable = parameterChanged and STABLE_BITS == 0
+                            parameters.add(
+                                ParameterInformation(
+                                    name = field.name.substring(1),
+                                    value = value,
+                                    fromDefault = fromDefault,
+                                    static = static,
+                                    compared = compared && !fromDefault,
+                                    inlineClass = metadata.inlineClass,
+                                    stable = stable
                                 )
-                            }
-                            return parameters
+                            )
                         }
+                        return parameters
                     }
-                } catch (_: Throwable) {
                 }
+            } catch (_: Throwable) {
             }
         }
     }
diff --git a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTree.kt b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTree.kt
index b831653..f2acc87 100644
--- a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTree.kt
+++ b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/inspector/LayoutInspectorTree.kt
@@ -17,9 +17,10 @@
 package androidx.compose.ui.tooling.inspector
 
 import android.view.View
+import androidx.compose.runtime.CompositionData
 import androidx.compose.runtime.InternalComposeApi
-import androidx.compose.runtime.SlotTable
 import androidx.compose.ui.layout.LayoutInfo
+import androidx.compose.ui.node.LayoutNode
 import androidx.compose.ui.node.OwnedLayer
 import androidx.compose.ui.tooling.Group
 import androidx.compose.ui.tooling.NodeGroup
@@ -73,13 +74,13 @@
         Collections.newSetFromMap(IdentityHashMap<MutableInspectorNode, Boolean>())
 
     /**
-     * Converts the [SlotTable] set held by [view] into a list of root nodes.
+     * Converts the [CompositionData] set held by [view] into a list of root nodes.
      */
     @OptIn(InternalComposeApi::class)
     fun convert(view: View): List<InspectorNode> {
         parameterFactory.density = Density(view.context)
         @Suppress("UNCHECKED_CAST")
-        val tables = view.getTag(R.id.inspection_slot_table_set) as? Set<SlotTable>
+        val tables = view.getTag(R.id.inspection_slot_table_set) as? Set<CompositionData>
             ?: return emptyList()
         clear()
         val result = convert(tables)
@@ -111,7 +112,7 @@
     }
 
     @OptIn(InternalComposeApi::class)
-    private fun convert(tables: Set<SlotTable>): List<InspectorNode> {
+    private fun convert(tables: Set<CompositionData>): List<InspectorNode> {
         val trees = tables.map { convert(it) }
         return when (trees.size) {
             0 -> listOf()
@@ -121,11 +122,12 @@
     }
 
     /**
-     * Stitch separate trees together using the [LayoutInfo]s found in the [SlotTable]s.
+     * Stitch separate trees together using the [LayoutNode]s found in the [CompositionData]s.
      *
-     * Some constructs in Compose (e.g. ModalDrawerLayout) will result is multiple [SlotTable]s.
-     * This code will attempt to stitch the resulting [InspectorNode] trees together by looking
-     * at the parent of each [LayoutInfo].
+     * Some constructs in Compose (e.g. ModalDrawerLayout) will result is multiple
+     * [CompositionData]s. This code will attempt to stitch the resulting [InspectorNode] trees
+     * together by looking at the parent of each [LayoutNode].
+     *
      * If this algorithm is successful the result of this function will be a list with a single
      * tree.
      */
@@ -199,7 +201,7 @@
     }
 
     @OptIn(InternalComposeApi::class)
-    private fun convert(table: SlotTable): MutableInspectorNode {
+    private fun convert(table: CompositionData): MutableInspectorNode {
         val fakeParent = newNode()
         addToParent(fakeParent, listOf(convert(table.asTree())))
         return fakeParent
diff --git a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/preview/ComposeViewAdapter.kt b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/preview/ComposeViewAdapter.kt
index e25b4ae..99eb764 100644
--- a/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/preview/ComposeViewAdapter.kt
+++ b/compose/ui/ui-tooling/src/main/java/androidx/compose/ui/tooling/preview/ComposeViewAdapter.kt
@@ -45,7 +45,7 @@
 import androidx.compose.ui.platform.ViewRootForTest
 import androidx.compose.ui.tooling.Group
 import androidx.compose.ui.tooling.Inspectable
-import androidx.compose.ui.tooling.SlotTableRecord
+import androidx.compose.ui.tooling.CompositionDataRecord
 import androidx.compose.ui.tooling.SourceLocation
 import androidx.compose.ui.tooling.asTree
 import androidx.compose.ui.tooling.preview.animation.PreviewAnimationClock
@@ -126,7 +126,7 @@
      */
     private var debugPaintBounds = false
     internal var viewInfos: List<ViewInfo> = emptyList()
-    private val slotTableRecord = SlotTableRecord.create()
+    private val slotTableRecord = CompositionDataRecord.create()
 
     /**
      * Simple function name of the Composable being previewed.
diff --git a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/Wrapper.kt b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/Wrapper.kt
index 0e2b0e2..2728ac1 100644
--- a/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/Wrapper.kt
+++ b/compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/Wrapper.kt
@@ -24,13 +24,13 @@
 import androidx.annotation.MainThread
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.Composition
+import androidx.compose.runtime.CompositionData
 import androidx.compose.runtime.CompositionReference
 import androidx.compose.runtime.ExperimentalComposeApi
 import androidx.compose.runtime.InternalComposeApi
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.Providers
 import androidx.compose.runtime.Recomposer
-import androidx.compose.runtime.SlotTable
 import androidx.compose.runtime.compositionFor
 import androidx.compose.runtime.currentComposer
 import androidx.compose.runtime.emptyContent
@@ -185,7 +185,7 @@
     if (inspectionWanted(owner)) {
         owner.setTag(
             R.id.inspection_slot_table_set,
-            Collections.newSetFromMap(WeakHashMap<SlotTable, Boolean>())
+            Collections.newSetFromMap(WeakHashMap<CompositionData, Boolean>())
         )
         enableDebugInspectorInfo()
     }
@@ -236,11 +236,12 @@
                         @Suppress("UNCHECKED_CAST")
                         val inspectionTable =
                             owner.getTag(R.id.inspection_slot_table_set) as?
-                                MutableSet<SlotTable>
+                                MutableSet<CompositionData>
                                 ?: (owner.parent as? View)?.getTag(R.id.inspection_slot_table_set)
-                                    as? MutableSet<SlotTable>
+                                    as? MutableSet<CompositionData>
                         if (inspectionTable != null) {
-                            inspectionTable.add(currentComposer.slotTable)
+                            @OptIn(InternalComposeApi::class)
+                            inspectionTable.add(currentComposer.compositionData)
                             currentComposer.collectParameterInformation()
                         }
 
diff --git a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/ComposedModifierTest.kt b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/ComposedModifierTest.kt
index 7485666..8b0058f 100644
--- a/compose/ui/ui/src/test/kotlin/androidx/compose/ui/ComposedModifierTest.kt
+++ b/compose/ui/ui/src/test/kotlin/androidx/compose/ui/ComposedModifierTest.kt
@@ -22,7 +22,6 @@
 import androidx.compose.runtime.ExperimentalComposeApi
 import androidx.compose.runtime.InternalComposeApi
 import androidx.compose.runtime.Recomposer
-import androidx.compose.runtime.SlotTable
 import androidx.compose.runtime.currentComposer
 import androidx.compose.runtime.dispatch.MonotonicFrameClock
 import androidx.compose.runtime.invalidate
@@ -211,7 +210,6 @@
     block: @Composable () -> Unit
 ): Composer<Unit> {
     return Composer(
-        SlotTable(),
         EmptyApplier(),
         recomposer
     ).apply {
@@ -221,7 +219,7 @@
             fn(this, 0)
         }
         applyChanges()
-        slotTable.verifyWellFormed()
+        verifyConsistent()
     }
 }