JS IR: JsMapping serialization

This commit is contained in:
Anton Bannykh
2021-04-02 17:16:12 +03:00
committed by TeamCityServer
parent ba5582de99
commit c224dd4cb1
2 changed files with 202 additions and 46 deletions
@@ -36,18 +36,18 @@ interface Mapping {
}
}
open class DefaultMapping : Mapping {
interface DelegateFactory {
fun <K : IrDeclaration, V : IrDeclaration> newDeclarationToDeclarationMapping(): Mapping.Delegate<K, V>
override val defaultArgumentsDispatchFunction: Mapping.Delegate<IrFunction, IrFunction> = newMapping()
override val defaultArgumentsOriginalFunction: Mapping.Delegate<IrFunction, IrFunction> = newMapping()
override val suspendFunctionToCoroutineConstructor: Mapping.Delegate<IrFunction, IrConstructor> = newMapping()
override val lateInitFieldToNullableField: Mapping.Delegate<IrField, IrField> = newMapping()
override val inlineClassMemberToStatic: Mapping.Delegate<IrFunction, IrSimpleFunction> = newMapping()
override val capturedFields: Mapping.Delegate<IrClass, Collection<IrField>> = newMapping()
override val capturedConstructors: Mapping.Delegate<IrConstructor, IrConstructor> = newMapping()
override val reflectedNameAccessor: Mapping.Delegate<IrClass, IrSimpleFunction> = newMapping()
fun <K : IrDeclaration, V : Collection<IrDeclaration>> newDeclarationToDeclarationCollectionMapping(): Mapping.Delegate<K, V>
}
protected open fun <K : IrDeclaration, V> newMapping() = object : Mapping.Delegate<K, V>() {
private object DefaultDelegateFactory : DelegateFactory {
override fun <K : IrDeclaration, V : IrDeclaration> newDeclarationToDeclarationMapping(): Mapping.Delegate<K, V> = newMappingImpl()
override fun <K : IrDeclaration, V : Collection<IrDeclaration>> newDeclarationToDeclarationCollectionMapping(): Mapping.Delegate<K, V> = newMappingImpl()
private fun <K : IrDeclaration, V> newMappingImpl() = object : Mapping.Delegate<K, V>() {
private val map: MutableMap<K, V> = ConcurrentHashMap()
override operator fun get(key: K): V? {
@@ -70,6 +70,17 @@ open class DefaultMapping : Mapping {
}
}
open class DefaultMapping(delegateFactory: DelegateFactory = DefaultDelegateFactory) : Mapping {
override val defaultArgumentsDispatchFunction: Mapping.Delegate<IrFunction, IrFunction> = delegateFactory.newDeclarationToDeclarationMapping()
override val defaultArgumentsOriginalFunction: Mapping.Delegate<IrFunction, IrFunction> = delegateFactory.newDeclarationToDeclarationMapping()
override val suspendFunctionToCoroutineConstructor: Mapping.Delegate<IrFunction, IrConstructor> = delegateFactory.newDeclarationToDeclarationMapping()
override val lateInitFieldToNullableField: Mapping.Delegate<IrField, IrField> = delegateFactory.newDeclarationToDeclarationMapping()
override val inlineClassMemberToStatic: Mapping.Delegate<IrFunction, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
override val capturedFields: Mapping.Delegate<IrClass, Collection<IrField>> = delegateFactory.newDeclarationToDeclarationCollectionMapping()
override val capturedConstructors: Mapping.Delegate<IrConstructor, IrConstructor> = delegateFactory.newDeclarationToDeclarationMapping()
override val reflectedNameAccessor: Mapping.Delegate<IrClass, IrSimpleFunction> = delegateFactory.newDeclarationToDeclarationMapping()
}
fun <V : Any> KMutableProperty0<V?>.getOrPut(fn: () -> V) = this.get() ?: fn().also {
this.set(it)
}
@@ -6,52 +6,197 @@
package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.DefaultMapping
import org.jetbrains.kotlin.backend.common.DelegateFactory
import org.jetbrains.kotlin.backend.common.Mapping
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.library.impl.*
class JsMapping(private val irFactory: IrFactory) : DefaultMapping() {
val outerThisFieldSymbols = newMapping<IrClass, IrField>()
val innerClassConstructors = newMapping<IrConstructor, IrConstructor>()
val originalInnerClassPrimaryConstructorByClass = newMapping<IrClass, IrConstructor>()
val secondaryConstructorToDelegate = newMapping<IrConstructor, IrSimpleFunction>()
val secondaryConstructorToFactory = newMapping<IrConstructor, IrSimpleFunction>()
val objectToGetInstanceFunction = newMapping<IrClass, IrSimpleFunction>()
val objectToInstanceField = newMapping<IrClass, IrField>()
val classToSyntheticPrimaryConstructor = newMapping<IrClass, IrConstructor>()
val privateMemberToCorrespondingStatic = newMapping<IrFunction, IrSimpleFunction>()
fun JsMapping(irFactory: IrFactory) = JsMapping(JsMappingState(irFactory))
val constructorToInitFunction = newMapping<IrConstructor, IrSimpleFunction>()
class JsMapping(val state: JsMappingState) : DefaultMapping(state) {
val outerThisFieldSymbols = state.newDeclarationToDeclarationMapping<IrClass, IrField>()
val innerClassConstructors = state.newDeclarationToDeclarationMapping<IrConstructor, IrConstructor>()
val originalInnerClassPrimaryConstructorByClass = state.newDeclarationToDeclarationMapping<IrClass, IrConstructor>()
val secondaryConstructorToDelegate = state.newDeclarationToDeclarationMapping<IrConstructor, IrSimpleFunction>()
val secondaryConstructorToFactory = state.newDeclarationToDeclarationMapping<IrConstructor, IrSimpleFunction>()
val objectToGetInstanceFunction = state.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
val objectToInstanceField = state.newDeclarationToDeclarationMapping<IrClass, IrField>()
val classToSyntheticPrimaryConstructor = state.newDeclarationToDeclarationMapping<IrClass, IrConstructor>()
val privateMemberToCorrespondingStatic = state.newDeclarationToDeclarationMapping<IrFunction, IrSimpleFunction>()
val enumEntryToGetInstanceFun = newMapping<IrEnumEntry, IrSimpleFunction>()
val enumEntryToInstanceField = newMapping<IrEnumEntry, IrField>()
val enumConstructorToNewConstructor = newMapping<IrConstructor, IrConstructor>()
val enumClassToCorrespondingEnumEntry = newMapping<IrClass, IrEnumEntry>()
val enumConstructorOldToNewValueParameters = newMapping<IrValueDeclaration, IrValueParameter>()
val enumEntryToCorrespondingField = newMapping<IrEnumEntry, IrField>()
val enumClassToInitEntryInstancesFun = newMapping<IrClass, IrSimpleFunction>()
val constructorToInitFunction = state.newDeclarationToDeclarationMapping<IrConstructor, IrSimpleFunction>()
// Triggers `StageController.lazyLower` on access
override fun <K : IrDeclaration, V> newMapping(): Mapping.Delegate<K, V> = object : Mapping.Delegate<K, V>() {
private val map: MutableMap<K, V> = mutableMapOf()
val enumEntryToGetInstanceFun = state.newDeclarationToDeclarationMapping<IrEnumEntry, IrSimpleFunction>()
val enumEntryToInstanceField = state.newDeclarationToDeclarationMapping<IrEnumEntry, IrField>()
val enumConstructorToNewConstructor = state.newDeclarationToDeclarationMapping<IrConstructor, IrConstructor>()
val enumClassToCorrespondingEnumEntry = state.newDeclarationToDeclarationMapping<IrClass, IrEnumEntry>()
val enumConstructorOldToNewValueParameters = state.newDeclarationToDeclarationMapping<IrValueDeclaration, IrValueParameter>()
val enumEntryToCorrespondingField = state.newDeclarationToDeclarationMapping<IrEnumEntry, IrField>()
val enumClassToInitEntryInstancesFun = state.newDeclarationToDeclarationMapping<IrClass, IrSimpleFunction>()
}
override operator fun get(key: K): V? {
irFactory.stageController.lazyLower(key)
return map[key]
class JsMappingState(val irFactory: IrFactory) : DelegateFactory {
override fun <K : IrDeclaration, V : IrDeclaration> newDeclarationToDeclarationMapping(): Mapping.Delegate<K, V> {
return JsMappingDelegate<K, V>(irFactory).also {
allMappings += it
}
}
override fun <K : IrDeclaration, V : Collection<IrDeclaration>> newDeclarationToDeclarationCollectionMapping(): Mapping.Delegate<K, V> {
return JsMappingCollectionDelegate<K, V>(irFactory).also {
allMappings += it
}
}
private val allMappings = mutableListOf<SerializableMapping>()
fun serializeMappings(declarations: Iterable<IrDeclaration>, symbolSerializer: (IrSymbol) -> Long): SerializedMappings {
return SerializedMappings(allMappings.map { mapping ->
val keys = mutableListOf<Long>()
val values = mutableListOf<ByteArray>()
declarations.forEach { d ->
mapping.serializeMapping(d, symbolSerializer)?.let { bytes ->
keys += symbolSerializer((d as IrSymbolOwner).symbol)
values += bytes
}
}
SerializedMapping(
IrMemoryLongArrayWriter(keys).writeIntoMemory(),
IrMemoryArrayWriter(values).writeIntoMemory(),
)
})
}
fun mappingsDeserializer(mapping: SerializedMappings, signatureDeserializer: (Long) -> IdSignature, symbolDeserializer: (Long) -> IrSymbol): (IdSignature, IrDeclaration) -> Unit {
if (allMappings.size != mapping.mappings.size) error("Mapping size mismatch")
val index = Array<Map<IdSignature, ByteArray>>(allMappings.size) { i ->
val bytes = mapping.mappings[i]
val s = IrLongArrayMemoryReader(bytes.keys).array.map(signatureDeserializer)
val v = IrArrayMemoryReader(bytes.values).toArray()
if (s.size != v.size) error("Keys size != values size")
s.withIndex().associate { it.value to v[it.index] }
}
override operator fun set(key: K, value: V?) {
irFactory.stageController.lazyLower(key)
if (value == null) {
map.remove(key)
} else {
map[key] = value
return { signature, declaration ->
for (i in allMappings.indices) {
index[i][signature]?.let { bytes ->
allMappings[i].loadMapping(declaration, bytes, symbolDeserializer)
}
}
}
override val keys: Set<K>
get() = map.keys
override val values: Collection<V>
get() = map.values
}
}
class SerializedMappings(
val mappings: List<SerializedMapping>
)
class SerializedMapping(
val keys: ByteArray,
val values: ByteArray,
)
private interface SerializableMapping {
fun serializeMapping(declaration: IrDeclaration, symbolSerializer: (IrSymbol) -> Long): ByteArray?
fun loadMapping(declaration: IrDeclaration, mapping: ByteArray, symbolDeserializer: (Long) -> IrSymbol)
}
private class JsMappingDelegate<K : IrDeclaration, V : IrDeclaration>(val irFactory: IrFactory) : Mapping.Delegate<K, V>(), SerializableMapping {
private val map: MutableMap<IrSymbol, IrSymbol> = mutableMapOf()
@Suppress("UNCHECKED_CAST")
override operator fun get(key: K): V? {
irFactory.stageController.lazyLower(key)
return map[(key as IrSymbolOwner).symbol]?.owner as? V
}
override operator fun set(key: K, value: V?) {
irFactory.stageController.lazyLower(key)
if (value == null) {
map.remove((key as IrSymbolOwner).symbol)
} else {
map[(key as IrSymbolOwner).symbol] = (value as IrSymbolOwner).symbol
}
}
override fun serializeMapping(declaration: IrDeclaration, symbolSerializer: (IrSymbol) -> Long): ByteArray? {
return map[(declaration as IrSymbolOwner).symbol]?.let { symbol ->
symbolSerializer(symbol).toByteArray()
}
}
override fun loadMapping(declaration: IrDeclaration, mapping: ByteArray, symbolDeserializer: (Long) -> IrSymbol) {
map[(declaration as IrSymbolOwner).symbol] = symbolDeserializer(mapping.toLong())
}
override val keys: Set<K>
get() = TODO("Not yet implemented")
override val values: Collection<V>
get() = TODO("Not yet implemented")
}
private class JsMappingCollectionDelegate<K : IrDeclaration, V : Collection<IrDeclaration>>(val irFactory: IrFactory) : Mapping.Delegate<K, V>(), SerializableMapping {
private val map: MutableMap<IrSymbol, Collection<IrSymbol>> = mutableMapOf()
@Suppress("UNCHECKED_CAST")
override operator fun get(key: K): V? {
irFactory.stageController.lazyLower(key)
return map[(key as IrSymbolOwner).symbol]?.map { it.owner as IrDeclaration } as? V
}
override operator fun set(key: K, value: V?) {
irFactory.stageController.lazyLower(key)
if (value == null) {
map.remove((key as IrSymbolOwner).symbol)
} else {
map[(key as IrSymbolOwner).symbol] = value.map { (it as IrSymbolOwner).symbol }
}
}
override fun serializeMapping(declaration: IrDeclaration, symbolSerializer: (IrSymbol) -> Long): ByteArray? {
return map[(declaration as IrSymbolOwner).symbol]?.let { symbols ->
IrMemoryLongArrayWriter(symbols.map(symbolSerializer)).writeIntoMemory()
}
}
override fun loadMapping(declaration: IrDeclaration, mapping: ByteArray, symbolDeserializer: (Long) -> IrSymbol) {
map[(declaration as IrSymbolOwner).symbol] = IrLongArrayMemoryReader(mapping).array.map(symbolDeserializer)
}
override val keys: Set<K>
get() = TODO("Not yet implemented")
override val values: Collection<V>
get() = TODO("Not yet implemented")
}
fun ByteArray.toLong(): Long {
var result = this[0].toLong() and 0xFFL
for (i in 1..7) {
result = (result shl 8) or (this[i].toLong() and 0xFFL)
}
return result
}
fun Long.toByteArray(): ByteArray {
val result = ByteArray(8)
var self = this
for (i in 7 downTo 0) {
result[i] = self.toByte()
self = self ushr 8
}
return result
}