DFG: added parameter types to Function

This commit is contained in:
Igor Chevdar
2018-01-30 14:02:47 +03:00
parent 0629513fd9
commit 51801b9009
4 changed files with 31 additions and 18 deletions
@@ -55,12 +55,11 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.typeUtil.isNothing import org.jetbrains.kotlin.types.typeUtil.isNothing
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
private fun computeErasure(type: KotlinType, erasure: MutableList<KotlinType>) { private fun computeErasure(type: KotlinType, erasure: MutableList<ClassDescriptor>) {
val descriptor = type.constructor.declarationDescriptor val descriptor = type.constructor.declarationDescriptor
when (descriptor) { when (descriptor) {
is ClassDescriptor -> erasure += type.makeNotNullable() is ClassDescriptor -> erasure += descriptor
is TypeParameterDescriptor -> { is TypeParameterDescriptor -> {
descriptor.upperBounds.forEach { descriptor.upperBounds.forEach {
computeErasure(it, erasure) computeErasure(it, erasure)
@@ -70,8 +69,8 @@ private fun computeErasure(type: KotlinType, erasure: MutableList<KotlinType>) {
} }
} }
internal fun KotlinType.erasure(): List<KotlinType> { internal fun KotlinType.erasure(): List<ClassDescriptor> {
val result = mutableListOf<KotlinType>() val result = mutableListOf<ClassDescriptor>()
computeErasure(this, result) computeErasure(this, result)
return result return result
} }
@@ -409,6 +408,7 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
private val doResumeFunctionDescriptor = context.getInternalClass("CoroutineImpl").unsubstitutedMemberScope private val doResumeFunctionDescriptor = context.getInternalClass("CoroutineImpl").unsubstitutedMemberScope
.getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single() .getContributedFunctions(Name.identifier("doResume"), NoLookupLocation.FROM_BACKEND).single()
private val getContinuationSymbol = context.ir.symbols.getContinuation private val getContinuationSymbol = context.ir.symbols.getContinuation
private val continuationType = getContinuationSymbol.descriptor.returnType!!
private val arrayGetSymbol = context.ir.symbols.arrayGet private val arrayGetSymbol = context.ir.symbols.arrayGet
private val arraySetSymbol = context.ir.symbols.arraySet private val arraySetSymbol = context.ir.symbols.arraySet
@@ -440,6 +440,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
{ DataFlowIR.Node.Variable(mutableListOf(), false) } { DataFlowIR.Node.Variable(mutableListOf(), false) }
) )
private fun choosePrimary(erasure: List<ClassDescriptor>): ClassDescriptor {
if (erasure.size == 1) return erasure[0]
// A parameter with constraints - choose class if exists.
return erasure.singleOrNull { !it.isInterface } ?: context.builtIns.any
}
fun build(): DataFlowIR.Function { fun build(): DataFlowIR.Function {
expressions.forEach { getNode(it) } expressions.forEach { getNode(it) }
val returnsNode = DataFlowIR.Node.Variable(returnValues.map { expressionToEdge(it) }, true) val returnsNode = DataFlowIR.Node.Variable(returnValues.map { expressionToEdge(it) }, true)
@@ -452,10 +458,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
val allNodes = nodes.values + variables.values + templateParameters.values + returnsNode + throwsNode + val allNodes = nodes.values + variables.values + templateParameters.values + returnsNode + throwsNode +
(if (descriptor.isSuspend) listOf(continuationParameter!!) else emptyList()) (if (descriptor.isSuspend) listOf(continuationParameter!!) else emptyList())
val parameterTypes = (allParameters.map { it.type } + (if (descriptor.isSuspend) listOf(continuationType) else emptyList()))
.map { symbolTable.mapClass(choosePrimary(it.erasure())) }
.toTypedArray()
return DataFlowIR.Function( return DataFlowIR.Function(
symbol = symbolTable.mapFunction(descriptor), symbol = symbolTable.mapFunction(descriptor),
numberOfParameters = templateParameters.size + if (descriptor.isSuspend) 1 else 0, parameterTypes = parameterTypes,
body = DataFlowIR.FunctionBody(allNodes.distinct().toList(), returnsNode, throwsNode) body = DataFlowIR.FunctionBody(allNodes.distinct().toList(), returnsNode, throwsNode)
) )
} }
@@ -663,13 +663,13 @@ internal object DFGSerializer {
} }
} }
class Function(val symbol: Int, val numberOfParameters: Int, val body: FunctionBody) { class Function(val symbol: Int, val parameterTypes: IntArray, val body: FunctionBody) {
constructor(data: ArraySlice) : this(data.readInt(), data.readInt(), FunctionBody(data)) constructor(data: ArraySlice) : this(data.readInt(), data.readIntArray(), FunctionBody(data))
fun write(result: ArraySlice) { fun write(result: ArraySlice) {
result.writeInt(symbol) result.writeInt(symbol)
result.writeInt(numberOfParameters) result.writeIntArray(parameterTypes)
body.write(result) body.write(result)
} }
} }
@@ -816,7 +816,7 @@ internal object DFGSerializer {
.toTypedArray() .toTypedArray()
Function( Function(
functionSymbolMap[function.symbol]!!, functionSymbolMap[function.symbol]!!,
function.numberOfParameters, function.parameterTypes.map { typeMap[it]!! }.toIntArray(),
FunctionBody(nodes, nodeMap[body.returns]!!, nodeMap[body.throws]!!) FunctionBody(nodes, nodeMap[body.returns]!!, nodeMap[body.throws]!!)
) )
} }
@@ -1100,7 +1100,12 @@ internal object DFGSerializer {
moduleDataFlowGraph.functions.forEach { moduleDataFlowGraph.functions.forEach {
val symbol = functionSymbols[it.symbol] val symbol = functionSymbols[it.symbol]
functions.put(symbol, DataFlowIR.Function(symbol, it.numberOfParameters, deserializeBody(it.body))) val function = DataFlowIR.Function(
symbol = symbol,
parameterTypes = it.parameterTypes.map { types[it] }.toTypedArray(),
body = deserializeBody(it.body)
)
functions.put(symbol, function)
} }
} }
} }
@@ -234,12 +234,12 @@ internal object DataFlowIR {
class FunctionBody(val nodes: List<Node>, val returns: Node.Variable, val throws: Node.Variable) class FunctionBody(val nodes: List<Node>, val returns: Node.Variable, val throws: Node.Variable)
class Function(val symbol: FunctionSymbol, class Function(val symbol: FunctionSymbol,
val numberOfParameters: Int, val parameterTypes: Array<Type>,
val body: FunctionBody) { val body: FunctionBody) {
fun debugOutput() { fun debugOutput() {
println("FUNCTION $symbol") println("FUNCTION $symbol")
println("Params: $numberOfParameters") println("Params: ${parameterTypes.contentToString()}")
val ids = body.nodes.withIndex().associateBy({ it.value }, { it.index }) val ids = body.nodes.withIndex().associateBy({ it.value }, { it.index })
body.nodes.forEach { body.nodes.forEach {
println(" NODE #${ids[it]!!}") println(" NODE #${ids[it]!!}")
@@ -489,8 +489,7 @@ internal object DataFlowIR {
return type return type
} }
fun mapType(type: KotlinType) = fun mapType(type: KotlinType) = mapClass(type.erasure().single())
mapClass(type.erasure().single().constructor.declarationDescriptor as ClassDescriptor)
// TODO: use from LlvmDeclarations. // TODO: use from LlvmDeclarations.
private fun getFqName(descriptor: DeclarationDescriptor): FqName { private fun getFqName(descriptor: DeclarationDescriptor): FqName {
@@ -267,7 +267,7 @@ internal object EscapeAnalysis {
} }
for (functionSymbol in callGraph.directEdges.keys) { for (functionSymbol in callGraph.directEdges.keys) {
val numberOfParameters = intraproceduralAnalysisResult[functionSymbol]!!.function.numberOfParameters val numberOfParameters = intraproceduralAnalysisResult[functionSymbol]!!.function.parameterTypes.size
escapeAnalysisResults[functionSymbol] = FunctionEscapeAnalysisResult( escapeAnalysisResults[functionSymbol] = FunctionEscapeAnalysisResult(
// Assume no edges at the beginning. // Assume no edges at the beginning.
// Then iteratively add needed. // Then iteratively add needed.