IC mangling: Replace compiler hack with configuration flag

This commit is contained in:
Ilmir Usmanov
2020-11-14 00:47:17 +01:00
parent bc1b6fef1f
commit 2cd9016016
27 changed files with 108 additions and 30 deletions
@@ -44,6 +44,7 @@ import org.jetbrains.kotlin.codegen.when.SwitchCodegen;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
import org.jetbrains.kotlin.config.ApiVersion;
import org.jetbrains.kotlin.config.JVMAssertionsMode;
import org.jetbrains.kotlin.config.JVMConfigurationKeys;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
@@ -2686,7 +2687,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
CallableMethod method = typeMapper.mapToCallableMethod(fd, superCall, null, resolvedCall);
if (method.getAsmMethod().getName().contains("-")) {
if (method.getAsmMethod().getName().contains("-") &&
!state.getConfiguration().getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME)
) {
Boolean classFileContainsMethod =
InlineClassesCodegenUtilKt.classFileContainsMethod(fd, state, method.getAsmMethod());
if (classFileContainsMethod != null && !classFileContainsMethod) {
@@ -2912,7 +2915,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
sourceCompiler.initializeInlineFunctionContext(functionDescriptor);
JvmMethodSignature signature = typeMapper.mapSignatureWithGeneric(functionDescriptor, sourceCompiler.getContextKind());
if (signature.getAsmMethod().getName().contains("-")) {
if (signature.getAsmMethod().getName().contains("-") &&
!state.getConfiguration().getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME)
) {
Boolean classFileContainsMethod =
InlineClassesCodegenUtilKt.classFileContainsMethod(functionDescriptor, state, signature.getAsmMethod());
if (classFileContainsMethod != null && !classFileContainsMethod) {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.createFreeFakeLocalPropertyDescriptor
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.*
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapperBase
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.JvmDefaultMode
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
@@ -60,6 +61,7 @@ class JvmSerializerExtension @JvmOverloads constructor(
override val metadataVersion = state.metadataVersion
private val jvmDefaultMode = state.jvmDefaultMode
private val approximator = state.typeApproximator
private val useOldManglingScheme = state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME)
override fun shouldUseTypeTable(): Boolean = useTypeTable
override fun shouldSerializeFunction(descriptor: FunctionDescriptor): Boolean {
@@ -399,4 +401,6 @@ class JvmSerializerExtension @JvmOverloads constructor(
override fun releaseCoroutines(): Boolean {
return languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
}
override fun useOldInlineClassesManglingScheme(): Boolean = useOldManglingScheme
}
@@ -17,7 +17,8 @@ class KotlinToJvmSignatureMapperImpl : KotlinToJvmSignatureMapper {
private val typeMapper = KotlinTypeMapper(
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
JvmProtoBufUtil.DEFAULT_MODULE_NAME,
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT// TODO use proper LanguageVersionSettings
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT,// TODO use proper LanguageVersionSettings
useOldInlineClassesManglingScheme = false
)
override fun mapToJvmMethodSignature(function: FunctionDescriptor) = typeMapper.mapAsmMethod(function)
@@ -55,7 +55,8 @@ class BuilderFactoryForDuplicateSignatureDiagnostics(
private val mapAsmMethod: (FunctionDescriptor) -> Method = KotlinTypeMapper(
// Avoid errors when some classes are not loaded for some reason
bindingContext, ClassBuilderMode.LIGHT_CLASSES, moduleName, languageVersionSettings, isIrBackend = false
bindingContext, ClassBuilderMode.LIGHT_CLASSES, moduleName, languageVersionSettings, isIrBackend = false,
useOldInlineClassesManglingScheme = false
)::mapAsmMethod
private val reportDiagnosticsTasks = ArrayList<() -> Unit>()
@@ -214,6 +214,7 @@ class GenerationState private constructor(
classBuilderMode,
this.moduleName,
languageVersionSettings,
configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME),
IncompatibleClassTrackerImpl(extraJvmDiagnosticsTrace),
target,
isIrBackend
@@ -83,6 +83,7 @@ class KotlinTypeMapper @JvmOverloads constructor(
val classBuilderMode: ClassBuilderMode,
private val moduleName: String,
val languageVersionSettings: LanguageVersionSettings,
private val useOldInlineClassesManglingScheme: Boolean,
private val incompatibleClassTracker: IncompatibleClassTracker = IncompatibleClassTracker.DoNothing,
val jvmTarget: JvmTarget = JvmTarget.DEFAULT,
private val isIrBackend: Boolean = false,
@@ -91,7 +92,11 @@ class KotlinTypeMapper @JvmOverloads constructor(
) : KotlinTypeMapperBase() {
private val isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines)
val jvmDefaultMode = languageVersionSettings.getFlag(JvmAnalysisFlags.jvmDefaultMode)
var useOldManglingRulesForFunctionAcceptingInlineClass: Boolean = false
var useOldManglingRulesForFunctionAcceptingInlineClass: Boolean = useOldInlineClassesManglingScheme
set(value) {
require(!useOldInlineClassesManglingScheme)
field = value
}
private val typeMappingConfiguration = object : TypeMappingConfiguration<Type> {
override fun commonSupertype(types: Collection<KotlinType>): KotlinType {
@@ -22,8 +22,6 @@ import java.util.*
const val NOT_INLINE_CLASS_PARAMETER_PLACEHOLDER = "_"
private fun FunctionDescriptor.isFunctionFromStdlib(): Boolean = fqNameSafe.startsWith(Name.identifier("kotlin"))
class InfoForMangling(
val fqName: FqNameUnsafe,
val isInline: Boolean,
@@ -96,7 +94,7 @@ fun getManglingSuffixBasedOnKotlinSignature(
val unwrappedDescriptor = descriptor.unwrapInitialDescriptorForSuspendFunction()
val resultNew = collectFunctionSignatureForManglingSuffix(
useOldManglingRules = useOldManglingRules || descriptor.isFunctionFromStdlib(),
useOldManglingRules = useOldManglingRules,
requiresFunctionNameManglingForParameterTypes = requiresFunctionNameManglingForParameterTypes(descriptor),
fqNamesForMangling =
(listOfNotNull(descriptor.extensionReceiverParameter?.type) + descriptor.valueParameters.map { it.type })
@@ -412,6 +412,12 @@ class K2JVMCompilerArguments : CommonCompilerArguments() {
)
var useOldSpilledVarTypeAnalysis: Boolean by FreezableVar(false)
@Argument(
value = "-Xuse-14-inline-classes-mangling-scheme",
description = "Use 1.4 inline classes mangling scheme instead of 1.4.30 one"
)
var useOldInlineClassesManglingScheme: Boolean by FreezableVar(false)
override fun configureAnalysisFlags(collector: MessageCollector): MutableMap<AnalysisFlag<*>, Any> {
val result = super.configureAnalysisFlags(collector)
result[JvmAnalysisFlags.strictMetadataVersionSemantics] = strictMetadataVersionSemantics
@@ -87,6 +87,7 @@ class CliLightClassGenerationSupport(
ClassBuilderMode.LIGHT_CLASSES,
moduleName,
languageVersionSettings,
useOldInlineClassesManglingScheme = false,
jvmTarget = JvmTarget.JVM_1_8,
typePreprocessor = KotlinType::cleanFromAnonymousTypes,
namePreprocessor = ::tryGetPredefinedName
@@ -231,6 +231,7 @@ fun CompilerConfiguration.configureAdvancedJvmOptions(arguments: K2JVMCompilerAr
put(CLIConfigurationKeys.ALLOW_KOTLIN_PACKAGE, arguments.allowKotlinPackage)
put(JVMConfigurationKeys.USE_SINGLE_MODULE, arguments.singleModule)
put(JVMConfigurationKeys.USE_OLD_SPILLED_VAR_TYPE_ANALYSIS, arguments.useOldSpilledVarTypeAnalysis)
put(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME, arguments.useOldInlineClassesManglingScheme)
arguments.declarationsOutputPath?.let { put(JVMConfigurationKeys.DECLARATIONS_JSON_PATH, it) }
}
@@ -137,4 +137,7 @@ public class JVMConfigurationKeys {
public static final CompilerConfigurationKey<Boolean> USE_OLD_SPILLED_VAR_TYPE_ANALYSIS =
CompilerConfigurationKey.create("Use old, SourceInterpreter-based analysis for fields, used for spilled variables in coroutines");
public static final CompilerConfigurationKey<Boolean> USE_OLD_INLINE_CLASSES_MANGLING_SCHEME =
CompilerConfigurationKey.create("Use old, 1.4 version of inline classes mangling scheme");
}
@@ -61,8 +61,6 @@ object InlineClassAbi {
return irClass.primaryConstructor!!.valueParameters[0].type
}
private fun IrFunction.isFunctionFromStdlib(): Boolean = fqNameForIrSerialization.startsWith(Name.identifier("kotlin"))
/**
* Returns a mangled name for a function taking inline class arguments
* to avoid clashes between overloaded methods.
@@ -99,7 +97,7 @@ object InlineClassAbi {
alwaysMangleReturnType: Boolean = false
): String? {
val signatureForMangling = collectFunctionSignatureForManglingSuffix(
useOldManglingRules = useOldMangleRules || irFunction.isFunctionFromStdlib(),
useOldManglingRules = useOldMangleRules,
requiresFunctionNameManglingForParameterTypes = irFunction.fullValueParameterList.any { it.type.requiresMangling },
fqNamesForMangling = irFunction.fullValueParameterList.map {
it.type.asInfoForMangling()
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.jvm.codegen.classFileContainsMethod
import org.jetbrains.kotlin.backend.jvm.ir.isStaticInlineClassReplacement
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi.mangledNameFor
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
@@ -221,8 +222,13 @@ class MemoizedInlineClassReplacements(
if (noFakeOverride) {
isFakeOverride = false
}
name = mangledNameFor(function, mangleReturnTypes, false)
if (name.asString().contains("-") && classFileContainsMethod(function, context, name.asString()) == false) {
val useOldManglingScheme = context.state.configuration.getBoolean(JVMConfigurationKeys.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME)
name = mangledNameFor(function, mangleReturnTypes, useOldManglingScheme)
if (
!useOldManglingScheme &&
name.asString().contains("-") &&
classFileContainsMethod(function, context, name.asString()) == false
) {
name = mangledNameFor(function, mangleReturnTypes, true)
}
returnType = function.returnType
@@ -362,7 +362,7 @@ class DescriptorSerializer private constructor(
}
if (descriptor.hasInlineClassTypesInSignature()) {
if (descriptor.fqNameSafe.startsWith(Name.identifier("kotlin"))) {
if (extension.useOldInlineClassesManglingScheme()) {
builder.addVersionRequirement(writeVersionRequirement(LanguageFeature.InlineClasses))
} else {
builder.addVersionRequirement(
@@ -94,4 +94,6 @@ abstract class SerializerExtension {
}
open fun releaseCoroutines(): Boolean = false
open fun useOldInlineClassesManglingScheme(): Boolean = false
}
+2
View File
@@ -112,6 +112,8 @@ where advanced options include:
-Xuse-javac Use javac for Java source and class files analysis
-Xuse-old-class-files-reading Use old class files reading implementation. This may slow down the build and cause problems with Groovy interop.
Should be used in case of problems with the new implementation
-Xuse-14-inline-classes-mangling-scheme
Use 1.4 inline classes mangling scheme instead of 1.4.30 one
-Xuse-old-spilled-var-type-analysis
Use old, SourceInterpreter-based analysis for fields, used for spilled variables in coroutines
-Xuse-type-table Use type table in metadata serialization
@@ -1,3 +1,4 @@
// KOTLIN_CONFIGURATION_FLAGS: +JVM.USE_OLD_INLINE_CLASSES_MANGLING_SCHEME
// FILE: 1.kt
package test
@@ -0,0 +1,17 @@
package test
inline class IC(val x: String)
typealias ICAlias = IC
class Ctor(ic: IC)
fun simpleFun(f: IC) {}
fun aliasedFun(f: ICAlias) {}
val simpleProp: IC = IC("")
fun result(r: List<Result<Any>?>) {}
abstract class Foo : List<IC>
interface Bar<T : IC>
@@ -203,18 +203,26 @@ abstract class AbstractVersionRequirementTest : TestCaseWithTmpdir() {
)
}
fun testInlineClassesAndRelevantDeclarations() {
fun testInlineClassesAndRelevantDeclarations13() {
doTest(
VersionRequirement.Version(1, 3), DeprecationLevel.ERROR, null, ProtoBuf.VersionRequirement.VersionKind.LANGUAGE_VERSION, null,
fqNamesWithRequirements = listOf(
"test.IC",
"test.Ctor.<init>",
"test.Foo",
"test.Bar",
"test.simpleProp"
)
)
}
fun testInlineClassesAndRelevantDeclarations1430() {
doTest(
VersionRequirement.Version(1, 4, 30), DeprecationLevel.ERROR, null, ProtoBuf.VersionRequirement.VersionKind.COMPILER_VERSION, null,
fqNamesWithRequirements = listOf(
"test.simpleFun",
"test.aliasedFun",
"test.simpleProp",
"test.result",
"test.Foo",
"test.Bar"
)
)
}
@@ -145,26 +145,38 @@ class JvmVersionRequirementTest : AbstractVersionRequirementTest() {
doTest(
VersionRequirement.Version(1, 3, 0), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null,
fqNamesWithRequirements = listOf(
"test.C.returnsInlineClassTypeJvmName",
"test.returnsInlineClassType",
"test.propertyOfInlineClassType"
),
shouldBeSingleRequirement = true,
customLanguageVersion = LanguageVersion.KOTLIN_1_4
)
// In Kotlin 1.3, all functions and properties returning inline class values are NOT mangled,
// and have "since 1.3" version requirement for inline class in signature only.
doTest(
VersionRequirement.Version(1, 3, 0), DeprecationLevel.ERROR, null, LANGUAGE_VERSION, null,
fqNamesWithRequirements = listOf(
"test.returnsInlineClassType",
"test.propertyOfInlineClassType",
"test.C.returnsInlineClassType",
"test.C.propertyOfInlineClassType"
),
shouldBeSingleRequirement = true,
customLanguageVersion = LanguageVersion.KOTLIN_1_3
)
// In Kotlin 1.3, all functions and properties returning inline class values are NOT mangled,
// and have "since 1.3" version requirement for inline class in signature only.
doTest(
VersionRequirement.Version(1, 4, 30), DeprecationLevel.ERROR, null, COMPILER_VERSION, null,
fqNamesWithRequirements = listOf(
"test.C.returnsInlineClassTypeJvmName",
"test.returnsInlineClassType"
),
shouldBeSingleRequirement = true,
customLanguageVersion = LanguageVersion.KOTLIN_1_4
)
doTest(
VersionRequirement.Version(1, 4, 30), DeprecationLevel.ERROR, null, COMPILER_VERSION, null,
fqNamesWithRequirements = listOf(
"test.C.returnsInlineClassType"
),
shouldBeSingleRequirement = false,
customLanguageVersion = LanguageVersion.KOTLIN_1_4
)
}
fun testSuspendFun_1_2() {
@@ -81,6 +81,7 @@ class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSup
KotlinTypeMapper(
BindingContext.EMPTY, ClassBuilderMode.LIGHT_CLASSES,
moduleName, languageVersionSettings,
useOldInlineClassesManglingScheme = false,
jvmTarget = JvmTarget.JVM_1_8,
typePreprocessor = KotlinType::cleanFromAnonymousTypes,
namePreprocessor = ::tryGetPredefinedName
@@ -342,7 +342,8 @@ abstract class FileRankingCalculator(private val checkClassFqName: Boolean = tru
bindingContext,
ClassBuilderMode.LIGHT_CLASSES,
"debugger",
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT // TODO use proper LanguageVersionSettings
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT, // TODO use proper LanguageVersionSettings
useOldInlineClassesManglingScheme = false
)
}
@@ -195,7 +195,8 @@ class ParcelableDeclarationChecker : DeclarationChecker {
bindingContext,
ClassBuilderMode.FULL,
descriptor.module.name.asString(),
languageVersionSettings
languageVersionSettings,
useOldInlineClassesManglingScheme = false
)
for (parameter in primaryConstructor?.valueParameters.orEmpty<KtParameter>()) {
@@ -212,7 +212,8 @@ open class ParcelizeDeclarationChecker : DeclarationChecker {
bindingContext,
ClassBuilderMode.FULL,
descriptor.module.name.asString(),
languageVersionSettings
languageVersionSettings,
useOldInlineClassesManglingScheme = false
)
for (parameter in primaryConstructor?.valueParameters.orEmpty<KtParameter>()) {
@@ -35,7 +35,8 @@ class IdeaKotlinUastResolveProviderService : KotlinUastResolveProviderService {
override fun getTypeMapper(element: KtElement): KotlinTypeMapper? {
return KotlinTypeMapper(
getBindingContext(element), ClassBuilderMode.LIGHT_CLASSES,
JvmProtoBufUtil.DEFAULT_MODULE_NAME, element.languageVersionSettings
JvmProtoBufUtil.DEFAULT_MODULE_NAME, element.languageVersionSettings,
useOldInlineClassesManglingScheme = false
)
}
@@ -60,7 +60,8 @@ class UastAnalysisHandlerExtension : AnalysisHandlerExtension {
val typeMapper = KotlinTypeMapper(
bindingContext, ClassBuilderMode.LIGHT_CLASSES,
JvmProtoBufUtil.DEFAULT_MODULE_NAME,
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT // TODO use proper LanguageVersionSettings
KotlinTypeMapper.LANGUAGE_VERSION_SETTINGS_DEFAULT, // TODO use proper LanguageVersionSettings
useOldInlineClassesManglingScheme = false
)
this.typeMapper = typeMapper
return typeMapper