[KLIB] Deserialize backing field initializers of const in IB-only mode

Missing const initializer leads to crash in property accessors inline
lowering during IC recompilation on JS.

 - fix #KT-50512
 - add test for JS IR IC
This commit is contained in:
Roman Artemev
2021-12-27 17:22:28 +03:00
parent 188d073cc3
commit 723ef8f1fb
4 changed files with 36 additions and 6 deletions
@@ -456,11 +456,11 @@ class IrDeclarationDeserializer(
} }
private fun IrField.withInitializerGuard(f: IrField.() -> Unit) { private fun IrField.withInitializerGuard(isConst: Boolean, f: IrField.() -> Unit) {
val oldBodiesPolicy = deserializeBodies val oldBodiesPolicy = deserializeBodies
try { try {
deserializeBodies = oldBodiesPolicy || type.checkObjectLeak() deserializeBodies = isConst || oldBodiesPolicy || type.checkObjectLeak()
f() f()
} finally { } finally {
deserializeBodies = oldBodiesPolicy deserializeBodies = oldBodiesPolicy
@@ -611,7 +611,7 @@ class IrDeclarationDeserializer(
} }
private fun deserializeIrField(proto: ProtoField): IrField = private fun deserializeIrField(proto: ProtoField, isConst: Boolean): IrField =
withDeserializedIrDeclarationBase(proto.base) { symbol, uniqId, startOffset, endOffset, origin, fcode -> withDeserializedIrDeclarationBase(proto.base) { symbol, uniqId, startOffset, endOffset, origin, fcode ->
checkSymbolType<IrFieldSymbol>(symbol) checkSymbolType<IrFieldSymbol>(symbol)
val nameType = BinaryNameAndType.decode(proto.nameType) val nameType = BinaryNameAndType.decode(proto.nameType)
@@ -633,7 +633,7 @@ class IrDeclarationDeserializer(
field.usingParent { field.usingParent {
if (proto.hasInitializer()) { if (proto.hasInitializer()) {
withInitializerGuard { withInitializerGuard(isConst) {
initializer = deserializeExpressionBody(proto.initializer) initializer = deserializeExpressionBody(proto.initializer)
} }
} }
@@ -699,7 +699,7 @@ class IrDeclarationDeserializer(
} }
} }
if (proto.hasBackingField()) { if (proto.hasBackingField()) {
backingField = deserializeIrField(proto.backingField).also { backingField = deserializeIrField(proto.backingField, prop.isConst).also {
it.correspondingPropertySymbol = symbol it.correspondingPropertySymbol = symbol
} }
} }
@@ -722,7 +722,7 @@ class IrDeclarationDeserializer(
val declaration: IrDeclaration = when (proto.declaratorCase!!) { val declaration: IrDeclaration = when (proto.declaratorCase!!) {
IR_ANONYMOUS_INIT -> deserializeIrAnonymousInit(proto.irAnonymousInit) IR_ANONYMOUS_INIT -> deserializeIrAnonymousInit(proto.irAnonymousInit)
IR_CONSTRUCTOR -> deserializeIrConstructor(proto.irConstructor) IR_CONSTRUCTOR -> deserializeIrConstructor(proto.irConstructor)
IR_FIELD -> deserializeIrField(proto.irField) IR_FIELD -> deserializeIrField(proto.irField, isConst = false)
IR_CLASS -> deserializeIrClass(proto.irClass) IR_CLASS -> deserializeIrClass(proto.irClass)
IR_FUNCTION -> deserializeIrFunction(proto.irFunction) IR_FUNCTION -> deserializeIrFunction(proto.irFunction)
IR_PROPERTY -> deserializeIrProperty(proto.irProperty) IR_PROPERTY -> deserializeIrProperty(proto.irProperty)
@@ -4150,6 +4150,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
runTest("js/js.translator/testData/box/incremental/classReferencingClass.kt"); runTest("js/js.translator/testData/box/incremental/classReferencingClass.kt");
} }
@Test
@TestMetadata("constValInInlineFun.kt")
public void testConstValInInlineFun() throws Exception {
runTest("js/js.translator/testData/box/incremental/constValInInlineFun.kt");
}
@Test @Test
@TestMetadata("coroutines.kt") @TestMetadata("coroutines.kt")
public void testCoroutines() throws Exception { public void testCoroutines() throws Exception {
@@ -4522,6 +4522,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
runTest("js/js.translator/testData/box/incremental/classReferencingClass.kt"); runTest("js/js.translator/testData/box/incremental/classReferencingClass.kt");
} }
@Test
@TestMetadata("constValInInlineFun.kt")
public void testConstValInInlineFun() throws Exception {
runTest("js/js.translator/testData/box/incremental/constValInInlineFun.kt");
}
@Test @Test
@TestMetadata("coroutines.kt") @TestMetadata("coroutines.kt")
public void testCoroutines() throws Exception { public void testCoroutines() throws Exception {
@@ -0,0 +1,18 @@
// NO_COMMON_FILES
// MODULE: lib
// FILE: lib.kt
const val FOO: String = "OK"
class B {
inline fun bar(): String {
return FOO // Constant property has to have a backing field with initializer
}
}
// MODULE: main(lib)
// FILE: main.kt
// RECOMPILE
fun box(): String {
return B().bar()
}