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:
committed by
Space Team
parent
5456ef3ad8
commit
8f2825506a
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+3
-3
@@ -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)
|
||||
|
||||
+9
@@ -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"))
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+5
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user