Inliner: fixed bug with leaking descriptors
An inline function might return an object, internal of which are leaked to the outside, we need to substitute those descriptors as well
This commit is contained in:
+46
-15
@@ -23,13 +23,12 @@ import org.jetbrains.kotlin.backend.konan.ir.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
@@ -555,12 +554,20 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: DeclarationDe
|
||||
|
||||
val descriptorSubstitutorForExternalScope = object : IrElementTransformerVoid() {
|
||||
|
||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||
if (declaration.descriptor == targetDescriptor)
|
||||
return declaration
|
||||
return super.visitFunction(declaration)
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
val oldExpression = super.visitCall(expression) as IrCall
|
||||
|
||||
if (oldExpression is IrCallImpl)
|
||||
return copyIrCallImpl(oldExpression)
|
||||
return oldExpression
|
||||
return when (oldExpression) {
|
||||
is IrCallImpl -> copyIrCallImpl(oldExpression)
|
||||
is IrCallWithShallowCopy -> copyIrCallWithShallowCopy(oldExpression)
|
||||
else -> oldExpression
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,18 +576,26 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: DeclarationDe
|
||||
private fun copyIrCallImpl(oldExpression: IrCallImpl): IrCallImpl {
|
||||
|
||||
val oldDescriptor = oldExpression.descriptor
|
||||
val newDescriptor = descriptorSubstituteMap.getOrDefault(oldDescriptor.original,
|
||||
oldDescriptor) as FunctionDescriptor
|
||||
val newDescriptor = (descriptorSubstituteMap[oldDescriptor.original] ?: oldDescriptor) as FunctionDescriptor
|
||||
|
||||
val newSuperQualifier = oldExpression.superQualifier?.let { (descriptorSubstituteMap[it] ?: it) as ClassDescriptor }
|
||||
val oldSuperQualifier = oldExpression.superQualifier
|
||||
val newSuperQualifier = oldSuperQualifier?.let { (descriptorSubstituteMap[it] ?: it) as ClassDescriptor }
|
||||
|
||||
val newType = substituteType(oldExpression.type)!!
|
||||
val newTypeArguments = substituteTypeArguments(oldExpression.typeArguments)
|
||||
|
||||
if (newDescriptor == oldDescriptor && newSuperQualifier == oldSuperQualifier && newType == oldExpression.type
|
||||
&& ((newTypeArguments == null && oldExpression.typeArguments == null)
|
||||
|| (newTypeArguments!!.all { it.value == oldExpression.typeArguments!![it.key] })))
|
||||
return oldExpression
|
||||
|
||||
val newExpression = IrCallImpl(
|
||||
startOffset = oldExpression.startOffset,
|
||||
endOffset = oldExpression.endOffset,
|
||||
type = substituteType(oldExpression.type)!!,
|
||||
calleeDescriptor = newDescriptor,
|
||||
typeArguments = substituteTypeArguments(oldExpression.typeArguments),
|
||||
origin = oldExpression.origin,
|
||||
startOffset = oldExpression.startOffset,
|
||||
endOffset = oldExpression.endOffset,
|
||||
type = newType,
|
||||
calleeDescriptor = newDescriptor,
|
||||
typeArguments = newTypeArguments,
|
||||
origin = oldExpression.origin,
|
||||
superQualifierDescriptor = newSuperQualifier
|
||||
).apply {
|
||||
oldExpression.descriptor.valueParameters.forEach {
|
||||
@@ -593,6 +608,22 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: DeclarationDe
|
||||
|
||||
return newExpression
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun copyIrCallWithShallowCopy(oldExpression: IrCallWithShallowCopy): IrCall {
|
||||
|
||||
val oldDescriptor = oldExpression.descriptor
|
||||
val newDescriptor = (descriptorSubstituteMap[oldDescriptor.original] ?: oldDescriptor) as FunctionDescriptor
|
||||
|
||||
val oldSuperQualifier = oldExpression.superQualifier
|
||||
val newSuperQualifier = oldSuperQualifier?.let { (descriptorSubstituteMap[it] ?: it) as ClassDescriptor }
|
||||
|
||||
if (newDescriptor == oldDescriptor && newSuperQualifier == oldSuperQualifier)
|
||||
return oldExpression
|
||||
|
||||
return oldExpression.shallowCopy(oldExpression.origin, newDescriptor, newSuperQualifier)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+12
-10
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.descriptors.ValueDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.getDefault
|
||||
@@ -59,7 +60,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
|
||||
val irCall = super.visitCall(expression) as IrCall
|
||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||
val functionDescriptor = irCall.descriptor
|
||||
if (!functionDescriptor.needsInlining) return irCall // This call does not need inlining.
|
||||
|
||||
val functionDeclaration = getFunctionDeclaration(irCall) // Get declaration of the function to be inlined.
|
||||
@@ -71,15 +72,15 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
}
|
||||
|
||||
functionDeclaration.transformChildrenVoid(this) // Process recursive inline.
|
||||
val inliner = Inliner(currentScope!!, context) // Create inliner for this scope.
|
||||
return inliner.inline(irCall, functionDeclaration) // Return newly created IrInlineBody instead of IrCall.
|
||||
val inliner = Inliner(currentFile, functionDeclaration, currentScope!!, context) // Create inliner for this scope.
|
||||
return inliner.inline(irCall ) // Return newly created IrInlineBody instead of IrCall.
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun getFunctionDeclaration(irCall: IrCall): IrFunction? {
|
||||
|
||||
val functionDescriptor = irCall.descriptor as FunctionDescriptor
|
||||
val functionDescriptor = irCall.descriptor
|
||||
val originalDescriptor = functionDescriptor.resolveFakeOverride().original
|
||||
val functionDeclaration =
|
||||
context.ir.originalModuleIndex.functions[originalDescriptor] ?: // If function is declared in the current module.
|
||||
@@ -94,19 +95,20 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
|
||||
|
||||
//-----------------------------------------------------------------------------//
|
||||
|
||||
private class Inliner(val currentScope: ScopeWithIr, val context: Context) {
|
||||
private class Inliner(val irFile: IrFile,
|
||||
val functionDeclaration: IrFunction, // Function to substitute.
|
||||
val currentScope: ScopeWithIr,
|
||||
val context: Context) {
|
||||
|
||||
val copyIrElement = DeepCopyIrTreeWithDescriptors(currentScope.scope.scopeOwner, context) // Create DeepCopy for current scope.
|
||||
val copyIrElement = DeepCopyIrTreeWithDescriptors(functionDeclaration.descriptor, context) // Create DeepCopy for current scope.
|
||||
val substituteMap = mutableMapOf<ValueDescriptor, IrExpression>()
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun inline(irCall : IrCall, // Call to be substituted.
|
||||
functionDeclaration: IrFunction): IrReturnableBlockImpl { // Function to substitute.
|
||||
|
||||
fun inline(irCall: IrCall): IrReturnableBlockImpl { // Call to be substituted.
|
||||
val inlineFunctionBody = inlineFunction(irCall, functionDeclaration)
|
||||
val descriptorSubstitutor = copyIrElement.descriptorSubstitutorForExternalScope
|
||||
currentScope.irElement.transformChildrenVoid(descriptorSubstitutor) // Transform calls to object that might be returned from inline function call.
|
||||
irFile.transformChildrenVoid(descriptorSubstitutor) // Transform calls to object that might be returned from inline function call.
|
||||
return inlineFunctionBody
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user