JVM IR: Don't generate line numbers and null checks in SAM wrapper constructors
This commit is contained in:
committed by
Alexander Udalov
parent
68e2d0d245
commit
8574cb4466
Generated
+5
@@ -4314,6 +4314,11 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("samWrapperConstructorNonSynthetic.kt")
|
||||||
|
public void testSamWrapperConstructorNonSynthetic() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperConstructorNonSynthetic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("samWrapperForNullInitialization.kt")
|
@TestMetadata("samWrapperForNullInitialization.kt")
|
||||||
public void testSamWrapperForNullInitialization() throws Exception {
|
public void testSamWrapperForNullInitialization() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullInitialization.kt");
|
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullInitialization.kt");
|
||||||
|
|||||||
+6
-2
@@ -69,6 +69,10 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
|||||||
protected open fun getWrappedFunctionType(klass: IrClass): IrType =
|
protected open fun getWrappedFunctionType(klass: IrClass): IrType =
|
||||||
klass.defaultType
|
klass.defaultType
|
||||||
|
|
||||||
|
protected open fun IrFunctionBuilder.setConstructorSourceRange(createFor: IrElement) {
|
||||||
|
setSourceRange(createFor)
|
||||||
|
}
|
||||||
|
|
||||||
abstract val IrType.needEqualsHashCodeMethods: Boolean
|
abstract val IrType.needEqualsHashCodeMethods: Boolean
|
||||||
|
|
||||||
open val inInlineFunctionScope get() = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false }
|
open val inInlineFunctionScope get() = allScopes.any { scope -> (scope.irElement as? IrFunction)?.isInline ?: false }
|
||||||
@@ -187,10 +191,10 @@ abstract class SingleAbstractMethodLowering(val context: CommonBackendContext) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
subclass.addConstructor {
|
subclass.addConstructor {
|
||||||
origin = subclass.origin
|
origin = IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION
|
||||||
isPrimary = true
|
isPrimary = true
|
||||||
visibility = wrapperVisibility
|
visibility = wrapperVisibility
|
||||||
setSourceRange(createFor)
|
setConstructorSourceRange(createFor)
|
||||||
}.apply {
|
}.apply {
|
||||||
val parameter = addValueParameter {
|
val parameter = addValueParameter {
|
||||||
name = field.name
|
name = field.name
|
||||||
|
|||||||
+6
-3
@@ -18,7 +18,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.isMultifileBridge
|
|||||||
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
|
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
import org.jetbrains.kotlin.codegen.AsmUtil.*
|
||||||
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.*
|
import org.jetbrains.kotlin.codegen.DescriptorAsmUtil.getNameForReceiverParameter
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.SuspensionPointKind
|
import org.jetbrains.kotlin.codegen.coroutines.SuspensionPointKind
|
||||||
import org.jetbrains.kotlin.codegen.coroutines.generateCoroutineSuspendedCheck
|
import org.jetbrains.kotlin.codegen.coroutines.generateCoroutineSuspendedCheck
|
||||||
import org.jetbrains.kotlin.codegen.inline.*
|
import org.jetbrains.kotlin.codegen.inline.*
|
||||||
@@ -48,7 +48,8 @@ import org.jetbrains.kotlin.ir.util.*
|
|||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind
|
||||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||||
@@ -285,7 +286,9 @@ class ExpressionCodegen(
|
|||||||
irFunction.origin.isSynthetic ||
|
irFunction.origin.isSynthetic ||
|
||||||
// TODO: refine this condition to not generate nullability assertions on parameters
|
// TODO: refine this condition to not generate nullability assertions on parameters
|
||||||
// corresponding to captured variables and anonymous object super constructor arguments
|
// corresponding to captured variables and anonymous object super constructor arguments
|
||||||
(irFunction is IrConstructor && irFunction.parentAsClass.isAnonymousObject) ||
|
(irFunction is IrConstructor &&
|
||||||
|
(irFunction.parentAsClass.isAnonymousObject ||
|
||||||
|
irFunction.parentAsClass.origin == IrDeclarationOrigin.GENERATED_SAM_IMPLEMENTATION)) ||
|
||||||
// TODO: Implement this as a lowering, so that we can more easily exclude generated methods.
|
// TODO: Implement this as a lowering, so that we can more easily exclude generated methods.
|
||||||
irFunction.origin == JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD ||
|
irFunction.origin == JvmLoweredDeclarationOrigin.INLINE_CLASS_GENERATED_IMPL_METHOD ||
|
||||||
// Although these are accessible from Java, the functions they bridge to already have the assertions.
|
// Although these are accessible from Java, the functions they bridge to already have the assertions.
|
||||||
|
|||||||
+10
@@ -12,6 +12,9 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
|||||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.rawType
|
import org.jetbrains.kotlin.backend.jvm.ir.rawType
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
|
import org.jetbrains.kotlin.ir.builders.declarations.IrFunctionBuilder
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
@@ -47,6 +50,13 @@ private class JvmSingleAbstractMethodLowering(context: JvmBackendContext) : Sing
|
|||||||
override fun getWrappedFunctionType(klass: IrClass): IrType =
|
override fun getWrappedFunctionType(klass: IrClass): IrType =
|
||||||
klass.symbol.rawType(context as JvmBackendContext)
|
klass.symbol.rawType(context as JvmBackendContext)
|
||||||
|
|
||||||
|
// The constructor of a SAM wrapper is non-synthetic and should not have line numbers.
|
||||||
|
// Otherwise the debugger will try to step into it.
|
||||||
|
override fun IrFunctionBuilder.setConstructorSourceRange(createFor: IrElement) {
|
||||||
|
startOffset = UNDEFINED_OFFSET
|
||||||
|
endOffset = UNDEFINED_OFFSET
|
||||||
|
}
|
||||||
|
|
||||||
private val IrType.isKotlinFunInterface: Boolean
|
private val IrType.isKotlinFunInterface: Boolean
|
||||||
get() = getClass()?.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
get() = getClass()?.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
||||||
|
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
// FILE: J.java
|
||||||
|
|
||||||
|
public class J {
|
||||||
|
public static void g(Runnable r) {
|
||||||
|
r.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
|
||||||
|
fun nonInlineFun() {
|
||||||
|
val f = {}
|
||||||
|
J.g(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun inlineFun() {
|
||||||
|
val f = {}
|
||||||
|
J.g(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The SAM wrapper constructor is public inside of inline functions.
|
||||||
|
// It has no other flags. In particular, it is not synthetic.
|
||||||
|
// 1 access flags 0x0\n\s*<init>\(Lkotlin/jvm/functions/Function0;\)V
|
||||||
|
// 1 access flags 0x1\n\s*public <init>\(Lkotlin/jvm/functions/Function0;\)V
|
||||||
@@ -4386,6 +4386,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("samWrapperConstructorNonSynthetic.kt")
|
||||||
|
public void testSamWrapperConstructorNonSynthetic() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperConstructorNonSynthetic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("samWrapperForNullInitialization.kt")
|
@TestMetadata("samWrapperForNullInitialization.kt")
|
||||||
public void testSamWrapperForNullInitialization() throws Exception {
|
public void testSamWrapperForNullInitialization() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullInitialization.kt");
|
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullInitialization.kt");
|
||||||
|
|||||||
+5
@@ -4314,6 +4314,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeText/sam"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("samWrapperConstructorNonSynthetic.kt")
|
||||||
|
public void testSamWrapperConstructorNonSynthetic() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperConstructorNonSynthetic.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("samWrapperForNullInitialization.kt")
|
@TestMetadata("samWrapperForNullInitialization.kt")
|
||||||
public void testSamWrapperForNullInitialization() throws Exception {
|
public void testSamWrapperForNullInitialization() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullInitialization.kt");
|
runTest("compiler/testData/codegen/bytecodeText/sam/samWrapperForNullInitialization.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user