New scheme for copy descriptors names

This commit is contained in:
Konstantin Anisimov
2017-04-10 11:57:23 +07:00
committed by KonstantinAnisimov
parent 34e49ffb82
commit 8235c8b2be
2 changed files with 70 additions and 98 deletions
@@ -49,15 +49,13 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf() private val descriptorSubstituteMap: MutableMap<DeclarationDescriptor, DeclarationDescriptor> = mutableMapOf()
private var typeSubstitutor: TypeSubstitutor? = null private var typeSubstitutor: TypeSubstitutor? = null
private var inlinedFunctionName = ""
private var nameIndex = 0 private var nameIndex = 0
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
fun copy(irElement: IrElement, typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?, functionName: String): IrElement { fun copy(irElement: IrElement, typeArgumentsMap: Map <TypeParameterDescriptor, KotlinType>?): IrElement {
typeSubstitutor = createTypeSubstitutor(typeArgsMap) typeSubstitutor = createTypeSubstitutor(typeArgumentsMap)
inlinedFunctionName = functionName
descriptorSubstituteMap.clear() descriptorSubstituteMap.clear()
irElement.acceptChildrenVoid(DescriptorCollector()) irElement.acceptChildrenVoid(DescriptorCollector())
// Transform calls to object that might be returned from inline function call. // Transform calls to object that might be returned from inline function call.
@@ -220,7 +218,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
val oldDescriptor = declaration.descriptor val oldDescriptor = declaration.descriptor
val newDescriptor = IrTemporaryVariableDescriptorImpl( val newDescriptor = IrTemporaryVariableDescriptorImpl(
containingDeclaration = targetScope.scope.scopeOwner, containingDeclaration = targetScope.scope.scopeOwner,
name = generateName(oldDescriptor.name), name = generateCopyName(oldDescriptor.name),
outType = substituteType(oldDescriptor.type)!!, outType = substituteType(oldDescriptor.type)!!,
isMutable = oldDescriptor.isVar) isMutable = oldDescriptor.isVar)
descriptorSubstituteMap[oldDescriptor] = newDescriptor descriptorSubstituteMap[oldDescriptor] = newDescriptor
@@ -230,12 +228,11 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
//--- Copy descriptors ------------------------------------------------// //--- Copy descriptors ------------------------------------------------//
private fun generateName(name: Name): Name { private fun generateCopyName(name: Name): Name {
val containingName = targetScope.scope.scopeOwner.name.toString() // Name of inline target (function we inline in)
val declarationName = name.toString() // Name of declaration val declarationName = name.toString() // Name of declaration
val indexStr = (nameIndex++).toString() // Unique for inline target index val indexStr = (nameIndex++).toString() // Unique for inline target index
return Name.identifier(containingName + "_" + inlinedFunctionName + "_" + declarationName + "_" + indexStr) return Name.identifier(declarationName + "_" + indexStr)
} }
//---------------------------------------------------------------------// //---------------------------------------------------------------------//
@@ -258,7 +255,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
return SimpleFunctionDescriptorImpl.create( return SimpleFunctionDescriptorImpl.create(
/* containingDeclaration = */ newContainingDeclaration, /* containingDeclaration = */ newContainingDeclaration,
/* annotations = */ oldDescriptor.annotations, /* annotations = */ oldDescriptor.annotations,
/* name = */ generateName(oldDescriptor.name), /* name = */ generateCopyName(oldDescriptor.name),
/* kind = */ oldDescriptor.kind, /* kind = */ oldDescriptor.kind,
/* source = */ oldDescriptor.source /* source = */ oldDescriptor.source
).apply { ).apply {
@@ -401,7 +398,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
val newName = if (DescriptorUtils.isAnonymousObject(oldDescriptor)) // Anonymous objects are identified by their name. val newName = if (DescriptorUtils.isAnonymousObject(oldDescriptor)) // Anonymous objects are identified by their name.
oldDescriptor.name // We need to preserve it for LocalDeclarationsLowering. oldDescriptor.name // We need to preserve it for LocalDeclarationsLowering.
else else
generateName(oldDescriptor.name) generateCopyName(oldDescriptor.name)
return ClassDescriptorImpl( return ClassDescriptorImpl(
/* containingDeclaration = */ newContainingDeclaration, /* containingDeclaration = */ newContainingDeclaration,
/* name = */ newName, /* name = */ newName,
@@ -601,10 +598,10 @@ internal class DeepCopyIrTreeWithDescriptors(val targetScope: ScopeWithIr,
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private fun createTypeSubstitutor(typeArgsMap: Map <TypeParameterDescriptor, KotlinType>?): TypeSubstitutor? { private fun createTypeSubstitutor(typeArgumentsMap: Map <TypeParameterDescriptor, KotlinType>?): TypeSubstitutor? {
if (typeArgsMap == null) return null if (typeArgumentsMap == null) return null
val substitutionContext = typeArgsMap.entries.associate { val substitutionContext = typeArgumentsMap.entries.associate {
(typeParameter, typeArgument) -> (typeParameter, typeArgument) ->
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument) typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
} }
@@ -44,7 +44,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() { internal class FunctionInlining(val context: Context): IrElementTransformerVoidWithContext() {
private var copyWithDescriptors: DeepCopyIrTreeWithDescriptors? = null private var copyIrElement: DeepCopyIrTreeWithDescriptors? = null
private val deserializer = DeserializerDriver(context) private val deserializer = DeserializerDriver(context)
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
@@ -61,13 +61,11 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
val irCall = super.visitCall(expression) as IrCall val irCall = super.visitCall(expression) as IrCall
val functionDescriptor = irCall.descriptor as FunctionDescriptor val functionDescriptor = irCall.descriptor as FunctionDescriptor
if (functionDescriptor.needsInlining) { if (functionDescriptor.needsInlining) {
copyWithDescriptors = DeepCopyIrTreeWithDescriptors(currentScope!!, context) copyIrElement = DeepCopyIrTreeWithDescriptors(currentScope!!, context)
val functionDeclaration = getFunctionDeclaration(irCall) val functionDeclaration = getFunctionDeclaration(irCall)
if (functionDeclaration == null) return irCall if (functionDeclaration == null) return irCall
functionDeclaration.transformChildrenVoid(this) // Process recursive inline. functionDeclaration.transformChildrenVoid(this) // Process recursive inline.
return inlineFunction(irCall, functionDeclaration) // Return newly created IrInlineBody instead of IrCall. return inlineFunction(irCall, functionDeclaration) // Return newly created IrInlineBody instead of IrCall.
} }
@@ -78,57 +76,28 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
private fun inlineFunction(irCall: IrCall, functionDeclaration: IrFunction): IrExpression { private fun inlineFunction(irCall: IrCall, functionDeclaration: IrFunction): IrExpression {
val evaluatedParameters = evaluateParameters(irCall, functionDeclaration) val evaluatedParameters = evaluateParameters(irCall, functionDeclaration)
val parameterToArgument = evaluatedParameters.parameters val parameterSubstituteMap = evaluatedParameters.parameters
val evaluationStatements = evaluatedParameters.statements val evaluationStatements = evaluatedParameters.statements
val statements = (functionDeclaration.body as IrBlockBody).statements val typeArgumentsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
val returnType = functionDeclaration.descriptor.returnType!! val copyFunctionDeclaration = copyIrElement!!.copy( // Create copy of original function.
val inlineFunctionBody1 = IrInlineFunctionBody( functionDeclaration,
startOffset = functionDeclaration.startOffset, typeArgumentsMap
endOffset = functionDeclaration.endOffset, ) as IrFunction
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements
val returnType = copyFunctionDeclaration.descriptor.returnType!!
val inlineFunctionBody = IrInlineFunctionBody(
startOffset = copyFunctionDeclaration.startOffset,
endOffset = copyFunctionDeclaration.endOffset,
type = returnType, type = returnType,
descriptor = functionDeclaration.descriptor.original, descriptor = copyFunctionDeclaration.descriptor.original,
origin = null, origin = null,
statements = statements statements = statements
) )
val functionName = functionDeclaration.descriptor.name.toString() val transformer = ParameterSubstitutor(parameterSubstituteMap)
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
val inlineFunctionBody = copyWithDescriptors!!.copy(inlineFunctionBody1, typeArgsMap, functionName) as IrInlineFunctionBody // Create copy of original function body.
val transformer = ParameterSubstitutor(parameterToArgument)
inlineFunctionBody.transformChildrenVoid(transformer) // Replace parameters with expression.
inlineFunctionBody.statements.addAll(0, evaluationStatements)
return inlineFunctionBody // Replace call site with InlineFunctionBody.
}
//---------------------------------------------------------------------//
private fun inlineLambda(irCall: IrCall, functionDeclaration: IrFunction): IrExpression {
val evaluatedParameters = evaluateParameters(irCall, functionDeclaration)
val parameterToArgument = evaluatedParameters.parameters
val evaluationStatements = evaluatedParameters.statements
val statements = (functionDeclaration.body as IrBlockBody).statements
val returnType = functionDeclaration.descriptor.returnType!!
val inlineFunctionBody1 = IrInlineFunctionBody(
startOffset = functionDeclaration.startOffset,
endOffset = functionDeclaration.endOffset,
type = returnType,
descriptor = functionDeclaration.descriptor.original,
origin = null,
statements = statements
)
val functionName = functionDeclaration.descriptor.name.toString()
val typeArgsMap = (irCall as IrMemberAccessExpressionBase).typeArguments
val inlineFunctionBody = copyWithDescriptors!!.copy(inlineFunctionBody1, typeArgsMap, functionName) as IrInlineFunctionBody // Create copy of original function body.
val transformer = ParameterSubstitutor(parameterToArgument)
inlineFunctionBody.transformChildrenVoid(transformer) // Replace parameters with expression. inlineFunctionBody.transformChildrenVoid(transformer) // Replace parameters with expression.
inlineFunctionBody.statements.addAll(0, evaluationStatements) inlineFunctionBody.statements.addAll(0, evaluationStatements)
@@ -150,7 +119,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
val argument = substituteMap[descriptor] // Find expression to replace this parameter. val argument = substituteMap[descriptor] // Find expression to replace this parameter.
if (argument == null) return newExpression // If there is no such expression - do nothing if (argument == null) return newExpression // If there is no such expression - do nothing
val newArgument = copyWithDescriptors!!.copy(argument, null, "lambda") val newArgument = copyIrElement!!.copy(argument, null)
return newArgument as IrExpression return newArgument as IrExpression
} }
@@ -170,7 +139,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
val functionDeclaration = getLambdaFunction(lambdaArgument) val functionDeclaration = getLambdaFunction(lambdaArgument)
if (functionDeclaration == null) return return super.visitCall(expression) // TODO if (functionDeclaration == null) return return super.visitCall(expression) // TODO
val newExpression = inlineLambda(expression, functionDeclaration) val newExpression = inlineFunction(expression, functionDeclaration)
return newExpression.transform(this, null) return newExpression.transform(this, null)
} }
} }
@@ -194,8 +163,6 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
return null return null
} }
// TODO: the following checks must be asserts, however it is not sane until the bugs are fixed.
val statements = lambdaArgument.statements val statements = lambdaArgument.statements
if (statements.size != 2) return null if (statements.size != 2) return null
@@ -233,39 +200,61 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private class ArgumentWithValue(val descriptor: ValueDescriptor, val value: IrExpression) private fun getFunctionDeclaration(irCall: IrCall): IrFunction? {
val functionDescriptor = irCall.descriptor as FunctionDescriptor
val originalDescriptor = functionDescriptor.original
val functionDeclaration =
(context.ir.originalModuleIndex.functions[originalDescriptor] ?: // Function is declared in the current module.
deserializer.deserializeInlineBody(originalDescriptor) as IrFunction?) // Function is declared in another module.
return functionDeclaration
}
//-------------------------------------------------------------------------//
private class ParameterWithArgument(
val parameterDescriptor: ValueDescriptor,
val argument : IrExpression
)
//-------------------------------------------------------------------------//
private class EvaluatedParameters(
val parameters: MutableMap<ValueDescriptor, IrExpression>,
val statements: MutableList<IrStatement>
)
//---------------------------------------------------------------------// //---------------------------------------------------------------------//
private fun getArguments(irCall: IrCall, declaration: IrFunction): MutableList<ArgumentWithValue> { private fun buildParameterToArgumentMap(irCall: IrCall, declaration: IrFunction): MutableList<ParameterWithArgument> {
val result = mutableListOf<ArgumentWithValue>() val result = mutableListOf<ParameterWithArgument>()
val descriptor = declaration.descriptor.original val descriptor = declaration.descriptor.original
if (irCall.dispatchReceiver != null && descriptor.dispatchReceiverParameter != null) if (irCall.dispatchReceiver != null && descriptor.dispatchReceiverParameter != null)
result += ArgumentWithValue(descriptor.dispatchReceiverParameter!!, irCall.dispatchReceiver!!) result += ParameterWithArgument(descriptor.dispatchReceiverParameter!!, irCall.dispatchReceiver!!)
if (irCall.extensionReceiver != null && descriptor.extensionReceiverParameter != null) if (irCall.extensionReceiver != null && descriptor.extensionReceiverParameter != null)
result += ArgumentWithValue(descriptor.extensionReceiverParameter!!, irCall.extensionReceiver!!) result += ParameterWithArgument(descriptor.extensionReceiverParameter!!, irCall.extensionReceiver!!)
descriptor.valueParameters.forEach { parameter -> descriptor.valueParameters.forEach { parameterDescriptor ->
val argument = irCall.getValueArgument(parameter.index) val argument = irCall.getValueArgument(parameterDescriptor.index)
when { when {
argument != null -> { argument != null -> {
result += ArgumentWithValue(parameter, argument) result += ParameterWithArgument(parameterDescriptor, argument)
} }
parameter.hasDefaultValue() -> { parameterDescriptor.hasDefaultValue() -> {
val defaultArgument = declaration.getDefault(parameter)!!.expression val defaultArgument = declaration.getDefault(parameterDescriptor)!!.expression
result += ArgumentWithValue(parameter, defaultArgument) result += ParameterWithArgument(parameterDescriptor, defaultArgument)
} }
parameter.varargElementType != null -> { parameterDescriptor.varargElementType != null -> {
val emptyArray = IrVarargImpl(irCall.startOffset, irCall.endOffset, parameter.type, parameter.varargElementType!!) val emptyArray = IrVarargImpl(irCall.startOffset, irCall.endOffset, parameterDescriptor.type, parameterDescriptor.varargElementType!!)
result += ArgumentWithValue(parameter, emptyArray) result += ParameterWithArgument(parameterDescriptor, emptyArray)
} }
else -> throw Error("Incomplete expression: call to $descriptor has no argument at index ${parameter.index}") else -> throw Error("Incomplete expression: call to $descriptor has no argument at index ${parameterDescriptor.index}")
} }
} }
return result return result
@@ -273,19 +262,17 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private class EvaluatedParameters(val parameters: MutableMap<ValueDescriptor, IrExpression>, val statements: MutableList<IrStatement>)
private fun evaluateParameters(irCall: IrCall, functionDeclaration: IrFunction): EvaluatedParameters { private fun evaluateParameters(irCall: IrCall, functionDeclaration: IrFunction): EvaluatedParameters {
val parametersOld = getArguments(irCall, functionDeclaration) // Create map call_site_argument -> inline_function_parameter. val parametersOld = buildParameterToArgumentMap(irCall, functionDeclaration) // Create map call_site_argument -> inline_function_parameter.
val parametersNew = mutableMapOf<ValueDescriptor, IrExpression> () val parametersNew = mutableMapOf<ValueDescriptor, IrExpression> ()
val statements = mutableListOf<IrStatement>() val statements = mutableListOf<IrStatement>()
parametersOld.forEach { parametersOld.forEach {
val parameter = it.descriptor.original as ValueDescriptor val parameterDescriptor = it.parameterDescriptor.original as ValueDescriptor
val argument = it.value val argument = it.argument
if (!needsEvaluation(argument)) { if (!needsEvaluation(argument)) {
parametersNew[parameter] = argument parametersNew[parameterDescriptor] = argument
return@forEach return@forEach
} }
@@ -297,22 +284,10 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoidW
val startOffset = currentScope.irElement.startOffset val startOffset = currentScope.irElement.startOffset
val endOffset = currentScope.irElement.endOffset val endOffset = currentScope.irElement.endOffset
val getVal = IrGetValueImpl(startOffset, endOffset, newVar.descriptor) // Create new IR element representing access the new variable. val getVal = IrGetValueImpl(startOffset, endOffset, newVar.descriptor) // Create new IR element representing access the new variable.
parametersNew[parameter] = getVal // Parameter will be replaced with the new variable. parametersNew[parameterDescriptor] = getVal // Parameter will be replaced with the new variable.
} }
return EvaluatedParameters(parametersNew, statements) return EvaluatedParameters(parametersNew, statements)
} }
//-------------------------------------------------------------------------//
private fun getFunctionDeclaration(irCall: IrCall): IrFunction? {
val functionDescriptor = irCall.descriptor as FunctionDescriptor
val originalDescriptor = functionDescriptor.original
val functionDeclaration =
(context.ir.originalModuleIndex.functions[originalDescriptor] ?: // Function is declared in the current module.
deserializer.deserializeInlineBody(originalDescriptor) as IrFunction?) // Function is declared in another module.
return functionDeclaration
}
} }