Revert "JVM IR: Implement CHECK_NOT_NULL as a lowering"
This reverts commit dcd72b06d8.
Using a temporary variable has an effect on casts and GC.
This commit is contained in:
+6
@@ -3950,6 +3950,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("unitAsAny.kt")
|
@TestMetadata("unitAsAny.kt")
|
||||||
public void testUnitAsAny() throws Exception {
|
public void testUnitAsAny() throws Exception {
|
||||||
|
|||||||
@@ -326,7 +326,6 @@ private val jvmFilePhases = listOf(
|
|||||||
polymorphicSignaturePhase,
|
polymorphicSignaturePhase,
|
||||||
varargPhase,
|
varargPhase,
|
||||||
arrayConstructorPhase,
|
arrayConstructorPhase,
|
||||||
checkNotNullPhase,
|
|
||||||
|
|
||||||
lateinitNullableFieldsPhase,
|
lateinitNullableFieldsPhase,
|
||||||
lateinitDeclarationLoweringPhase,
|
lateinitDeclarationLoweringPhase,
|
||||||
|
|||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
||||||
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
|
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
|
import org.jetbrains.org.objectweb.asm.Label
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
|
private fun ExpressionCodegen.checkTopValueForNull() {
|
||||||
|
mv.dup()
|
||||||
|
if (state.unifiedNullChecks) {
|
||||||
|
mv.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "checkNotNull", "(Ljava/lang/Object;)V", false)
|
||||||
|
} else {
|
||||||
|
val ifNonNullLabel = Label()
|
||||||
|
mv.ifnonnull(ifNonNullLabel)
|
||||||
|
mv.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwNpe", "()V", false)
|
||||||
|
mv.mark(ifNonNullLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object IrCheckNotNull : IntrinsicMethod() {
|
||||||
|
override fun invoke(expression: IrFunctionAccessExpression, codegen: ExpressionCodegen, data: BlockInfo): PromisedValue? {
|
||||||
|
val arg0 = expression.getValueArgument(0)!!.accept(codegen, data)
|
||||||
|
if (AsmUtil.isPrimitive(arg0.type)) return arg0
|
||||||
|
return object : PromisedValue(codegen, arg0.type, expression.type) {
|
||||||
|
override fun materializeAt(target: Type, irTarget: IrType, castForReified: Boolean) =
|
||||||
|
arg0.materialized().also { codegen.checkTopValueForNull() }.materializeAt(target, irTarget, castForReified)
|
||||||
|
|
||||||
|
override fun discard() =
|
||||||
|
arg0.materialized().also { codegen.checkTopValueForNull() }.discard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -110,6 +110,7 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
|
|||||||
irBuiltIns.booleanNotSymbol.toKey()!! to Not,
|
irBuiltIns.booleanNotSymbol.toKey()!! to Not,
|
||||||
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
|
irBuiltIns.noWhenBranchMatchedExceptionSymbol.toKey()!! to IrNoWhenBranchMatchedException,
|
||||||
irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException,
|
irBuiltIns.illegalArgumentExceptionSymbol.toKey()!! to IrIllegalArgumentException,
|
||||||
|
irBuiltIns.checkNotNullSymbol.toKey()!! to IrCheckNotNull,
|
||||||
irBuiltIns.andandSymbol.toKey()!! to AndAnd,
|
irBuiltIns.andandSymbol.toKey()!! to AndAnd,
|
||||||
irBuiltIns.ororSymbol.toKey()!! to OrOr,
|
irBuiltIns.ororSymbol.toKey()!! to OrOr,
|
||||||
irBuiltIns.dataClassArrayMemberHashCodeSymbol.toKey()!! to IrDataClassArrayMemberHashCode,
|
irBuiltIns.dataClassArrayMemberHashCodeSymbol.toKey()!! to IrDataClassArrayMemberHashCode,
|
||||||
|
|||||||
-56
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
||||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.lower
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
|
||||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
|
||||||
|
|
||||||
internal val checkNotNullPhase = makeIrFilePhase(
|
|
||||||
::CheckNotNullLowering,
|
|
||||||
name = "CheckNotNullLowering",
|
|
||||||
description = "Lower calls to the CHECK_NOT_NULL intrinsic, which are generated by psi2ir for \"!!\" expressions."
|
|
||||||
)
|
|
||||||
|
|
||||||
private class CheckNotNullLowering(private val backendContext: JvmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() {
|
|
||||||
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid()
|
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
|
||||||
if (expression.symbol != backendContext.irBuiltIns.checkNotNullSymbol)
|
|
||||||
return super.visitCall(expression)
|
|
||||||
|
|
||||||
expression.transformChildrenVoid()
|
|
||||||
return backendContext.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset).irBlock {
|
|
||||||
val valueArgument = expression.getValueArgument(0)!!
|
|
||||||
|
|
||||||
// For a null-check on a variable we should not introduce a temporary, since null checks are
|
|
||||||
// optimized by RedundantNullCheckMethodTransformer, which remembers that the argument variable
|
|
||||||
// is non-nullable if this call succeeds.
|
|
||||||
val argument = if (valueArgument is IrGetValue) valueArgument.symbol.owner else irTemporary(valueArgument)
|
|
||||||
|
|
||||||
// Starting with Kotlin 1.4 null-checks are lowered to calls to the "checkNotNull" intrinsic, which
|
|
||||||
// throws a NullPointerException on failure. Prior to Kotlin 1.4 we instead inline the null-check and
|
|
||||||
// call the "throwNpe" intrinsic on failure which throws a KotlinNullPointerException.
|
|
||||||
if (backendContext.state.unifiedNullChecks) {
|
|
||||||
+irCall(backendContext.ir.symbols.checkNotNull).apply {
|
|
||||||
putValueArgument(0, irGet(argument))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
+irIfThen(irEqualsNull(irGet(argument)), irCall(backendContext.ir.symbols.throwNpe))
|
|
||||||
}
|
|
||||||
|
|
||||||
+irImplicitCast(irGet(argument), expression.type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
// IGNORE_BACKEND: JS, JS_IR, WASM
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <T> f() = 1L as T
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val x: Int = f()!! // T = Int?, but the cast succeeds because it's immediately upcasted to Number
|
||||||
|
return if (x == 1) "OK" else "fail: $x"
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
// NB '!!' uses Intrinsics.throwNpe/checkNotNull
|
// NB '!!' uses Intrinsics.throwNpe/checkNotNull, but IR follows it with ATHROW
|
||||||
|
// while the old backend returns null from `exit`
|
||||||
inline fun exit(): Nothing = null!!
|
inline fun exit(): Nothing = null!!
|
||||||
|
|
||||||
fun box(): String {
|
fun box(): String {
|
||||||
@@ -13,4 +14,7 @@ fun box(): String {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JVM_TEMPLATES
|
||||||
// 1 ATHROW
|
// 1 ATHROW
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 ATHROW
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
// NB '!!' uses Intrinsics.throwNpe/checkNotNull, but IR follows it with ATHROW
|
||||||
|
// while the old backend returns null from `exit`
|
||||||
inline fun exit(): Nothing = null!!
|
inline fun exit(): Nothing = null!!
|
||||||
inline fun exita(): Nothing = exit() // ATHROW
|
inline fun exita(): Nothing = exit() // ATHROW
|
||||||
inline fun exitb(): Nothing = exita() // ATHROW
|
inline fun exitb(): Nothing = exita() // ATHROW
|
||||||
@@ -14,4 +16,7 @@ fun box(): String {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4 ATHROW
|
// JVM_TEMPLATES
|
||||||
|
// 4 ATHROW
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 5 ATHROW
|
||||||
|
|||||||
+6
@@ -3950,6 +3950,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("unitAsAny.kt")
|
@TestMetadata("unitAsAny.kt")
|
||||||
public void testUnitAsAny() throws Exception {
|
public void testUnitAsAny() throws Exception {
|
||||||
|
|||||||
+6
@@ -3950,6 +3950,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("unitAsAny.kt")
|
@TestMetadata("unitAsAny.kt")
|
||||||
public void testUnitAsAny() throws Exception {
|
public void testUnitAsAny() throws Exception {
|
||||||
|
|||||||
+5
@@ -3450,6 +3450,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unitAsAny.kt")
|
@TestMetadata("unitAsAny.kt")
|
||||||
public void testUnitAsAny() throws Exception {
|
public void testUnitAsAny() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -2625,6 +2625,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unitAsAny.kt")
|
@TestMetadata("unitAsAny.kt")
|
||||||
public void testUnitAsAny() throws Exception {
|
public void testUnitAsAny() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
||||||
|
|||||||
Generated
+5
@@ -2625,6 +2625,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unitAsAny.kt")
|
@TestMetadata("unitAsAny.kt")
|
||||||
public void testUnitAsAny() throws Exception {
|
public void testUnitAsAny() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
||||||
|
|||||||
Generated
+5
@@ -2625,6 +2625,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
runTest("compiler/testData/codegen/box/casts/nullableSafeCastToTypeParameterWithInterfaceUpperBound.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("unitAsAny.kt")
|
@TestMetadata("unitAsAny.kt")
|
||||||
public void testUnitAsAny() throws Exception {
|
public void testUnitAsAny() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
runTest("compiler/testData/codegen/box/casts/unitAsAny.kt");
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -1820,6 +1820,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt");
|
runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectToPrimitiveWithAssertion.kt")
|
||||||
|
public void testObjectToPrimitiveWithAssertion() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/casts/objectToPrimitiveWithAssertion.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/casts/functions")
|
@TestMetadata("compiler/testData/codegen/box/casts/functions")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user