Revert "Revert commits: (#1162)
This commit is contained in:
committed by
Nikolay Igotti
parent
5d856665c8
commit
d237afdea5
+26
-48
@@ -26,7 +26,10 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
import org.jetbrains.kotlin.backend.konan.ir.DeserializerDriver
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
@@ -44,7 +47,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
|
|||||||
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------//
|
||||||
|
|
||||||
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
|
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
|
||||||
@@ -66,31 +68,21 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
|||||||
|
|
||||||
override fun visitCall(expression: IrCall): IrExpression {
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
|
||||||
val functionDescriptor = expression.descriptor
|
val irCall = super.visitCall(expression) as IrCall
|
||||||
if (!functionDescriptor.needsInlining) return super.visitCall(expression) // This call does not need inlining.
|
val functionDescriptor = irCall.descriptor
|
||||||
if (isInlineFunctionScope()) return super.visitCall(expression) // Ignore inlining in functions declared as "inline"
|
if (!functionDescriptor.needsInlining) return irCall // This call does not need inlining.
|
||||||
|
|
||||||
val functionDeclaration = getFunctionDeclaration(expression) // Get declaration of the function to be inlined.
|
val functionDeclaration = getFunctionDeclaration(irCall) // Get declaration of the function to be inlined.
|
||||||
if (functionDeclaration == null) { // We failed to get the declaration.
|
if (functionDeclaration == null) { // We failed to get the declaration.
|
||||||
val message = "Inliner failed to obtain function declaration: " +
|
val message = "Inliner failed to obtain function declaration: " +
|
||||||
functionDescriptor.fqNameSafe.toString()
|
functionDescriptor.fqNameSafe.toString()
|
||||||
context.reportWarning(message, currentFile, expression) // Report warning.
|
context.reportWarning(message, currentFile, irCall) // Report warning.
|
||||||
return super.visitCall(expression)
|
return irCall
|
||||||
}
|
}
|
||||||
|
|
||||||
|
functionDeclaration.transformChildrenVoid(this) // Process recursive inline.
|
||||||
val inliner = Inliner(globalSubstituteMap, functionDeclaration, currentScope!!, context) // Create inliner for this scope.
|
val inliner = Inliner(globalSubstituteMap, functionDeclaration, currentScope!!, context) // Create inliner for this scope.
|
||||||
val inlinedFunctionBody = inliner.inline(expression) // Return newly created IrInlineBody instead of IrCall.
|
return inliner.inline(irCall ) // Return newly created IrInlineBody instead of IrCall.
|
||||||
inlinedFunctionBody.transformChildrenVoid(this)
|
|
||||||
return inlinedFunctionBody
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun isInlineFunctionScope(): Boolean {
|
|
||||||
if (currentFunction == null) return false
|
|
||||||
val scopeOwner = currentFunction!!.scope.scopeOwner
|
|
||||||
if (scopeOwner !is FunctionDescriptor) return false
|
|
||||||
return scopeOwner.isInline
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -234,35 +226,21 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
private class ParameterToArgument(val parameterDescriptor: ValueDescriptor,
|
private class ParameterToArgument(val parameterDescriptor: ValueDescriptor,
|
||||||
val argumentExpression : IrExpression) {
|
val argumentExpression : IrExpression) {
|
||||||
|
|
||||||
val needsEvaluation : Boolean
|
val isInlinableLambda : Boolean
|
||||||
get() {
|
get() {
|
||||||
if (parameterDescriptor.isNoinline()) return true
|
if (argumentExpression !is IrBlock) return false // Lambda must be represented with IrBlock.
|
||||||
if (argumentExpression.isInlinableBody()) return false
|
if (argumentExpression.origin != IrStatementOrigin.LAMBDA && // Origin must be LAMBDA or ANONYMOUS.
|
||||||
return true // The expression must be evaluated.
|
argumentExpression.origin != IrStatementOrigin.ANONYMOUS_FUNCTION) return false
|
||||||
|
|
||||||
|
val statements = argumentExpression.statements
|
||||||
|
val irFunction = statements[0] // Lambda function declaration.
|
||||||
|
val irCallableReference = statements[1] // Lambda callable reference.
|
||||||
|
if (irFunction !is IrFunction) return false // First statement of the block must be lambda declaration.
|
||||||
|
if (irCallableReference !is IrCallableReference) return false // Second statement of the block must be CallableReference.
|
||||||
|
if (parameterDescriptor is ValueParameterDescriptor &&
|
||||||
|
parameterDescriptor.isNoinline) return false // If parameter marked as "noinline" - do not inline.
|
||||||
|
return true // The expression represents lambda.
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
fun ValueDescriptor.isNoinline(): Boolean {
|
|
||||||
if (this !is ValueParameterDescriptor) return false
|
|
||||||
if (this.isNoinline) return true // If parameter marked as "noinline" - do not inline.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun isAnonymousFunction(descriptor: DeclarationDescriptor): Boolean {
|
|
||||||
return descriptor is SimpleFunctionDescriptor && descriptor.name.asString().contains("<anonymous>")
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
fun IrExpression.isInlinableBody(): Boolean {
|
|
||||||
if (this !is IrBlock) return false // Lambda must be represented with IrBlock.
|
|
||||||
val lastStatement = statements.last()
|
|
||||||
if (lastStatement !is IrCallableReference) return false // Second statement of the lambda block must be CallableReference.
|
|
||||||
return isAnonymousFunction(lastStatement.descriptor)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
@@ -353,7 +331,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
parameterToArgumentOld.forEach {
|
parameterToArgumentOld.forEach {
|
||||||
val parameterDescriptor = it.parameterDescriptor
|
val parameterDescriptor = it.parameterDescriptor
|
||||||
|
|
||||||
if (!it.needsEvaluation) { // If parameter has functional type - it can not be evaluated.
|
if (it.isInlinableLambda) { // If argument is inlinable lambda.
|
||||||
substituteMap[parameterDescriptor] = it.argumentExpression // Associate parameter with lambda argument.
|
substituteMap[parameterDescriptor] = it.argumentExpression // Associate parameter with lambda argument.
|
||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user