JVM_IR serializable indy method references
This commit is contained in:
committed by
teamcityserver
parent
eec16b83c6
commit
1dbbe22c8c
+148
@@ -23001,6 +23001,154 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Serializable {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipleTopLevelFunRefs.kt")
|
||||||
|
public void testMultipleTopLevelFunRefs() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/multipleTopLevelFunRefs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("sameImplMethodDifferentInterfaces.kt")
|
||||||
|
public void testSameImplMethodDifferentInterfaces() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/sameImplMethodDifferentInterfaces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundClassMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundInnerConstructorRef.kt")
|
||||||
|
public void testSerializableBoundInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRef.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRefPrimitiveReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableClassMemberFunRef.kt")
|
||||||
|
public void testSerializableClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableConstructorRef.kt")
|
||||||
|
public void testSerializableConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableFakeOverrideFunRef.kt")
|
||||||
|
public void testSerializableFakeOverrideFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableFakeOverrideFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableInnerConstructorRef.kt")
|
||||||
|
public void testSerializableInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableJavaStaticMethodRef.kt")
|
||||||
|
public void testSerializableJavaStaticMethodRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableJavaStaticMethodRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambda.kt")
|
||||||
|
public void testSerializableLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingBoxedInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingBoxedInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingBoxedInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassInt.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassInt() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassInt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingNullableInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingNullableInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingNullableInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaToKotlinInterface.kt")
|
||||||
|
public void testSerializableLambdaToKotlinInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaToKotlinInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaWithCapture.kt")
|
||||||
|
public void testSerializableLambdaWithCapture() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaWithCapture.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableTopLevelFunRef.kt")
|
||||||
|
public void testSerializableTopLevelFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableTopLevelFunRefAsGenericInterface.kt")
|
||||||
|
public void testSerializableTopLevelFunRefAsGenericInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRefAsGenericInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableWithBridge.kt")
|
||||||
|
public void testSerializableWithBridge() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableWithBridge.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+1
@@ -504,6 +504,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
|||||||
putValueArgument(1, lambdaMetafactoryArguments.implMethodReference)
|
putValueArgument(1, lambdaMetafactoryArguments.implMethodReference)
|
||||||
putValueArgument(2, irRawFunctionRef(lambdaMetafactoryArguments.fakeInstanceMethod))
|
putValueArgument(2, irRawFunctionRef(lambdaMetafactoryArguments.fakeInstanceMethod))
|
||||||
putValueArgument(3, irVarargOfRawFunctionRefs(lambdaMetafactoryArguments.extraOverriddenMethods))
|
putValueArgument(3, irVarargOfRawFunctionRefs(lambdaMetafactoryArguments.extraOverriddenMethods))
|
||||||
|
putValueArgument(4, irBoolean(lambdaMetafactoryArguments.shouldBeSerializable))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+328
-46
@@ -10,12 +10,20 @@ import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
|||||||
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
import org.jetbrains.kotlin.backend.common.lower.IrBuildingTransformer
|
||||||
import org.jetbrains.kotlin.backend.common.lower.at
|
import org.jetbrains.kotlin.backend.common.lower.at
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irNot
|
import org.jetbrains.kotlin.backend.common.lower.irNot
|
||||||
|
import org.jetbrains.kotlin.backend.common.lower.irThrow
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
|
import org.jetbrains.kotlin.backend.common.push
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.fileParent
|
import org.jetbrains.kotlin.backend.jvm.codegen.fileParent
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.generateMethodHandle
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.intrinsics.getBooleanConstArgument
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.unboxInlineClass
|
||||||
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||||
@@ -26,13 +34,11 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.types.*
|
||||||
import org.jetbrains.kotlin.ir.util.defaultType
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.org.objectweb.asm.Handle
|
import org.jetbrains.org.objectweb.asm.Handle
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
@@ -101,35 +107,29 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
|||||||
|
|
||||||
private val jvmIndyLambdaMetafactoryIntrinsic = context.ir.symbols.indyLambdaMetafactoryIntrinsic
|
private val jvmIndyLambdaMetafactoryIntrinsic = context.ir.symbols.indyLambdaMetafactoryIntrinsic
|
||||||
|
|
||||||
private val indyIntrinsic = context.ir.symbols.jvmIndyIntrinsic
|
private fun JvmIrBuilder.jvmMethodHandle(handle: Handle) =
|
||||||
|
irCall(backendContext.ir.symbols.jvmMethodHandle).apply {
|
||||||
|
putValueArgument(0, irInt(handle.tag))
|
||||||
|
putValueArgument(1, irString(handle.owner))
|
||||||
|
putValueArgument(2, irString(handle.name))
|
||||||
|
putValueArgument(3, irString(handle.desc))
|
||||||
|
putValueArgument(4, irBoolean(handle.isInterface))
|
||||||
|
}
|
||||||
|
|
||||||
private fun IrBuilderWithScope.jvmInvokeDynamic(
|
private fun JvmIrBuilder.jvmInvokeDynamic(
|
||||||
dynamicCall: IrCall,
|
dynamicCall: IrCall,
|
||||||
bootstrapMethod: Handle,
|
bootstrapMethodHandle: Handle,
|
||||||
bootstrapMethodArguments: List<IrExpression>
|
bootstrapMethodArguments: List<IrExpression>
|
||||||
) =
|
) =
|
||||||
irCall(indyIntrinsic, dynamicCall.type).apply {
|
irCall(backendContext.ir.symbols.jvmIndyIntrinsic, dynamicCall.type).apply {
|
||||||
putTypeArgument(0, dynamicCall.type)
|
putTypeArgument(0, dynamicCall.type)
|
||||||
putValueArgument(0, dynamicCall)
|
putValueArgument(0, dynamicCall)
|
||||||
putValueArgument(1, irInt(bootstrapMethod.tag))
|
putValueArgument(1, jvmMethodHandle(bootstrapMethodHandle))
|
||||||
putValueArgument(2, irString(bootstrapMethod.owner))
|
putValueArgument(2, irVararg(context.irBuiltIns.anyType, bootstrapMethodArguments))
|
||||||
putValueArgument(3, irString(bootstrapMethod.name))
|
|
||||||
putValueArgument(4, irString(bootstrapMethod.desc))
|
|
||||||
putValueArgument(5, irVararg(context.irBuiltIns.anyType, bootstrapMethodArguments))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val originalMethodTypeIntrinsic = context.ir.symbols.jvmOriginalMethodTypeIntrinsic
|
private fun JvmIrBuilder.jvmOriginalMethodType(methodSymbol: IrFunctionSymbol) =
|
||||||
private val substitutedMethodTypeIntrinsic = context.ir.symbols.jvmSubstitutedMethodTypeIntrinsic
|
irCall(backendContext.ir.symbols.jvmOriginalMethodTypeIntrinsic, context.irBuiltIns.anyType).apply {
|
||||||
|
|
||||||
private fun IrBuilderWithScope.jvmOriginalMethodType(methodSymbol: IrFunctionSymbol) =
|
|
||||||
irCall(originalMethodTypeIntrinsic, context.irBuiltIns.anyType).apply {
|
|
||||||
putValueArgument(0, irRawFunctionReferefence(context.irBuiltIns.anyType, methodSymbol))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
private fun IrBuilderWithScope.jvmSubstitutedMethodType(ownerType: IrType, methodSymbol: IrFunctionSymbol) =
|
|
||||||
irCall(substitutedMethodTypeIntrinsic, context.irBuiltIns.anyType).apply {
|
|
||||||
putTypeArgument(0, ownerType)
|
|
||||||
putValueArgument(0, irRawFunctionReferefence(context.irBuiltIns.anyType, methodSymbol))
|
putValueArgument(0, irRawFunctionReferefence(context.irBuiltIns.anyType, methodSymbol))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,6 +179,236 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class SerializableMethodRefInfo(
|
||||||
|
val samType: IrType,
|
||||||
|
val samMethodSymbol: IrSimpleFunctionSymbol,
|
||||||
|
val implFunSymbol: IrFunctionSymbol,
|
||||||
|
val instanceFunSymbol: IrFunctionSymbol,
|
||||||
|
val requiredBridges: Collection<IrSimpleFunction>,
|
||||||
|
val dynamicCallSymbol: IrSimpleFunctionSymbol
|
||||||
|
)
|
||||||
|
|
||||||
|
private class ClassContext {
|
||||||
|
val serializableMethodRefInfos = ArrayList<SerializableMethodRefInfo>()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val classContextStack = ArrayDeque<ClassContext>()
|
||||||
|
|
||||||
|
private fun enterClass(): ClassContext {
|
||||||
|
return ClassContext().also {
|
||||||
|
classContextStack.push(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun leaveClass() {
|
||||||
|
classContextStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getClassContext(): ClassContext {
|
||||||
|
if (classContextStack.isEmpty()) {
|
||||||
|
throw AssertionError("No class context")
|
||||||
|
}
|
||||||
|
return classContextStack.last()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass): IrStatement {
|
||||||
|
val context = enterClass()
|
||||||
|
val result = super.visitClass(declaration)
|
||||||
|
if (context.serializableMethodRefInfos.isNotEmpty()) {
|
||||||
|
generateDeserializeLambdaMethod(declaration, context.serializableMethodRefInfos)
|
||||||
|
}
|
||||||
|
leaveClass()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private data class DeserializedLambdaInfo(
|
||||||
|
val functionalInterfaceClass: String,
|
||||||
|
val implMethodHandle: Handle,
|
||||||
|
val functionalInterfaceMethod: Method
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun generateDeserializeLambdaMethod(
|
||||||
|
irClass: IrClass,
|
||||||
|
serializableMethodRefInfos: List<SerializableMethodRefInfo>
|
||||||
|
) {
|
||||||
|
// fun `$deserializeLambda$`(lambda: java.lang.invoke.SerializedLambda): Object {
|
||||||
|
// val tmp = lambda.getImplMethodName()
|
||||||
|
// when {
|
||||||
|
// ...
|
||||||
|
// tmp == NAME_i -> {
|
||||||
|
// when {
|
||||||
|
// ...
|
||||||
|
// lambda.getImplMethodKind() == [LAMBDA_i_k].implMethodKind &&
|
||||||
|
// lambda.getFunctionalInterfaceClass() == [LAMBDA_i_k].functionalInterfaceClass &&
|
||||||
|
// lambda.getFunctionalInterfaceMethodName() == [LAMBDA_i_k].functionalInterfaceMethodName &&
|
||||||
|
// lambda.getFunctionalInterfaceMethodSignature() == [LAMBDA_i_k].functionalInterfaceMethodSignature &&
|
||||||
|
// lambda.getImplClass() == [LAMBDA_i_k].implClass &&
|
||||||
|
// lambda.getImplMethodSignature() = [LAMBDA_i_k].implMethodSignature ->
|
||||||
|
// `<jvm-indy>`([LAMBDA_i_k])
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// ...
|
||||||
|
// }
|
||||||
|
// throw IllegalArgumentException("Invalid lambda deserialization")
|
||||||
|
// }
|
||||||
|
|
||||||
|
val groupedByImplMethodName = HashMap<String, HashMap<DeserializedLambdaInfo, SerializableMethodRefInfo>>()
|
||||||
|
for (serializableMethodRefInfo in serializableMethodRefInfos) {
|
||||||
|
val deserializedLambdaInfo = mapDeserializedLambda(serializableMethodRefInfo)
|
||||||
|
val implMethodName = deserializedLambdaInfo.implMethodHandle.name
|
||||||
|
val byDeserializedLambdaInfo = groupedByImplMethodName.getOrPut(implMethodName) { HashMap() }
|
||||||
|
byDeserializedLambdaInfo[deserializedLambdaInfo] = serializableMethodRefInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
val deserializeLambdaFun = context.irFactory.buildFun {
|
||||||
|
name = Name.identifier("\$deserializeLambda\$")
|
||||||
|
visibility = DescriptorVisibilities.PRIVATE
|
||||||
|
}
|
||||||
|
deserializeLambdaFun.parent = irClass
|
||||||
|
val lambdaParameter = deserializeLambdaFun.addValueParameter("lambda", context.ir.symbols.serializedLambda.irType)
|
||||||
|
deserializeLambdaFun.returnType = context.irBuiltIns.anyType
|
||||||
|
deserializeLambdaFun.body = context.createJvmIrBuilder(deserializeLambdaFun.symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET).run {
|
||||||
|
irBlockBody {
|
||||||
|
val tmp = irTemporary(
|
||||||
|
irCall(backendContext.ir.symbols.serializedLambda.getImplMethodName).apply {
|
||||||
|
dispatchReceiver = irGet(lambdaParameter)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
+irWhen(
|
||||||
|
backendContext.irBuiltIns.unitType,
|
||||||
|
groupedByImplMethodName.entries.map { (implMethodName, infos) ->
|
||||||
|
irBranch(
|
||||||
|
irEquals(irGet(tmp), irString(implMethodName)),
|
||||||
|
irWhen(
|
||||||
|
backendContext.irBuiltIns.unitType,
|
||||||
|
infos.entries.map { (deserializedLambdaInfo, serializedMethodRefInfo) ->
|
||||||
|
irBranch(
|
||||||
|
generateSerializedLambdaEquals(lambdaParameter, deserializedLambdaInfo),
|
||||||
|
irReturn(generateCreateDeserializedMethodRef(lambdaParameter, serializedMethodRefInfo))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
+irThrow(
|
||||||
|
irCall(backendContext.ir.symbols.illegalArgumentExceptionCtorString).also { ctorCall ->
|
||||||
|
ctorCall.putValueArgument(
|
||||||
|
0,
|
||||||
|
// Replace argument with:
|
||||||
|
// irCall(backendContext.irBuiltIns.anyClass.getSimpleFunction("toString")!!).apply {
|
||||||
|
// dispatchReceiver = irGet(lambdaParameter)
|
||||||
|
// }
|
||||||
|
// for debugging "Invalid lambda deserialization" exceptions.
|
||||||
|
irString("Invalid lambda deserialization")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
irClass.declarations.add(deserializeLambdaFun)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun mapDeserializedLambda(info: SerializableMethodRefInfo) =
|
||||||
|
DeserializedLambdaInfo(
|
||||||
|
functionalInterfaceClass = context.typeMapper.mapType(info.samType).internalName,
|
||||||
|
implMethodHandle = generateMethodHandle(context, info.implFunSymbol.owner),
|
||||||
|
functionalInterfaceMethod = context.methodSignatureMapper.mapAsmMethod(info.samMethodSymbol.owner)
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun JvmIrBuilder.generateSerializedLambdaEquals(
|
||||||
|
lambdaParameter: IrValueParameter,
|
||||||
|
deserializedLambdaInfo: DeserializedLambdaInfo
|
||||||
|
): IrExpression {
|
||||||
|
val functionalInterfaceClass = deserializedLambdaInfo.functionalInterfaceClass
|
||||||
|
val implMethodHandle = deserializedLambdaInfo.implMethodHandle
|
||||||
|
val samMethod = deserializedLambdaInfo.functionalInterfaceMethod
|
||||||
|
|
||||||
|
fun irGetLambdaProperty(getter: IrSimpleFunction) =
|
||||||
|
irCall(getter).apply { dispatchReceiver = irGet(lambdaParameter) }
|
||||||
|
|
||||||
|
return irAndAnd(
|
||||||
|
irEquals(
|
||||||
|
irGetLambdaProperty(backendContext.ir.symbols.serializedLambda.getImplMethodKind),
|
||||||
|
irInt(implMethodHandle.tag)
|
||||||
|
),
|
||||||
|
irObjectEquals(
|
||||||
|
irGetLambdaProperty(backendContext.ir.symbols.serializedLambda.getFunctionalInterfaceClass),
|
||||||
|
irString(functionalInterfaceClass)
|
||||||
|
),
|
||||||
|
irObjectEquals(
|
||||||
|
irGetLambdaProperty(backendContext.ir.symbols.serializedLambda.getFunctionalInterfaceMethodName),
|
||||||
|
irString(samMethod.name)
|
||||||
|
),
|
||||||
|
irObjectEquals(
|
||||||
|
irGetLambdaProperty(backendContext.ir.symbols.serializedLambda.getFunctionalInterfaceMethodSignature),
|
||||||
|
irString(samMethod.descriptor)
|
||||||
|
),
|
||||||
|
irObjectEquals(
|
||||||
|
irGetLambdaProperty(backendContext.ir.symbols.serializedLambda.getImplClass),
|
||||||
|
irString(implMethodHandle.owner)
|
||||||
|
),
|
||||||
|
irObjectEquals(
|
||||||
|
irGetLambdaProperty(backendContext.ir.symbols.serializedLambda.getImplMethodSignature),
|
||||||
|
irString(implMethodHandle.desc)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val equalsAny = context.irBuiltIns.anyClass.getSimpleFunction("equals")!!
|
||||||
|
|
||||||
|
private fun JvmIrBuilder.irObjectEquals(receiver: IrExpression, arg: IrExpression) =
|
||||||
|
irCall(equalsAny).apply {
|
||||||
|
dispatchReceiver = receiver
|
||||||
|
putValueArgument(0, arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JvmIrBuilder.irAndAnd(vararg args: IrExpression): IrExpression {
|
||||||
|
if (args.isEmpty()) throw AssertionError("At least one argument expected")
|
||||||
|
var result = args[0]
|
||||||
|
for (i in 1 until args.size) {
|
||||||
|
result = irCall(backendContext.irBuiltIns.andandSymbol).apply {
|
||||||
|
putValueArgument(0, result)
|
||||||
|
putValueArgument(1, args[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JvmIrBuilder.generateCreateDeserializedMethodRef(
|
||||||
|
lambdaParameter: IrValueParameter,
|
||||||
|
info: SerializableMethodRefInfo
|
||||||
|
): IrExpression {
|
||||||
|
val dynamicCall = irCall(info.dynamicCallSymbol)
|
||||||
|
for ((index, dynamicValueParameter) in info.dynamicCallSymbol.owner.valueParameters.withIndex()) {
|
||||||
|
val capturedArg = irCall(backendContext.ir.symbols.serializedLambda.getCapturedArg).also { call ->
|
||||||
|
call.dispatchReceiver = irGet(lambdaParameter)
|
||||||
|
call.putValueArgument(0, irInt(index))
|
||||||
|
}
|
||||||
|
val expectedType = dynamicValueParameter.type
|
||||||
|
val downcastArg =
|
||||||
|
if (expectedType.isInlineClassType()) {
|
||||||
|
// Inline class type arguments are stored as their underlying representation.
|
||||||
|
val unboxedType = expectedType.unboxInlineClass()
|
||||||
|
irCall(backendContext.ir.symbols.unsafeCoerceIntrinsic).also { coercion ->
|
||||||
|
coercion.putTypeArgument(0, unboxedType)
|
||||||
|
coercion.putTypeArgument(1, expectedType)
|
||||||
|
coercion.putValueArgument(0, capturedArg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
irAs(capturedArg, expectedType)
|
||||||
|
}
|
||||||
|
dynamicCall.putValueArgument(index, downcastArg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return createLambdaMetafactoryCall(
|
||||||
|
info.samMethodSymbol, info.implFunSymbol, info.instanceFunSymbol, true, info.requiredBridges, dynamicCall
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see FunctionReferenceLowering.wrapWithIndySamConversion
|
* @see FunctionReferenceLowering.wrapWithIndySamConversion
|
||||||
*/
|
*/
|
||||||
@@ -211,6 +441,8 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val shouldBeSerializable = call.getBooleanConstArgument(4)
|
||||||
|
|
||||||
val samMethod = samMethodRef.symbol.owner as? IrSimpleFunction
|
val samMethod = samMethodRef.symbol.owner as? IrSimpleFunction
|
||||||
?: fail("SAM method is expected to be 'IrSimpleFunction': ${samMethodRef.symbol.owner.render()}")
|
?: fail("SAM method is expected to be 'IrSimpleFunction': ${samMethodRef.symbol.owner.render()}")
|
||||||
val instanceMethod = instanceMethodRef.symbol.owner as? IrSimpleFunction
|
val instanceMethod = instanceMethodRef.symbol.owner as? IrSimpleFunction
|
||||||
@@ -220,30 +452,80 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil
|
|||||||
|
|
||||||
val requiredBridges = getOverriddenMethodsRequiringBridges(instanceMethod, samMethod, extraOverriddenMethods)
|
val requiredBridges = getOverriddenMethodsRequiringBridges(instanceMethod, samMethod, extraOverriddenMethods)
|
||||||
|
|
||||||
return context.createJvmIrBuilder(implFunSymbol, startOffset, endOffset).run {
|
if (shouldBeSerializable) {
|
||||||
val samMethodType = jvmOriginalMethodType(samMethod.symbol)
|
getClassContext().serializableMethodRefInfos.add(
|
||||||
val irRawFunRef = irRawFunctionReferefence(implFunRef.type, implFunSymbol)
|
SerializableMethodRefInfo(
|
||||||
val instanceMethodType = jvmOriginalMethodType(instanceMethodRef.symbol)
|
samType, samMethod.symbol, implFunSymbol, instanceMethodRef.symbol, requiredBridges, dynamicCall.symbol
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (requiredBridges.isNotEmpty()) {
|
return context.createJvmIrBuilder(implFunSymbol, startOffset, endOffset)
|
||||||
val bridgeMethodTypes = requiredBridges.map { jvmOriginalMethodType(it.symbol) }
|
.createLambdaMetafactoryCall(
|
||||||
jvmInvokeDynamic(
|
samMethod.symbol, implFunSymbol, instanceMethodRef.symbol, shouldBeSerializable, requiredBridges, dynamicCall
|
||||||
dynamicCall,
|
)
|
||||||
jdkAltMetafactoryHandle,
|
}
|
||||||
listOf(
|
|
||||||
samMethodType, irRawFunRef, instanceMethodType,
|
private fun JvmIrBuilder.createLambdaMetafactoryCall(
|
||||||
irInt(LambdaMetafactory.FLAG_BRIDGES),
|
samMethodSymbol: IrSimpleFunctionSymbol,
|
||||||
irInt(requiredBridges.size)
|
implFunSymbol: IrFunctionSymbol,
|
||||||
) + bridgeMethodTypes
|
instanceMethodSymbol: IrFunctionSymbol,
|
||||||
)
|
shouldBeSerializable: Boolean,
|
||||||
} else {
|
requiredBridges: Collection<IrSimpleFunction>,
|
||||||
jvmInvokeDynamic(
|
dynamicCall: IrCall
|
||||||
dynamicCall,
|
): IrCall {
|
||||||
jdkMetafactoryHandle,
|
val samMethodType = jvmOriginalMethodType(samMethodSymbol)
|
||||||
listOf(samMethodType, irRawFunRef, instanceMethodType)
|
val implFunRawRef = irRawFunctionReferefence(context.irBuiltIns.anyType, implFunSymbol)
|
||||||
)
|
val instanceMethodType = jvmOriginalMethodType(instanceMethodSymbol)
|
||||||
|
|
||||||
|
var bootstrapMethod = jdkMetafactoryHandle
|
||||||
|
val bootstrapMethodArguments = arrayListOf<IrExpression>(
|
||||||
|
samMethodType,
|
||||||
|
implFunRawRef,
|
||||||
|
instanceMethodType
|
||||||
|
)
|
||||||
|
var bridgeMethodTypes = emptyList<IrExpression>()
|
||||||
|
|
||||||
|
var flags = 0
|
||||||
|
|
||||||
|
if (shouldBeSerializable) {
|
||||||
|
flags += LambdaMetafactory.FLAG_SERIALIZABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredBridges.isNotEmpty()) {
|
||||||
|
flags += LambdaMetafactory.FLAG_BRIDGES
|
||||||
|
bridgeMethodTypes = requiredBridges.map { jvmOriginalMethodType(it.symbol) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags != 0) {
|
||||||
|
bootstrapMethod = jdkAltMetafactoryHandle
|
||||||
|
// Bootstrap arguments for LambdaMetafactory#altMetafactory should be:
|
||||||
|
// MethodType samMethodType,
|
||||||
|
// MethodHandle implMethod,
|
||||||
|
// MethodType instantiatedMethodType,
|
||||||
|
// // ---------------------------- same as LambdaMetafactory#metafactory until here
|
||||||
|
// int flags, // combination of LambdaMetafactory.{ FLAG_SERIALIZABLE, FLAG_MARKERS, FLAG_BRIDGES }
|
||||||
|
// int markerInterfaceCount, // IF flags has MARKERS set
|
||||||
|
// Class... markerInterfaces, // IF flags has MARKERS set
|
||||||
|
// int bridgeCount, // IF flags has BRIDGES set
|
||||||
|
// MethodType... bridges // IF flags has BRIDGES set
|
||||||
|
|
||||||
|
// `flags`
|
||||||
|
bootstrapMethodArguments.add(irInt(flags))
|
||||||
|
|
||||||
|
// `markerInterfaceCount`, `markerInterfaces`
|
||||||
|
// Currently, it looks like there's no way a Kotlin function expression should be SAM-converted to a type implementing
|
||||||
|
// additional marker interfaces (such as `Runnable r = (Runnable & Marker) () -> { ... }` in Java).
|
||||||
|
// If such additional marker interfaces would appear, they should go here, between `flags` and `bridgeCount`.
|
||||||
|
|
||||||
|
if (bridgeMethodTypes.isNotEmpty()) {
|
||||||
|
// `bridgeCount`, `bridges`
|
||||||
|
bootstrapMethodArguments.add(irInt(bridgeMethodTypes.size))
|
||||||
|
bootstrapMethodArguments.addAll(bridgeMethodTypes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return jvmInvokeDynamic(dynamicCall, bootstrapMethod, bootstrapMethodArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOverriddenMethodsRequiringBridges(
|
private fun getOverriddenMethodsRequiringBridges(
|
||||||
|
|||||||
+32
-23
@@ -52,7 +52,7 @@ internal sealed class MetafactoryArgumentsResult {
|
|||||||
// TODO might use Kotlin-specific metafactory if there would be one.
|
// TODO might use Kotlin-specific metafactory if there would be one.
|
||||||
object LambdaMetafactorySemanticsHazard : Failure()
|
object LambdaMetafactorySemanticsHazard : Failure()
|
||||||
|
|
||||||
// There's an ABI incompatibility between classes generated by j.l.invoke.LambdaMetafactory and classes generatede by Kotlin.
|
// There's an ABI incompatibility between classes generated by j.l.invoke.LambdaMetafactory and classes generated by Kotlin.
|
||||||
// TODO might use Kotlin-specific metafactory if there would be one.
|
// TODO might use Kotlin-specific metafactory if there would be one.
|
||||||
object LambdaMetafactoryAbiHazard : Failure()
|
object LambdaMetafactoryAbiHazard : Failure()
|
||||||
|
|
||||||
@@ -75,7 +75,8 @@ internal class LambdaMetafactoryArguments(
|
|||||||
val samMethod: IrSimpleFunction,
|
val samMethod: IrSimpleFunction,
|
||||||
val fakeInstanceMethod: IrSimpleFunction,
|
val fakeInstanceMethod: IrSimpleFunction,
|
||||||
val implMethodReference: IrFunctionReference,
|
val implMethodReference: IrFunctionReference,
|
||||||
val extraOverriddenMethods: List<IrSimpleFunction>
|
val extraOverriddenMethods: List<IrSimpleFunction>,
|
||||||
|
val shouldBeSerializable: Boolean
|
||||||
) : MetafactoryArgumentsResult.Success()
|
) : MetafactoryArgumentsResult.Success()
|
||||||
|
|
||||||
|
|
||||||
@@ -203,14 +204,13 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
|||||||
semanticsHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactorySemanticsHazard
|
semanticsHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactorySemanticsHazard
|
||||||
abiHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactoryAbiHazard
|
abiHazard -> return MetafactoryArgumentsResult.Failure.LambdaMetafactoryAbiHazard
|
||||||
inliningHazard -> return MetafactoryArgumentsResult.Failure.InliningHazard
|
inliningHazard -> return MetafactoryArgumentsResult.Failure.InliningHazard
|
||||||
shouldBeSerializable -> return MetafactoryArgumentsResult.Failure.SerializationHazard
|
|
||||||
functionHazard -> return MetafactoryArgumentsResult.Failure.FunctionHazard
|
functionHazard -> return MetafactoryArgumentsResult.Failure.FunctionHazard
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the hard work of matching Kotlin functional interface hierarchy against LambdaMetafactory constraints.
|
// Do the hard work of matching Kotlin functional interface hierarchy against LambdaMetafactory constraints.
|
||||||
// Briefly: sometimes we have to force boxing on the primitive and inline class values, sometimes we have to keep them unboxed.
|
// Briefly: sometimes we have to force boxing on the primitive and inline class values, sometimes we have to keep them unboxed.
|
||||||
// If this results in conflicting requirements, we can't use INVOKEDYNAMIC with LambdaMetafactory for creating a closure.
|
// If this results in conflicting requirements, we can't use INVOKEDYNAMIC with LambdaMetafactory for creating a closure.
|
||||||
return getLambdaMetafactoryArgsOrNullInner(reference, samMethod, samType, implFun)
|
return getLambdaMetafactoryArgsOrNullInner(reference, samMethod, samType, implFun, shouldBeSerializable)
|
||||||
?: MetafactoryArgumentsResult.Failure.FunctionHazard
|
?: MetafactoryArgumentsResult.Failure.FunctionHazard
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +242,8 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
|||||||
reference: IrFunctionReference,
|
reference: IrFunctionReference,
|
||||||
samMethod: IrSimpleFunction,
|
samMethod: IrSimpleFunction,
|
||||||
samType: IrType,
|
samType: IrType,
|
||||||
implFun: IrFunction
|
implFun: IrFunction,
|
||||||
|
shouldBeSerializable: Boolean
|
||||||
): LambdaMetafactoryArguments? {
|
): LambdaMetafactoryArguments? {
|
||||||
val nonFakeOverriddenFuns = samMethod.allOverridden().filterNot { it.isFakeOverride }
|
val nonFakeOverriddenFuns = samMethod.allOverridden().filterNot { it.isFakeOverride }
|
||||||
val relevantOverriddenFuns = if (samMethod.isFakeOverride) nonFakeOverriddenFuns else nonFakeOverriddenFuns + samMethod
|
val relevantOverriddenFuns = if (samMethod.isFakeOverride) nonFakeOverriddenFuns else nonFakeOverriddenFuns + samMethod
|
||||||
@@ -334,9 +335,15 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
|||||||
reference
|
reference
|
||||||
|
|
||||||
if (samMethod.isFakeOverride && nonFakeOverriddenFuns.size == 1) {
|
if (samMethod.isFakeOverride && nonFakeOverriddenFuns.size == 1) {
|
||||||
return LambdaMetafactoryArguments(nonFakeOverriddenFuns.single(), fakeInstanceMethod, newReference, listOf())
|
return LambdaMetafactoryArguments(
|
||||||
|
nonFakeOverriddenFuns.single(),
|
||||||
|
fakeInstanceMethod,
|
||||||
|
newReference,
|
||||||
|
listOf(),
|
||||||
|
shouldBeSerializable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return LambdaMetafactoryArguments(samMethod, fakeInstanceMethod, newReference, nonFakeOverriddenFuns)
|
return LambdaMetafactoryArguments(samMethod, fakeInstanceMethod, newReference, nonFakeOverriddenFuns, shouldBeSerializable)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkMethodSignatureCompliance(
|
private fun checkMethodSignatureCompliance(
|
||||||
@@ -351,14 +358,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
|||||||
withExtensionReceiver = reference.extensionReceiver == null
|
withExtensionReceiver = reference.extensionReceiver == null
|
||||||
)
|
)
|
||||||
val methodParameters = collectValueParameters(fakeInstanceMethod)
|
val methodParameters = collectValueParameters(fakeInstanceMethod)
|
||||||
if (implParameters.size != methodParameters.size)
|
validateMethodParameters(implParameters, methodParameters, implFun, fakeInstanceMethod)
|
||||||
throw AssertionError(
|
|
||||||
"Mismatching lambda and instance method parameters:\n" +
|
|
||||||
"implFun: ${implFun.render()}\n" +
|
|
||||||
" (${implParameters.size} parameters)\n" +
|
|
||||||
"instance method: ${fakeInstanceMethod.render()}\n" +
|
|
||||||
" (${methodParameters.size} parameters)"
|
|
||||||
)
|
|
||||||
for ((implParameter, methodParameter) in implParameters.zip(methodParameters)) {
|
for ((implParameter, methodParameter) in implParameters.zip(methodParameters)) {
|
||||||
val constraint = constraints.valueParameters[methodParameter]
|
val constraint = constraints.valueParameters[methodParameter]
|
||||||
if (!checkTypeCompliesWithConstraint(implParameter.type, constraint))
|
if (!checkTypeCompliesWithConstraint(implParameter.type, constraint))
|
||||||
@@ -397,14 +397,7 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
|||||||
|
|
||||||
val implParameters = collectValueParameters(implFun)
|
val implParameters = collectValueParameters(implFun)
|
||||||
val methodParameters = collectValueParameters(fakeInstanceMethod)
|
val methodParameters = collectValueParameters(fakeInstanceMethod)
|
||||||
if (implParameters.size != methodParameters.size)
|
validateMethodParameters(implParameters, methodParameters, implFun, fakeInstanceMethod)
|
||||||
throw AssertionError(
|
|
||||||
"Mismatching lambda and instance method parameters:\n" +
|
|
||||||
"implFun: ${implFun.render()}\n" +
|
|
||||||
" (${implParameters.size} parameters)\n" +
|
|
||||||
"instance method: ${fakeInstanceMethod.render()}\n" +
|
|
||||||
" (${methodParameters.size} parameters)"
|
|
||||||
)
|
|
||||||
for ((implParameter, methodParameter) in implParameters.zip(methodParameters)) {
|
for ((implParameter, methodParameter) in implParameters.zip(methodParameters)) {
|
||||||
val parameterConstraint = constraints.valueParameters[methodParameter]
|
val parameterConstraint = constraints.valueParameters[methodParameter]
|
||||||
if (parameterConstraint.requiresImplLambdaBoxing()) {
|
if (parameterConstraint.requiresImplLambdaBoxing()) {
|
||||||
@@ -418,6 +411,22 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun validateMethodParameters(
|
||||||
|
implParameters: List<IrValueParameter>,
|
||||||
|
methodParameters: List<IrValueParameter>,
|
||||||
|
implFun: IrFunction,
|
||||||
|
fakeInstanceMethod: IrSimpleFunction
|
||||||
|
) {
|
||||||
|
if (implParameters.size != methodParameters.size)
|
||||||
|
throw AssertionError(
|
||||||
|
"Mismatching lambda and instance method parameters:\n" +
|
||||||
|
"implFun: ${implFun.render()}\n" +
|
||||||
|
" (${implParameters.size} parameters)\n" +
|
||||||
|
"instance method: ${fakeInstanceMethod.render()}\n" +
|
||||||
|
" (${methodParameters.size} parameters)"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun remapExtensionLambda(lambda: IrSimpleFunction, reference: IrFunctionReference): IrFunctionReference {
|
private fun remapExtensionLambda(lambda: IrSimpleFunction, reference: IrFunctionReference): IrFunctionReference {
|
||||||
val oldExtensionReceiver = lambda.extensionReceiverParameter
|
val oldExtensionReceiver = lambda.extensionReceiverParameter
|
||||||
?: return reference
|
?: return reference
|
||||||
|
|||||||
@@ -59,8 +59,10 @@ class JvmSymbols(
|
|||||||
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
private val kotlinJvmFunctionsPackage: IrPackageFragment = createPackage(FqName("kotlin.jvm.functions"))
|
||||||
private val kotlinReflectPackage: IrPackageFragment = createPackage(FqName("kotlin.reflect"))
|
private val kotlinReflectPackage: IrPackageFragment = createPackage(FqName("kotlin.reflect"))
|
||||||
private val javaLangPackage: IrPackageFragment = createPackage(FqName("java.lang"))
|
private val javaLangPackage: IrPackageFragment = createPackage(FqName("java.lang"))
|
||||||
|
private val javaLangInvokePackage: IrPackageFragment = createPackage(FqName("java.lang.invoke"))
|
||||||
private val javaUtilPackage: IrPackageFragment = createPackage(FqName("java.util"))
|
private val javaUtilPackage: IrPackageFragment = createPackage(FqName("java.util"))
|
||||||
|
|
||||||
|
|
||||||
private val kotlinInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.internal"))
|
private val kotlinInternalPackage: IrPackageFragment = createPackage(FqName("kotlin.internal"))
|
||||||
|
|
||||||
// Special package for functions representing dynamic symbols referenced by 'INVOKEDYNAMIC' instruction - e.g.,
|
// Special package for functions representing dynamic symbols referenced by 'INVOKEDYNAMIC' instruction - e.g.,
|
||||||
@@ -101,6 +103,7 @@ class JvmSymbols(
|
|||||||
"kotlin.jvm" -> kotlinJvmPackage
|
"kotlin.jvm" -> kotlinJvmPackage
|
||||||
"kotlin.reflect" -> kotlinReflectPackage
|
"kotlin.reflect" -> kotlinReflectPackage
|
||||||
"java.lang" -> javaLangPackage
|
"java.lang" -> javaLangPackage
|
||||||
|
"java.lang.invoke" -> javaLangInvokePackage
|
||||||
"java.util" -> javaUtilPackage
|
"java.util" -> javaUtilPackage
|
||||||
"kotlin.internal" -> kotlinInternalPackage
|
"kotlin.internal" -> kotlinInternalPackage
|
||||||
else -> error("Other packages are not supported yet: $fqName")
|
else -> error("Other packages are not supported yet: $fqName")
|
||||||
@@ -232,7 +235,7 @@ class JvmSymbols(
|
|||||||
klass.addConstructor { isPrimary = true }
|
klass.addConstructor { isPrimary = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
// This annotations also implies ACC_DEPRECATED flag in generated bytecode
|
// This annotation also implies ACC_DEPRECATED flag in generated bytecode
|
||||||
val javaLangDeprecatedConstructorWithDeprecatedFlag = javaLangDeprecatedWithDeprecatedFlag.constructors.single()
|
val javaLangDeprecatedConstructorWithDeprecatedFlag = javaLangDeprecatedWithDeprecatedFlag.constructors.single()
|
||||||
|
|
||||||
private val javaLangAssertionError: IrClassSymbol =
|
private val javaLangAssertionError: IrClassSymbol =
|
||||||
@@ -596,14 +599,16 @@ class JvmSymbols(
|
|||||||
// samMethodType,
|
// samMethodType,
|
||||||
// implMethodReference,
|
// implMethodReference,
|
||||||
// instantiatedMethodType,
|
// instantiatedMethodType,
|
||||||
// vararg extraOverriddenMethodTypes
|
// vararg extraOverriddenMethodTypes,
|
||||||
|
// shouldBeSerializable
|
||||||
// ): SAM_TYPE
|
// ): SAM_TYPE
|
||||||
// where:
|
// where:
|
||||||
// `SAM_TYPE` is a single abstract method interface, which is implemented by a resulting closure;
|
// `SAM_TYPE` is a single abstract method interface, which is implemented by a resulting closure;
|
||||||
// `samMethodType` is a method type (signature and return type) of a method to be implemented by a closure;
|
// `samMethodType` is a method type (signature and return type) of a method to be implemented by a closure;
|
||||||
// `implMethodReference` is an actual implementation method (e.g., method for a lambda function);
|
// `implMethodReference` is an actual implementation method (e.g., method for a lambda function);
|
||||||
// `instantiatedMethodType` is a specialized implementation method type;
|
// `instantiatedMethodType` is a specialized implementation method type;
|
||||||
// `extraOverriddenMethodTypes` is a possibly empty vararg of additional methods to be implemented by a closure.
|
// `extraOverriddenMethodTypes` is a possibly empty vararg of additional methods to be implemented by a closure;
|
||||||
|
// `shouldBeSerializable` is true if the class of the resulting object should implement `java.io.Serializable`.
|
||||||
//
|
//
|
||||||
// At this stage, "method types" are represented as IrRawFunctionReference nodes for the functions with corresponding signature.
|
// At this stage, "method types" are represented as IrRawFunctionReference nodes for the functions with corresponding signature.
|
||||||
// `<jvm-indy-lambda-metafactory>` call rewriting selects a particular bootstrap method (`metafactory` or `altMetafactory`)
|
// `<jvm-indy-lambda-metafactory>` call rewriting selects a particular bootstrap method (`metafactory` or `altMetafactory`)
|
||||||
@@ -632,34 +637,74 @@ class JvmSymbols(
|
|||||||
type = arrayOfAnyType
|
type = arrayOfAnyType
|
||||||
varargElementType = irBuiltIns.anyType
|
varargElementType = irBuiltIns.anyType
|
||||||
}
|
}
|
||||||
|
addValueParameter("shouldBeSerializable", irBuiltIns.booleanType)
|
||||||
returnType = samType.defaultType
|
returnType = samType.defaultType
|
||||||
}.symbol
|
}.symbol
|
||||||
|
|
||||||
|
|
||||||
|
inner class SerializedLambdaClass
|
||||||
|
@Deprecated("Should not be used outside of JvmSymbols") internal constructor() {
|
||||||
|
val symbol = createClass(FqName("java.lang.invoke.SerializedLambda"))
|
||||||
|
val irClass = symbol.owner
|
||||||
|
val irType = irClass.defaultType
|
||||||
|
|
||||||
|
val getImplMethodName = irClass.addFunction("getImplMethodName", irBuiltIns.stringType)
|
||||||
|
val getImplMethodKind = irClass.addFunction("getImplMethodKind", irBuiltIns.intType)
|
||||||
|
val getImplClass = irClass.addFunction("getImplClass", irBuiltIns.stringType)
|
||||||
|
val getImplMethodSignature = irClass.addFunction("getImplMethodSignature", irBuiltIns.stringType)
|
||||||
|
|
||||||
|
val getFunctionalInterfaceClass = irClass.addFunction("getFunctionalInterfaceClass", irBuiltIns.stringType)
|
||||||
|
val getFunctionalInterfaceMethodName = irClass.addFunction("getFunctionalInterfaceMethodName", irBuiltIns.stringType)
|
||||||
|
val getFunctionalInterfaceMethodSignature = irClass.addFunction("getFunctionalInterfaceMethodSignature", irBuiltIns.stringType)
|
||||||
|
|
||||||
|
val getCapturedArg = irClass.addFunction("getCapturedArg", irBuiltIns.anyNType).apply {
|
||||||
|
addValueParameter(Name.identifier("i"), irBuiltIns.intType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
val serializedLambda = SerializedLambdaClass()
|
||||||
|
|
||||||
|
val illegalArgumentException = createClass(FqName("java.lang.IllegalArgumentException")) { irClass ->
|
||||||
|
irClass.addConstructor {
|
||||||
|
name = Name.special("<init>")
|
||||||
|
}.apply {
|
||||||
|
addValueParameter("message", irBuiltIns.stringType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val illegalArgumentExceptionCtorString = illegalArgumentException.constructors.single()
|
||||||
|
|
||||||
|
val jvmMethodType: IrSimpleFunctionSymbol =
|
||||||
|
irFactory.buildFun {
|
||||||
|
name = Name.special("<jvm-method-type>")
|
||||||
|
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||||
|
}.apply {
|
||||||
|
returnType = irBuiltIns.anyType
|
||||||
|
parent = kotlinJvmInternalPackage
|
||||||
|
addValueParameter("descriptor", irBuiltIns.stringType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
|
val jvmMethodHandle: IrSimpleFunctionSymbol =
|
||||||
|
irFactory.buildFun {
|
||||||
|
name = Name.special("<jvm-method-handle>")
|
||||||
|
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||||
|
}.apply {
|
||||||
|
returnType = irBuiltIns.anyType
|
||||||
|
parent = kotlinJvmInternalPackage
|
||||||
|
addValueParameter("tag", irBuiltIns.intType)
|
||||||
|
addValueParameter("owner", irBuiltIns.stringType)
|
||||||
|
addValueParameter("name", irBuiltIns.stringType)
|
||||||
|
addValueParameter("descriptor", irBuiltIns.stringType)
|
||||||
|
addValueParameter("isInterface", irBuiltIns.booleanType)
|
||||||
|
}.symbol
|
||||||
|
|
||||||
// Intrinsic to represent INVOKEDYNAMIC calls in IR.
|
// Intrinsic to represent INVOKEDYNAMIC calls in IR.
|
||||||
// fun <T> `<jvm-indy>`(
|
// fun <T> `<jvm-indy>`(
|
||||||
// dynamicCall: T,
|
// dynamicCall: T,
|
||||||
// bootstrapMethodTag: Int,
|
// bootstrapMethodHandle: Any,
|
||||||
// bootstrapMethodOwner: String,
|
|
||||||
// bootstrapMethodName: String,
|
|
||||||
// bootstrapMethodDesc: String,
|
|
||||||
// vararg bootstrapMethodArgs: Any
|
// vararg bootstrapMethodArgs: Any
|
||||||
// ): T
|
// ): T
|
||||||
// Bootstrap method handle is encoded as a bunch of constants.
|
// Bootstrap method handle is represented as a `<jvm-method-handle>` call.
|
||||||
// For example,
|
|
||||||
// REF_invokeStatic java/lang/invoke/LambdaMetafactory.metafactory:(
|
|
||||||
// Ljava/lang/invoke/MethodHandles$Lookup;
|
|
||||||
// Ljava/lang/String;
|
|
||||||
// Ljava/lang/invoke/MethodType;
|
|
||||||
// Ljava/lang/invoke/MethodType;
|
|
||||||
// Ljava/lang/invoke/MethodHandle;
|
|
||||||
// Ljava/lang/invoke/MethodType;
|
|
||||||
// )Ljava/lang/invoke/CallSite;
|
|
||||||
// is represented as
|
|
||||||
// bootstrapMethodTag: IrConst<Int>(value = H_INVOKESTATIC)
|
|
||||||
// bootstrapMethodOwner: IrConst<String>(value = "java/lang/invoke/LambdaMetafactory")
|
|
||||||
// bootstrapMethodName: IrConst<String>(value = "metafactory")
|
|
||||||
// bootstrapMethodDesc: IrConst<String>(value = "(...)Ljava/lang/invoke/CallSite;")
|
|
||||||
// Bootstrap method owner is assumed to be a class (which is true for both LambdaMetafactory and StringConcatFactory).
|
|
||||||
val jvmIndyIntrinsic: IrSimpleFunctionSymbol =
|
val jvmIndyIntrinsic: IrSimpleFunctionSymbol =
|
||||||
irFactory.buildFun {
|
irFactory.buildFun {
|
||||||
name = Name.special("<jvm-indy>")
|
name = Name.special("<jvm-indy>")
|
||||||
@@ -668,10 +713,7 @@ class JvmSymbols(
|
|||||||
parent = kotlinJvmInternalPackage
|
parent = kotlinJvmInternalPackage
|
||||||
val t = addTypeParameter("T", irBuiltIns.anyNType)
|
val t = addTypeParameter("T", irBuiltIns.anyNType)
|
||||||
addValueParameter("dynamicCall", t.defaultType)
|
addValueParameter("dynamicCall", t.defaultType)
|
||||||
addValueParameter("bootstrapMethodTag", irBuiltIns.intType)
|
addValueParameter("bootstrapMethodHandle", irBuiltIns.anyType)
|
||||||
addValueParameter("bootstrapMethodOwner", irBuiltIns.stringType)
|
|
||||||
addValueParameter("bootstrapMethodName", irBuiltIns.stringType)
|
|
||||||
addValueParameter("bootstrapMethodDesc", irBuiltIns.stringType)
|
|
||||||
addValueParameter {
|
addValueParameter {
|
||||||
name = Name.identifier("bootstrapMethodArguments")
|
name = Name.identifier("bootstrapMethodArguments")
|
||||||
type = arrayOfAnyType
|
type = arrayOfAnyType
|
||||||
@@ -693,21 +735,6 @@ class JvmSymbols(
|
|||||||
returnType = irBuiltIns.anyType
|
returnType = irBuiltIns.anyType
|
||||||
}.symbol
|
}.symbol
|
||||||
|
|
||||||
// Intrinsic used to represent MethodType objects in bootstrap method arguments (see jvmInvokeDynamicIntrinsic above).
|
|
||||||
// Type argument is a substituted method owner type (e.g., 'java.lang.function.Supplier<String>').
|
|
||||||
// Value argument is a raw function reference to a corresponding method (e.g., 'java.lang.function.Supplier#get').
|
|
||||||
// Resulting method type is substituted.
|
|
||||||
val jvmSubstitutedMethodTypeIntrinsic: IrSimpleFunctionSymbol =
|
|
||||||
irFactory.buildFun {
|
|
||||||
name = Name.special("<jvm-substituted-method-type>")
|
|
||||||
origin = IrDeclarationOrigin.IR_BUILTINS_STUB
|
|
||||||
}.apply {
|
|
||||||
parent = kotlinJvmInternalPackage
|
|
||||||
addTypeParameter("OwnerT", irBuiltIns.anyType)
|
|
||||||
addValueParameter("method", irBuiltIns.anyType)
|
|
||||||
returnType = irBuiltIns.anyType
|
|
||||||
}.symbol
|
|
||||||
|
|
||||||
private val collectionToArrayClass: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.CollectionToArray")) { klass ->
|
private val collectionToArrayClass: IrClassSymbol = createClass(FqName("kotlin.jvm.internal.CollectionToArray")) { klass ->
|
||||||
klass.origin = JvmLoweredDeclarationOrigin.TO_ARRAY
|
klass.origin = JvmLoweredDeclarationOrigin.TO_ARRAY
|
||||||
|
|
||||||
|
|||||||
+102
-107
@@ -5,19 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
package org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
import org.jetbrains.kotlin.backend.jvm.codegen.*
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.findSuperDeclaration
|
import org.jetbrains.kotlin.backend.jvm.ir.findSuperDeclaration
|
||||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.overrides.buildFakeOverrideMember
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
import org.jetbrains.kotlin.ir.types.*
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
import org.jetbrains.org.objectweb.asm.Handle
|
import org.jetbrains.org.objectweb.asm.Handle
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
@@ -36,24 +35,17 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
|||||||
)
|
)
|
||||||
fail("Unexpected dynamicCallee: '${dynamicCallee.render()}'")
|
fail("Unexpected dynamicCallee: '${dynamicCallee.render()}'")
|
||||||
|
|
||||||
val bootstrapMethodTag = expression.getValueArgument(1)?.getIntConst()
|
val bootstrapMethodHandleArg = expression.getValueArgument(1) as? IrCall
|
||||||
?: fail("'bootstrapMethodTag' is expected to be an int const")
|
?: fail("'bootstrapMethodHandle' should be a call")
|
||||||
val bootstrapMethodOwner = expression.getValueArgument(2)?.getStringConst()
|
val bootstrapMethodHandle = evalMethodHandle(bootstrapMethodHandleArg)
|
||||||
?: fail("'bootstrapMethodOwner' is expected to be a string const")
|
|
||||||
val bootstrapMethodName = expression.getValueArgument(3)?.getStringConst()
|
|
||||||
?: fail("'bootstrapMethodName' is expected to be a string const")
|
|
||||||
val bootstrapMethodDesc = expression.getValueArgument(4)?.getStringConst()
|
|
||||||
?: fail("'bootstrapMethodDesc' is expected to be a string const")
|
|
||||||
val bootstrapMethodArgs = (expression.getValueArgument(5)?.safeAs<IrVararg>()
|
|
||||||
?: fail("'bootstrapMethodArgs' is expected to be a vararg"))
|
|
||||||
|
|
||||||
|
val bootstrapMethodArgs = (expression.getValueArgument(2)?.safeAs<IrVararg>()
|
||||||
|
?: fail("'bootstrapMethodArgs' is expected to be a vararg"))
|
||||||
val asmBootstrapMethodArgs = bootstrapMethodArgs.elements
|
val asmBootstrapMethodArgs = bootstrapMethodArgs.elements
|
||||||
.map { generateBootstrapMethodArg(it, codegen) }
|
.map { generateBootstrapMethodArg(it, codegen) }
|
||||||
.toTypedArray()
|
.toTypedArray()
|
||||||
|
|
||||||
val dynamicCalleeMethod = codegen.methodSignatureMapper.mapAsmMethod(dynamicCallee)
|
val dynamicCalleeMethod = codegen.methodSignatureMapper.mapAsmMethod(dynamicCallee)
|
||||||
val bootstrapMethodHandle = Handle(bootstrapMethodTag, bootstrapMethodOwner, bootstrapMethodName, bootstrapMethodDesc, false)
|
|
||||||
|
|
||||||
val dynamicCallGenerator = IrCallGenerator.DefaultCallGenerator
|
val dynamicCallGenerator = IrCallGenerator.DefaultCallGenerator
|
||||||
val dynamicCalleeArgumentTypes = dynamicCalleeMethod.argumentTypes
|
val dynamicCalleeArgumentTypes = dynamicCalleeMethod.argumentTypes
|
||||||
for (i in dynamicCallee.valueParameters.indices) {
|
for (i in dynamicCallee.valueParameters.indices) {
|
||||||
@@ -76,14 +68,8 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
|||||||
is IrRawFunctionReference ->
|
is IrRawFunctionReference ->
|
||||||
generateMethodHandle(element, codegen)
|
generateMethodHandle(element, codegen)
|
||||||
is IrCall ->
|
is IrCall ->
|
||||||
when (element.symbol) {
|
evalBootstrapArgumentIntrinsicCall(element, codegen)
|
||||||
codegen.context.ir.symbols.jvmOriginalMethodTypeIntrinsic ->
|
?: throw AssertionError("Unexpected callee in bootstrap method argument:\n${element.dump()}")
|
||||||
generateOriginalMethodType(element, codegen)
|
|
||||||
codegen.context.ir.symbols.jvmSubstitutedMethodTypeIntrinsic ->
|
|
||||||
generateSubstitutedMethodType(element, codegen)
|
|
||||||
else ->
|
|
||||||
throw AssertionError("Unexpected callee in bootstrap method argument:\n${element.dump()}")
|
|
||||||
}
|
|
||||||
is IrConst<*> ->
|
is IrConst<*> ->
|
||||||
when (element.kind) {
|
when (element.kind) {
|
||||||
IrConstKind.Byte -> (element.value as Byte).toInt()
|
IrConstKind.Byte -> (element.value as Byte).toInt()
|
||||||
@@ -100,40 +86,38 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
|||||||
throw AssertionError("Unexpected bootstrap method argument:\n${element.dump()}")
|
throw AssertionError("Unexpected bootstrap method argument:\n${element.dump()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateMethodHandle(irRawFunctionReference: IrRawFunctionReference, codegen: ExpressionCodegen): Handle {
|
private fun evalBootstrapArgumentIntrinsicCall(irCall: IrCall, codegen: ExpressionCodegen): Any? {
|
||||||
val irFun = when (val irFun0 = irRawFunctionReference.symbol.owner) {
|
return when (irCall.symbol) {
|
||||||
is IrConstructor ->
|
codegen.context.ir.symbols.jvmOriginalMethodTypeIntrinsic ->
|
||||||
irFun0
|
evalOriginalMethodType(irCall, codegen)
|
||||||
is IrSimpleFunction -> {
|
codegen.context.ir.symbols.jvmMethodType ->
|
||||||
// Note that if the given function is a fake override, we emit a method handle with explicit super class.
|
evalMethodType(irCall)
|
||||||
// This has the same binary compatibility guarantees as in Java.
|
codegen.context.ir.symbols.jvmMethodHandle ->
|
||||||
findSuperDeclaration(irFun0, false, codegen.state.jvmDefaultMode)
|
evalMethodHandle(irCall)
|
||||||
}
|
|
||||||
else ->
|
else ->
|
||||||
throw java.lang.AssertionError("Simple function or constructor expected: ${irFun0.render()}")
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
val irParentClass = irFun.parent as? IrClass
|
|
||||||
?: throw AssertionError("Unexpected parent: ${irFun.parent.render()}")
|
|
||||||
val owner = codegen.typeMapper.mapOwner(irParentClass)
|
|
||||||
|
|
||||||
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(irFun)
|
|
||||||
|
|
||||||
val handleTag = when {
|
|
||||||
irFun is IrConstructor ->
|
|
||||||
Opcodes.H_NEWINVOKESPECIAL
|
|
||||||
irFun.dispatchReceiverParameter == null ->
|
|
||||||
Opcodes.H_INVOKESTATIC
|
|
||||||
irParentClass.isJvmInterface ->
|
|
||||||
Opcodes.H_INVOKEINTERFACE
|
|
||||||
else ->
|
|
||||||
Opcodes.H_INVOKEVIRTUAL
|
|
||||||
}
|
|
||||||
|
|
||||||
return Handle(handleTag, owner.internalName, asmMethod.name, asmMethod.descriptor, irParentClass.isJvmInterface)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateOriginalMethodType(irCall: IrCall, codegen: ExpressionCodegen): Type {
|
private fun evalMethodType(irCall: IrCall): Type {
|
||||||
|
val descriptor = irCall.getStringConstArgument(0)
|
||||||
|
return Type.getMethodType(descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evalMethodHandle(irCall: IrCall): Handle {
|
||||||
|
val tag = irCall.getIntConstArgument(0)
|
||||||
|
val owner = irCall.getStringConstArgument(1)
|
||||||
|
val name = irCall.getStringConstArgument(2)
|
||||||
|
val descriptor = irCall.getStringConstArgument(3)
|
||||||
|
val isInterface = irCall.getBooleanConstArgument(4)
|
||||||
|
return Handle(tag, owner, name, descriptor, isInterface)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateMethodHandle(irRawFunctionReference: IrRawFunctionReference, codegen: ExpressionCodegen): Handle {
|
||||||
|
return generateMethodHandle(codegen.context, irRawFunctionReference)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun evalOriginalMethodType(irCall: IrCall, codegen: ExpressionCodegen): Type {
|
||||||
val irRawFunRef = irCall.getValueArgument(0) as? IrRawFunctionReference
|
val irRawFunRef = irCall.getValueArgument(0) as? IrRawFunctionReference
|
||||||
?: throw AssertionError(
|
?: throw AssertionError(
|
||||||
"Argument in ${irCall.symbol.owner.name} call is expected to be a raw function reference:\n" +
|
"Argument in ${irCall.symbol.owner.name} call is expected to be a raw function reference:\n" +
|
||||||
@@ -144,64 +128,75 @@ object JvmInvokeDynamic : IntrinsicMethod() {
|
|||||||
return Type.getMethodType(asmMethod.descriptor)
|
return Type.getMethodType(asmMethod.descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateSubstitutedMethodType(irCall: IrCall, codegen: ExpressionCodegen): Type {
|
}
|
||||||
fun fail(message: String): Nothing =
|
|
||||||
throw AssertionError("$message; irCall:\n${irCall.dump()}")
|
|
||||||
|
|
||||||
val irRawFunRef = irCall.getValueArgument(0) as? IrRawFunctionReference
|
fun IrCall.getIntConstArgument(i: Int) =
|
||||||
?: fail("Argument in ${irCall.symbol.owner.name} call is expected to be a raw function reference")
|
getValueArgument(i)?.getIntConst()
|
||||||
val irOriginalFun = irRawFunRef.symbol.owner as? IrSimpleFunction
|
?: throw AssertionError("Value argument #$i should be an Int const: ${dump()}")
|
||||||
?: fail("IrSimpleFunction expected: ${irRawFunRef.symbol.owner.render()}")
|
|
||||||
|
|
||||||
val superType = irCall.getTypeArgument(0) as? IrSimpleType
|
fun IrCall.getStringConstArgument(i: Int) =
|
||||||
?: fail("Type argument expected")
|
getValueArgument(i)?.getStringConst()
|
||||||
val patchedSuperType = replaceTypeArgumentsWithNullable(superType)
|
?: throw AssertionError("Value argument #$i should be a String const: ${dump()}")
|
||||||
|
|
||||||
val fakeClass = codegen.context.irFactory.buildClass { name = Name.special("<fake>") }
|
fun IrCall.getBooleanConstArgument(i: Int) =
|
||||||
fakeClass.parent = codegen.context.ir.symbols.kotlinJvmInternalInvokeDynamicPackage
|
getValueArgument(i)?.getBooleanConst()
|
||||||
val irFakeOverride = buildFakeOverrideMember(patchedSuperType, irOriginalFun, fakeClass) as IrSimpleFunction
|
?: throw AssertionError("Value argument #$i should be a Boolean const: ${dump()}")
|
||||||
irFakeOverride.overriddenSymbols = listOf(irOriginalFun.symbol)
|
|
||||||
|
|
||||||
val asmMethod = codegen.methodSignatureMapper.mapAsmMethod(irFakeOverride)
|
|
||||||
return Type.getMethodType(asmMethod.descriptor)
|
internal fun IrExpression.getIntConst() =
|
||||||
|
if (this is IrConst<*> && kind == IrConstKind.Int)
|
||||||
|
this.value as Int
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
internal fun IrExpression.getStringConst() =
|
||||||
|
if (this is IrConst<*> && kind == IrConstKind.String)
|
||||||
|
this.value as String
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
internal fun IrExpression.getBooleanConst() =
|
||||||
|
if (this is IrConst<*> && kind == IrConstKind.Boolean)
|
||||||
|
this.value as Boolean
|
||||||
|
else
|
||||||
|
null
|
||||||
|
|
||||||
|
internal fun generateMethodHandle(jvmBackendContext: JvmBackendContext, irRawFunctionReference: IrRawFunctionReference): Handle {
|
||||||
|
return generateMethodHandle(jvmBackendContext, irRawFunctionReference.symbol.owner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateMethodHandle(jvmBackendContext: JvmBackendContext, irFun: IrFunction): Handle {
|
||||||
|
val irNonFakeFun = when (irFun) {
|
||||||
|
is IrConstructor ->
|
||||||
|
irFun
|
||||||
|
is IrSimpleFunction -> {
|
||||||
|
findSuperDeclaration(irFun, false, jvmBackendContext.state.jvmDefaultMode)
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
throw java.lang.AssertionError("Simple function or constructor expected: ${irFun.render()}")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given the following functional interface
|
val irParentClass = irNonFakeFun.parent as? IrClass
|
||||||
// fun interface IFoo<T> {
|
?: throw AssertionError("Unexpected parent: ${irNonFakeFun.parent.render()}")
|
||||||
// fun foo(x: T): T
|
val owner = jvmBackendContext.typeMapper.mapOwner(irParentClass)
|
||||||
// }
|
|
||||||
// To comply with java.lang.invoke.LambdaMetafactory requirements, we need an instance method that accepts references
|
|
||||||
// (not primitives, and not unboxed inline classes).
|
|
||||||
// In order to do so, we replace type arguments with nullable types.
|
|
||||||
private fun replaceTypeArgumentsWithNullable(substitutedType: IrSimpleType) =
|
|
||||||
substitutedType.classifier.typeWithArguments(
|
|
||||||
substitutedType.arguments.map { typeArgument ->
|
|
||||||
when (typeArgument) {
|
|
||||||
is IrStarProjection -> typeArgument
|
|
||||||
is IrTypeProjection -> {
|
|
||||||
val type = typeArgument.type
|
|
||||||
if (type !is IrSimpleType || type.hasQuestionMark)
|
|
||||||
typeArgument
|
|
||||||
else {
|
|
||||||
makeTypeProjection(type.withHasQuestionMark(true), typeArgument.variance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else ->
|
|
||||||
throw AssertionError("Unexpected type argument '$typeArgument' :: ${typeArgument::class.simpleName}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun IrExpression.getIntConst() =
|
val asmMethod = jvmBackendContext.methodSignatureMapper.mapAsmMethod(irNonFakeFun)
|
||||||
if (this is IrConst<*> && kind == IrConstKind.Int)
|
|
||||||
this.value as Int
|
|
||||||
else
|
|
||||||
null
|
|
||||||
|
|
||||||
private fun IrExpression.getStringConst() =
|
val handleTag = getMethodKindTag(irNonFakeFun)
|
||||||
if (this is IrConst<*> && kind == IrConstKind.String)
|
|
||||||
this.value as String
|
|
||||||
else
|
|
||||||
null
|
|
||||||
|
|
||||||
|
return Handle(handleTag, owner.internalName, asmMethod.name, asmMethod.descriptor, irParentClass.isJvmInterface)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun getMethodKindTag(irFun: IrFunction) =
|
||||||
|
when {
|
||||||
|
irFun is IrConstructor ->
|
||||||
|
Opcodes.H_NEWINVOKESPECIAL
|
||||||
|
irFun.dispatchReceiverParameter == null ->
|
||||||
|
Opcodes.H_INVOKESTATIC
|
||||||
|
irFun.parentAsClass.isJvmInterface ->
|
||||||
|
Opcodes.H_INVOKEINTERFACE
|
||||||
|
else ->
|
||||||
|
Opcodes.H_INVOKEVIRTUAL
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
// CHECK_BYTECODE_TEXT
|
// CHECK_BYTECODE_TEXT
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 0 java/lang/invoke/LambdaMetafactory
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
// FILE: serializableSam1.kt
|
// FILE: serializableSam1.kt
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
// CHECK_BYTECODE_TEXT
|
// CHECK_BYTECODE_TEXT
|
||||||
// JVM_IR_TEMPLATES
|
// JVM_IR_TEMPLATES
|
||||||
// 0 java/lang/invoke/LambdaMetafactory
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
// FILE: serializableSam2.kt
|
// FILE: serializableSam2.kt
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
|
|||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// We generate 1 clause in '$deserializeLambda' for each unique possible combination of deserialized lambda parameters
|
||||||
|
// (that's all information stored during indy lambda serialization, anyway).
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 12 java/lang/invoke/LambdaMetafactory
|
||||||
|
// 1 (LOOKUP|TABLE)SWITCH
|
||||||
|
// 24 java/lang/String\.equals
|
||||||
|
|
||||||
|
// FILE: multipleTopLevelFunRefs.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun plusK1(s: String) = s + "K"
|
||||||
|
fun plusK2(s: String) = s + "K"
|
||||||
|
fun plusK3(s: String) = s + "K"
|
||||||
|
fun plusK4(s: String) = s + "K"
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val t1 = roundtrip(Sam(::plusK1)).get("O")
|
||||||
|
if (t1 != "OK") return "Failed: t1='$t1'"
|
||||||
|
|
||||||
|
val t1a = roundtrip(Sam(::plusK1)).get("O")
|
||||||
|
if (t1a != "OK") return "Failed: t1a='$t1a'"
|
||||||
|
|
||||||
|
val t1b = roundtrip(Sam(::plusK1)).get("O")
|
||||||
|
if (t1b != "OK") return "Failed: t1b='$t1b'"
|
||||||
|
|
||||||
|
val t2 = roundtrip(Sam(::plusK2)).get("O")
|
||||||
|
if (t2 != "OK") return "Failed: t2='$t2'"
|
||||||
|
|
||||||
|
val t2a = roundtrip(Sam(::plusK2)).get("O")
|
||||||
|
if (t2a != "OK") return "Failed: t2a='$t2a'"
|
||||||
|
|
||||||
|
val t3 = roundtrip(Sam(::plusK3)).get("O")
|
||||||
|
if (t3 != "OK") return "Failed: t3='$t3'"
|
||||||
|
|
||||||
|
val t4 = roundtrip(Sam(::plusK4)).get("O")
|
||||||
|
if (t4 != "OK") return "Failed: t4='$t4'"
|
||||||
|
|
||||||
|
val t4a = roundtrip(Sam(::plusK4)).get("O")
|
||||||
|
if (t4a != "OK") return "Failed: t4a='$t4a'"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
Vendored
+47
@@ -0,0 +1,47 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 4 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: sameImplMethodDifferentInterfaces.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun plusK(s: String) = s + "K"
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val sam1 = roundtrip(Sam1(::plusK))
|
||||||
|
if (sam1 !is Sam1) return "Failed: $sam1 !is Sam1"
|
||||||
|
val t1 = sam1.get("O")
|
||||||
|
if (t1 != "OK") return "Failed: $t1='$t1'"
|
||||||
|
|
||||||
|
val sam2 = roundtrip(Sam2(::plusK))
|
||||||
|
if (sam2 !is Sam2) return "Failed: $sam2 !is Sam2"
|
||||||
|
val t2 = sam2.get("O")
|
||||||
|
if (t2 != "OK") return "Failed: $t2='$t2'"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam1.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam1 extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam2.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam2 extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
Vendored
+33
@@ -0,0 +1,33 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableBoundClassMemberFunRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
class C(val s: String) : Serializable {
|
||||||
|
fun plus(ss: String) = ss + s
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(C("K")::plus))
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
Vendored
+35
@@ -0,0 +1,35 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableBoundInnerConstructorRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
class Outer(val s1: String) : Serializable {
|
||||||
|
inner class Inner (val s2: String) {
|
||||||
|
fun test() = s1 + s2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(Outer("O")::Inner))
|
||||||
|
.get("K").test()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
Outer.Inner get(String s);
|
||||||
|
}
|
||||||
Vendored
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableBoundInterfaceMemberFunRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
interface Plus {
|
||||||
|
fun plus(ss: String): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class C(val s: String) : Plus, Serializable {
|
||||||
|
override fun plus(ss: String) = ss + s
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val p: Plus = C("K")
|
||||||
|
return roundtrip(Sam(p::plus))
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRef.kt
Vendored
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableBoundTopLevelExtensionFunRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun String.plusK(k: String) = this + k
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam("O"::plusK))
|
||||||
|
.get("K")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun Int.plusK(k: String) = this.toChar().toString() + k
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(('O'.toInt())::plusK))
|
||||||
|
.get("K")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableClassMemberFunRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
class C(val s: String) {
|
||||||
|
fun plus(ss: String) = ss + s
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(C::plus))
|
||||||
|
.get(C("K"), "O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(C x, String s);
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableConstructorRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
class C(val t: String)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(::C))
|
||||||
|
.get("OK").t
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
C get(String s);
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
// 2 A\.plus\(Ljava/lang/String;\)Ljava/lang/String;\,
|
||||||
|
// ^ check that we generate a reference to A::plus (same as javac)
|
||||||
|
|
||||||
|
// FILE: serializableFakeOverrideFunRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
abstract class A(val s: String) {
|
||||||
|
fun plus(ss: String) = ss + s
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class B(s: String) : A(s)
|
||||||
|
|
||||||
|
class C(s: String) : B(s)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(C::plus))
|
||||||
|
.get(C("K"), "O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(C x, String s);
|
||||||
|
}
|
||||||
Vendored
+35
@@ -0,0 +1,35 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableInnerConstructorRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
class Outer(val s1: String) {
|
||||||
|
inner class Inner (val s2: String) {
|
||||||
|
fun test() = s1 + s2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(Outer::Inner))
|
||||||
|
.get(Outer("O"), "K").test()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
Outer.Inner get(Outer outer, String s);
|
||||||
|
}
|
||||||
Vendored
+37
@@ -0,0 +1,37 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableInterfaceMemberFunRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
interface Plus {
|
||||||
|
fun plus(ss: String): String
|
||||||
|
}
|
||||||
|
|
||||||
|
class C(val s: String) : Plus {
|
||||||
|
override fun plus(ss: String) = ss + s
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(Plus::plus))
|
||||||
|
.get(C("K"), "O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(Plus x, String s);
|
||||||
|
}
|
||||||
Vendored
+36
@@ -0,0 +1,36 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableJavaStaticMethodRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(J::plusK))
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: J.java
|
||||||
|
public class J {
|
||||||
|
public static String plusK(String s) {
|
||||||
|
return s + "K";
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableLambda.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam { s -> s + "K" })
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableLambdaCapturingBoxedInlineClassAny.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
inline class IC(val x: Any) : Serializable
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val k: Any = IC("K")
|
||||||
|
return roundtrip(Sam { s -> s + (k as IC).x })
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableLambdaCapturingInlineClassAny.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
inline class IC(val x: Any)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val k = IC("K")
|
||||||
|
return roundtrip(Sam { s -> s + k.x })
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableLambdaCapturingInlineClassInt.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
inline class IC(val x: Int)
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val k = IC('K'.toInt())
|
||||||
|
return roundtrip(Sam { s -> s + k.x.toChar().toString() })
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableLambdaCapturingNullableInlineClassAny.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
inline class IC(val x: Any) : Serializable
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val k: IC? = IC("K")
|
||||||
|
return roundtrip(Sam { s -> s + k!!.x })
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
Vendored
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableLambdaToKotlinInterface.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun interface Sam : Serializable {
|
||||||
|
fun get(s: String): String
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam { s -> s + "K" })
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableLambdaWithCapture.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val k = "K"
|
||||||
|
return roundtrip(Sam { s -> s + k })
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableTopLevelFunRef.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun plusK(s: String) = s + "K"
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(::plusK))
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam extends Serializable {
|
||||||
|
String get(String s);
|
||||||
|
}
|
||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableTopLevelFunRefAsGenericInterface.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun plusK(s: String) = s + "K"
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam<String>(::plusK))
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public interface Sam<T> extends Serializable {
|
||||||
|
String get(T s);
|
||||||
|
}
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// SAM_CONVERSIONS: INDY
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
// CHECK_BYTECODE_TEXT
|
||||||
|
// JVM_IR_TEMPLATES
|
||||||
|
// 2 java/lang/invoke/LambdaMetafactory
|
||||||
|
|
||||||
|
// FILE: serializableWithBridge.kt
|
||||||
|
import java.io.*
|
||||||
|
|
||||||
|
fun plusK(s: String) = s + "K"
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return roundtrip(Sam(::plusK))
|
||||||
|
.get("O")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> roundtrip(x: T): T {
|
||||||
|
val out1 = ByteArrayOutputStream()
|
||||||
|
ObjectOutputStream(out1).writeObject(x)
|
||||||
|
return ObjectInputStream(ByteArrayInputStream(out1.toByteArray())).readObject() as T
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Base1.java
|
||||||
|
public interface Base1<T1> {
|
||||||
|
String get(T1 s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Base2.java
|
||||||
|
public interface Base2<T2 extends CharSequence> {
|
||||||
|
String get(T2 s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: Sam.java
|
||||||
|
public interface Sam extends Base1<String>, Base2<String>, java.io.Serializable {
|
||||||
|
}
|
||||||
+148
@@ -22863,6 +22863,154 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Serializable {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipleTopLevelFunRefs.kt")
|
||||||
|
public void testMultipleTopLevelFunRefs() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/multipleTopLevelFunRefs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("sameImplMethodDifferentInterfaces.kt")
|
||||||
|
public void testSameImplMethodDifferentInterfaces() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/sameImplMethodDifferentInterfaces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundClassMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundInnerConstructorRef.kt")
|
||||||
|
public void testSerializableBoundInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRef.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRefPrimitiveReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableClassMemberFunRef.kt")
|
||||||
|
public void testSerializableClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableConstructorRef.kt")
|
||||||
|
public void testSerializableConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableFakeOverrideFunRef.kt")
|
||||||
|
public void testSerializableFakeOverrideFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableFakeOverrideFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableInnerConstructorRef.kt")
|
||||||
|
public void testSerializableInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableJavaStaticMethodRef.kt")
|
||||||
|
public void testSerializableJavaStaticMethodRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableJavaStaticMethodRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambda.kt")
|
||||||
|
public void testSerializableLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingBoxedInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingBoxedInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingBoxedInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassInt.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassInt() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassInt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingNullableInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingNullableInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingNullableInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaToKotlinInterface.kt")
|
||||||
|
public void testSerializableLambdaToKotlinInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaToKotlinInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaWithCapture.kt")
|
||||||
|
public void testSerializableLambdaWithCapture() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaWithCapture.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableTopLevelFunRef.kt")
|
||||||
|
public void testSerializableTopLevelFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableTopLevelFunRefAsGenericInterface.kt")
|
||||||
|
public void testSerializableTopLevelFunRefAsGenericInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRefAsGenericInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableWithBridge.kt")
|
||||||
|
public void testSerializableWithBridge() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableWithBridge.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+148
@@ -23001,6 +23001,154 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Serializable {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipleTopLevelFunRefs.kt")
|
||||||
|
public void testMultipleTopLevelFunRefs() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/multipleTopLevelFunRefs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("sameImplMethodDifferentInterfaces.kt")
|
||||||
|
public void testSameImplMethodDifferentInterfaces() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/sameImplMethodDifferentInterfaces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundClassMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundInnerConstructorRef.kt")
|
||||||
|
public void testSerializableBoundInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRef.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRefPrimitiveReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableClassMemberFunRef.kt")
|
||||||
|
public void testSerializableClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableConstructorRef.kt")
|
||||||
|
public void testSerializableConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableFakeOverrideFunRef.kt")
|
||||||
|
public void testSerializableFakeOverrideFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableFakeOverrideFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableInnerConstructorRef.kt")
|
||||||
|
public void testSerializableInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableJavaStaticMethodRef.kt")
|
||||||
|
public void testSerializableJavaStaticMethodRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableJavaStaticMethodRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambda.kt")
|
||||||
|
public void testSerializableLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingBoxedInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingBoxedInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingBoxedInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassInt.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassInt() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassInt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaCapturingNullableInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingNullableInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingNullableInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaToKotlinInterface.kt")
|
||||||
|
public void testSerializableLambdaToKotlinInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaToKotlinInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableLambdaWithCapture.kt")
|
||||||
|
public void testSerializableLambdaWithCapture() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaWithCapture.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableTopLevelFunRef.kt")
|
||||||
|
public void testSerializableTopLevelFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableTopLevelFunRefAsGenericInterface.kt")
|
||||||
|
public void testSerializableTopLevelFunRefAsGenericInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRefAsGenericInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("serializableWithBridge.kt")
|
||||||
|
public void testSerializableWithBridge() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableWithBridge.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+128
@@ -19158,6 +19158,134 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Serializable extends AbstractLightAnalysisModeTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleTopLevelFunRefs.kt")
|
||||||
|
public void testMultipleTopLevelFunRefs() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/multipleTopLevelFunRefs.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sameImplMethodDifferentInterfaces.kt")
|
||||||
|
public void testSameImplMethodDifferentInterfaces() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/sameImplMethodDifferentInterfaces.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableBoundClassMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableBoundInnerConstructorRef.kt")
|
||||||
|
public void testSerializableBoundInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableBoundInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableBoundInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRef.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt")
|
||||||
|
public void testSerializableBoundTopLevelExtensionFunRefPrimitiveReceiver() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableBoundTopLevelExtensionFunRefPrimitiveReceiver.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableClassMemberFunRef.kt")
|
||||||
|
public void testSerializableClassMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableClassMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableConstructorRef.kt")
|
||||||
|
public void testSerializableConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableFakeOverrideFunRef.kt")
|
||||||
|
public void testSerializableFakeOverrideFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableFakeOverrideFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableInnerConstructorRef.kt")
|
||||||
|
public void testSerializableInnerConstructorRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInnerConstructorRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableInterfaceMemberFunRef.kt")
|
||||||
|
public void testSerializableInterfaceMemberFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableInterfaceMemberFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableJavaStaticMethodRef.kt")
|
||||||
|
public void testSerializableJavaStaticMethodRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableJavaStaticMethodRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableLambda.kt")
|
||||||
|
public void testSerializableLambda() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambda.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableLambdaCapturingBoxedInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingBoxedInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingBoxedInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableLambdaCapturingInlineClassInt.kt")
|
||||||
|
public void testSerializableLambdaCapturingInlineClassInt() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingInlineClassInt.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableLambdaCapturingNullableInlineClassAny.kt")
|
||||||
|
public void testSerializableLambdaCapturingNullableInlineClassAny() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaCapturingNullableInlineClassAny.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableLambdaToKotlinInterface.kt")
|
||||||
|
public void testSerializableLambdaToKotlinInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaToKotlinInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableLambdaWithCapture.kt")
|
||||||
|
public void testSerializableLambdaWithCapture() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableLambdaWithCapture.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableTopLevelFunRef.kt")
|
||||||
|
public void testSerializableTopLevelFunRef() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRef.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableTopLevelFunRefAsGenericInterface.kt")
|
||||||
|
public void testSerializableTopLevelFunRefAsGenericInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableTopLevelFunRefAsGenericInterface.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("serializableWithBridge.kt")
|
||||||
|
public void testSerializableWithBridge() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/invokedynamic/serializable/serializableWithBridge.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ir")
|
@TestMetadata("compiler/testData/codegen/box/ir")
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+13
@@ -16152,6 +16152,19 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Serializable extends AbstractIrJsCodegenBoxES6Test {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ir")
|
@TestMetadata("compiler/testData/codegen/box/ir")
|
||||||
|
|||||||
Generated
+13
@@ -15558,6 +15558,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Serializable extends AbstractIrJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ir")
|
@TestMetadata("compiler/testData/codegen/box/ir")
|
||||||
|
|||||||
Generated
+13
@@ -15588,6 +15588,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Serializable extends AbstractJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ir")
|
@TestMetadata("compiler/testData/codegen/box/ir")
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+13
@@ -14884,6 +14884,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/invokedynamic/serializable")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Serializable extends AbstractIrCodegenBoxWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInSerializable() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/invokedynamic/serializable"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/ir")
|
@TestMetadata("compiler/testData/codegen/box/ir")
|
||||||
|
|||||||
Reference in New Issue
Block a user