JVM_IR: generate more correct names for regenerated objects

and fake lambda types, too. (But those only matter for debugging.)

Also, share object name generators between methods with the same name to
avoid rewriting objects from one with objects from the other.
This commit is contained in:
pyos
2019-08-30 09:45:34 +02:00
committed by max-kammerer
parent 58775275e7
commit 07bde889b4
12 changed files with 74 additions and 16 deletions
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.backend.jvm.intrinsics.IrIntrinsicMethods
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.MemoizedInlineClassReplacements
import org.jetbrains.kotlin.codegen.ClassBuilder
import org.jetbrains.kotlin.codegen.inline.NameGenerator
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
@@ -35,6 +36,7 @@ import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi2ir.PsiSourceManager
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
@@ -71,6 +73,13 @@ class JvmBackendContext(
localClassInfo[container.attributeOwnerId] = value
}
// TODO cache these at ClassCodegen level. Currently, sharing this map between classes in a module is required
// because IrSourceCompilerForInline constructs a new (Fake)ClassCodegen for every call to
// an inline function in the same module. Thus, if two inline functions happen to have the same name
// and call a third inline function that has an anonymous object, the one which is called last
// will overwrite the other's regenerated copy. (Or don't recompile the inline function for every call.)
internal val regeneratedObjectNameGenerators = mutableMapOf<Pair<IrClass, Name>, NameGenerator>()
internal val localDelegatedProperties = mutableMapOf<IrClass, List<IrLocalDelegatedPropertySymbol>>()
internal val multifileFacadesToAdd = mutableMapOf<JvmClassName, MutableList<IrClass>>()
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.constantValue
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
import org.jetbrains.kotlin.codegen.inline.NameGenerator
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeParametersUsages
import org.jetbrains.kotlin.codegen.inline.SourceMapper
import org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
@@ -82,6 +84,13 @@ open class ClassCodegen protected constructor(
else -> null
}
fun getRegeneratedObjectNameGenerator(function: IrFunction): NameGenerator {
val name = if (function.name.isSpecial) Name.identifier("special") else function.name
return context.regeneratedObjectNameGenerators.getOrPut(irClass to name) {
NameGenerator("${type.internalName}\$$name\$\$inlined")
}
}
fun generate(): ReifiedTypeParametersUsages {
if (withinInline) {
getOrCreateSourceMapper() //initialize default mapping that would be later written in class file
@@ -116,7 +116,7 @@ class ExpressionCodegen(
override val visitor: InstructionAdapter
get() = mv
override val inlineNameGenerator: NameGenerator = NameGenerator("${classCodegen.type.internalName}\$todo") // TODO
override val inlineNameGenerator: NameGenerator = classCodegen.getRegeneratedObjectNameGenerator(irFunction)
override val typeSystem: TypeSystemCommonBackendContext
get() = typeMapper.typeSystem
@@ -151,11 +151,14 @@ class IrExpressionLambdaImpl(
return false //always false
}
companion object {
private var counter: Int = 123//TODO: pass proper type
}
override val lambdaClassType: Type = Type.getObjectType("test${counter++}")
// This name doesn't actually matter: it is used internally to tell this lambda's captured
// arguments apart from any other scope's. So long as it's unique, any value is fine.
// This particular string slightly aids in debugging internal compiler errors as it at least
// points towards the function containing the lambda.
override val lambdaClassType: Type = Type.getObjectType(
context.getLocalClassInfo(reference)?.internalName
?: throw AssertionError("callable reference ${reference.dump()} has no name in context")
)
override val capturedVars: List<CapturedParamDesc> =
arrayListOf<CapturedParamDesc>().apply {
@@ -24,10 +24,7 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.IrConstructor
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.util.defaultType
@@ -51,6 +48,7 @@ internal val inlineCallableReferenceToLambdaPhase = makeIrFilePhase(
//
internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendContext) : FileLoweringPass {
private val inlinableCR = mutableSetOf<IrCallableReference>()
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() {
@@ -118,7 +116,9 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
expression.startOffset, expression.endOffset, field.type,
newLambda.symbol, newLambda.symbol.descriptor, 0,
IrStatementOrigin.LAMBDA
)
).apply {
copyAttributes(expression)
}
}
}
@@ -209,7 +209,9 @@ internal class InlineCallableReferenceToLambdaPhase(val context: JvmBackendConte
expression.startOffset, expression.endOffset, referencedFunction.returnType,
newLambda.symbol, newLambda.symbol.descriptor, referencedFunction.typeParameters.size,
IrStatementOrigin.LAMBDA
)
).apply {
copyAttributes(expression)
}
}
}
}
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
package test
@@ -0,0 +1,19 @@
// FILE: 1.kt
package test
inline fun <R> call(crossinline f: () -> R) : R {
return { f() }()
}
// FILE: 2.kt
//NO_CHECK_LAMBDA_INLINING
import test.*
inline fun sameName(s: Long): String = call { "FAIL" }
inline fun sameName(s: Int): String = call { "OK" }
fun box(): String {
val result = sameName(1)
sameName(1L)
return result
}
@@ -1,5 +1,3 @@
// IGNORE_BACKEND: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM_IR
// FILE: 1.kt
package test
@@ -1888,6 +1888,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt");
}
@TestMetadata("regeneratedLambdaName2.kt")
public void testRegeneratedLambdaName2() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt");
}
@TestMetadata("sameCaptured.kt")
public void testSameCaptured() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt");
@@ -1888,6 +1888,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt");
}
@TestMetadata("regeneratedLambdaName2.kt")
public void testRegeneratedLambdaName2() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt");
}
@TestMetadata("sameCaptured.kt")
public void testSameCaptured() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt");
@@ -1888,6 +1888,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt");
}
@TestMetadata("regeneratedLambdaName2.kt")
public void testRegeneratedLambdaName2() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt");
}
@TestMetadata("sameCaptured.kt")
public void testSameCaptured() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt");
@@ -1888,6 +1888,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName.kt");
}
@TestMetadata("regeneratedLambdaName2.kt")
public void testRegeneratedLambdaName2() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/regeneratedLambdaName2.kt");
}
@TestMetadata("sameCaptured.kt")
public void testSameCaptured() throws Exception {
runTest("compiler/testData/codegen/boxInline/lambdaTransformation/sameCaptured.kt");