JVM_IR: do not inherit delegated property trackers

This is no longer needed now that lambdas are generated before
`$$delegatedProperties`.
This commit is contained in:
pyos
2020-09-25 14:58:39 +02:00
committed by Alexander Udalov
parent 05c856f1f7
commit a6c62d3339
16 changed files with 97 additions and 40 deletions
@@ -1739,6 +1739,11 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -91,9 +91,12 @@ class ClassCodegen private constructor(
)
}
// TODO: the order of entries in this set depends on the order in which methods are generated; this means it is unstable
// under incremental compilation, as calls to `inline fun`s declared in this class cause them to be generated out of order.
private val innerClasses = linkedSetOf<IrClass>()
private var regeneratedObjectNameGenerators = mutableMapOf<String, NameGenerator>()
// TODO: the names produced by generators in this map depend on the order in which methods are generated; see above.
private val regeneratedObjectNameGenerators = mutableMapOf<String, NameGenerator>()
fun getRegeneratedObjectNameGenerator(function: IrFunction): NameGenerator {
val name = if (function.name.isSpecial) "special" else function.name.asString()
@@ -104,19 +107,15 @@ class ClassCodegen private constructor(
private var generated = false
fun generate(parentDelegatedPropertyTracker: DelegatedPropertyOptimizer? = null) {
fun generate() {
// 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
generated = true
// We remove unused cached KProperties.
val classDelegatedPropertiesArray = irClass.fields.singleOrNull {
it.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
}
val delegatedPropertyTracker =
if (classDelegatedPropertiesArray != null) DelegatedPropertyOptimizer() else parentDelegatedPropertyTracker
// We remove reads of `$$delegatedProperties` (and the field itself) if they are not in fact used for anything.
val delegatedProperties = irClass.fields.singleOrNull { it.origin == JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE }
val delegatedPropertyOptimizer = if (delegatedProperties != null) DelegatedPropertyOptimizer() else null
// Generating a method node may cause the addition of a field with an initializer if an inline function
// call uses `assert` and the JVM assertions mode is enabled. To avoid concurrent modification errors,
// there is a very specific generation order.
@@ -124,14 +123,14 @@ class ClassCodegen private constructor(
// 1. Any method other than `<clinit>` can add a field and a `<clinit>` statement:
for (method in irClass.declarations.filterIsInstance<IrFunction>()) {
if (method.name.asString() != "<clinit>") {
generateMethod(method, smap, delegatedPropertyTracker)
generateMethod(method, smap, delegatedPropertyOptimizer)
}
}
// 2. `<clinit>` itself can add a field, but the statement is generated via the `return init` hack:
irClass.functions.find { it.name.asString() == "<clinit>" }?.let { generateMethod(it, smap, delegatedPropertyTracker) }
irClass.functions.find { it.name.asString() == "<clinit>" }?.let { generateMethod(it, smap, delegatedPropertyOptimizer) }
// 3. Now we have all the fields (`$$delegatedProperties` might be redundant if all reads were optimized out):
for (field in irClass.fields) {
if (field !== classDelegatedPropertiesArray || delegatedPropertyTracker?.needsDelegatedProperties == true) {
if (field !== delegatedProperties || delegatedPropertyOptimizer?.needsDelegatedProperties == true) {
generateField(field)
}
}
@@ -139,7 +138,7 @@ class ClassCodegen private constructor(
// 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)
getOrCreate(declaration, context).generate()
}
}
@@ -313,14 +312,14 @@ class ClassCodegen private constructor(
private val generatedInlineMethods = mutableMapOf<IrFunction, SMAPAndMethodNode>()
fun generateMethodNode(method: IrFunction, delegatedPropertyOptimizer: DelegatedPropertyOptimizer?): SMAPAndMethodNode {
fun generateMethodNode(method: IrFunction): 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(delegatedPropertyOptimizer)
return FunctionCodegen(method, this).generate()
}
val (node, smap) = generatedInlineMethods.getOrPut(method) { FunctionCodegen(method, this).generate(delegatedPropertyOptimizer) }
val (node, smap) = generatedInlineMethods.getOrPut(method) { FunctionCodegen(method, this).generate() }
val copy = with(node) { MethodNode(Opcodes.API_VERSION, access, name, desc, signature, exceptions.toTypedArray()) }
node.instructions.resetLabels()
node.accept(copy)
@@ -333,7 +332,7 @@ class ClassCodegen private constructor(
return
}
val (node, smap) = generateMethodNode(method, delegatedPropertyOptimizer)
val (node, smap) = generateMethodNode(method)
if (delegatedPropertyOptimizer != null) {
delegatedPropertyOptimizer.transform(node)
if (method.name.asString() == "<clinit>") {
@@ -358,7 +357,7 @@ class ClassCodegen private constructor(
if (method.isSuspend) continuationClassCodegen.value.visitor else visitor
}
if (continuationClassCodegen.isInitialized() || method.alwaysNeedsContinuation()) {
continuationClassCodegen.value.generate(delegatedPropertyOptimizer)
continuationClassCodegen.value.generate()
}
} else {
node.accept(smapCopyingVisitor)
@@ -111,7 +111,6 @@ class ExpressionCodegen(
val classCodegen: ClassCodegen,
val inlinedInto: ExpressionCodegen?,
val smap: SourceMapper,
val delegatedPropertyOptimizer: DelegatedPropertyOptimizer?,
) : IrElementVisitor<PromisedValue, BlockInfo>, BaseExpressionCodegen {
var finallyDepth = 0
@@ -793,7 +792,7 @@ class ExpressionCodegen(
override fun visitClass(declaration: IrClass, data: BlockInfo): PromisedValue {
if (declaration.origin != JvmLoweredDeclarationOrigin.CONTINUATION_CLASS) {
val childCodegen = ClassCodegen.getOrCreate(declaration, context, generateSequence(this) { it.inlinedInto }.last().irFunction)
childCodegen.generate(delegatedPropertyOptimizer)
childCodegen.generate()
closureReifiedMarkers[declaration] = childCodegen.reifiedTypeParametersUsages
}
return unitValue
@@ -46,14 +46,14 @@ class FunctionCodegen(
) {
private val context = classCodegen.context
fun generate(delegatedPropertyOptimizer: DelegatedPropertyOptimizer?): SMAPAndMethodNode =
fun generate(): SMAPAndMethodNode =
try {
doGenerate(delegatedPropertyOptimizer)
doGenerate()
} catch (e: Throwable) {
throw RuntimeException("Exception while generating code for:\n${irFunction.dump()}", e)
}
private fun doGenerate(delegatedPropertyOptimizer: DelegatedPropertyOptimizer?): SMAPAndMethodNode {
private fun doGenerate(): SMAPAndMethodNode {
val signature = context.methodSignatureMapper.mapSignatureWithGeneric(irFunction)
val flags = irFunction.calculateMethodFlags()
val methodNode = MethodNode(
@@ -104,7 +104,7 @@ class FunctionCodegen(
generateAnnotationDefaultValueIfNeeded(methodVisitor)
SMAP(listOf())
} else if (notForInline != null) {
val (originalNode, smap) = classCodegen.generateMethodNode(notForInline, delegatedPropertyOptimizer)
val (originalNode, smap) = classCodegen.generateMethodNode(notForInline)
originalNode.accept(MethodBodyVisitor(methodVisitor))
smap
} else {
@@ -113,16 +113,7 @@ class FunctionCodegen(
context.state.globalInlineContext.enterDeclaration(irFunction.suspendFunctionOriginal().toIrBasedDescriptor())
try {
val adapter = InstructionAdapter(methodVisitor)
ExpressionCodegen(
irFunction,
signature,
frameMap,
adapter,
classCodegen,
inlinedInto,
sourceMapper,
delegatedPropertyOptimizer,
).generate()
ExpressionCodegen(irFunction, signature, frameMap, adapter, classCodegen, inlinedInto, sourceMapper).generate()
} finally {
context.state.globalInlineContext.exitDeclaration()
}
@@ -41,7 +41,7 @@ object IrInlineDefaultCodegen : IrInlineCallGenerator {
isInsideIfCondition: Boolean
) {
val function = expression.symbol.owner
val nodeAndSmap = codegen.classCodegen.generateMethodNode(function, codegen.delegatedPropertyOptimizer)
val nodeAndSmap = codegen.classCodegen.generateMethodNode(function)
val childSourceMapper = SourceMapCopier(codegen.smap, nodeAndSmap.classSMAP)
val argsSize =
@@ -94,16 +94,15 @@ class IrSourceCompilerForInline(
get() = codegen.smap
override fun generateLambdaBody(lambdaInfo: ExpressionLambda): SMAPAndMethodNode =
FunctionCodegen((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, codegen).generate(codegen.delegatedPropertyOptimizer)
FunctionCodegen((lambdaInfo as IrExpressionLambdaImpl).function, codegen.classCodegen, codegen).generate()
override fun doCreateMethodNodeFromSource(
callableDescriptor: FunctionDescriptor,
jvmSignature: JvmMethodSignature,
callDefault: Boolean,
asmMethod: Method
): SMAPAndMethodNode {
return ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee, null)
}
): SMAPAndMethodNode =
ClassCodegen.getOrCreate(callee.parentAsClass, codegen.context).generateMethodNode(callee)
override fun hasFinallyBlocks() = data.hasFinallyBlocks()
@@ -115,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.delegatedPropertyOptimizer
codegen.inlinedInto, codegen.smap
).also {
it.finallyDepth = curFinallyDepth
}
@@ -0,0 +1,19 @@
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_IR_AGAINST_OLD
// FILE: test.kt
package test
import kotlin.reflect.KProperty
inline operator fun String.getValue(t:Any?, p: KProperty<*>): String = p.name + this
object C {
inline fun inlineFun() = {
val O by "K"
O
}()
}
// FILE: box.kt
import test.*
fun box(): String = C.inlineFun()
@@ -1739,6 +1739,11 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1739,6 +1739,11 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1739,6 +1739,11 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1739,6 +1739,11 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1739,6 +1739,11 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1739,6 +1739,11 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1574,6 +1574,11 @@ public class IrJsCodegenInlineES6TestGenerated extends AbstractIrJsCodegenInline
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1574,6 +1574,11 @@ public class IrJsCodegenInlineTestGenerated extends AbstractIrJsCodegenInlineTes
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");
@@ -1574,6 +1574,11 @@ public class JsCodegenInlineTestGenerated extends AbstractJsCodegenInlineTest {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/local.kt");
}
@TestMetadata("localDeclaredInLambda.kt")
public void testLocalDeclaredInLambda() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localDeclaredInLambda.kt");
}
@TestMetadata("localInAnonymousObject.kt")
public void testLocalInAnonymousObject() throws Exception {
runTest("compiler/testData/codegen/boxInline/delegatedProperty/localInAnonymousObject.kt");