Don't do full type parameters erasure in PromisedValue::materializeAt

The only case when erasure matters in a context of materialization of
`PromisedValue` is when the type is a type parameter which upper bound
is an inline class. Since `PromisedValue::materializeAt` is a hot spot
and `eraseTypeParameters` is an expensive operation, we should not do
type erasure in other cases.
This commit is contained in:
vladislav.grechko
2023-08-28 16:12:52 +02:00
committed by Space Team
parent 5456ef3ad8
commit 8f2825506a
8 changed files with 58 additions and 13 deletions
@@ -23485,6 +23485,12 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("nonImmediateInlineClassUpperBound.kt")
public void testNonImmediateInlineClassUpperBound() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt");
}
@Test
@TestMetadata("nullableEqeqNonNull.kt")
public void testNullableEqeqNonNull() throws Exception {
@@ -23485,6 +23485,12 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("nonImmediateInlineClassUpperBound.kt")
public void testNonImmediateInlineClassUpperBound() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt");
}
@Test
@TestMetadata("nullableEqeqNonNull.kt")
public void testNullableEqeqNonNull() throws Exception {
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.backend.jvm.codegen
import org.jetbrains.kotlin.backend.jvm.InlineClassAbi
import org.jetbrains.kotlin.backend.jvm.inlineClassFieldName
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
import org.jetbrains.kotlin.backend.jvm.ir.eraseIfTypeParameter
import org.jetbrains.kotlin.backend.jvm.mapping.IrTypeMapper
import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.kotlin.codegen.StackValue
@@ -29,8 +29,8 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
// If this value is immaterial, construct an object on the top of the stack. This
// must always be done before generating other values or emitting raw bytecode.
open fun materializeAt(target: Type, irTarget: IrType, castForReified: Boolean) {
val erasedSourceType = irType.eraseTypeParameters()
val erasedTargetType = irTarget.eraseTypeParameters()
val erasedSourceType = irType.eraseIfTypeParameter()
val erasedTargetType = irTarget.eraseIfTypeParameter()
// Coerce inline classes
val isFromTypeUnboxed = InlineClassAbi.unboxType(erasedSourceType)?.let(typeMapper::mapType) == type
@@ -44,16 +44,7 @@ fun IrType.eraseTypeParameters(): IrType = when (this) {
IrSimpleTypeImpl(classifier, nullability, emptyList(), annotations)
}
is IrClass -> IrSimpleTypeImpl(classifier, nullability, arguments.map { it.eraseTypeParameters() }, annotations)
is IrTypeParameter -> {
val upperBound = owner.erasedUpperBound
IrSimpleTypeImpl(
upperBound.symbol,
isNullable(),
// Should not affect JVM signature, but may result in an invalid type object
List(upperBound.typeParameters.size) { IrStarProjectionImpl },
owner.annotations
)
}
is IrTypeParameter -> owner.erasedType(isNullable())
else -> error("Unknown IrSimpleType classifier kind: $owner")
}
is IrErrorType ->
@@ -61,6 +52,22 @@ fun IrType.eraseTypeParameters(): IrType = when (this) {
else -> error("Unknown IrType kind: $this")
}
fun IrType.eraseIfTypeParameter(): IrType {
val typeParameter = (this as? IrSimpleType)?.classifier?.owner as? IrTypeParameter ?: return this
return typeParameter.erasedType(isNullable())
}
private fun IrTypeParameter.erasedType(isNullable: Boolean): IrType {
val upperBound = erasedUpperBound
return IrSimpleTypeImpl(
upperBound.symbol,
isNullable,
// Should not affect JVM signature, but may result in an invalid type object
List(upperBound.typeParameters.size) { IrStarProjectionImpl },
annotations
)
}
private fun IrTypeArgument.eraseTypeParameters(): IrTypeArgument = when (this) {
is IrStarProjection -> this
is IrTypeProjection -> makeTypeProjection(type.eraseTypeParameters(), variance)
@@ -0,0 +1,9 @@
// TARGET_BACKEND: JVM_IR
// WITH_STDLIB
@JvmInline
value class Z(val value: String)
fun <T : U, U : Z> foo(t: T) = t.value
fun box() = foo(Z("OK"))
@@ -23485,6 +23485,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("nonImmediateInlineClassUpperBound.kt")
public void testNonImmediateInlineClassUpperBound() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt");
}
@Test
@TestMetadata("nullableEqeqNonNull.kt")
public void testNullableEqeqNonNull() throws Exception {
@@ -23485,6 +23485,12 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@Test
@TestMetadata("nonImmediateInlineClassUpperBound.kt")
public void testNonImmediateInlineClassUpperBound() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt");
}
@Test
@TestMetadata("nullableEqeqNonNull.kt")
public void testNullableEqeqNonNull() throws Exception {
@@ -19618,6 +19618,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/noReturnTypeManglingJvmNameGeneric.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());
}
@TestMetadata("nonImmediateInlineClassUpperBound.kt")
public void testNonImmediateInlineClassUpperBound() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/nonImmediateInlineClassUpperBound.kt");
}
@TestMetadata("nullableEqeqNonNull.kt")
public void testNullableEqeqNonNull() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/nullableEqeqNonNull.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());