JVM_IR: make CallableReferenceLowering a bit shorter

This commit is contained in:
pyos
2019-06-12 10:25:00 +02:00
committed by Georgy Bronnikov
parent 6d63214d1b
commit b45e8c7021
2 changed files with 88 additions and 223 deletions
@@ -31,21 +31,15 @@ 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.isInlineFunctionCall import org.jetbrains.kotlin.backend.jvm.codegen.isInlineFunctionCall
import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression import org.jetbrains.kotlin.backend.jvm.codegen.isInlineIrExpression
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isPrimaryInlineClassConstructor import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
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.buildClass import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildField
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
@@ -88,13 +82,11 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
val callee = expression.symbol.owner val callee = expression.symbol.owner
if (callee.isInlineFunctionCall(context)) { if (callee.isInlineFunctionCall(context)) {
//TODO: more wise filtering //TODO: more wise filtering
callee.valueParameters.forEach { valueParameter -> for (valueParameter in callee.valueParameters) {
if (valueParameter.isInlineParameter()) { if (valueParameter.isInlineParameter()) {
expression.getValueArgument(valueParameter.index)?.let { expression.getValueArgument(valueParameter.index)?.let {
if (isInlineIrExpression(it)) { if (isInlineIrExpression(it)) {
(it as IrBlock).statements.filterIsInstance<IrFunctionReference>().forEach { reference -> inlineLambdaReferences += (it as IrBlock).statements.filterIsInstance<IrFunctionReference>()
inlineLambdaReferences.add(reference)
}
} }
} }
} }
@@ -103,7 +95,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
val argumentsCount = expression.valueArgumentsCount val argumentsCount = expression.valueArgumentsCount
// Change calls to FunctionN with large N to varargs calls. // Change calls to FunctionN with large N to varargs calls.
val newCall = if (argumentsCount > MAX_ARGCOUNT_WITHOUT_VARARG && val newCall = if (argumentsCount >= FunctionInvokeDescriptor.Factory.BIG_ARITY &&
callee.parentAsClass.defaultType.isFunctionOrKFunction() callee.parentAsClass.defaultType.isFunctionOrKFunction()
) { ) {
val vararg = IrVarargImpl( val vararg = IrVarargImpl(
@@ -145,8 +137,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
val currentDeclarationParent = allScopes.map { it.irElement }.last { it is IrDeclarationParent } as IrDeclarationParent val currentDeclarationParent = allScopes.map { it.irElement }.last { it is IrDeclarationParent } as IrDeclarationParent
val loweredFunctionReference = FunctionReferenceBuilder(currentDeclarationParent, expression).build() val loweredFunctionReference = FunctionReferenceBuilder(currentDeclarationParent, expression).build()
val irBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol, expression.startOffset, expression.endOffset) return context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol).irBlock(expression) {
return irBuilder.irBlock(expression) {
+loweredFunctionReference.functionReferenceClass +loweredFunctionReference.functionReferenceClass
+irCall(loweredFunctionReference.functionReferenceConstructor.symbol).apply { +irCall(loweredFunctionReference.functionReferenceConstructor.symbol).apply {
expression.getArguments().forEachIndexed { index, argument -> expression.getArguments().forEachIndexed { index, argument ->
@@ -158,6 +149,14 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
}) })
} }
private val arrayGetFun by lazy {
context.irBuiltIns.arrayClass.owner.functions.find { it.name.asString() == "get" }!!
}
private val arraySizeProperty by lazy {
context.irBuiltIns.arrayClass.owner.properties.find { it.name.toString() == "size" }!!
}
private class BuiltFunctionReference( private class BuiltFunctionReference(
val functionReferenceClass: IrClass, val functionReferenceClass: IrClass,
val functionReferenceConstructor: IrConstructor val functionReferenceConstructor: IrConstructor
@@ -182,7 +181,6 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
} }
private lateinit var functionReferenceClass: IrClass private lateinit var functionReferenceClass: IrClass
private lateinit var functionReferenceThis: IrValueParameterSymbol
private lateinit var argumentToFieldMap: Map<IrValueParameter, IrField> private lateinit var argumentToFieldMap: Map<IrValueParameter, IrField>
private val isLambda = irFunctionReference.origin == IrStatementOrigin.LAMBDA private val isLambda = irFunctionReference.origin == IrStatementOrigin.LAMBDA
@@ -196,13 +194,12 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
val functionReferenceClassSuperTypes: MutableList<IrType> = mutableListOf(functionReferenceOrLambda.owner.defaultType) val functionReferenceClassSuperTypes: MutableList<IrType> = mutableListOf(functionReferenceOrLambda.owner.defaultType)
val numberOfParameters = unboundCalleeParameters.size val numberOfParameters = unboundCalleeParameters.size
useVararg = (numberOfParameters > MAX_ARGCOUNT_WITHOUT_VARARG) useVararg = (numberOfParameters >= FunctionInvokeDescriptor.Factory.BIG_ARITY)
val functionClassSymbol = if (useVararg) val functionClassSymbol = if (useVararg)
context.ir.symbols.functionN context.ir.symbols.functionN
else else
context.ir.symbols.getJvmFunctionClass(numberOfParameters) context.ir.symbols.getJvmFunctionClass(numberOfParameters)
val functionClass = functionClassSymbol.owner
val functionParameterTypes = unboundCalleeParameters.map { it.type } val functionParameterTypes = unboundCalleeParameters.map { it.type }
val functionClassTypeParameters = if (useVararg) val functionClassTypeParameters = if (useVararg)
listOf(returnType) listOf(returnType)
@@ -236,88 +233,53 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
setSourceRange(irFunctionReference) setSourceRange(irFunctionReference)
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
name = "${callee.name.safeName()}\$${functionReferenceCount++}".synthesizedName name = "${callee.name.safeName()}\$${functionReferenceCount++}".synthesizedName
kind = ClassKind.CLASS
visibility = Visibilities.PUBLIC
modality = Modality.FINAL
}.apply { }.apply {
parent = referenceParent parent = referenceParent
superTypes.addAll(functionReferenceClassSuperTypes) superTypes.addAll(functionReferenceClassSuperTypes)
createImplicitParameterDeclarationWithWrappedDescriptor() createImplicitParameterDeclarationWithWrappedDescriptor()
} }
functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol
argumentToFieldMap = boundCalleeParameters.associate { argumentToFieldMap = boundCalleeParameters.associate {
it to buildField(it.name.safeName(), it.type) it to buildField(it.name.safeName(), it.type)
} }
val constructor = createConstructor() val constructor = createConstructor()
functionReferenceClass.declarations.add(constructor) createInvokeMethod(functionClassSymbol.owner.functions.find { it.name.asString() == "invoke" }!!)
val superInvokeFunction = functionClass.functions.find { it.name.asString() == "invoke" }!!
val invokeMethod = createInvokeMethod(superInvokeFunction)
functionReferenceClass.declarations.add(invokeMethod)
if (!isLambda) { if (!isLambda) {
val getSignatureMethod = createGetSignatureMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getSignature"}!!)
createGetSignatureMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getSignature"}!!) createGetNameMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getName" }!!)
val getNameMethod = createGetOwnerMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getOwner" }!!)
createGetNameMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getName" }!!) if (suspendFunctionClass != null) {
val getOwnerMethod = createInvokeMethod(suspendFunctionClass.functions.find { it.name.asString() == "invoke" }!!)
createGetOwnerMethod(functionReferenceOrLambda.owner.functions.find { it.name.asString() == "getOwner" }!!) }
val suspendInvokeMethod =
if (suspendFunctionClass != null) {
val suspendInvokeFunction =
suspendFunctionClass.functions.find { it.name.asString() == "invoke" }!!
createInvokeMethod(suspendInvokeFunction)
} else null
functionReferenceClass.declarations.add(getSignatureMethod)
functionReferenceClass.declarations.add(getNameMethod)
functionReferenceClass.declarations.add(getOwnerMethod)
suspendInvokeMethod?.let { functionReferenceClass.declarations.add(it) }
} }
return BuiltFunctionReference(functionReferenceClass, constructor) return BuiltFunctionReference(functionReferenceClass, constructor)
} }
private fun createConstructor(): IrConstructor = private fun createConstructor(): IrConstructor =
buildConstructor { functionReferenceClass.addConstructor {
setSourceRange(irFunctionReference) setSourceRange(irFunctionReference)
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
visibility = Visibilities.PUBLIC visibility = Visibilities.PUBLIC
returnType = functionReferenceClass.defaultType returnType = functionReferenceClass.defaultType
isPrimary = true isPrimary = true
}.apply { }.apply {
val constructor = this for (param in boundCalleeParameters) {
parent = functionReferenceClass valueParameters += param.copyTo(
this,
val boundArgsSet = boundCalleeParameters.toSet() index = valueParameters.size,
for (param in callee.explicitParameters) { type = param.type.substitute(typeArgumentsMap)
if (param in boundArgsSet) { )
val newParam = param.copyTo(
constructor,
index = valueParameters.size,
type = param.type.substitute(typeArgumentsMap)
)
valueParameters.add(newParam)
}
} }
val kFunctionRefConstructorSymbol = val kFunctionRefConstructorSymbol =
functionReferenceOrLambda.constructors.filter { it.owner.valueParameters.size == if (isLambda) 1 else 2 }.single() functionReferenceOrLambda.constructors.filter { it.owner.valueParameters.size == if (isLambda) 1 else 2 }.single()
val irBuilder = context.createIrBuilder(this.symbol, startOffset, endOffset) body = context.createIrBuilder(symbol).irBlockBody(startOffset, endOffset) {
body = irBuilder.irBlockBody { +irDelegatingConstructorCall(kFunctionRefConstructorSymbol.owner).apply {
+IrDelegatingConstructorCallImpl( putValueArgument(0, irInt(unboundCalleeParameters.size))
startOffset, endOffset, context.irBuiltIns.unitType,
kFunctionRefConstructorSymbol, kFunctionRefConstructorSymbol.descriptor
).apply {
val const =
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, unboundCalleeParameters.size)
putValueArgument(0, const)
if (!isLambda) { if (!isLambda) {
val irReceiver = valueParameters.firstOrNull() val irReceiver = valueParameters.firstOrNull()
val receiver = boundCalleeParameters.singleOrNull() val receiver = boundCalleeParameters.singleOrNull()
@@ -333,7 +295,7 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
//TODO don't write receiver again: use it from base class //TODO don't write receiver again: use it from base class
boundCalleeParameters.forEachIndexed { index, it -> boundCalleeParameters.forEachIndexed { index, it ->
+irSetField( +irSetField(
irGet(functionReferenceThis.owner), irGet(functionReferenceClass.thisReceiver!!),
argumentToFieldMap[it]!!, argumentToFieldMap[it]!!,
irGet(valueParameters[index]) irGet(valueParameters[index])
) )
@@ -342,61 +304,27 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
} }
} }
private fun IrSimpleFunction.invokeInlineClassConstructor(irConstructor: IrConstructor): IrBody {
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
val param = irConstructor.valueParameters[0].copyTo(this)
valueParameters.add(param)
val from = irConstructor.valueParameters[0].type
val to = irConstructor.returnType
val call = irBuilder.irCall(context.ir.symbols.unsafeCoerceIntrinsicSymbol, to, listOf(from, to)).apply {
putValueArgument(0, irBuilder.irGet(param))
}
return irBuilder.irExprBody(call)
}
private fun createInvokeMethod(superFunction: IrSimpleFunction): IrSimpleFunction = private fun createInvokeMethod(superFunction: IrSimpleFunction): IrSimpleFunction =
buildFun { buildOverride(superFunction, callee.returnType).apply {
setSourceRange(irFunctionReference)
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
name = Name.identifier("invoke")
visibility = Visibilities.PUBLIC
returnType = callee.returnType
isSuspend = superFunction.isSuspend
}.apply {
val function = this
parent = functionReferenceClass
overriddenSymbols.add(superFunction.symbol)
annotations.addAll(callee.annotations) annotations.addAll(callee.annotations)
dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function)
if (callee.isPrimaryInlineClassConstructor) {
body = invokeInlineClassConstructor(callee as IrConstructor)
return this
}
val unboundArgsSet = unboundCalleeParameters.toSet() val unboundArgsSet = unboundCalleeParameters.toSet()
if (useVararg) { if (useVararg) {
valueParameters.add(superFunction.valueParameters[0].copyTo(function)) valueParameters.add(superFunction.valueParameters[0].copyTo(this))
} else { } else {
for (param in callee.explicitParameters) { for (param in unboundCalleeParameters) {
if (param in unboundArgsSet) { valueParameters += param.copyTo(
val newParam = param.copyTo( this,
function, index = valueParameters.size,
index = valueParameters.size, type = param.type.substitute(typeArgumentsMap)
type = param.type.substitute(typeArgumentsMap) )
)
valueParameters.add(newParam)
}
} }
} }
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset) val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) { body = irBuilder.irBlockBody(startOffset, endOffset) {
val arrayGetFun = context.irBuiltIns.arrayClass.owner.functions.find { it.name.asString() == "get" }!!
if (useVararg) { if (useVararg) {
val varargParam = valueParameters.single() val varargParam = valueParameters.single()
val arraySizeProperty = context.irBuiltIns.arrayClass.owner.properties.find { it.name.toString() == "size" }!!
+irIfThen( +irIfThen(
irNotEquals( irNotEquals(
irCall(arraySizeProperty.getter!!).apply { irCall(arraySizeProperty.getter!!).apply {
@@ -422,11 +350,12 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
!unboundArgsSet.contains(parameter) -> !unboundArgsSet.contains(parameter) ->
// Bound parameter - read from field. // Bound parameter - read from field.
irGetField(irGet(dispatchReceiverParameter!!), argumentToFieldMap[parameter]!!) irGetField(irGet(dispatchReceiverParameter!!), argumentToFieldMap[parameter]!!)
function.isSuspend && unboundIndex == valueParameters.size ->
isSuspend && unboundIndex == valueParameters.size ->
// For suspend functions the last argument is continuation and it is implicit. // For suspend functions the last argument is continuation and it is implicit.
// irCall(getContinuationSymbol, listOf(ourSymbol.descriptor.returnType!!))
TODO() TODO()
// irCall(getContinuationSymbol,
// listOf(ourSymbol.descriptor.returnType!!))
useVararg -> { useVararg -> {
val type = parameter.type val type = parameter.type
val varargParam = valueParameters.single() val varargParam = valueParameters.single()
@@ -446,14 +375,12 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
+irGet(argValue) +irGet(argValue)
} }
} }
else -> {
else ->
irGet(valueParameters[unboundIndex++]) irGet(valueParameters[unboundIndex++])
}
} }
putArgument(callee, parameter, argument) putArgument(callee, parameter, argument)
} }
if (!useVararg) assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
} }
) )
} }
@@ -461,113 +388,56 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
} }
private fun buildField(fieldName: Name, fieldType: IrType): IrField = private fun buildField(fieldName: Name, fieldType: IrType): IrField =
buildField { functionReferenceClass.addField {
setSourceRange(irFunctionReference) setSourceRange(irFunctionReference)
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
name = fieldName name = fieldName
type = fieldType type = fieldType
visibility = JavaVisibilities.PACKAGE_VISIBILITY visibility = JavaVisibilities.PACKAGE_VISIBILITY
isFinal = true isFinal = true
}.also {
it.parent = functionReferenceClass
functionReferenceClass.declarations.add(it)
} }
private fun createGetSignatureMethod(superFunction: IrSimpleFunction): IrSimpleFunction = private fun buildOverride(superFunction: IrSimpleFunction, newReturnType: IrType = superFunction.returnType): IrSimpleFunction =
buildFun { functionReferenceClass.addFunction {
setSourceRange(irFunctionReference) setSourceRange(irFunctionReference)
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL origin = functionReferenceClass.origin
name = Name.identifier("getSignature") name = superFunction.name
returnType = superFunction.returnType returnType = newReturnType
visibility = superFunction.visibility visibility = superFunction.visibility
modality = superFunction.modality isSuspend = superFunction.isSuspend
}.apply { }.apply {
val function = this overriddenSymbols += superFunction.symbol
parent = functionReferenceClass dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(this)
overriddenSymbols.add(superFunction.symbol)
dispatchReceiverParameter = functionReferenceClass.thisReceiver!!.copyTo(function)
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
+irReturn(
IrConstImpl.string(
-1, -1, context.irBuiltIns.stringType,
PropertyReferenceCodegen.getSignatureString(
irFunctionReference.symbol.descriptor, this@CallableReferenceLowering.context.state
)
)
)
}
} }
private val IrFunction.originalName: Name private val IrFunction.originalName: Name
get() = (metadata as? MetadataSource.Function)?.descriptor?.name ?: name get() = (metadata as? MetadataSource.Function)?.descriptor?.name ?: name
private fun createGetNameMethod(superFunction: IrSimpleFunction): IrSimpleFunction = private fun createGetSignatureMethod(superFunction: IrSimpleFunction): IrSimpleFunction = buildOverride(superFunction).apply {
buildFun { val state = context.state
setSourceRange(irFunctionReference) body = context.createIrBuilder(symbol, startOffset, endOffset).run {
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL // TODO do not use descriptors
name = Name.identifier("getName") irExprBody(irString(PropertyReferenceCodegen.getSignatureString(irFunctionReference.symbol.descriptor, state)))
returnType = superFunction.returnType
visibility = superFunction.visibility
modality = superFunction.modality
}.apply {
val function = this
parent = functionReferenceClass
overriddenSymbols.add(superFunction.symbol)
dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function)
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
+irReturn(
IrConstImpl.string(-1, -1, context.irBuiltIns.stringType, callee.originalName.asString())
)
}
} }
}
private fun createGetOwnerMethod(superFunction: IrSimpleFunction): IrSimpleFunction = private fun createGetNameMethod(superFunction: IrSimpleFunction): IrSimpleFunction = buildOverride(superFunction).apply {
buildFun { body = context.createIrBuilder(symbol, startOffset, endOffset).run {
setSourceRange(functionReferenceClass) irExprBody(irString(callee.originalName.asString()))
origin = JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL
name = Name.identifier("getOwner")
returnType = superFunction.returnType
visibility = superFunction.visibility
modality = superFunction.modality
}.apply {
val function = this
parent = functionReferenceClass
overriddenSymbols.add(superFunction.symbol)
dispatchReceiverParameter = functionReferenceClass.thisReceiver?.copyTo(function)
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
+irReturn(
generateCallableReferenceDeclarationContainer()
)
}
} }
}
fun IrBuilderWithScope.generateCallableReferenceDeclarationContainer(): IrExpression { private fun createGetOwnerMethod(superFunction: IrSimpleFunction): IrSimpleFunction = buildOverride(superFunction).apply {
val globalContext = this@CallableReferenceLowering.context val globalContext = context
val state = globalContext.state val state = globalContext.state
val irContainer = callee.parent val irContainer = callee.parent
val isContainerPackage = val isContainerPackage =
((irContainer as? IrClass)?.origin == IrDeclarationOrigin.FILE_CLASS) || irContainer is IrPackageFragment ((irContainer as? IrClass)?.origin == IrDeclarationOrigin.FILE_CLASS) || irContainer is IrPackageFragment
val type = when { val type = when (irContainer) {
irContainer is IrClass -> // TODO: getDefaultType() here is wrong and won't work for arrays
// TODO: getDefaultType() here is wrong and won't work for arrays is IrClass -> state.typeMapper.mapType(irContainer.defaultType.toKotlinType())
state.typeMapper.mapType(irContainer.defaultType.toKotlinType())
// // TODO: this code is only needed for property references, which are not yet supported.
// descriptor is VariableDescriptorWithAccessors -> {
// assert(false) { "VariableDescriptorWithAccessors" }
// globalContext.state.bindingContext.get(
// CodegenBinding.DELEGATED_PROPERTY_METADATA_OWNER, descriptor
// )!!
// }
else -> state.typeMapper.mapOwner(callee.descriptor) else -> state.typeMapper.mapOwner(callee.descriptor)
} }
@@ -580,22 +450,20 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
CrIrType(type) CrIrType(type)
) )
return if (isContainerPackage) { body = context.createIrBuilder(symbol, startOffset, endOffset).run {
// Note that this name is not used in reflection. There should be the name of the referenced declaration's module instead, irExprBody(if (isContainerPackage) {
// but there's no nice API to obtain that name here yet irCall(globalContext.ir.symbols.getOrCreateKotlinPackage).apply {
// TODO: write the referenced declaration's module name and use it in reflection putValueArgument(0, clazzRef)
val module = IrConstImpl.string( // Note that this name is not used in reflection. There should be the name of the referenced declaration's
-1, -1, globalContext.irBuiltIns.stringType, // module instead, but there's no nice API to obtain that name here yet
state.moduleName // TODO: write the referenced declaration's module name and use it in reflection
) putValueArgument(1, irString(state.moduleName))
irCall(globalContext.ir.symbols.getOrCreateKotlinPackage).apply { }
putValueArgument(0, clazzRef) } else {
putValueArgument(1, module) irCall(globalContext.ir.symbols.getOrCreateKotlinClass).apply {
} putValueArgument(0, clazzRef)
} else { }
irCall(globalContext.ir.symbols.getOrCreateKotlinClass).apply { })
putValueArgument(0, clazzRef)
}
} }
} }
} }
@@ -607,8 +475,4 @@ internal class CallableReferenceLowering(val context: JvmBackendContext) : FileL
Name.identifier("$${name.substring(1, name.length - 1)}") Name.identifier("$${name.substring(1, name.length - 1)}")
} else this } else this
} }
companion object {
const val MAX_ARGCOUNT_WITHOUT_VARARG = 22
}
} }
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.lower.irIfThen
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
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.builtins.functions.FunctionInvokeDescriptor
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
@@ -44,7 +45,7 @@ private class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : Cl
val invokeFunctions = irClass.filterDeclarations<IrSimpleFunction> { it.name.toString() == "invoke" } val invokeFunctions = irClass.filterDeclarations<IrSimpleFunction> { it.name.toString() == "invoke" }
if (invokeFunctions.isEmpty() || if (invokeFunctions.isEmpty() ||
invokeFunctions.any { it.valueParameters.size > 0 && it.valueParameters.last().varargElementType != null } || 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 } invokeFunctions.all { it.valueParameters.size + (if (it.extensionReceiverParameter != null) 1 else 0) < FunctionInvokeDescriptor.Factory.BIG_ARITY }
) { ) {
// No need to add a new vararg invoke method // No need to add a new vararg invoke method
return return