From 8c9ad81c7674fbb84c6ba37d1cd59bc508672675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steven=20Sch=C3=A4fer?= Date: Tue, 20 Apr 2021 21:23:19 +0200 Subject: [PATCH] Psi2Ir: Fold constants when generating IR This is necessary to avoid stack overflow errors on large constant expressions. --- .../psi2ir/generators/PropertyGenerator.kt | 37 +++++++++++++------ .../ir/irText/declarations/kt29833.kt.txt | 2 +- .../ir/irText/declarations/kt29833.txt | 2 +- .../primitivesImplicitConversions.kt.txt | 6 +-- .../primitivesImplicitConversions.txt | 9 ++--- .../irText/stubs/constFromBuiltins.fir.kt.txt | 4 ++ .../ir/irText/stubs/constFromBuiltins.fir.txt | 11 ++++++ .../ir/irText/stubs/constFromBuiltins.kt | 1 - .../ir/irText/stubs/constFromBuiltins.kt.txt | 2 +- .../ir/irText/stubs/constFromBuiltins.txt | 3 +- .../ir/irText/stubs/simple.fir.kt.txt | 4 ++ .../testData/ir/irText/stubs/simple.fir.txt | 12 ++++++ compiler/testData/ir/irText/stubs/simple.kt | 1 - .../testData/ir/irText/stubs/simple.kt.txt | 2 +- compiler/testData/ir/irText/stubs/simple.txt | 4 +- 15 files changed, 69 insertions(+), 31 deletions(-) create mode 100644 compiler/testData/ir/irText/stubs/constFromBuiltins.fir.kt.txt create mode 100644 compiler/testData/ir/irText/stubs/constFromBuiltins.fir.txt create mode 100644 compiler/testData/ir/irText/stubs/simple.fir.kt.txt create mode 100644 compiler/testData/ir/irText/stubs/simple.fir.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt index 7f47b167afc..301e424f038 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/PropertyGenerator.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.psi2ir.generators +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyGetterDescriptorImpl @@ -110,7 +111,10 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio } else throw AssertionError("Property declared in primary constructor has no getter: $propertyDescriptor") irProperty.getter = - FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(getter, ktDeclarationContainer) + FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter( + getter, + ktDeclarationContainer + ) if (propertyDescriptor.isVar) { val setter = propertyDescriptor.setter @@ -130,7 +134,10 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio } else throw AssertionError("Property declared in primary constructor has no setter: $propertyDescriptor") irProperty.setter = - FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(setter, ktDeclarationContainer) + FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter( + setter, + ktDeclarationContainer + ) } irProperty.linkCorrespondingPropertySymbol() @@ -173,17 +180,25 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio irProperty.backingField = if (propertyDescriptor.actuallyHasBackingField(context.bindingContext)) generatePropertyBackingField(ktProperty, propertyDescriptor) { irField -> - ktProperty.initializer?.let { ktInitializer -> + ktProperty.initializer?.let evaluateInitializer@{ ktInitializer -> val compileTimeConst = propertyDescriptor.compileTimeInitializer - if (propertyDescriptor.isConst && compileTimeConst != null) - context.irFactory.createExpressionBody( - context.constantValueGenerator.generateConstantValueAsExpression( - ktInitializer.startOffsetSkippingComments, ktInitializer.endOffset, - compileTimeConst + if (compileTimeConst != null) { + val constantInfo = context.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, ktInitializer) + if (propertyDescriptor.isConst || + (constantInfo?.usesNonConstValAsConstant == false && + (!constantInfo.usesVariableAsConstant || + context.languageVersionSettings.supportsFeature(LanguageFeature.InlineConstVals))) + ) { + return@evaluateInitializer context.irFactory.createExpressionBody( + context.constantValueGenerator.generateConstantValueAsExpression( + ktInitializer.startOffsetSkippingComments, ktInitializer.endOffset, + compileTimeConst + ) ) - ) - else - declarationGenerator.generateInitializerBody(irField.symbol, ktInitializer) + } + } + + declarationGenerator.generateInitializerBody(irField.symbol, ktInitializer) } } else diff --git a/compiler/testData/ir/irText/declarations/kt29833.kt.txt b/compiler/testData/ir/irText/declarations/kt29833.kt.txt index 2d7eaf44ddf..dcfc5bc963f 100644 --- a/compiler/testData/ir/irText/declarations/kt29833.kt.txt +++ b/compiler/testData/ir/irText/declarations/kt29833.kt.txt @@ -12,7 +12,7 @@ object Definitions { get val ktValue: String - field = super.#CONSTANT + field = "constant" get } diff --git a/compiler/testData/ir/irText/declarations/kt29833.txt b/compiler/testData/ir/irText/declarations/kt29833.txt index b25fe902829..924e3ca4c34 100644 --- a/compiler/testData/ir/irText/declarations/kt29833.txt +++ b/compiler/testData/ir/irText/declarations/kt29833.txt @@ -19,7 +19,7 @@ FILE fqName:interop fileName:/Definitions.kt PROPERTY name:ktValue visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:ktValue type:kotlin.String visibility:private [final] EXPRESSION_BODY - GET_FIELD 'FIELD IR_EXTERNAL_JAVA_DECLARATION_STUB name:CONSTANT type:kotlin.String visibility:public [final,static]' type=kotlin.String origin=GET_PROPERTY + CONST String type=kotlin.String value="constant" FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> ($this:interop.Definitions) returnType:kotlin.String correspondingProperty: PROPERTY name:ktValue visibility:public modality:FINAL [val] $this: VALUE_PARAMETER name: type:interop.Definitions diff --git a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt.txt b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt.txt index b837b055c64..cc841fd738f 100644 --- a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt.txt +++ b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.kt.txt @@ -11,15 +11,15 @@ val test3: Byte get val test4: Long - field = 42.unaryMinus() + field = -42L get val test5: Short - field = 42.unaryMinus() + field = -42S get val test6: Byte - field = 42.unaryMinus() + field = -42B get fun test() { diff --git a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt index 6ad8eda1e07..35b5e73055c 100644 --- a/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt +++ b/compiler/testData/ir/irText/expressions/primitivesImplicitConversions.txt @@ -29,8 +29,7 @@ FILE fqName: fileName:/primitivesImplicitConversions.kt PROPERTY name:test4 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test4 type:kotlin.Long visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null - $this: CONST Int type=kotlin.Int value=42 + CONST Long type=kotlin.Long value=-42 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Long correspondingProperty: PROPERTY name:test4 visibility:public modality:FINAL [val] BLOCK_BODY @@ -39,8 +38,7 @@ FILE fqName: fileName:/primitivesImplicitConversions.kt PROPERTY name:test5 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test5 type:kotlin.Short visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null - $this: CONST Int type=kotlin.Int value=42 + CONST Short type=kotlin.Short value=-42 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Short correspondingProperty: PROPERTY name:test5 visibility:public modality:FINAL [val] BLOCK_BODY @@ -49,8 +47,7 @@ FILE fqName: fileName:/primitivesImplicitConversions.kt PROPERTY name:test6 visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test6 type:kotlin.Byte visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun unaryMinus (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null - $this: CONST Int type=kotlin.Int value=42 + CONST Byte type=kotlin.Byte value=-42 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Byte correspondingProperty: PROPERTY name:test6 visibility:public modality:FINAL [val] BLOCK_BODY diff --git a/compiler/testData/ir/irText/stubs/constFromBuiltins.fir.kt.txt b/compiler/testData/ir/irText/stubs/constFromBuiltins.fir.kt.txt new file mode 100644 index 00000000000..93fc677192d --- /dev/null +++ b/compiler/testData/ir/irText/stubs/constFromBuiltins.fir.kt.txt @@ -0,0 +1,4 @@ +val test: Int + field = Companion.() + get + diff --git a/compiler/testData/ir/irText/stubs/constFromBuiltins.fir.txt b/compiler/testData/ir/irText/stubs/constFromBuiltins.fir.txt new file mode 100644 index 00000000000..745e26fb074 --- /dev/null +++ b/compiler/testData/ir/irText/stubs/constFromBuiltins.fir.txt @@ -0,0 +1,11 @@ +FILE fqName: fileName:/constFromBuiltins.kt + PROPERTY name:test visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Int visibility:private [final,static] + EXPRESSION_BODY + CALL 'public final fun (): kotlin.Int declared in kotlin.Int.Companion' type=kotlin.Int origin=GET_PROPERTY + $this: GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlin.Any]' type=kotlin.Int.Companion + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int + correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Int visibility:private [final,static]' type=kotlin.Int origin=null diff --git a/compiler/testData/ir/irText/stubs/constFromBuiltins.kt b/compiler/testData/ir/irText/stubs/constFromBuiltins.kt index ae04771280b..9f6808fb8db 100644 --- a/compiler/testData/ir/irText/stubs/constFromBuiltins.kt +++ b/compiler/testData/ir/irText/stubs/constFromBuiltins.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // DUMP_EXTERNAL_CLASS: kotlin.Int val test = Int.MIN_VALUE \ No newline at end of file diff --git a/compiler/testData/ir/irText/stubs/constFromBuiltins.kt.txt b/compiler/testData/ir/irText/stubs/constFromBuiltins.kt.txt index 93fc677192d..767f8d8148f 100644 --- a/compiler/testData/ir/irText/stubs/constFromBuiltins.kt.txt +++ b/compiler/testData/ir/irText/stubs/constFromBuiltins.kt.txt @@ -1,4 +1,4 @@ val test: Int - field = Companion.() + field = -2147483648 get diff --git a/compiler/testData/ir/irText/stubs/constFromBuiltins.txt b/compiler/testData/ir/irText/stubs/constFromBuiltins.txt index 745e26fb074..fe841d6d5ed 100644 --- a/compiler/testData/ir/irText/stubs/constFromBuiltins.txt +++ b/compiler/testData/ir/irText/stubs/constFromBuiltins.txt @@ -2,8 +2,7 @@ FILE fqName: fileName:/constFromBuiltins.kt PROPERTY name:test visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Int visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun (): kotlin.Int declared in kotlin.Int.Companion' type=kotlin.Int origin=GET_PROPERTY - $this: GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Companion modality:FINAL visibility:public [companion] superTypes:[kotlin.Any]' type=kotlin.Int.Companion + CONST Int type=kotlin.Int value=-2147483648 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val] BLOCK_BODY diff --git a/compiler/testData/ir/irText/stubs/simple.fir.kt.txt b/compiler/testData/ir/irText/stubs/simple.fir.kt.txt new file mode 100644 index 00000000000..136cd737001 --- /dev/null +++ b/compiler/testData/ir/irText/stubs/simple.fir.kt.txt @@ -0,0 +1,4 @@ +val test: Int + field = 2.plus(other = 2) + get + diff --git a/compiler/testData/ir/irText/stubs/simple.fir.txt b/compiler/testData/ir/irText/stubs/simple.fir.txt new file mode 100644 index 00000000000..8e6abd0cb9a --- /dev/null +++ b/compiler/testData/ir/irText/stubs/simple.fir.txt @@ -0,0 +1,12 @@ +FILE fqName: fileName:/simple.kt + PROPERTY name:test visibility:public modality:FINAL [val] + FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Int visibility:private [final,static] + EXPRESSION_BODY + CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS + $this: CONST Int type=kotlin.Int value=2 + other: CONST Int type=kotlin.Int value=2 + FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int + correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val] + BLOCK_BODY + RETURN type=kotlin.Nothing from='public final fun (): kotlin.Int declared in ' + GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Int visibility:private [final,static]' type=kotlin.Int origin=null diff --git a/compiler/testData/ir/irText/stubs/simple.kt b/compiler/testData/ir/irText/stubs/simple.kt index 0178645a003..3de5bfcc2db 100644 --- a/compiler/testData/ir/irText/stubs/simple.kt +++ b/compiler/testData/ir/irText/stubs/simple.kt @@ -1,4 +1,3 @@ -// FIR_IDENTICAL // !DUMP_DEPENDENCIES val test = 2 + 2 \ No newline at end of file diff --git a/compiler/testData/ir/irText/stubs/simple.kt.txt b/compiler/testData/ir/irText/stubs/simple.kt.txt index 136cd737001..b3bb98d09a2 100644 --- a/compiler/testData/ir/irText/stubs/simple.kt.txt +++ b/compiler/testData/ir/irText/stubs/simple.kt.txt @@ -1,4 +1,4 @@ val test: Int - field = 2.plus(other = 2) + field = 4 get diff --git a/compiler/testData/ir/irText/stubs/simple.txt b/compiler/testData/ir/irText/stubs/simple.txt index 8e6abd0cb9a..af2c22ddc47 100644 --- a/compiler/testData/ir/irText/stubs/simple.txt +++ b/compiler/testData/ir/irText/stubs/simple.txt @@ -2,9 +2,7 @@ FILE fqName: fileName:/simple.kt PROPERTY name:test visibility:public modality:FINAL [val] FIELD PROPERTY_BACKING_FIELD name:test type:kotlin.Int visibility:private [final,static] EXPRESSION_BODY - CALL 'public final fun plus (other: kotlin.Int): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=PLUS - $this: CONST Int type=kotlin.Int value=2 - other: CONST Int type=kotlin.Int value=2 + CONST Int type=kotlin.Int value=4 FUN DEFAULT_PROPERTY_ACCESSOR name: visibility:public modality:FINAL <> () returnType:kotlin.Int correspondingProperty: PROPERTY name:test visibility:public modality:FINAL [val] BLOCK_BODY