JS IR: serialize declarations without mutable state

This commit is contained in:
Anton Bannykh
2021-04-02 17:56:06 +03:00
committed by TeamCityServer
parent 1e822aa28a
commit 8fe8419ad4
4 changed files with 217 additions and 145 deletions
@@ -567,6 +567,8 @@ class IrBodyDeserializer(
IrTypeOperator.SAM_CONVERSION IrTypeOperator.SAM_CONVERSION
ProtoTypeOperator.IMPLICIT_DYNAMIC_CAST -> ProtoTypeOperator.IMPLICIT_DYNAMIC_CAST ->
IrTypeOperator.IMPLICIT_DYNAMIC_CAST IrTypeOperator.IMPLICIT_DYNAMIC_CAST
ProtoTypeOperator.REINTERPRET_CAST ->
IrTypeOperator.REINTERPRET_CAST
} }
private fun deserializeTypeOp(proto: ProtoTypeOp, start: Int, end: Int, type: IrType): IrTypeOperatorCall { private fun deserializeTypeOp(proto: ProtoTypeOp, start: Int, end: Int, type: IrType): IrTypeOperatorCall {
@@ -62,12 +62,13 @@ class IrDeclarationDeserializer(
private val allowErrorNodes: Boolean, private val allowErrorNodes: Boolean,
private val deserializeInlineFunctions: Boolean, private val deserializeInlineFunctions: Boolean,
private var deserializeBodies: Boolean, private var deserializeBodies: Boolean,
private val symbolDeserializer: IrSymbolDeserializer, val symbolDeserializer: IrSymbolDeserializer,
private val platformFakeOverrideClassFilter: FakeOverrideClassFilter, private val platformFakeOverrideClassFilter: FakeOverrideClassFilter,
private val fakeOverrideBuilder: FakeOverrideBuilder, private val fakeOverrideBuilder: FakeOverrideBuilder,
private val skipMutableState: Boolean = false,
) { ) {
private val bodyDeserializer = IrBodyDeserializer(builtIns, allowErrorNodes, irFactory, fileReader, this) val bodyDeserializer = IrBodyDeserializer(builtIns, allowErrorNodes, irFactory, fileReader, this)
private fun deserializeName(index: Int): Name { private fun deserializeName(index: Int): Name {
val name = fileReader.deserializeString(index) val name = fileReader.deserializeString(index)
@@ -83,7 +84,7 @@ class IrDeclarationDeserializer(
return ProtoType.parseFrom(readType(index), ExtensionRegistryLite.newInstance()) return ProtoType.parseFrom(readType(index), ExtensionRegistryLite.newInstance())
} }
internal fun deserializeIrType(index: Int): IrType { fun deserializeIrType(index: Int): IrType {
return irTypeCache.getOrPut(index) { return irTypeCache.getOrPut(index) {
val typeData = loadTypeProto(index) val typeData = loadTypeProto(index)
deserializeIrTypeData(typeData) deserializeIrTypeData(typeData)
@@ -216,7 +217,9 @@ class IrDeclarationDeserializer(
deserializeIrDeclarationOrigin(proto.originName), proto.flags deserializeIrDeclarationOrigin(proto.originName), proto.flags
) )
result.annotations += deserializeAnnotations(proto.annotationList) result.annotations += deserializeAnnotations(proto.annotationList)
result.parent = currentParent if (!skipMutableState) {
result.parent = currentParent
}
return result return result
} finally { } finally {
eraseDelegatedSymbol(s) eraseDelegatedSymbol(s)
@@ -305,19 +308,19 @@ class IrDeclarationDeserializer(
flags.isFun, flags.isFun,
) )
}.usingParent { }.usingParent {
typeParameters = deserializeTypeParameters(proto.typeParameterList, true) if (!skipMutableState) {
typeParameters = deserializeTypeParameters(proto.typeParameterList, true)
superTypes = proto.superTypeList.map { deserializeIrType(it) } superTypes = proto.superTypeList.map { deserializeIrType(it) }
withExternalValue(isExternal) { withExternalValue(isExternal) {proto.declarationList
proto.declarationList
.filterNot { isSkippableFakeOverride(it, this) } .filterNot { isSkippableFakeOverride(it, this) }
.mapTo(declarations) { deserializeDeclaration(it) } .mapTo(declarations) { deserializeDeclaration(it) }}
thisReceiver = deserializeIrValueParameter(proto.thisReceiver, -1)
fakeOverrideBuilder.enqueueClass(this, signature)
} }
thisReceiver = deserializeIrValueParameter(proto.thisReceiver, -1)
fakeOverrideBuilder.enqueueClass(this, signature)
} }
} }
@@ -337,7 +340,9 @@ class IrDeclarationDeserializer(
origin origin
) )
}.usingParent { }.usingParent {
typeParameters = deserializeTypeParameters(proto.typeParameterList, true) if (!skipMutableState) {
typeParameters = deserializeTypeParameters(proto.typeParameterList, true)
}
} }
} }
@@ -437,7 +442,7 @@ class IrDeclarationDeserializer(
return ProtoExpression.parseFrom(readBody(index), ExtensionRegistryLite.newInstance()) return ProtoExpression.parseFrom(readBody(index), ExtensionRegistryLite.newInstance())
} }
private fun deserializeExpressionBody(index: Int): IrExpressionBody { fun deserializeExpressionBody(index: Int): IrExpressionBody {
return irFactory.createExpressionBody( return irFactory.createExpressionBody(
if (deserializeBodies) { if (deserializeBodies) {
val bodyData = loadExpressionBodyProto(index) val bodyData = loadExpressionBodyProto(index)
@@ -449,7 +454,7 @@ class IrDeclarationDeserializer(
) )
} }
private fun deserializeStatementBody(index: Int): IrElement { fun deserializeStatementBody(index: Int): IrElement {
return if (deserializeBodies) { return if (deserializeBodies) {
val bodyData = loadStatementBodyProto(index) val bodyData = loadStatementBodyProto(index)
bodyDeserializer.deserializeStatement(bodyData) bodyDeserializer.deserializeStatement(bodyData)
@@ -467,18 +472,20 @@ class IrDeclarationDeserializer(
): T = withDeserializedIrDeclarationBase(proto.base) { symbol, idSig, startOffset, endOffset, origin, fcode -> ): T = withDeserializedIrDeclarationBase(proto.base) { symbol, idSig, startOffset, endOffset, origin, fcode ->
symbolTable.withScope(symbol) { symbolTable.withScope(symbol) {
block(symbol as IrFunctionSymbol, idSig, startOffset, endOffset, origin, fcode).usingParent { block(symbol as IrFunctionSymbol, idSig, startOffset, endOffset, origin, fcode).usingParent {
typeParameters = deserializeTypeParameters(proto.typeParameterList, false) if (!skipMutableState) {
val nameType = BinaryNameAndType.decode(proto.nameType) typeParameters = deserializeTypeParameters(proto.typeParameterList, false)
returnType = deserializeIrType(nameType.typeIndex) val nameType = BinaryNameAndType.decode(proto.nameType)
returnType = deserializeIrType(nameType.typeIndex)
withBodyGuard { withBodyGuard {
valueParameters = deserializeValueParameters(proto.valueParameterList) valueParameters = deserializeValueParameters(proto.valueParameterList)
if (proto.hasDispatchReceiver()) if (proto.hasDispatchReceiver())
dispatchReceiverParameter = deserializeIrValueParameter(proto.dispatchReceiver, -1) dispatchReceiverParameter = deserializeIrValueParameter(proto.dispatchReceiver, -1)
if (proto.hasExtensionReceiver()) if (proto.hasExtensionReceiver())
extensionReceiverParameter = deserializeIrValueParameter(proto.extensionReceiver, -1) extensionReceiverParameter = deserializeIrValueParameter(proto.extensionReceiver, -1)
if (proto.hasBody()) { if (proto.hasBody()) {
body = deserializeStatementBody(proto.body) as IrBody body = deserializeStatementBody(proto.body) as IrBody
}
} }
} }
} }
@@ -512,7 +519,7 @@ class IrDeclarationDeserializer(
} }
} }
internal fun deserializeIrVariable(proto: ProtoVariable): IrVariable = fun deserializeIrVariable(proto: ProtoVariable): IrVariable =
withDeserializedIrDeclarationBase(proto.base) { symbol, _, startOffset, endOffset, origin, fcode -> withDeserializedIrDeclarationBase(proto.base) { symbol, _, startOffset, endOffset, origin, fcode ->
val flags = LocalVariableFlags.decode(fcode) val flags = LocalVariableFlags.decode(fcode)
val nameType = BinaryNameAndType.decode(proto.nameType) val nameType = BinaryNameAndType.decode(proto.nameType)
@@ -535,10 +542,12 @@ class IrDeclarationDeserializer(
symbolTable.declareEnumEntry(uniqId, { symbol as IrEnumEntrySymbol }) { symbolTable.declareEnumEntry(uniqId, { symbol as IrEnumEntrySymbol }) {
irFactory.createEnumEntry(startOffset, endOffset, origin, it, deserializeName(proto.name)) irFactory.createEnumEntry(startOffset, endOffset, origin, it, deserializeName(proto.name))
}.apply { }.apply {
if (proto.hasCorrespondingClass()) if (!skipMutableState) {
correspondingClass = deserializeIrClass(proto.correspondingClass) if (proto.hasCorrespondingClass())
if (proto.hasInitializer()) correspondingClass = deserializeIrClass(proto.correspondingClass)
initializerExpression = deserializeExpressionBody(proto.initializer) if (proto.hasInitializer())
initializerExpression = deserializeExpressionBody(proto.initializer)
}
} }
} }
@@ -607,10 +616,12 @@ class IrDeclarationDeserializer(
deserializeIrType(nameAndType.typeIndex), deserializeIrType(nameAndType.typeIndex),
flags.isVar flags.isVar
).apply { ).apply {
delegate = deserializeIrVariable(proto.delegate) if (!skipMutableState) {
getter = deserializeIrFunction(proto.getter) delegate = deserializeIrVariable(proto.delegate)
if (proto.hasSetter()) getter = deserializeIrFunction(proto.getter)
setter = deserializeIrFunction(proto.setter) if (proto.hasSetter())
setter = deserializeIrFunction(proto.setter)
}
} }
} }
@@ -634,20 +645,22 @@ class IrDeclarationDeserializer(
flags.isFakeOverride flags.isFakeOverride
) )
}.apply { }.apply {
withExternalValue(isExternal) { if (!skipMutableState) {
if (proto.hasGetter()) { withExternalValue(isExternal) {
getter = deserializeIrFunction(proto.getter).also { if (proto.hasGetter()) {
it.correspondingPropertySymbol = symbol getter = deserializeIrFunction(proto.getter).also {
it.correspondingPropertySymbol = symbol
}
} }
} if (proto.hasSetter()) {
if (proto.hasSetter()) { setter = deserializeIrFunction(proto.setter).also {
setter = deserializeIrFunction(proto.setter).also { it.correspondingPropertySymbol = symbol
it.correspondingPropertySymbol = symbol }
} }
} if (proto.hasBackingField()) {
if (proto.hasBackingField()) { backingField = deserializeIrField(proto.backingField).also {
backingField = deserializeIrField(proto.backingField).also { it.correspondingPropertySymbol = symbol
it.correspondingPropertySymbol = symbol }
} }
} }
} }
@@ -661,7 +674,7 @@ class IrDeclarationDeserializer(
allKnownDeclarationOrigins.map { it.objectInstance as IrDeclarationOriginImpl }.associateBy { it.name } allKnownDeclarationOrigins.map { it.objectInstance as IrDeclarationOriginImpl }.associateBy { it.name }
} }
private fun deserializeIrDeclarationOrigin(protoName: Int): IrDeclarationOriginImpl { fun deserializeIrDeclarationOrigin(protoName: Int): IrDeclarationOriginImpl {
val originName = fileReader.deserializeString(protoName) val originName = fileReader.deserializeString(protoName)
return declarationOriginIndex[originName] ?: object : IrDeclarationOriginImpl(originName) {} return declarationOriginIndex[originName] ?: object : IrDeclarationOriginImpl(originName) {}
} }
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.library.impl.IrMemoryDeclarationWriter
import org.jetbrains.kotlin.library.impl.IrMemoryStringWriter import org.jetbrains.kotlin.library.impl.IrMemoryStringWriter
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.backend.common.serialization.proto.AccessorIdSignature as ProtoAccessorIdSignature
import org.jetbrains.kotlin.backend.common.serialization.proto.Actual as ProtoActual import org.jetbrains.kotlin.backend.common.serialization.proto.Actual as ProtoActual
import org.jetbrains.kotlin.backend.common.serialization.proto.FieldAccessCommon as ProtoFieldAccessCommon import org.jetbrains.kotlin.backend.common.serialization.proto.FieldAccessCommon as ProtoFieldAccessCommon
import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry import org.jetbrains.kotlin.backend.common.serialization.proto.FileEntry as ProtoFileEntry
@@ -53,9 +52,9 @@ import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicOperator
import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicType as ProtoDynamicType import org.jetbrains.kotlin.backend.common.serialization.proto.IrDynamicType as ProtoDynamicType
import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumConstructorCall as ProtoEnumConstructorCall import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumConstructorCall as ProtoEnumConstructorCall
import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumEntry as ProtoEnumEntry import org.jetbrains.kotlin.backend.common.serialization.proto.IrEnumEntry as ProtoEnumEntry
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorCallExpression as ProtoErrorCallExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorDeclaration as ProtoErrorDeclaration import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorDeclaration as ProtoErrorDeclaration
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorExpression as ProtoErrorExpression import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorExpression as ProtoErrorExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorCallExpression as ProtoErrorCallExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorType as ProtoErrorType import org.jetbrains.kotlin.backend.common.serialization.proto.IrErrorType as ProtoErrorType
import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression import org.jetbrains.kotlin.backend.common.serialization.proto.IrExpression as ProtoExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.IrField as ProtoField import org.jetbrains.kotlin.backend.common.serialization.proto.IrField as ProtoField
@@ -102,13 +101,15 @@ import org.jetbrains.kotlin.backend.common.serialization.proto.Loop as ProtoLoop
import org.jetbrains.kotlin.backend.common.serialization.proto.MemberAccessCommon as ProtoMemberAccessCommon import org.jetbrains.kotlin.backend.common.serialization.proto.MemberAccessCommon as ProtoMemberAccessCommon
import org.jetbrains.kotlin.backend.common.serialization.proto.NullableIrExpression as ProtoNullableIrExpression import org.jetbrains.kotlin.backend.common.serialization.proto.NullableIrExpression as ProtoNullableIrExpression
import org.jetbrains.kotlin.backend.common.serialization.proto.PublicIdSignature as ProtoPublicIdSignature import org.jetbrains.kotlin.backend.common.serialization.proto.PublicIdSignature as ProtoPublicIdSignature
import org.jetbrains.kotlin.backend.common.serialization.proto.AccessorIdSignature as ProtoAccessorIdSignature
open class IrFileSerializer( open class IrFileSerializer(
val messageLogger: IrMessageLogger, val messageLogger: IrMessageLogger,
private val declarationTable: DeclarationTable, private val declarationTable: DeclarationTable,
private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, private val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
private val bodiesOnlyForInlines: Boolean = false, private val bodiesOnlyForInlines: Boolean = false,
private val skipExpects: Boolean = false private val skipExpects: Boolean = false,
private val skipMutableState: Boolean = false, // required for JS IC caches
) { ) {
private val loopIndex = mutableMapOf<IrLoop, Int>() private val loopIndex = mutableMapOf<IrLoop, Int>()
private var currentLoopIndex = 0 private var currentLoopIndex = 0
@@ -154,19 +155,19 @@ open class IrFileSerializer(
} }
} }
private fun serializeIrExpressionBody(expression: IrExpression): Int { fun serializeIrExpressionBody(expression: IrExpression): Int {
protoBodyArray.add(XStatementOrExpression.XExpression(serializeExpression(expression))) protoBodyArray.add(XStatementOrExpression.XExpression(serializeExpression(expression)))
return protoBodyArray.size - 1 return protoBodyArray.size - 1
} }
private fun serializeIrStatementBody(statement: IrElement): Int { fun serializeIrStatementBody(statement: IrElement): Int {
protoBodyArray.add(XStatementOrExpression.XStatement(serializeStatement(statement))) protoBodyArray.add(XStatementOrExpression.XStatement(serializeStatement(statement)))
return protoBodyArray.size - 1 return protoBodyArray.size - 1
} }
/* ------- Common fields ---------------------------------------------------- */ /* ------- Common fields ---------------------------------------------------- */
private fun serializeIrDeclarationOrigin(origin: IrDeclarationOrigin): Int = serializeString((origin as IrDeclarationOriginImpl).name) fun serializeIrDeclarationOrigin(origin: IrDeclarationOrigin): Int = serializeString((origin as IrDeclarationOriginImpl).name)
private fun serializeIrStatementOrigin(origin: IrStatementOrigin): Int = serializeString((origin as IrStatementOriginImpl).debugName) private fun serializeIrStatementOrigin(origin: IrStatementOrigin): Int = serializeString((origin as IrStatementOriginImpl).debugName)
@@ -238,7 +239,7 @@ open class IrFileSerializer(
return protoIdSignature(idSig) return protoIdSignature(idSig)
} }
private fun protoIdSignature(idSig: IdSignature): Int { fun protoIdSignature(idSig: IdSignature): Int {
return protoIdSignatureMap.getOrPut(idSig) { return protoIdSignatureMap.getOrPut(idSig) {
protoIdSignatureArray.add(serializeIdSignature(idSig)) protoIdSignatureArray.add(serializeIdSignature(idSig))
protoIdSignatureArray.size - 1 protoIdSignatureArray.size - 1
@@ -247,41 +248,43 @@ open class IrFileSerializer(
/* ------- IrSymbols -------------------------------------------------------- */ /* ------- IrSymbols -------------------------------------------------------- */
private fun protoSymbolKind(symbol: IrSymbol): BinarySymbolData.SymbolKind = when (symbol) { companion object {
is IrAnonymousInitializerSymbol -> fun protoSymbolKind(symbol: IrSymbol): BinarySymbolData.SymbolKind = when (symbol) {
BinarySymbolData.SymbolKind.ANONYMOUS_INIT_SYMBOL is IrAnonymousInitializerSymbol ->
is IrClassSymbol -> BinarySymbolData.SymbolKind.ANONYMOUS_INIT_SYMBOL
BinarySymbolData.SymbolKind.CLASS_SYMBOL is IrClassSymbol ->
is IrConstructorSymbol -> BinarySymbolData.SymbolKind.CLASS_SYMBOL
BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL is IrConstructorSymbol ->
is IrTypeParameterSymbol -> BinarySymbolData.SymbolKind.CONSTRUCTOR_SYMBOL
BinarySymbolData.SymbolKind.TYPE_PARAMETER_SYMBOL is IrTypeParameterSymbol ->
is IrEnumEntrySymbol -> BinarySymbolData.SymbolKind.TYPE_PARAMETER_SYMBOL
BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL is IrEnumEntrySymbol ->
is IrVariableSymbol -> BinarySymbolData.SymbolKind.ENUM_ENTRY_SYMBOL
BinarySymbolData.SymbolKind.VARIABLE_SYMBOL is IrVariableSymbol ->
is IrValueParameterSymbol -> BinarySymbolData.SymbolKind.VARIABLE_SYMBOL
if (symbol.descriptor is ReceiverParameterDescriptor) // TODO: we use descriptor here. is IrValueParameterSymbol ->
BinarySymbolData.SymbolKind.RECEIVER_PARAMETER_SYMBOL if (symbol.descriptor is ReceiverParameterDescriptor) // TODO: we use descriptor here.
else BinarySymbolData.SymbolKind.RECEIVER_PARAMETER_SYMBOL
BinarySymbolData.SymbolKind.VALUE_PARAMETER_SYMBOL else
is IrSimpleFunctionSymbol -> BinarySymbolData.SymbolKind.VALUE_PARAMETER_SYMBOL
BinarySymbolData.SymbolKind.FUNCTION_SYMBOL is IrSimpleFunctionSymbol ->
is IrReturnableBlockSymbol -> BinarySymbolData.SymbolKind.FUNCTION_SYMBOL
BinarySymbolData.SymbolKind.RETURNABLE_BLOCK_SYMBOL is IrReturnableBlockSymbol ->
is IrFieldSymbol -> BinarySymbolData.SymbolKind.RETURNABLE_BLOCK_SYMBOL
if (symbol.owner.correspondingPropertySymbol?.owner.let { it == null || it.isDelegated }) is IrFieldSymbol ->
BinarySymbolData.SymbolKind.STANDALONE_FIELD_SYMBOL if (symbol.owner.correspondingPropertySymbol?.owner.let { it == null || it.isDelegated })
else BinarySymbolData.SymbolKind.STANDALONE_FIELD_SYMBOL
BinarySymbolData.SymbolKind.FIELD_SYMBOL else
is IrPropertySymbol -> BinarySymbolData.SymbolKind.FIELD_SYMBOL
BinarySymbolData.SymbolKind.PROPERTY_SYMBOL is IrPropertySymbol ->
is IrLocalDelegatedPropertySymbol -> BinarySymbolData.SymbolKind.PROPERTY_SYMBOL
BinarySymbolData.SymbolKind.LOCAL_DELEGATED_PROPERTY_SYMBOL is IrLocalDelegatedPropertySymbol ->
is IrTypeAliasSymbol -> BinarySymbolData.SymbolKind.LOCAL_DELEGATED_PROPERTY_SYMBOL
BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL is IrTypeAliasSymbol ->
else -> BinarySymbolData.SymbolKind.TYPEALIAS_SYMBOL
TODO("Unexpected symbol kind: $symbol") else ->
TODO("Unexpected symbol kind: $symbol")
}
} }
fun serializeIrSymbol(symbol: IrSymbol): Long { fun serializeIrSymbol(symbol: IrSymbol): Long {
@@ -412,7 +415,7 @@ open class IrFileSerializer(
type = (this as? IrTypeProjection)?.type?.toIrTypeKey type = (this as? IrTypeProjection)?.type?.toIrTypeKey
) )
private fun serializeIrType(type: IrType) = protoTypeMap.getOrPut(type.toIrTypeKey) { fun serializeIrType(type: IrType) = protoTypeMap.getOrPut(type.toIrTypeKey) {
protoTypeArray.add(serializeIrTypeData(type)) protoTypeArray.add(serializeIrTypeData(type))
protoTypeArray.size - 1 protoTypeArray.size - 1
} }
@@ -518,7 +521,7 @@ open class IrFileSerializer(
return proto.build() return proto.build()
} }
private fun serializeConstructorCall(call: IrConstructorCall): ProtoConstructorCall = fun serializeConstructorCall(call: IrConstructorCall): ProtoConstructorCall =
ProtoConstructorCall.newBuilder().apply { ProtoConstructorCall.newBuilder().apply {
symbol = serializeIrSymbol(call.symbol) symbol = serializeIrSymbol(call.symbol)
constructorTypeArgumentsCount = call.constructorTypeArgumentsCount constructorTypeArgumentsCount = call.constructorTypeArgumentsCount
@@ -741,7 +744,7 @@ open class IrFileSerializer(
IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> IrTypeOperator.IMPLICIT_DYNAMIC_CAST ->
ProtoTypeOperator.IMPLICIT_DYNAMIC_CAST ProtoTypeOperator.IMPLICIT_DYNAMIC_CAST
IrTypeOperator.REINTERPRET_CAST -> IrTypeOperator.REINTERPRET_CAST ->
error("Unreachable execution") ProtoTypeOperator.REINTERPRET_CAST
} }
private fun serializeTypeOp(expression: IrTypeOperatorCall): ProtoTypeOp { private fun serializeTypeOp(expression: IrTypeOperatorCall): ProtoTypeOp {
@@ -1024,8 +1027,10 @@ open class IrFileSerializer(
.setBase(serializeIrDeclarationBase(parameter, ValueParameterFlags.encode(parameter))) .setBase(serializeIrDeclarationBase(parameter, ValueParameterFlags.encode(parameter)))
.setNameType(serializeNameAndType(parameter.name, parameter.type)) .setNameType(serializeNameAndType(parameter.name, parameter.type))
parameter.varargElementType?.let { proto.setVarargElementType(serializeIrType(it)) } if (!skipMutableState) {
parameter.defaultValue?.let { proto.setDefaultValue(serializeIrExpressionBody(it.expression)) } parameter.varargElementType?.let { proto.setVarargElementType(serializeIrType(it)) }
parameter.defaultValue?.let { proto.setDefaultValue(serializeIrExpressionBody(it.expression)) }
}
return proto.build() return proto.build()
} }
@@ -1045,18 +1050,21 @@ open class IrFileSerializer(
.setBase(serializeIrDeclarationBase(function, flags)) .setBase(serializeIrDeclarationBase(function, flags))
.setNameType(serializeNameAndType(function.name, function.returnType)) .setNameType(serializeNameAndType(function.name, function.returnType))
function.typeParameters.forEach { if (!skipMutableState) {
proto.addTypeParameter(serializeIrTypeParameter(it)) function.typeParameters.forEach {
proto.addTypeParameter(serializeIrTypeParameter(it))
}
function.dispatchReceiverParameter?.let { proto.setDispatchReceiver(serializeIrValueParameter(it)) }
function.extensionReceiverParameter?.let { proto.setExtensionReceiver(serializeIrValueParameter(it)) }
function.valueParameters.forEach {
proto.addValueParameter(serializeIrValueParameter(it))
}
if (!bodiesOnlyForInlines || function.isInline) {
function.body?.let { proto.body = serializeIrStatementBody(it) }
}
} }
function.dispatchReceiverParameter?.let { proto.setDispatchReceiver(serializeIrValueParameter(it)) }
function.extensionReceiverParameter?.let { proto.setExtensionReceiver(serializeIrValueParameter(it)) }
function.valueParameters.forEach {
proto.addValueParameter(serializeIrValueParameter(it))
}
if (!bodiesOnlyForInlines || function.isInline) {
function.body?.let { proto.body = serializeIrStatementBody(it) }
}
return proto.build() return proto.build()
} }
@@ -1076,20 +1084,27 @@ open class IrFileSerializer(
return proto.build() return proto.build()
} }
private fun serializeIrAnonymousInit(declaration: IrAnonymousInitializer) = private fun serializeIrAnonymousInit(declaration: IrAnonymousInitializer): ProtoAnonymousInit {
ProtoAnonymousInit.newBuilder() val proto = ProtoAnonymousInit.newBuilder()
.setBase(serializeIrDeclarationBase(declaration, null)) .setBase(serializeIrDeclarationBase(declaration, null))
.setBody(serializeIrStatementBody(declaration.body))
.build() if (!skipMutableState) {
proto.setBody(serializeIrStatementBody(declaration.body))
}
return proto.build()
}
private fun serializeIrLocalDelegatedProperty(variable: IrLocalDelegatedProperty): ProtoLocalDelegatedProperty { private fun serializeIrLocalDelegatedProperty(variable: IrLocalDelegatedProperty): ProtoLocalDelegatedProperty {
val proto = ProtoLocalDelegatedProperty.newBuilder() val proto = ProtoLocalDelegatedProperty.newBuilder()
.setBase(serializeIrDeclarationBase(variable, LocalVariableFlags.encode(variable))) .setBase(serializeIrDeclarationBase(variable, LocalVariableFlags.encode(variable)))
.setNameType(serializeNameAndType(variable.name, variable.type)) .setNameType(serializeNameAndType(variable.name, variable.type))
.setDelegate(serializeIrVariable(variable.delegate))
.setGetter(serializeIrFunction(variable.getter))
variable.setter?.let { proto.setSetter(serializeIrFunction(it)) } if (!skipMutableState) {
proto.delegate = serializeIrVariable(variable.delegate)
proto.getter = serializeIrFunction(variable.getter)
variable.setter?.let { proto.setSetter(serializeIrFunction(it)) }
}
return proto.build() return proto.build()
} }
@@ -1099,15 +1114,11 @@ open class IrFileSerializer(
.setBase(serializeIrDeclarationBase(property, PropertyFlags.encode(property))) .setBase(serializeIrDeclarationBase(property, PropertyFlags.encode(property)))
.setName(serializeName(property.name)) .setName(serializeName(property.name))
val backingField = property.backingField if (!skipMutableState) {
val getter = property.getter property.backingField?.let { proto.backingField = serializeIrField(it) }
val setter = property.setter property.getter?.let { proto.getter = serializeIrFunction(it) }
if (backingField != null) property.setter?.let { proto.setter = serializeIrFunction(it) }
proto.backingField = serializeIrField(backingField) }
if (getter != null)
proto.getter = serializeIrFunction(getter)
if (setter != null)
proto.setter = serializeIrFunction(setter)
return proto.build() return proto.build()
} }
@@ -1116,14 +1127,16 @@ open class IrFileSerializer(
val proto = ProtoField.newBuilder() val proto = ProtoField.newBuilder()
.setBase(serializeIrDeclarationBase(field, FieldFlags.encode(field))) .setBase(serializeIrDeclarationBase(field, FieldFlags.encode(field)))
.setNameType(serializeNameAndType(field.name, field.type)) .setNameType(serializeNameAndType(field.name, field.type))
val initializer = field.initializer?.expression if (!skipMutableState) {
if (initializer != null) { val initializer = field.initializer?.expression
proto.initializer = serializeIrExpressionBody(initializer) if (initializer != null) {
proto.initializer = serializeIrExpressionBody(initializer)
}
} }
return proto.build() return proto.build()
} }
private fun serializeIrVariable(variable: IrVariable): ProtoVariable { fun serializeIrVariable(variable: IrVariable): ProtoVariable {
val proto = ProtoVariable.newBuilder() val proto = ProtoVariable.newBuilder()
.setBase(serializeIrDeclarationBase(variable, LocalVariableFlags.encode(variable))) .setBase(serializeIrDeclarationBase(variable, LocalVariableFlags.encode(variable)))
.setNameType(serializeNameAndType(variable.name, variable.type)) .setNameType(serializeNameAndType(variable.name, variable.type))
@@ -1136,19 +1149,21 @@ open class IrFileSerializer(
.setBase(serializeIrDeclarationBase(clazz, ClassFlags.encode(clazz))) .setBase(serializeIrDeclarationBase(clazz, ClassFlags.encode(clazz)))
.setName(serializeName(clazz.name)) .setName(serializeName(clazz.name))
clazz.declarations.forEach { if (!skipMutableState) {
if (memberNeedsSerialization(it)) proto.addDeclaration(serializeDeclaration(it)) clazz.declarations.forEach {
} if (memberNeedsSerialization(it)) proto.addDeclaration(serializeDeclaration(it))
}
clazz.typeParameters.forEach { clazz.typeParameters.forEach {
proto.addTypeParameter(serializeIrTypeParameter(it)) proto.addTypeParameter(serializeIrTypeParameter(it))
} }
clazz.superTypes.forEach { clazz.thisReceiver?.let { proto.thisReceiver = serializeIrValueParameter(it) }
proto.addSuperType(serializeIrType(it))
}
clazz.thisReceiver?.let { proto.thisReceiver = serializeIrValueParameter(it) } clazz.superTypes.forEach {
proto.addSuperType(serializeIrType(it))
}
}
return proto.build() return proto.build()
} }
@@ -1160,7 +1175,9 @@ open class IrFileSerializer(
.setNameType(serializeNameAndType(typeAlias.name, typeAlias.expandedType)) .setNameType(serializeNameAndType(typeAlias.name, typeAlias.expandedType))
typeAlias.typeParameters.forEach { typeAlias.typeParameters.forEach {
proto.addTypeParameter(serializeIrTypeParameter(it)) if (!skipMutableState) {
proto.addTypeParameter(serializeIrTypeParameter(it))
}
} }
return proto.build() return proto.build()
@@ -1177,16 +1194,18 @@ open class IrFileSerializer(
.setBase(serializeIrDeclarationBase(enumEntry, null)) .setBase(serializeIrDeclarationBase(enumEntry, null))
.setName(serializeName(enumEntry.name)) .setName(serializeName(enumEntry.name))
enumEntry.initializerExpression?.let { if (!skipMutableState) {
proto.initializer = serializeIrExpressionBody(it.expression) enumEntry.initializerExpression?.let {
} proto.initializer = serializeIrExpressionBody(it.expression)
enumEntry.correspondingClass?.let { }
proto.correspondingClass = serializeIrClass(it) enumEntry.correspondingClass?.let {
proto.correspondingClass = serializeIrClass(it)
}
} }
return proto.build() return proto.build()
} }
private fun serializeDeclaration(declaration: IrDeclaration): ProtoDeclaration { fun serializeDeclaration(declaration: IrDeclaration): ProtoDeclaration {
val proto = ProtoDeclaration.newBuilder() val proto = ProtoDeclaration.newBuilder()
when (declaration) { when (declaration) {
@@ -1279,6 +1298,41 @@ open class IrFileSerializer(
} }
} }
fun serializeDeclarationsForIC(file: IrFile, declarations: Iterable<IrDeclaration>): SerializedIrFile {
val proto = ProtoFile.newBuilder()
.setFileEntry(serializeFileEntry(file.fileEntry))
.addAllFqName(serializeFqName(file.fqName.asString()))
val topLevelDeclarations = mutableListOf<SerializedDeclaration>()
for (declaration in declarations) {
val byteArray = serializeDeclaration(declaration).toByteArray()
val idSig = declarationTable.signatureByDeclaration(declaration)
// TODO: keep order similar
// ^ TODO what does that mean?
val sigIndex = protoIdSignatureMap[idSig]
?: if (declaration is IrErrorDeclaration) protoIdSignature(idSig) else error("Not found ID for $idSig (${declaration.render()})")
topLevelDeclarations.add(TopLevelDeclaration(sigIndex, idSig.toString(), byteArray))
}
topLevelDeclarations.forEach {
proto.addDeclarationId(it.id)
}
return SerializedIrFile(
proto.build().toByteArray(),
file.fqName.asString(),
file.path,
IrMemoryArrayWriter(protoTypeArray.map { it.toByteArray() }).writeIntoMemory(),
IrMemoryArrayWriter(protoIdSignatureArray.map { it.toByteArray() }).writeIntoMemory(),
IrMemoryArrayWriter(protoStringArray.map { it.toByteArray() }).writeIntoMemory(),
IrMemoryArrayWriter(protoBodyArray.map { it.toByteArray() }).writeIntoMemory(),
IrMemoryDeclarationWriter(topLevelDeclarations).writeIntoMemory()
)
}
fun serializeIrFile(file: IrFile): SerializedIrFile { fun serializeIrFile(file: IrFile): SerializedIrFile {
val topLevelDeclarations = mutableListOf<SerializedDeclaration>() val topLevelDeclarations = mutableListOf<SerializedDeclaration>()
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer import org.jetbrains.kotlin.backend.common.serialization.IrFileSerializer
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IrMessageLogger import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.ir.util.hasAnnotation import org.jetbrains.kotlin.ir.util.hasAnnotation
@@ -19,13 +20,15 @@ class JsIrFileSerializer(
declarationTable: DeclarationTable, declarationTable: DeclarationTable,
expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>,
skipExpects: Boolean, skipExpects: Boolean,
bodiesOnlyForInlines: Boolean = false bodiesOnlyForInlines: Boolean = false,
icMode: Boolean = false,
) : IrFileSerializer( ) : IrFileSerializer(
messageLogger, messageLogger,
declarationTable, declarationTable,
expectDescriptorToSymbol, expectDescriptorToSymbol,
bodiesOnlyForInlines = bodiesOnlyForInlines, bodiesOnlyForInlines = bodiesOnlyForInlines,
skipExpects = skipExpects skipExpects = skipExpects,
skipMutableState = icMode,
) { ) {
companion object { companion object {
private val JS_EXPORT_FQN = FqName("kotlin.js.JsExport") private val JS_EXPORT_FQN = FqName("kotlin.js.JsExport")