JVM_IR. support big arity

This commit is contained in:
Georgy Bronnikov
2018-08-31 12:00:32 +03:00
parent 03f092fd39
commit f04733ef33
22 changed files with 473 additions and 37 deletions
@@ -169,6 +169,8 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
abstract val coroutineSuspendedGetter: IrSimpleFunctionSymbol
fun getFunction(parameterCount: Int) = symbolTable.referenceClass(context.builtIns.getFunction(parameterCount))
val functionReference = calc { symbolTable.referenceClass(context.getInternalClass("FunctionReference")) }
fun getFunction(name: Name, receiverType: KotlinType, vararg argTypes: KotlinType) =
@@ -57,6 +57,7 @@ class JvmLower(val context: JvmBackendContext) {
true
).runOnFilePostfix(irFile)
CallableReferenceLowering(context).lower(irFile)
FunctionNVarargInvokeLowering(context).runOnFilePostfix(irFile)
InnerClassesLowering(context).runOnFilePostfix(irFile)
InnerClassConstructorCallsLowering(context).runOnFilePostfix(irFile)
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.backend.jvm.intrinsics
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
class IrIllegalArgumentException : IntrinsicMethod() {
val exceptionTypeDescriptor = Type.getInternalName(IllegalArgumentException::class.java)
override fun toCallable(
expression: IrMemberAccessExpression,
signature: JvmMethodSignature,
context: JvmBackendContext
): IrIntrinsicFunction {
return object : IrIntrinsicFunction(expression, signature, context, listOf(JAVA_STRING_TYPE)) {
override fun genInvokeInstruction(v: InstructionAdapter) {
v.invokespecial(exceptionTypeDescriptor, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, JAVA_STRING_TYPE), false)
v.athrow()
}
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
v.anew(Type.getType(exceptionTypeDescriptor))
v.dup()
return super.invoke(v, codegen, data)
}
}
}
}
@@ -52,6 +52,7 @@ class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) {
irMapping[irBuiltIns.enumValueOf] = IrEnumValueOf()
irMapping[irBuiltIns.noWhenBranchMatchedException] = IrNoWhenBranchMatchedException()
irMapping[irBuiltIns.illegalArgumentException] = IrIllegalArgumentException()
irMapping[irBuiltIns.throwNpe] = ThrowNPE()
}
@@ -37,20 +37,14 @@ import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.types.toIrType
import org.jetbrains.kotlin.ir.types.toKotlinType
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.JavaVisibilities
@@ -99,8 +93,41 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
}
}
val argumentsCount = expression.valueArgumentsCount
// Change calls to FunctionN with large N to varargs calls.
val newCall = if (argumentsCount > MAX_ARGCOUNT_WITHOUT_VARARG &&
descriptor.containingDeclaration in listOf(
context.builtIns.getFunction(argumentsCount),
context.reflectionTypes.getKFunction(argumentsCount)
)
) {
val vararg = IrVarargImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
context.ir.symbols.array.typeWith(),
context.ir.symbols.any.typeWith(),
(0 until argumentsCount).map { i -> expression.getValueArgument(i)!! }
)
val invokeFunDescriptor = context.getClass(FqName("kotlin.jvm.functions.FunctionN"))
.getFunction("invoke", listOf(expression.type.toKotlinType()))
val invokeFunSymbol = context.ir.symbols.externalSymbolTable.referenceSimpleFunction(invokeFunDescriptor)
IrCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
expression.type,
invokeFunSymbol, invokeFunDescriptor,
1,
expression.origin,
expression.superQualifier?.let { context.ir.symbols.externalSymbolTable.referenceClass(it) }
).apply {
putTypeArgument(0, expression.type)
dispatchReceiver = expression.dispatchReceiver
extensionReceiver = expression.extensionReceiver
putValueArgument(0, vararg)
}
} else expression
//TODO: clean
return super.visitCall(expression)
return super.visitCall(newCall)
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
@@ -155,6 +182,8 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
private val functionReferenceOrLambda = if (isLambda) context.ir.symbols.lambdaClass else context.ir.symbols.functionReference
var useVararg: Boolean = false
fun build(): BuiltFunctionReference {
val startOffset = irFunctionReference.startOffset
val endOffset = irFunctionReference.endOffset
@@ -165,9 +194,17 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
)
val numberOfParameters = unboundFunctionParameters.size
val functionClassDescriptor = context.getClass(FqName("kotlin.jvm.functions.Function$numberOfParameters"))
useVararg = (numberOfParameters > MAX_ARGCOUNT_WITHOUT_VARARG)
val functionClassDescriptor = if (useVararg)
context.getClass(FqName("kotlin.jvm.functions.FunctionN"))
else
context.getClass(FqName("kotlin.jvm.functions.Function$numberOfParameters"))
val functionParameterTypes = unboundFunctionParameters.map { it.type }
val functionClassTypeParameters = functionParameterTypes + returnType
val functionClassTypeParameters = if (useVararg)
listOf(returnType)
else
functionParameterTypes + returnType
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters)
var suspendFunctionClassDescriptor: ClassDescriptor? = null
@@ -197,7 +234,17 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
endOffset = endOffset,
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
descriptor = functionReferenceClassDescriptor
)
).apply {
createParameterDeclarations()
val typeTranslator = TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings,
enterTableScope=true)
val constantValueGenerator = ConstantValueGenerator(context.state.module, context.ir.symbols.externalSymbolTable)
typeTranslator.constantValueGenerator = constantValueGenerator
constantValueGenerator.typeTranslator = typeTranslator
functionReferenceClassDescriptor.typeConstructor.supertypes.mapTo(this.superTypes) {
typeTranslator.translateType(it)
}
}
val contributedDescriptors = mutableListOf<DeclarationDescriptor>()
val constructorBuilder = createConstructorBuilder()
@@ -205,8 +252,6 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null
)
functionReferenceClass.createParameterDeclarations()
functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol
val invokeFunctionDescriptor = functionClassDescriptor.getFunction("invoke", functionClassTypeParameters)
@@ -219,7 +264,6 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
invokeMethodBuilder.initialize()
functionReferenceClass.declarations.add(invokeMethodBuilder.ir)
if (!isLambda) {
val getSignatureBuilder =
createGetSignatureMethodBuilder(functionReferenceOrLambda.owner.descriptor.getFunction("getSignature", emptyList()))
@@ -245,7 +289,6 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
).filterNotNull()
)
getSignatureBuilder.initialize()
functionReferenceClass.declarations.add(getSignatureBuilder.ir)
@@ -391,31 +434,74 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
createParameterDeclarations()
body = irBuilder.irBlockBody(startOffset, endOffset) {
val arrayGetFun = context.irBuiltIns.arrayClass.owner
.declarations.find {
(it as? IrSimpleFunction)?.name?.toString() == "get"
}!! as IrSimpleFunction
if (useVararg) {
val varargParam = valueParameters.single()
val arraySizeProperty = context.irBuiltIns.arrayClass.owner.declarations.find {
(it as? IrProperty)?.name?.toString() == "size"
} as IrProperty
+irIfThen(
irNotEquals(
irCall(arraySizeProperty.getter!!).apply {
dispatchReceiver = irGet(varargParam)
},
irInt(unboundFunctionParameters.size)
),
irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply {
putValueArgument(0, irString("Expected ${unboundFunctionParameters.size} arguments"))
}
)
}
+irReturn(
irCall(irFunctionReference.symbol).apply {
var unboundIndex = 0
val unboundArgsSet = unboundFunctionParameters.toSet()
functionParameters.forEach {
val argument =
if (!unboundArgsSet.contains(it))
// Bound parameter - read from field.
irGetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[it]!!.owner)
else {
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
functionParameters.forEach { parameter ->
val argument = when {
!unboundArgsSet.contains(parameter) ->
// Bound parameter - read from field.
irGetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[parameter]!!.owner)
ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size ->
// For suspend functions the last argument is continuation and it is implicit.
TODO()
TODO()
// irCall(getContinuationSymbol,
// listOf(ourSymbol.descriptor.returnType!!))
else
irGet(valueParameters[unboundIndex++])
useVararg -> {
val type = parameter.type.toIrType()!!
val varargParam = valueParameters.single()
irBlock(resultType = type) {
val argValue = irTemporary(
irCall(arrayGetFun).apply {
dispatchReceiver = irGet(varargParam)
putValueArgument(0, irInt(unboundIndex++))
}
)
+irIfThen(
irNotIs(irGet(argValue), type),
irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply {
putValueArgument(0, irString("Wrong type, expected $type"))
}
)
+irGet(argValue)
}
}
when (it) {
else -> {
irGet(valueParameters[unboundIndex++])
}
}
when (parameter) {
functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument
functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
else -> putValueArgument((parameter as ValueParameterDescriptor).index, argument)
}
}
assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
if (!useVararg) assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
}
)
}
@@ -703,6 +789,10 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
Name.identifier("$${name.substring(1, name.length - 1)}")
} else this
}
companion object {
const val MAX_ARGCOUNT_WITHOUT_VARARG = 22
}
}
// Copied from K/Native IrUtils2.kt
@@ -0,0 +1,144 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.filterDeclarations
import org.jetbrains.kotlin.ir.util.findDeclaration
import org.jetbrains.kotlin.ir.util.isSubclassOf
import org.jetbrains.kotlin.name.Name
class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : ClassLoweringPass {
override fun lower(irClass: IrClass) {
val invokeFunctions = irClass.filterDeclarations<IrSimpleFunction> { it.name.toString() == "invoke" }
if (invokeFunctions.isEmpty() ||
invokeFunctions.any { it.valueParameters.size > 0 && it.valueParameters.last().varargElementType != null } ||
invokeFunctions.all { it.valueParameters.size + (if (it.extensionReceiverParameter != null) 1 else 0) <= CallableReferenceLowering.MAX_ARGCOUNT_WITHOUT_VARARG }
) {
// No need to add a new vararg invoke method
return
}
val functionInvokes = invokeFunctions.filter { irClass.isSubclassOf(context.ir.symbols.getFunction(it.valueParameters.size).owner) }
if (functionInvokes.isEmpty()) return
irClass.declarations.add(generateVarargInvoke(irClass, functionInvokes))
}
private fun generateVarargInvoke(irClass: IrClass, invokesToDelegateTo: List<IrSimpleFunction>): IrFunction {
val backendContext = context
val descriptor = WrappedSimpleFunctionDescriptor()
return IrFunctionImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
origin = CallableReferenceLowering.DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
symbol = IrSimpleFunctionSymbolImpl(descriptor),
name = Name.identifier("invoke"),
visibility = Visibilities.PUBLIC,
modality = Modality.OPEN,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = false
).apply {
descriptor.bind(this)
returnType = context.irBuiltIns.anyNType
dispatchReceiverParameter = irClass.thisReceiver
val varargParameterDescriptor = WrappedValueParameterDescriptor()
val varargParam = IrValueParameterImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
origin = CallableReferenceLowering.DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
symbol = IrValueParameterSymbolImpl(varargParameterDescriptor),
name = Name.identifier("args"),
index = 0,
type = context.irBuiltIns.arrayClass.typeWith(),
varargElementType = context.irBuiltIns.anyClass.typeWith(),
isCrossinline = false,
isNoinline = false
).apply {
varargParameterDescriptor.bind(this)
}
valueParameters.add(varargParam)
val irBuilder = context.createIrBuilder(symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET)
body = irBuilder.irBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
val arrayGetFun =
backendContext.irBuiltIns.arrayClass.owner.findDeclaration<IrSimpleFunction> { it.name.toString() == "get" }!!
val arraySizeProperty = context.irBuiltIns.arrayClass.owner.findDeclaration<IrProperty> { it.name.toString() == "size" }!!
val numberOfArguments = irTemporary(irCall(arraySizeProperty.getter!!).apply {
dispatchReceiver = irGet(varargParam)
})
for (target in invokesToDelegateTo) {
+irIfThen(
backendContext.irBuiltIns.unitType,
irEquals(irGet(numberOfArguments), irInt(target.valueParameters.size)),
irReturn(
IrTypeOperatorCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
backendContext.irBuiltIns.anyNType,
IrTypeOperator.CAST,
target.returnType,
target.returnType.classifierOrFail,
irCall(target).apply {
dispatchReceiver = irGet(irClass.thisReceiver!!)
target.valueParameters.forEachIndexed { i, irValueParameter ->
val type = irValueParameter.type
putValueArgument(
i,
irBlock(resultType = type) {
val argValue = irTemporary(
irCallOp(
arrayGetFun.symbol,
context.irBuiltIns.anyNType,
irGet(varargParam),
irInt(i)
)
)
+irIfThen(
irNotIs(irGet(argValue), type),
irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply {
putValueArgument(0, irString("Wrong type, expected $type"))
}
)
+irGet(argValue)
}
)
}
}
)
)
)
}
val throwMessage = invokesToDelegateTo.map { it.valueParameters.size.toString() }.joinToString(
prefix = "Expected ",
separator = " or ",
postfix = " arguments to invoke call"
)
+irCall(context.irBuiltIns.illegalArgumentExceptionFun.symbol).apply {
putValueArgument(0, irString(throwMessage))
}
}
}
}
}
@@ -124,6 +124,8 @@ class IrBuiltIns(
val stringType = string.toIrType()
val stringClass = builtIns.string.toIrSymbol()
val arrayClass = builtIns.array.toIrSymbol()
val throwableType = builtIns.throwable.defaultType.toIrType()
val throwableClass = builtIns.throwable.toIrSymbol()
@@ -152,6 +154,7 @@ class IrBuiltIns(
val throwIseFun = defineOperator("THROW_ISE", nothing, listOf())
val booleanNotFun = defineOperator("NOT", bool, listOf(bool))
val noWhenBranchMatchedExceptionFun = defineOperator("noWhenBranchMatchedException", nothing, listOf())
val illegalArgumentExceptionFun = defineOperator("illegalArgumentException", nothing, listOf(string))
val eqeqeq = eqeqeqFun.descriptor
val eqeq = eqeqFun.descriptor
@@ -159,6 +162,7 @@ class IrBuiltIns(
val throwCce = throwCceFun.descriptor
val booleanNot = booleanNotFun.descriptor
val noWhenBranchMatchedException = noWhenBranchMatchedExceptionFun.descriptor
val illegalArgumentException = illegalArgumentExceptionFun.descriptor
val eqeqeqSymbol = eqeqeqFun.symbol
val eqeqSymbol = eqeqFun.symbol
@@ -167,6 +171,7 @@ class IrBuiltIns(
val throwIseSymbol = throwIseFun.symbol
val booleanNotSymbol = booleanNotFun.symbol
val noWhenBranchMatchedExceptionSymbol = noWhenBranchMatchedExceptionFun.symbol
val illegalArgumentExceptionSymbol = illegalArgumentExceptionFun.symbol
val enumValueOfFun = createEnumValueOfFun()
val enumValueOf = enumValueOfFun.descriptor
@@ -266,6 +266,26 @@ val IrClass.defaultType: IrType
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
fun IrClass.isImmediateSubClassOf(ancestor: IrClass) = ancestor.symbol in superTypes.mapNotNull {
(it as? IrSimpleType)?.classifier
}
fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
val alreadyVisited = mutableSetOf<IrClass>()
fun IrClass.hasAncestorInSuperTypes(): Boolean = when {
this === ancestor -> true
this in alreadyVisited -> false
else -> {
alreadyVisited.add(this)
superTypes.mapNotNull { ((it as? IrSimpleType)?.classifier as? IrClassSymbol)?.owner }.any { it.hasAncestorInSuperTypes() }
}
}
return this.hasAncestorInSuperTypes()
}
// This implementation is from kotlin-native
// TODO: use this implementation instead of any other
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
@@ -339,6 +359,12 @@ fun IrDeclaration.isEffectivelyExternal(): Boolean {
fun IrDeclaration.isDynamic() = this is IrFunction && dispatchReceiverParameter?.type is IrDynamicType
inline fun <reified T : IrDeclaration> IrDeclarationContainer.findDeclaration(predicate: (T) -> Boolean): T? =
declarations.find { it is T && predicate(it) } as? T
inline fun <reified T : IrDeclaration> IrDeclarationContainer.filterDeclarations(predicate: (T) -> Boolean): List<T> =
declarations.filter { it is T && predicate(it) } as List<T>
fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter {
assert(this.descriptor.type == newDescriptor.type)
@@ -1,7 +1,6 @@
// !LANGUAGE: +FunctionTypesWithBigArity
// WITH_RUNTIME
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// FILE: J.java
import kotlin.jvm.functions.FunctionN;
@@ -0,0 +1,77 @@
// !LANGUAGE: +FunctionTypesWithBigArity
// WITH_RUNTIME
// TARGET_BACKEND: JVM_IR
// FILE: J.java
// import kotlin.jvm.functions.Arity;
import kotlin.jvm.functions.FunctionN;
import kotlin.Unit;
import java.util.Arrays;
public class J {
// TODO: uncomment arity as soon as Arity is introduced
public static void test(/* @Arity(30) */ FunctionN<Integer> f) {
Object o = new Integer(0);
for (int i = 0; i < 42; i++) {
Object[] args = new Object[i];
Arrays.fill(args, o);
try {
if (f.invoke(args).intValue() != 300 + i) {
throw new AssertionError("Bad return value from function");
}
} catch (IllegalArgumentException e) {
if (i == 3 || i == 13 || i == 30 || i == 33) {
throw new AssertionError(String.format("Call with %d arguments is expected to succeed", i), e);
}
// OK
if (!e.getMessage().contains("30")) {
throw new AssertionError("Exception must specify the expected number of arguments: " + e.getMessage(), e);
}
continue;
} catch (Throwable e) {
throw new AssertionError(
"Incorrect exception (IllegalArgumentException expected): " + e.getClass().getName() + ", i = " + i, e
);
}
if (i != 3 && i != 13 && i != 30 && i != 33) {
throw new AssertionError ("IllegalArgumentException expected, but nothing was thrown, i = " + i);
}
}
}
}
// FILE: K.kt
class Fun : (Int, Int, Int) -> Int,
(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Int,
(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Int,
(Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int,
Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Int {
override fun invoke(p00: Int, p01: Int, p02: Int): Int = 303
override fun invoke(
p00: Int, p01: Int, p02: Int, p03: Int, p04: Int, p05: Int, p06: Int, p07: Int, p08: Int, p09: Int,
p10: Int, p11: Int, p12: Int
): Int = 313
override fun invoke(
p00: Int, p01: Int, p02: Int, p03: Int, p04: Int, p05: Int, p06: Int, p07: Int, p08: Int, p09: Int,
p10: Int, p11: Int, p12: Int, p13: Int, p14: Int, p15: Int, p16: Int, p17: Int, p18: Int, p19: Int,
p20: Int, p21: Int, p22: Int, p23: Int, p24: Int, p25: Int, p26: Int, p27: Int, p28: Int, p29: Int
): Int = 330
override fun invoke(
p00: Int, p01: Int, p02: Int, p03: Int, p04: Int, p05: Int, p06: Int, p07: Int, p08: Int, p09: Int,
p10: Int, p11: Int, p12: Int, p13: Int, p14: Int, p15: Int, p16: Int, p17: Int, p18: Int, p19: Int,
p20: Int, p21: Int, p22: Int, p23: Int, p24: Int, p25: Int, p26: Int, p27: Int, p28: Int, p29: Int,
p30: Int, p31: Int, p32: Int
): Int = 333
}
fun box(): String {
J.test(Fun() as kotlin.jvm.functions.FunctionN<Int>)
return "OK"
}
@@ -1,7 +1,6 @@
// !LANGUAGE: +FunctionTypesWithBigArity
// WITH_RUNTIME
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// FILE: J.java
// import kotlin.jvm.functions.Arity;
@@ -1,6 +1,5 @@
// !LANGUAGE: +FunctionTypesWithBigArity
// IGNORE_BACKEND: JS_IR
// IGNORE_BACKEND: JVM_IR
class A(val value: Int) {
// for (i in 1..254) { print("p${"%03d".format(i)}: A, "); if (i % 10 == 0) println() }; println()
@@ -1,5 +1,4 @@
// !LANGUAGE: +FunctionTypesWithBigArity
// IGNORE_BACKEND: JVM_IR
class A
@@ -1,5 +1,4 @@
// !LANGUAGE: +FunctionTypesWithBigArity
// IGNORE_BACKEND: JVM_IR
class A(val value: Int)
@@ -0,0 +1,17 @@
// !LANGUAGE: +FunctionTypesWithBigArity
class A {
fun foo(
p00: A, p01: A, p02: A, p03: A, p04: A, p05: A, p06: A, p07: A, p08: A, p09: A,
p10: A, p11: A, p12: A, p13: A, p14: A, p15: A, p16: A, p17: A, p18: A, p19: A,
p20: A, p21: A, p22: A, p23: A, p24: A, p25: A, p26: A, p27: A, p28: A, p29: A
): String {
return "OK"
}
}
fun box(): String {
val a = A()
val ref = a::foo
return ref(a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a)
}
@@ -1,7 +1,6 @@
// !LANGUAGE: +FunctionTypesWithBigArity
// WITH_RUNTIME
// TARGET_BACKEND: JVM
// IGNORE_BACKEND: JVM_IR
// FILE: J.java
// import kotlin.jvm.functions.Arity;
@@ -1,9 +1,8 @@
// !LANGUAGE: -FunctionTypesWithBigArity
// IGNORE_BACKEND: JVM_IR
// This test does not make sense for JVM because a diagnostic is reported when function types with big arity are not available
// (see diagnostics/tests/sourceCompatibility/noBigFunctionTypes.kt)
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: JVM, JVM_IR
class A
@@ -10729,6 +10729,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
}
@TestMetadata("invokeMemberCallableReference.kt")
public void testInvokeMemberCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeMemberCallableReference.kt");
}
@TestMetadata("javaLambda.kt")
public void testJavaLambda() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/javaLambda.kt");
@@ -10734,6 +10734,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
}
@TestMetadata("invokeMemberCallableReference.kt")
public void testInvokeMemberCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeMemberCallableReference.kt");
}
@TestMetadata("javaLambda.kt")
public void testJavaLambda() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/javaLambda.kt");
@@ -10704,6 +10704,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/functions/bigArity/callFromJava.kt");
}
@TestMetadata("callFunViaVararg.kt")
public void testCallFunViaVararg() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/callFunViaVararg.kt");
}
@TestMetadata("callWithIncorrectNumberOfArguments.kt")
public void testCallWithIncorrectNumberOfArguments() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/callWithIncorrectNumberOfArguments.kt");
@@ -10729,6 +10734,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
}
@TestMetadata("invokeMemberCallableReference.kt")
public void testInvokeMemberCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeMemberCallableReference.kt");
}
@TestMetadata("javaLambda.kt")
public void testJavaLambda() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/javaLambda.kt");
@@ -9279,6 +9279,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
}
@TestMetadata("invokeMemberCallableReference.kt")
public void testInvokeMemberCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeMemberCallableReference.kt");
}
@TestMetadata("noBigFunctionTypes.kt")
public void testNoBigFunctionTypes() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/noBigFunctionTypes.kt");
@@ -10344,6 +10344,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeLambda.kt");
}
@TestMetadata("invokeMemberCallableReference.kt")
public void testInvokeMemberCallableReference() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/invokeMemberCallableReference.kt");
}
@TestMetadata("noBigFunctionTypes.kt")
public void testNoBigFunctionTypes() throws Exception {
runTest("compiler/testData/codegen/box/functions/bigArity/noBigFunctionTypes.kt");