From b2617199bc727726227ccff7d86e02ea64508d9d Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Fri, 26 Feb 2021 17:42:58 +0300 Subject: [PATCH] JVM_IR: call serialization for IR. Serializer for IR is called when -Xserialize-ir flag is set. --- .../arguments/K2JVMCompilerArguments.kt | 6 +++++ .../jetbrains/kotlin/cli/jvm/jvmArguments.kt | 2 ++ .../kotlin/config/JVMConfigurationKeys.java | 3 +++ .../kotlin/fir/backend/FirMetadataSource.kt | 8 ++++-- .../kotlin/backend/jvm/JvmIrCodegenFactory.kt | 11 ++++++++ .../kotlin/backend/jvm/JvmBackendContext.kt | 9 ++++--- .../kotlin/backend/jvm/serialization.kt | 27 +++++++++++++++++++ .../kotlin/ir/declarations/MetadataSource.kt | 16 ++++++++--- .../JvmGlobalDeclarationTable.kt | 12 +++++++++ compiler/testData/cli/jvm/extraHelp.out | 2 +- 10 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization.kt create mode 100644 compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmGlobalDeclarationTable.kt diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt index a38f024a0d7..7f69f3005ba 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JVMCompilerArguments.kt @@ -499,6 +499,12 @@ default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise"" ) var typeEnhancementImprovementsInStrictMode: Boolean by FreezableVar(false) + @Argument( + value = "-Xserialize-ir", + description = "Save IR to metadata (EXPERIMENTAL)" + ) + var serializeIr: Boolean by FreezableVar(false) + override fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap, Any> { val result = super.configureAnalysisFlags(collector, languageVersion) result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt index a1a639f9c51..1eae0f92f8b 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/jvmArguments.kt @@ -252,6 +252,8 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr put(JVMConfigurationKeys.NO_RESET_JAR_TIMESTAMPS, arguments.noResetJarTimestamps) put(JVMConfigurationKeys.NO_UNIFIED_NULL_CHECKS, arguments.noUnifiedNullChecks) + put(JVMConfigurationKeys.SERIALIZE_IR, arguments.serializeIr) + if (!JVMConstructorCallNormalizationMode.isSupportedValue(arguments.constructorCallNormalizationMode)) { messageCollector.report( ERROR, diff --git a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java index ed8f37de4af..28d35ab5b83 100644 --- a/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java +++ b/compiler/config.jvm/src/org/jetbrains/kotlin/config/JVMConfigurationKeys.java @@ -152,4 +152,7 @@ public class JVMConfigurationKeys { public static final CompilerConfigurationKey NO_REFLECT = CompilerConfigurationKey.create("Don't automatically include kotlin-reflect.jar into the output if the output is a jar"); + + public static final CompilerConfigurationKey SERIALIZE_IR = + CompilerConfigurationKey.create("serialize IR to class metadata"); } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirMetadataSource.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirMetadataSource.kt index 3332a0e89cf..347f4343c3d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirMetadataSource.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirMetadataSource.kt @@ -26,9 +26,13 @@ sealed class FirMetadataSource : MetadataSource { else -> null } - class File(override val fir: FirFile) : FirMetadataSource(), MetadataSource.File + class File(override val fir: FirFile) : FirMetadataSource(), MetadataSource.File { + override var serializedIr: ByteArray? = null + } - class Class(override val fir: FirClass) : FirMetadataSource(), MetadataSource.Class + class Class(override val fir: FirClass) : FirMetadataSource(), MetadataSource.Class { + override var serializedIr: ByteArray? = null + } class Function(override val fir: FirFunction) : FirMetadataSource(), MetadataSource.Function diff --git a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt index b6c1a054783..347e58f65d7 100644 --- a/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt +++ b/compiler/ir/backend.jvm/entrypoint/src/org/jetbrains/kotlin/backend/jvm/JvmIrCodegenFactory.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrLinker import org.jetbrains.kotlin.ir.builders.TranslationPluginContext import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.MetadataSource import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrFunctionFactory @@ -186,6 +187,16 @@ open class JvmIrCodegenFactory( /* JvmBackendContext creates new unbound symbols, have to resolve them. */ ExternalDependenciesGenerator(symbolTable, irProviders).generateUnboundSymbolsAsDependencies() + if (state.configuration.getBoolean(JVMConfigurationKeys.SERIALIZE_IR)) { + for (irFile in irModuleFragment.files) { + (irFile.metadata as? MetadataSource.File)?.serializedIr = serializeIrFile(context, irFile) + + for (irClass in irFile.declarations.filterIsInstance()) { + (irClass.metadata as? MetadataSource.Class)?.serializedIr = serializeTopLevelIrClass(context, irClass) + } + } + } + context.state.factory.registerSourceFiles(irModuleFragment.files.map(IrFile::getKtFile)) jvmPhases.invokeToplevel(phaseConfig, context, irModuleFragment) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt index f8eda83a10f..8fc4d7563e4 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/JvmBackendContext.kt @@ -11,10 +11,8 @@ import org.jetbrains.kotlin.backend.common.Mapping import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.psi.PsiErrorBuilder -import org.jetbrains.kotlin.backend.jvm.codegen.ClassCodegen -import org.jetbrains.kotlin.backend.jvm.codegen.IrTypeMapper -import org.jetbrains.kotlin.backend.jvm.codegen.MethodSignatureMapper -import org.jetbrains.kotlin.backend.jvm.codegen.createFakeContinuation +import org.jetbrains.kotlin.backend.common.serialization.DeclarationTable +import org.jetbrains.kotlin.backend.jvm.codegen.* import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSharedVariablesManager import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods import org.jetbrains.kotlin.backend.jvm.lower.BridgeLowering @@ -22,6 +20,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.CollectionStubComputer import org.jetbrains.kotlin.backend.jvm.lower.JvmInnerClassesSupport import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements +import org.jetbrains.kotlin.backend.jvm.serialization.JvmGlobalDeclarationTable import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor @@ -224,4 +223,6 @@ class JvmBackendContext( override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true } + + val declarationTable = DeclarationTable(JvmGlobalDeclarationTable()) } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization.kt new file mode 100644 index 00000000000..7c9a60a3a2d --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2021 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.jvm + +import org.jetbrains.kotlin.backend.jvm.serialization.JvmIrSerializer +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.util.IrMessageLogger + +fun serializeIrFile(context: JvmBackendContext, irFile: IrFile): ByteArray { + return makeSerializer(context).serializeJvmIrFile(irFile).toByteArray() +} + +fun serializeTopLevelIrClass(context: JvmBackendContext, irClass: IrClass): ByteArray { + assert(irClass.parent is IrFile) + return makeSerializer(context).serializeTopLevelClass(irClass).toByteArray() +} + +private fun makeSerializer(context: JvmBackendContext) = + JvmIrSerializer( + context.configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None, + context.declarationTable, + mutableMapOf(), + ) \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/MetadataSource.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/MetadataSource.kt index fad74961031..8e5be2ac771 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/MetadataSource.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/MetadataSource.kt @@ -11,8 +11,12 @@ import org.jetbrains.kotlin.name.Name interface MetadataSource { val name: Name? - interface File : MetadataSource - interface Class : MetadataSource + interface File : MetadataSource { + var serializedIr: ByteArray? + } + interface Class : MetadataSource { + var serializedIr: ByteArray? + } interface Script : MetadataSource interface Function : MetadataSource interface Property : MetadataSource { @@ -27,9 +31,13 @@ sealed class DescriptorMetadataSource : MetadataSource { override val name: Name? get() = descriptor?.name - class File(val descriptors: List) : DescriptorMetadataSource(), MetadataSource.File + class File(val descriptors: List) : DescriptorMetadataSource(), MetadataSource.File { + override var serializedIr: ByteArray? = null + } - class Class(override val descriptor: ClassDescriptor) : DescriptorMetadataSource(), MetadataSource.Class + class Class(override val descriptor: ClassDescriptor) : DescriptorMetadataSource(), MetadataSource.Class { + override var serializedIr: ByteArray? = null + } class Script(override val descriptor: ScriptDescriptor) : DescriptorMetadataSource(), MetadataSource.Script diff --git a/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmGlobalDeclarationTable.kt b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmGlobalDeclarationTable.kt new file mode 100644 index 00000000000..2297a22ee89 --- /dev/null +++ b/compiler/ir/serialization.jvm/src/org/jetbrains/kotlin/backend/jvm/serialization/JvmGlobalDeclarationTable.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2021 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.jvm.serialization + +import org.jetbrains.kotlin.backend.common.serialization.GlobalDeclarationTable +import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureSerializer +import org.jetbrains.kotlin.ir.backend.jvm.serialization.JvmIrMangler + +class JvmGlobalDeclarationTable : GlobalDeclarationTable(IdSignatureSerializer(JvmIrMangler), JvmIrMangler) \ No newline at end of file diff --git a/compiler/testData/cli/jvm/extraHelp.out b/compiler/testData/cli/jvm/extraHelp.out index 547bd67d40d..9702ea4e583 100644 --- a/compiler/testData/cli/jvm/extraHelp.out +++ b/compiler/testData/cli/jvm/extraHelp.out @@ -113,6 +113,7 @@ where advanced options include: problems with parentheses in identifiers on certain platforms -Xscript-resolver-environment= Script resolver environment in key-value pairs (the value could be quoted and escaped) + -Xserialize-ir Save IR to metadata (EXPERIMENTAL) -Xsingle-module Combine modules for source files and binary dependencies into a single module -Xskip-runtime-version-check Allow Kotlin runtime libraries of incompatible versions in the classpath -Xstrict-java-nullability-assertions @@ -203,4 +204,3 @@ where advanced options include: Advanced options are non-standard and may be changed or removed without any notice. OK -