[IrSerializer] Preparations for functional interfaces handling

This commit is contained in:
Igor Chevdar
2019-08-02 14:08:38 +03:00
parent c007f3efb3
commit 00dc335559
17 changed files with 145 additions and 91 deletions
@@ -221,8 +221,8 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
val intAnd = getBinaryOperator(OperatorNameConventions.AND, builtIns.intType, builtIns.intType) val intAnd = getBinaryOperator(OperatorNameConventions.AND, builtIns.intType, builtIns.intType)
val intPlusInt = getBinaryOperator(OperatorNameConventions.PLUS, builtIns.intType, builtIns.intType) val intPlusInt = getBinaryOperator(OperatorNameConventions.PLUS, builtIns.intType, builtIns.intType)
fun functionN(n: Int): IrClassSymbol = symbolTable.referenceClass(builtIns.getFunction(n)) open fun functionN(n: Int): IrClassSymbol = symbolTable.referenceClass(builtIns.getFunction(n))
fun suspendFunctionN(n: Int): IrClassSymbol = symbolTable.referenceClass(builtIns.getSuspendFunction(n)) open fun suspendFunctionN(n: Int): IrClassSymbol = symbolTable.referenceClass(builtIns.getSuspendFunction(n))
val extensionToString = getSimpleFunction(Name.identifier("toString")) { val extensionToString = getSimpleFunction(Name.identifier("toString")) {
it.dispatchReceiverParameter == null && it.extensionReceiverParameter != null && it.dispatchReceiverParameter == null && it.extensionReceiverParameter != null &&
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.IrDeserializer import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.IrProvider
import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
@@ -71,17 +72,18 @@ class Psi2IrTranslator(
fun generateModuleFragment( fun generateModuleFragment(
context: GeneratorContext, context: GeneratorContext,
ktFiles: Collection<KtFile>, ktFiles: Collection<KtFile>,
deserializer: IrDeserializer? = null deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList()
): IrModuleFragment { ): IrModuleFragment {
val moduleGenerator = ModuleGenerator(context) val moduleGenerator = ModuleGenerator(context)
val irModule = moduleGenerator.generateModuleFragmentWithoutDependencies(ktFiles) val irModule = moduleGenerator.generateModuleFragmentWithoutDependencies(ktFiles)
// This is required for implicit casts insertion on IrTypes (work-in-progress). // This is required for implicit casts insertion on IrTypes (work-in-progress).
moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, facadeClassGenerator) moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, facadeClassGenerator)
irModule.patchDeclarationParents() irModule.patchDeclarationParents()
postprocess(context, irModule) postprocess(context, irModule)
moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, facadeClassGenerator) moduleGenerator.generateUnboundSymbolsAsDependencies(irModule, deserializer, irProviders, facadeClassGenerator)
return irModule return irModule
} }
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrModuleFragmentImpl
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.IrDeserializer import org.jetbrains.kotlin.ir.util.IrDeserializer
import org.jetbrains.kotlin.ir.util.IrProvider
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile
@@ -48,6 +49,7 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
fun generateUnboundSymbolsAsDependencies( fun generateUnboundSymbolsAsDependencies(
irModule: IrModuleFragment, irModule: IrModuleFragment,
deserializer: IrDeserializer? = null, deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList(),
facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null }
) { ) {
ExternalDependenciesGenerator( ExternalDependenciesGenerator(
@@ -56,6 +58,7 @@ class ModuleGenerator(override val context: GeneratorContext) : Generator {
context.irBuiltIns, context.irBuiltIns,
context.extensions.externalDeclarationOrigin, context.extensions.externalDeclarationOrigin,
deserializer, deserializer,
irProviders,
facadeClassGenerator facadeClassGenerator
).generateUnboundSymbolsAsDependencies() ).generateUnboundSymbolsAsDependencies()
} }
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.lazy.* import org.jetbrains.kotlin.ir.declarations.lazy.*
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource import org.jetbrains.kotlin.serialization.deserialization.descriptors.DescriptorWithContainerSource
@@ -36,7 +37,7 @@ class DeclarationStubGenerator(
val symbolTable: SymbolTable, val symbolTable: SymbolTable,
languageVersionSettings: LanguageVersionSettings, languageVersionSettings: LanguageVersionSettings,
private val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null, private val externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null,
private val deserializer: IrDeserializer? = null, private val irProviders: List<IrProvider> = emptyList(),
private val facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } private val facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null }
) { ) {
private val lazyTable = symbolTable.lazyWrapper private val lazyTable = symbolTable.lazyWrapper
@@ -58,6 +59,12 @@ class DeclarationStubGenerator(
constantValueGenerator.typeTranslator = typeTranslator constantValueGenerator.typeTranslator = typeTranslator
} }
private fun getDeclaration(symbol: IrSymbol): IrDeclaration? {
for (irProvider in irProviders)
irProvider.getDeclaration(symbol)?.let { return it }
return null
}
fun generateOrGetEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment { fun generateOrGetEmptyExternalPackageFragmentStub(descriptor: PackageFragmentDescriptor): IrExternalPackageFragment {
val referenced = symbolTable.referenceExternalPackageFragment(descriptor) val referenced = symbolTable.referenceExternalPackageFragment(descriptor)
if (referenced.isBound) { if (referenced.isBound) {
@@ -114,7 +121,7 @@ class DeclarationStubGenerator(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original, UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original,
isDelegated = @Suppress("DEPRECATION") descriptor.isDelegated isDelegated = @Suppress("DEPRECATION") descriptor.isDelegated
) { ) {
deserializer?.findDeserializedDeclaration(referenced) as? IrProperty getDeclaration(referenced) as? IrProperty
?: IrLazyProperty(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator, bindingContext) ?: IrLazyProperty(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator, bindingContext)
} }
} }
@@ -131,7 +138,7 @@ class DeclarationStubGenerator(
else computeOrigin(descriptor) else computeOrigin(descriptor)
return symbolTable.declareField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original, descriptor.type.toIrType()) { return symbolTable.declareField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original, descriptor.type.toIrType()) {
deserializer?.findDeserializedDeclaration(referenced) as? IrField getDeclaration(referenced) as? IrField
?: IrLazyField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) ?: IrLazyField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
} }
} }
@@ -158,7 +165,7 @@ class DeclarationStubGenerator(
origin, origin,
descriptor.original descriptor.original
) { ) {
deserializer?.findDeserializedDeclaration(referenced) as? IrSimpleFunction getDeclaration(referenced) as? IrSimpleFunction
?: IrLazyFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) ?: IrLazyFunction(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
} }
} }
@@ -173,7 +180,7 @@ class DeclarationStubGenerator(
return symbolTable.declareConstructor( return symbolTable.declareConstructor(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original
) { ) {
deserializer?.findDeserializedDeclaration(referenced) as? IrConstructor getDeclaration(referenced) as? IrConstructor
?: IrLazyConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) ?: IrLazyConstructor(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
} }
} }
@@ -204,7 +211,7 @@ class DeclarationStubGenerator(
} }
val origin = computeOrigin(descriptor) val origin = computeOrigin(descriptor)
return symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) { return symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
deserializer?.findDeserializedDeclaration(referenceClass) as? IrClass getDeclaration(referenceClass) as? IrClass
?: IrLazyClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) ?: IrLazyClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
} }
} }
@@ -216,7 +223,7 @@ class DeclarationStubGenerator(
} }
val origin = computeOrigin(descriptor) val origin = computeOrigin(descriptor)
return symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) { return symbolTable.declareEnumEntry(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
deserializer?.findDeserializedDeclaration(referenced) as? IrEnumEntry getDeclaration(referenced) as? IrEnumEntry
?: IrLazyEnumEntryImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) ?: IrLazyEnumEntryImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
} }
} }
@@ -228,7 +235,7 @@ class DeclarationStubGenerator(
} }
val origin = computeOrigin(descriptor) val origin = computeOrigin(descriptor)
return symbolTable.declareGlobalTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) { return symbolTable.declareGlobalTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor) {
deserializer?.findDeserializedDeclaration(referenced) as? IrTypeParameter getDeclaration(referenced) as? IrTypeParameter
?: IrLazyTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator) ?: IrLazyTypeParameter(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, it, this, typeTranslator)
} }
} }
@@ -31,38 +31,45 @@ class ExternalDependenciesGenerator(
val irBuiltIns: IrBuiltIns, val irBuiltIns: IrBuiltIns,
externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null, externalDeclarationOrigin: ((DeclarationDescriptor) -> IrDeclarationOrigin)? = null,
private val deserializer: IrDeserializer? = null, private val deserializer: IrDeserializer? = null,
irProviders: List<IrProvider> = emptyList(),
facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null } facadeClassGenerator: (DeserializedContainerSource) -> IrClass? = { null }
) { ) {
private val stubGenerator = DeclarationStubGenerator( private val stubGenerator = DeclarationStubGenerator(
moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings, externalDeclarationOrigin, deserializer, facadeClassGenerator moduleDescriptor, symbolTable, irBuiltIns.languageVersionSettings, externalDeclarationOrigin,
listOfNotNull(deserializer) + irProviders, facadeClassGenerator
) )
fun generateUnboundSymbolsAsDependencies() { fun generateUnboundSymbolsAsDependencies() {
stubGenerator.unboundSymbolGeneration = true stubGenerator.unboundSymbolGeneration = true
ArrayList(symbolTable.unboundClasses).forEach { do {
stubGenerator.generateClassStub(it.descriptor) fun <T> haveNotStabilized(prev: ArrayList<T>, cur: Set<T>) =
} cur.isNotEmpty() && (prev.size != cur.size || prev.any { !cur.contains(it) })
ArrayList(symbolTable.unboundConstructors).forEach {
stubGenerator.generateConstructorStub(it.descriptor) val unboundClasses = ArrayList(symbolTable.unboundClasses)
} val unboundConstructors = ArrayList(symbolTable.unboundConstructors)
ArrayList(symbolTable.unboundEnumEntries).forEach { val unboundEnumEntries = ArrayList(symbolTable.unboundEnumEntries)
stubGenerator.generateEnumEntryStub(it.descriptor) val unboundFields = ArrayList(symbolTable.unboundFields)
} val unboundSimpleFunctions = ArrayList(symbolTable.unboundSimpleFunctions)
ArrayList(symbolTable.unboundFields).forEach { val unboundProperties = ArrayList(symbolTable.unboundProperties)
stubGenerator.generateFieldStub(it.descriptor) val unboundTypeParameters = ArrayList(symbolTable.unboundTypeParameters)
} val unboundTypeAliases = ArrayList(symbolTable.unboundTypeAliases)
ArrayList(symbolTable.unboundSimpleFunctions).forEach { unboundClasses.forEach { stubGenerator.generateClassStub(it.descriptor) }
stubGenerator.generateFunctionStub(it.descriptor) unboundConstructors.forEach { stubGenerator.generateConstructorStub(it.descriptor) }
} unboundEnumEntries.forEach { stubGenerator.generateEnumEntryStub(it.descriptor) }
ArrayList(symbolTable.unboundProperties).forEach { unboundFields.forEach { stubGenerator.generateFieldStub(it.descriptor) }
stubGenerator.generatePropertyStub(it.descriptor) unboundSimpleFunctions.forEach { stubGenerator.generateFunctionStub(it.descriptor) }
} unboundProperties.forEach { stubGenerator.generatePropertyStub(it.descriptor) }
ArrayList(symbolTable.unboundTypeParameters).forEach { unboundTypeParameters.forEach { stubGenerator.generateOrGetTypeParameterStub(it.descriptor) }
stubGenerator.generateOrGetTypeParameterStub(it.descriptor) unboundTypeAliases.forEach { stubGenerator.generateTypeAliasStub(it.descriptor) }
} } while (haveNotStabilized(unboundClasses, symbolTable.unboundClasses)
ArrayList(symbolTable.unboundTypeAliases).forEach { || haveNotStabilized(unboundConstructors, symbolTable.unboundConstructors)
stubGenerator.generateTypeAliasStub(it.descriptor) || haveNotStabilized(unboundEnumEntries, symbolTable.unboundEnumEntries)
} || haveNotStabilized(unboundFields, symbolTable.unboundFields)
|| haveNotStabilized(unboundSimpleFunctions, symbolTable.unboundSimpleFunctions)
|| haveNotStabilized(unboundProperties, symbolTable.unboundProperties)
|| haveNotStabilized(unboundTypeParameters, symbolTable.unboundTypeParameters)
|| haveNotStabilized(unboundTypeAliases, symbolTable.unboundTypeAliases)
)
deserializer?.declareForwardDeclarations() deserializer?.declareForwardDeclarations()
@@ -29,8 +29,11 @@ import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType
interface IrDeserializer { interface IrProvider {
fun findDeserializedDeclaration(symbol: IrSymbol): IrDeclaration? fun getDeclaration(symbol: IrSymbol): IrDeclaration?
}
interface IrDeserializer : IrProvider {
fun declareForwardDeclarations() fun declareForwardDeclarations()
} }
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
abstract class DescriptorReferenceDeserializer( abstract class DescriptorReferenceDeserializer(
val currentModule: ModuleDescriptor, val currentModule: ModuleDescriptor,
val mangler: KotlinMangler,
val resolvedForwardDeclarations: MutableMap<UniqIdKey, UniqIdKey> val resolvedForwardDeclarations: MutableMap<UniqIdKey, UniqIdKey>
) : DescriptorUniqIdAware { ) : DescriptorUniqIdAware {
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.regex.Pattern
private val functionPattern = Pattern.compile("^K?(Suspend)?Function\\d+$")
private val kotlinFqn = FqName("kotlin")
private val functionalPackages =
listOf(kotlinFqn, kotlinFqn.child(Name.identifier("coroutines")), kotlinFqn.child(Name.identifier("reflect")))
fun isBuiltInFunction(value: IrDeclaration): Boolean = when (value) {
is IrSimpleFunction ->
value.name == OperatorNameConventions.INVOKE && (value.parent as? IrClass)?.let { isBuiltInFunction(it) } == true
is IrClass ->
value.fqNameWhenAvailable?.parent() in functionalPackages &&
value.name.asString().let { functionPattern.matcher(it).find() }
else -> false
}
fun isBuiltInFunction(value: DeclarationDescriptor): Boolean = when (value) {
is FunctionInvokeDescriptor -> isBuiltInFunction(value.containingDeclaration)
is ClassDescriptor -> {
val fqn = (value.containingDeclaration as? PackageFragmentDescriptor)?.fqName
functionalPackages.any { it == fqn } && value.name.asString().let { functionPattern.matcher(it).find() }
}
else -> false
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.LoggingContext import org.jetbrains.kotlin.backend.common.LoggingContext
import org.jetbrains.kotlin.backend.common.ir.ir2string import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.builtins.FunctionInterfacePackageFragment
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.ClassKind.* import org.jetbrains.kotlin.descriptors.ClassKind.*
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
@@ -1306,11 +1307,12 @@ open class IrModuleSerializer(
val proto = ProtoModule.newBuilder() val proto = ProtoModule.newBuilder()
.setName(serializeName(module.name)) .setName(serializeName(module.name))
val topLevelDeclarationsCount = module.files.sumBy { it.declarations.size } val files = module.files.filter { it.packageFragmentDescriptor !is FunctionInterfacePackageFragment }
val topLevelDeclarationsCount = files.sumBy { it.declarations.size }
writer = CombinedIrFileWriter(topLevelDeclarationsCount) writer = CombinedIrFileWriter(topLevelDeclarationsCount)
module.files.forEach { files.forEach {
proto.addFile(serializeIrFile(it)) proto.addFile(serializeIrFile(it))
} }
@@ -414,7 +414,7 @@ abstract class KotlinIrLinker(
return topLevelDescriptor return topLevelDescriptor
} }
override fun findDeserializedDeclaration(symbol: IrSymbol): IrDeclaration? { override fun getDeclaration(symbol: IrSymbol): IrDeclaration? {
if (!symbol.isBound) { if (!symbol.isBound) {
findDeserializedDeclarationForDescriptor(symbol.descriptor) ?: return null findDeserializedDeclarationForDescriptor(symbol.descriptor) ?: return null
@@ -5,10 +5,7 @@
package org.jetbrains.kotlin.backend.common.serialization package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
@@ -22,6 +19,13 @@ interface KotlinMangler {
fun IrDeclaration.isExported(): Boolean fun IrDeclaration.isExported(): Boolean
val IrFunction.functionName: String val IrFunction.functionName: String
val IrType.isInlined: Boolean val IrType.isInlined: Boolean
val Long.isSpecial: Boolean
companion object {
private val FUNCTION_PREFIX = "<BUILT-IN-FUNCTION>"
fun functionClassSymbolName(name: Name) = "ktype:$FUNCTION_PREFIX$name"
fun functionInvokeSymbolName(name: Name) = "kfun:$FUNCTION_PREFIX$name.invoke"
}
} }
abstract class KotlinManglerImpl : KotlinMangler { abstract class KotlinManglerImpl : KotlinMangler {
@@ -177,6 +181,9 @@ abstract class KotlinManglerImpl : KotlinMangler {
return "$name$signature" return "$name$signature"
} }
override val Long.isSpecial: Boolean
get() = specialHashes.contains(this)
fun Name.mangleIfInternal(moduleDescriptor: ModuleDescriptor, visibility: Visibility): String = fun Name.mangleIfInternal(moduleDescriptor: ModuleDescriptor, visibility: Visibility): String =
if (visibility != Visibilities.INTERNAL) { if (visibility != Visibilities.INTERNAL) {
this.asString() this.asString()
@@ -199,6 +206,8 @@ abstract class KotlinManglerImpl : KotlinMangler {
val IrClass.typeInfoSymbolName: String val IrClass.typeInfoSymbolName: String
get() { get() {
assert(this.isExported()) assert(this.isExported())
if (isBuiltInFunction(this))
return KotlinMangler.functionClassSymbolName(name)
return "ktype:" + this.fqNameForIrSerialization.toString() return "ktype:" + this.fqNameForIrSerialization.toString()
} }
@@ -270,6 +279,8 @@ abstract class KotlinManglerImpl : KotlinMangler {
// In addition functions appearing in fq sequence appear as <full signature>. // In addition functions appearing in fq sequence appear as <full signature>.
private val IrFunction.uniqFunctionName: String private val IrFunction.uniqFunctionName: String
get() { get() {
if (isBuiltInFunction(this))
return KotlinMangler.functionInvokeSymbolName(parentAsClass.name)
val parent = this.parent val parent = this.parent
val containingDeclarationPart = parent.fqNameUnique.let { val containingDeclarationPart = parent.fqNameUnique.let {
@@ -279,5 +290,9 @@ abstract class KotlinManglerImpl : KotlinMangler {
return "kfun:$containingDeclarationPart#$functionName" return "kfun:$containingDeclarationPart#$functionName"
} }
private val specialHashes = listOf("Function", "KFunction", "SuspendFunction", "KSuspendFunction")
.flatMap { name ->
(0..255).map { KotlinMangler.functionClassSymbolName(Name.identifier(name + it)) }
}.map { it.hashMangle }
.toSet()
} }
@@ -19,10 +19,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsDeclarationTable import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.*
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrLinker
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsIrModuleSerializer
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.newJsDescriptorUniqId
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.* import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.*
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
@@ -127,7 +124,7 @@ fun loadIr(
val symbolTable = psi2IrContext.symbolTable val symbolTable = psi2IrContext.symbolTable
val moduleDescriptor = psi2IrContext.moduleDescriptor val moduleDescriptor = psi2IrContext.moduleDescriptor
val deserializer = JsIrLinker(moduleDescriptor, emptyLoggingContext, irBuiltIns, symbolTable) val deserializer = JsIrLinker(moduleDescriptor, JsMangler, emptyLoggingContext, irBuiltIns, symbolTable)
val deserializedModuleFragments = allDependencies.map { val deserializedModuleFragments = allDependencies.map {
deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it))!! deserializer.deserializeIrModuleHeader(depsDescriptors.getModuleDescriptor(it))!!
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.UniqId import org.jetbrains.kotlin.backend.common.serialization.UniqId
import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable
import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable import org.jetbrains.kotlin.backend.common.serialization.DescriptorTable
import org.jetbrains.kotlin.backend.common.serialization.isBuiltInFunction
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
@@ -8,24 +8,12 @@ package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.nameForIrSerialization import org.jetbrains.kotlin.ir.util.nameForIrSerialization
import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.findFirstFunction import org.jetbrains.kotlin.psi2ir.findFirstFunction
import java.util.regex.Pattern
private val functionPattern = Pattern.compile("^K?(Suspend)?Function\\d+$")
private val kotlinFqn = FqName("kotlin")
private val functionalPackages =
listOf(kotlinFqn, kotlinFqn.child(Name.identifier("coroutines")), kotlinFqn.child(Name.identifier("reflect")))
internal const val PUBLIC_LOCAL_UNIQ_ID_EDGE = 0x7FFF_FFFF_FFFF_FFFFL + 1L internal const val PUBLIC_LOCAL_UNIQ_ID_EDGE = 0x7FFF_FFFF_FFFF_FFFFL + 1L
internal const val BUILT_IN_FUNCTION_CLASS_COUNT = 4 internal const val BUILT_IN_FUNCTION_CLASS_COUNT = 4
@@ -33,16 +21,6 @@ internal const val BUILT_IN_FUNCTION_ARITY_COUNT = 256
internal const val BUILT_IN_UNIQ_ID_GAP = 2 * BUILT_IN_FUNCTION_ARITY_COUNT * BUILT_IN_FUNCTION_CLASS_COUNT internal const val BUILT_IN_UNIQ_ID_GAP = 2 * BUILT_IN_FUNCTION_ARITY_COUNT * BUILT_IN_FUNCTION_CLASS_COUNT
internal const val BUILT_IN_UNIQ_ID_CLASS_OFFSET = BUILT_IN_FUNCTION_CLASS_COUNT * BUILT_IN_FUNCTION_ARITY_COUNT internal const val BUILT_IN_UNIQ_ID_CLASS_OFFSET = BUILT_IN_FUNCTION_CLASS_COUNT * BUILT_IN_FUNCTION_ARITY_COUNT
internal fun isBuiltInFunction(value: IrDeclaration): Boolean = when (value) {
is IrSimpleFunction ->
value.name.asString() == "invoke" && (value.parent as? IrClass)?.let { isBuiltInFunction(it) } == true
is IrClass ->
value.fqNameWhenAvailable?.parent() in functionalPackages &&
value.name.asString().let { functionPattern.matcher(it).find() }
else -> false
}
private fun builtInOffset(function: IrSimpleFunction): Long { private fun builtInOffset(function: IrSimpleFunction): Long {
val isK = function.parentAsClass.name.asString().startsWith("K") val isK = function.parentAsClass.name.asString().startsWith("K")
return when { return when {
@@ -63,16 +41,6 @@ internal fun builtInFunctionId(value: IrDeclaration): Long = when (value) {
else -> error("Only class or function is expected") else -> error("Only class or function is expected")
} }
internal fun isBuiltInFunction(value: DeclarationDescriptor): Boolean = when (value) {
is FunctionInvokeDescriptor -> isBuiltInFunction(value.containingDeclaration)
is ClassDescriptor -> {
val fqn = (value.containingDeclaration as? PackageFragmentDescriptor)?.fqName
functionalPackages.any { it == fqn } && value.name.asString().let { functionPattern.matcher(it).find() }
}
else -> false
}
private fun builtInOffset(function: FunctionInvokeDescriptor): Long { private fun builtInOffset(function: FunctionInvokeDescriptor): Long {
val isK = function.containingDeclaration.name.asString().startsWith("K") val isK = function.containingDeclaration.name.asString().startsWith("K")
return when { return when {
@@ -5,9 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
import org.jetbrains.kotlin.backend.common.serialization.DescriptorReferenceDeserializer import org.jetbrains.kotlin.backend.common.serialization.*
import org.jetbrains.kotlin.backend.common.serialization.DescriptorUniqIdAware
import org.jetbrains.kotlin.backend.common.serialization.UniqIdKey
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
@@ -16,9 +14,10 @@ import org.jetbrains.kotlin.name.FqName
class JsDescriptorReferenceDeserializer( class JsDescriptorReferenceDeserializer(
currentModule: ModuleDescriptor, currentModule: ModuleDescriptor,
mangler: KotlinMangler,
val builtIns: IrBuiltIns, val builtIns: IrBuiltIns,
val FUNCTION_INDEX_START: Long) : val FUNCTION_INDEX_START: Long) :
DescriptorReferenceDeserializer(currentModule, mutableMapOf<UniqIdKey, UniqIdKey>()), DescriptorReferenceDeserializer(currentModule, mangler, mutableMapOf<UniqIdKey, UniqIdKey>()),
DescriptorUniqIdAware by JsDescriptorUniqIdAware { DescriptorUniqIdAware by JsDescriptorUniqIdAware {
override fun resolveSpecialDescriptor(fqn: FqName) = builtIns.builtIns.getBuiltInClassByFqName(fqn) override fun resolveSpecialDescriptor(fqn: FqName) = builtIns.builtIns.getBuiltInClassByFqName(fqn)
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.util.SymbolTable
class JsIrLinker( class JsIrLinker(
currentModule: ModuleDescriptor, currentModule: ModuleDescriptor,
mangler: KotlinMangler,
logger: LoggingContext, logger: LoggingContext,
builtIns: IrBuiltIns, builtIns: IrBuiltIns,
symbolTable: SymbolTable symbolTable: SymbolTable
@@ -28,7 +29,7 @@ class JsIrLinker(
builtIns.getPrimitiveTypeOrNullByDescriptor(symbol.descriptor, hasQuestionMark) builtIns.getPrimitiveTypeOrNullByDescriptor(symbol.descriptor, hasQuestionMark)
override val descriptorReferenceDeserializer = override val descriptorReferenceDeserializer =
JsDescriptorReferenceDeserializer(currentModule, builtIns, FUNCTION_INDEX_START) JsDescriptorReferenceDeserializer(currentModule, mangler, builtIns, FUNCTION_INDEX_START)
override fun reader(moduleDescriptor: ModuleDescriptor, uniqId: UniqId): ByteArray { override fun reader(moduleDescriptor: ModuleDescriptor, uniqId: UniqId): ByteArray {
return moduleDescriptor.kotlinLibrary.irDeclaration(uniqId.index, uniqId.isLocal) return moduleDescriptor.kotlinLibrary.irDeclaration(uniqId.index, uniqId.isLocal)
@@ -50,9 +50,13 @@ class FunctionInterfaceMemberScope(
TODO() TODO()
} }
private val classifiers = mutableMapOf<Name, ClassifierDescriptor>()
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = when { override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? = when {
classDescriptorFactory.shouldCreateClass(packageName, name) -> classDescriptorFactory.shouldCreateClass(packageName, name) ->
classDescriptorFactory.createClass(ClassId.topLevel(packageName.child(name))) classifiers.getOrPut(name) {
classDescriptorFactory.createClass(ClassId.topLevel(packageName.child(name)))!!
}
else -> null else -> null
} }
} }