IR KT-50039 don't initialize outer 'this' in delegating constructor

This commit is contained in:
Dmitry Petrov
2021-12-03 12:06:42 +03:00
committed by teamcity
parent 0f745032af
commit 7206c06d26
11 changed files with 82 additions and 2 deletions
@@ -22317,6 +22317,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@Test
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@Test
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {
@@ -68,8 +68,11 @@ class InnerClassesLowering(val context: BackendContext, private val innerClasses
if (blockBody !is IrBlockBody) throw AssertionError("Unexpected constructor body: ${irConstructor.body}")
loweredConstructor.body = context.irFactory.createBlockBody(blockBody.startOffset, blockBody.endOffset) {
context.createIrBuilder(irConstructor.symbol, irConstructor.startOffset, irConstructor.endOffset).apply {
statements.add(0, irSetField(irGet(irClass.thisReceiver!!), parentThisField, irGet(outerThisParameter)))
if (irConstructor.shouldInitializeOuterThis()) {
context.createIrBuilder(irConstructor.symbol, irConstructor.startOffset, irConstructor.endOffset).apply {
statements.add(0, irSetField(irGet(irClass.thisReceiver!!), parentThisField, irGet(outerThisParameter)))
}
}
statements.addAll(blockBody.statements)
@@ -90,6 +93,15 @@ class InnerClassesLowering(val context: BackendContext, private val innerClasses
return loweredConstructor
}
private fun IrConstructor.shouldInitializeOuterThis(): Boolean {
val irBlockBody = body as? IrBlockBody ?: return false
// Constructors are either delegating to a constructor of super class (and initializing an instance of this class),
// or delegating to a constructor of this class.
// Don't initialize outer 'this' in constructor delegating to this,
// otherwise final 'this$0' field will be initialized twice (in delegating constructor and in original constructor),
// which is legal, but causes a performance regression on JVM (KT-50039).
return irBlockBody.statements.any { it is IrInstanceInitializerCall }
}
}
private fun InnerClassesSupport.primaryConstructorParameterMap(originalConstructor: IrConstructor): Map<IrValueParameter, IrValueParameter> {
@@ -10,3 +10,8 @@ class A {
}
fun box() = A().box()
// CHECK_BYTECODE_TEXT
// 1 PUTFIELD A\$Inner\.this\$0 : LA;
// ^ A$Inner.this$0 SHOULD be written in primary constructor of A$Inner,
// and SHOULD NOT be written in corresponding default arguments stub.
@@ -0,0 +1,17 @@
class Outer(val outer: String) {
open inner class Inner(val inner: String) {
constructor() : this("K")
fun test() = outer + inner
}
fun obj(): Inner =
object : Inner() {}
}
fun box() = Outer("O").obj().test()
// CHECK_BYTECODE_TEXT
// 1 PUTFIELD Outer\$Inner\.this\$0 : LOuter;
// ^ Outer$Inner.this$0 SHOULD be written in primary constructor of Outer$Inner,
// and SHOULD NOT be written in delegating constructor.
@@ -21945,6 +21945,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@Test
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@Test
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {
@@ -22317,6 +22317,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@Test
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@Test
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {
@@ -18360,6 +18360,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt");
@@ -17507,6 +17507,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@Test
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@Test
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {
@@ -17471,6 +17471,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@Test
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@Test
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {
@@ -14807,6 +14807,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt");
@@ -18390,6 +18390,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt");
}
@Test
@TestMetadata("objectExtendsInnerWithDelegatingConstructor.kt")
public void testObjectExtendsInnerWithDelegatingConstructor() throws Exception {
runTest("compiler/testData/codegen/box/innerNested/superConstructorCall/objectExtendsInnerWithDelegatingConstructor.kt");
}
@Test
@TestMetadata("objectExtendsLocalCaptureInSuperCall.kt")
public void testObjectExtendsLocalCaptureInSuperCall() throws Exception {