Represent classes serialized to the instant execution cache using an integer id, rather than a string class name.

Apart from reducing the amount of stuff written to the cache, this will also allow multiple classes with the same name (but different ClassLoaders) to be referenced in the instant execution state.
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Codec.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Codec.kt
index 691691b..d22c0ad 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Codec.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Codec.kt
@@ -46,6 +46,8 @@
     fun beanPropertyWriterFor(beanType: Class<*>): BeanPropertyWriter
 
     suspend fun write(value: Any?)
+
+    fun writeClass(type: Class<*>)
 }
 
 
@@ -63,6 +65,8 @@
     fun getProject(path: String): ProjectInternal
 
     suspend fun read(): Any?
+
+    fun readClass(): Class<*>
 }
 
 
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Combinators.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Combinators.kt
index 79d1330..2e2d94d 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Combinators.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Combinators.kt
@@ -168,17 +168,6 @@
 
 
 internal
-fun WriteContext.writeClass(value: Class<*>) {
-    writeString(value.name)
-}
-
-
-internal
-fun ReadContext.readClass(): Class<*> =
-    Class.forName(readString(), false, classLoader)
-
-
-internal
 fun WriteContext.writeClassArray(values: Array<Class<*>>) {
     writeArray(values) { writeClass(it) }
 }
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Contexts.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Contexts.kt
index 262d4a2..cf17013 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Contexts.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/Contexts.kt
@@ -43,6 +43,9 @@
     private
     val beanPropertyWriters = hashMapOf<Class<*>, BeanPropertyWriter>()
 
+    private
+    val classes = hashMapOf<Class<*>, Int>()
+
     override fun beanPropertyWriterFor(beanType: Class<*>): BeanPropertyWriter =
         beanPropertyWriters.computeIfAbsent(beanType, ::BeanPropertyWriter)
 
@@ -55,6 +58,18 @@
         }
     }
 
+    override fun writeClass(type: Class<*>) {
+        val id = classes[type]
+        if (id != null) {
+            writeSmallInt(id)
+        } else {
+            val newId = classes.size
+            classes[type] = newId
+            writeSmallInt(newId)
+            writeString(type.name)
+        }
+    }
+
     // TODO: consider interning strings
     override fun writeString(string: CharSequence) =
         encoder.writeString(string)
@@ -94,6 +109,9 @@
     val beanPropertyReaders = hashMapOf<Class<*>, BeanPropertyReader>()
 
     private
+    val classes = hashMapOf<Int, Class<*>>()
+
+    private
     lateinit var projectProvider: ProjectProvider
 
     override lateinit var classLoader: ClassLoader
@@ -118,6 +136,17 @@
     override fun beanPropertyReaderFor(beanType: Class<*>): BeanPropertyReader =
         beanPropertyReaders.computeIfAbsent(beanType, beanPropertyReaderFactory)
 
+    override fun readClass(): Class<*> {
+        val id = readSmallInt()
+        val type = classes[id]
+        if (type != null) {
+            return type
+        }
+        val newType = Class.forName(readString(), false, classLoader)
+        classes[id] = newType
+        return newType
+    }
+
     override fun getProject(path: String): ProjectInternal =
         projectProvider(path)
 
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/BeanCodec.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/BeanCodec.kt
index 91669a7..9bae5aa 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/BeanCodec.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/BeanCodec.kt
@@ -22,9 +22,7 @@
 import org.gradle.instantexecution.serialization.PropertyTrace
 import org.gradle.instantexecution.serialization.ReadContext
 import org.gradle.instantexecution.serialization.WriteContext
-import org.gradle.instantexecution.serialization.readClass
 import org.gradle.instantexecution.serialization.withPropertyTrace
-import org.gradle.instantexecution.serialization.writeClass
 
 
 internal
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ClassCodec.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ClassCodec.kt
index faa9e18..b42db62 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ClassCodec.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ClassCodec.kt
@@ -19,8 +19,6 @@
 import org.gradle.instantexecution.serialization.Codec
 import org.gradle.instantexecution.serialization.ReadContext
 import org.gradle.instantexecution.serialization.WriteContext
-import org.gradle.instantexecution.serialization.readClass
-import org.gradle.instantexecution.serialization.writeClass
 
 
 internal
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/Codecs.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/Codecs.kt
index cc4ff7a..6863832 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/Codecs.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/Codecs.kt
@@ -94,6 +94,7 @@
         bind(ClassCodec)
         bind(MethodCodec)
 
+        // Only serialize certain List implementations
         bind(arrayListCodec)
         bind(linkedListCodec)
 
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ListenerBroadcastCodec.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ListenerBroadcastCodec.kt
index edee618..80be766 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ListenerBroadcastCodec.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/ListenerBroadcastCodec.kt
@@ -19,8 +19,6 @@
 import org.gradle.instantexecution.serialization.Codec
 import org.gradle.instantexecution.serialization.ReadContext
 import org.gradle.instantexecution.serialization.WriteContext
-import org.gradle.instantexecution.serialization.readClass
-import org.gradle.instantexecution.serialization.writeClass
 import org.gradle.internal.event.AnonymousListenerBroadcast
 import org.gradle.internal.event.ListenerManager
 
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/MethodCodec.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/MethodCodec.kt
index 955da6a..59200d5 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/MethodCodec.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/MethodCodec.kt
@@ -19,9 +19,7 @@
 import org.gradle.instantexecution.serialization.Codec
 import org.gradle.instantexecution.serialization.ReadContext
 import org.gradle.instantexecution.serialization.WriteContext
-import org.gradle.instantexecution.serialization.readClass
 import org.gradle.instantexecution.serialization.readClassArray
-import org.gradle.instantexecution.serialization.writeClass
 import org.gradle.instantexecution.serialization.writeClassArray
 import java.lang.reflect.Method
 
diff --git a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/TaskGraphCodec.kt b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/TaskGraphCodec.kt
index 732ef4a..7e150a8 100644
--- a/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/TaskGraphCodec.kt
+++ b/subprojects/instant-execution/src/main/kotlin/org/gradle/instantexecution/serialization/codecs/TaskGraphCodec.kt
@@ -45,13 +45,11 @@
 import org.gradle.instantexecution.serialization.beans.readEachProperty
 import org.gradle.instantexecution.serialization.beans.writeNextProperty
 import org.gradle.instantexecution.serialization.beans.writingProperties
-import org.gradle.instantexecution.serialization.readClass
 import org.gradle.instantexecution.serialization.readCollectionInto
 import org.gradle.instantexecution.serialization.readEnum
 import org.gradle.instantexecution.serialization.readStrings
 import org.gradle.instantexecution.serialization.withIsolate
 import org.gradle.instantexecution.serialization.withPropertyTrace
-import org.gradle.instantexecution.serialization.writeClass
 import org.gradle.instantexecution.serialization.writeCollection
 import org.gradle.instantexecution.serialization.writeEnum
 import org.gradle.instantexecution.serialization.writeStrings