JVM IR: Handle nested classes in DelegatedPropertyOptimizer

This commit is contained in:
Steven Schäfer
2020-08-05 15:55:24 +02:00
committed by Alexander Udalov
parent da9bff40f0
commit ca6e430e89
14 changed files with 174 additions and 42 deletions
@@ -9573,6 +9573,21 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt");
}
@TestMetadata("kt40815.kt")
public void testKt40815() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815.kt");
}
@TestMetadata("kt40815_2.kt")
public void testKt40815_2() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_2.kt");
}
@TestMetadata("kt40815_3.kt")
public void testKt40815_3() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_3.kt");
}
@TestMetadata("lazy.kt")
public void testLazy() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt");
@@ -110,7 +110,7 @@ abstract class ClassCodegen protected constructor(
private var generatingClInit = false
private var generated = false
fun generate(): ReifiedTypeParametersUsages {
fun generate(parentDelegatedPropertyTracker: DelegatedPropertyOptimizer? = null): ReifiedTypeParametersUsages {
// TODO: reject repeated generate() calls; currently, these can happen for objects in finally
// blocks since they are `accept`ed once per each CFG edge out of the try-finally.
if (generated) return reifiedTypeParametersUsages
@@ -120,7 +120,8 @@ abstract class ClassCodegen protected constructor(
val classDelegatedPropertiesArray = irClass.fields.singleOrNull {
it.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
}
val delegatedPropertyTracker = if (classDelegatedPropertiesArray != null) DelegatedPropertyOptimizer() else null
val delegatedPropertyTracker =
if (classDelegatedPropertiesArray != null) DelegatedPropertyOptimizer() else parentDelegatedPropertyTracker
val smap = context.getSourceMapper(irClass)
for (declaration in irClass.declarations) {
@@ -132,6 +133,14 @@ abstract class ClassCodegen protected constructor(
}
}
// Generate nested classes at the end, to ensure that when the companion's metadata is serialized
// everything moved to the outer class has already been recorded in `globalSerializationBindings`.
for (declaration in irClass.declarations) {
if (declaration is IrClass) {
getOrCreate(declaration, context).generate(delegatedPropertyTracker)
}
}
// Delay generation of <clinit> until the end because inline function calls
// might need to generate the `$assertionsDisabled` field initializer.
classInitializer?.let {
@@ -142,14 +151,6 @@ abstract class ClassCodegen protected constructor(
}
}
// Generate nested classes at the end, to ensure that when the companion's metadata is serialized
// everything moved to the outer class has already been recorded in `globalSerializationBindings`.
for (declaration in irClass.declarations) {
if (declaration is IrClass) {
getOrCreate(declaration, context).generate()
}
}
object : AnnotationCodegen(this@ClassCodegen, context) {
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
return visitor.visitor.visitAnnotation(descr, visible)
@@ -208,7 +209,7 @@ abstract class ClassCodegen protected constructor(
return null
}
abstract protected fun generateKotlinMetadataAnnotation()
protected abstract fun generateKotlinMetadataAnnotation()
private fun IrFile.loadSourceFilesInfo(): List<File> {
val entry = fileEntry
@@ -274,14 +275,14 @@ abstract class ClassCodegen protected constructor(
private val generatedInlineMethods = mutableMapOf<IrFunction, SMAPAndMethodNode>()
fun generateMethodNode(method: IrFunction): SMAPAndMethodNode {
fun generateMethodNode(method: IrFunction, delegatedPropertyOptimizer: DelegatedPropertyOptimizer?): SMAPAndMethodNode {
if (!method.isInline && !method.isSuspend) {
// Inline methods can be used multiple times by `IrSourceCompilerForInline`, suspend methods
// could be used twice if they capture crossinline lambdas, and everything else is only
// generated by `generateMethod` below so does not need caching.
return FunctionCodegen(method, this).generate()
return FunctionCodegen(method, this).generate(delegatedPropertyOptimizer)
}
val (node, smap) = generatedInlineMethods.getOrPut(method) { FunctionCodegen(method, this).generate() }
val (node, smap) = generatedInlineMethods.getOrPut(method) { FunctionCodegen(method, this).generate(delegatedPropertyOptimizer) }
val copy = with(node) { MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions.toTypedArray()) }
node.instructions.resetLabels()
node.accept(copy)
@@ -296,7 +297,7 @@ abstract class ClassCodegen protected constructor(
return
}
val (node, smap) = generateMethodNode(method)
val (node, smap) = generateMethodNode(method, delegatedPropertyOptimizer)
if (delegatedPropertyOptimizer != null) {
delegatedPropertyOptimizer.transform(node)
if (method.name.asString() == "<clinit>") {
@@ -321,7 +322,7 @@ abstract class ClassCodegen protected constructor(
if (method.isSuspend) continuationClassCodegen.value.visitor else visitor
}
if (continuationClassCodegen.isInitialized() || method.alwaysNeedsContinuation()) {
continuationClassCodegen.value.generate()
continuationClassCodegen.value.generate(delegatedPropertyOptimizer)
}
} else {
node.accept(smapCopyingVisitor)
@@ -104,7 +104,8 @@ class ExpressionCodegen(
val mv: InstructionAdapter,
val classCodegen: ClassCodegen,
val inlinedInto: ExpressionCodegen?,
val smap: SourceMapper
val smap: SourceMapper,
val delegatedPropertyOptimizer: DelegatedPropertyOptimizer?,
) : IrElementVisitor<PromisedValue, BlockInfo>, BaseExpressionCodegen {
var finallyDepth = 0
@@ -557,7 +558,7 @@ class ExpressionCodegen(
expression.receiver?.let { receiver ->
receiver.accept(this, data).materializeAt(ownerType, receiver.type)
}
return if (expression is IrSetField) {
val value = expression.value.accept(this, data)
@@ -725,7 +726,8 @@ class ExpressionCodegen(
override fun visitClass(declaration: IrClass, data: BlockInfo): PromisedValue {
if (declaration.origin != JvmLoweredDeclarationOrigin.CONTINUATION_CLASS) {
closureReifiedMarkers[declaration] =
ClassCodegen.getOrCreate(declaration, context, generateSequence(this) { it.inlinedInto }.last().irFunction).generate()
ClassCodegen.getOrCreate(declaration, context, generateSequence(this) { it.inlinedInto }.last().irFunction)
.generate(delegatedPropertyOptimizer)
}
return unitValue
}
@@ -45,14 +45,14 @@ class FunctionCodegen(
) {
private val context = classCodegen.context
fun generate(): SMAPAndMethodNode =
fun generate(delegatedPropertyOptimizer: DelegatedPropertyOptimizer?): SMAPAndMethodNode =
try {
doGenerate()
doGenerate(delegatedPropertyOptimizer)
} catch (e: Throwable) {
throw RuntimeException("Exception while generating code for:\n${irFunction.dump()}", e)
}
private fun doGenerate(): SMAPAndMethodNode {
private fun doGenerate(delegatedPropertyOptimizer: DelegatedPropertyOptimizer?): SMAPAndMethodNode {
val signature = context.methodSignatureMapper.mapSignatureWithGeneric(irFunction)
val flags = irFunction.calculateMethodFlags()
val methodNode = MethodNode(
@@ -103,7 +103,7 @@ class FunctionCodegen(
generateAnnotationDefaultValueIfNeeded(methodVisitor)
SMAP(listOf())
} else if (notForInline != null) {
val (originalNode, smap) = classCodegen.generateMethodNode(notForInline)
val (originalNode, smap) = classCodegen.generateMethodNode(notForInline, delegatedPropertyOptimizer)
originalNode.accept(MethodBodyVisitor(methodVisitor))
smap
} else {
@@ -112,7 +112,16 @@ class FunctionCodegen(
context.state.globalInlineContext.enterDeclaration(irFunction.suspendFunctionOriginal().descriptor)
try {
val adapter = InstructionAdapter(methodVisitor)
ExpressionCodegen(irFunction, signature, frameMap, adapter, classCodegen, inlinedInto, sourceMapper).generate()
ExpressionCodegen(
irFunction,
signature,
frameMap,
adapter,
classCodegen,
inlinedInto,
sourceMapper,
delegatedPropertyOptimizer,
).generate()
} finally {
context.state.globalInlineContext.exitDeclaration()
}
@@ -93,7 +93,7 @@ class IrSourceCompilerForInline(
get() = codegen.smap
override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode =
FunctionCodegen((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, codegen).generate()
FunctionCodegen((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, codegen).generate(codegen.delegatedPropertyOptimizer)
override fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor,
@@ -101,7 +101,7 @@ class IrSourceCompilerForInline(
callDefault: Boolean,
asmMethod: Method
): SMAPAndMethodNode {
return ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee)
return ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee, null)
}
override fun hasFinallyBlocks() = data.hasFinallyBlocks()
@@ -114,7 +114,7 @@ class IrSourceCompilerForInline(
override fun createCodegenForExternalFinallyBlockGenerationOnNonLocalReturn(finallyNode: MethodNode, curFinallyDepth: Int) =
ExpressionCodegen(
codegen.irFunction, codegen.signature, codegen.frameMap, InstructionAdapter(finallyNode), codegen.classCodegen,
codegen.inlinedInto, codegen.smap
codegen.inlinedInto, codegen.smap, codegen.delegatedPropertyOptimizer
).also {
it.finallyDepth = curFinallyDepth
}
@@ -0,0 +1,13 @@
// IGNORE_BACKEND_FIR: JVM_IR
import kotlin.reflect.KProperty
operator fun Int.provideDelegate(thiz: Any?, property: KProperty<*>): String = property.name
inline operator fun String.getValue(thiz: Any?, property: KProperty<*>): String = property.name
fun box(): String = with(42) {
val O by this
O
} + {
val K by ""
K
}()
@@ -0,0 +1,7 @@
import kotlin.reflect.KProperty
inline operator fun String.getValue(thiz: Any?, property: KProperty<*>): String = property.name
fun box(): String = object {
val OK by ""
}.OK
@@ -0,0 +1,10 @@
import kotlin.reflect.KProperty
inline operator fun String.getValue(thiz: Any?, property: KProperty<*>): String = property.name
fun box(): String {
class Local {
val OK by ""
}
return Local().OK
}
@@ -10798,6 +10798,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt");
}
@TestMetadata("kt40815.kt")
public void testKt40815() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815.kt");
}
@TestMetadata("kt40815_2.kt")
public void testKt40815_2() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_2.kt");
}
@TestMetadata("kt40815_3.kt")
public void testKt40815_3() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_3.kt");
}
@TestMetadata("lazy.kt")
public void testLazy() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt");
@@ -10798,6 +10798,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt");
}
@TestMetadata("kt40815.kt")
public void testKt40815() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815.kt");
}
@TestMetadata("kt40815_2.kt")
public void testKt40815_2() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_2.kt");
}
@TestMetadata("kt40815_3.kt")
public void testKt40815_3() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_3.kt");
}
@TestMetadata("lazy.kt")
public void testLazy() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt");
@@ -9573,6 +9573,21 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt");
}
@TestMetadata("kt40815.kt")
public void testKt40815() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815.kt");
}
@TestMetadata("kt40815_2.kt")
public void testKt40815_2() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_2.kt");
}
@TestMetadata("kt40815_3.kt")
public void testKt40815_3() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_3.kt");
}
@TestMetadata("lazy.kt")
public void testLazy() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt");
@@ -41,11 +41,6 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
}
@TestMetadata("annotatedObjectLiteral.kt")
public void testAnnotatedObjectLiteral() throws Exception {
runTest("compiler/testData/codegen/box/annotations/annotatedObjectLiteral.kt");
}
@TestMetadata("nestedAnnotation.kt")
public void testNestedAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/nestedAnnotation.kt");
@@ -8223,6 +8218,21 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt");
}
@TestMetadata("kt40815.kt")
public void testKt40815() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815.kt");
}
@TestMetadata("kt40815_2.kt")
public void testKt40815_2() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_2.kt");
}
@TestMetadata("kt40815_3.kt")
public void testKt40815_3() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_3.kt");
}
@TestMetadata("lazy.kt")
public void testLazy() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt");
@@ -41,11 +41,6 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
}
@TestMetadata("annotatedObjectLiteral.kt")
public void testAnnotatedObjectLiteral() throws Exception {
runTest("compiler/testData/codegen/box/annotations/annotatedObjectLiteral.kt");
}
@TestMetadata("nestedAnnotation.kt")
public void testNestedAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/nestedAnnotation.kt");
@@ -8223,6 +8218,21 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt");
}
@TestMetadata("kt40815.kt")
public void testKt40815() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815.kt");
}
@TestMetadata("kt40815_2.kt")
public void testKt40815_2() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_2.kt");
}
@TestMetadata("kt40815_3.kt")
public void testKt40815_3() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_3.kt");
}
@TestMetadata("lazy.kt")
public void testLazy() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt");
@@ -41,11 +41,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
}
@TestMetadata("annotatedObjectLiteral.kt")
public void testAnnotatedObjectLiteral() throws Exception {
runTest("compiler/testData/codegen/box/annotations/annotatedObjectLiteral.kt");
}
@TestMetadata("nestedAnnotation.kt")
public void testNestedAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/nestedAnnotation.kt");
@@ -8223,6 +8218,21 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/inSeparateModuleWithNonNullParameter.kt");
}
@TestMetadata("kt40815.kt")
public void testKt40815() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815.kt");
}
@TestMetadata("kt40815_2.kt")
public void testKt40815_2() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_2.kt");
}
@TestMetadata("kt40815_3.kt")
public void testKt40815_3() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/kt40815_3.kt");
}
@TestMetadata("lazy.kt")
public void testLazy() throws Exception {
runTest("compiler/testData/codegen/box/delegatedProperty/optimizedDelegatedProperties/lazy.kt");