DFG: Supported createUninitializedInstance/initInstance functions

This commit is contained in:
Igor Chevdar
2018-04-23 19:01:17 +03:00
parent 0d50877d63
commit 3cd290631c
4 changed files with 116 additions and 59 deletions
@@ -355,7 +355,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
val thrownValues = mutableListOf<IrExpression>() val thrownValues = mutableListOf<IrExpression>()
val catchParameters = mutableSetOf<VariableDescriptor>() val catchParameters = mutableSetOf<VariableDescriptor>()
private val returnableBlocks = mutableMapOf<FunctionDescriptor, IrReturnableBlock>()
private val suspendableExpressionStack = mutableListOf<IrSuspendableExpression>() private val suspendableExpressionStack = mutableListOf<IrSuspendableExpression>()
override fun visitElement(element: IrElement) { override fun visitElement(element: IrElement) {
@@ -453,6 +452,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
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
private val createUninitializedInstanceSymbol = context.ir.symbols.createUninitializedInstance
private val initInstanceSymbol = context.ir.symbols.initInstance
private val scheduleImplSymbol = context.ir.symbols.scheduleImpl private val scheduleImplSymbol = context.ir.symbols.scheduleImpl
private val scheduleImplProducerClassSymbol = context.ir.symbols.functions[0] private val scheduleImplProducerClassSymbol = context.ir.symbols.functions[0]
private val scheduleImplProducerParam = scheduleImplSymbol.descriptor.valueParameters[2].also { private val scheduleImplProducerParam = scheduleImplSymbol.descriptor.valueParameters[2].also {
@@ -473,14 +474,15 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
private val allParameters = (descriptor as? FunctionDescriptor)?.allParameters ?: emptyList() private val allParameters = (descriptor as? FunctionDescriptor)?.allParameters ?: emptyList()
private val templateParameters = allParameters.withIndex().associateBy({ it.value }, { DataFlowIR.Node.Parameter(it.index) }) private val templateParameters = allParameters.withIndex().associateBy({ it.value }, { DataFlowIR.Node.Parameter(it.index) })
private val continuationParameter = if (descriptor !is IrSimpleFunction) { private val continuationParameter = when {
null descriptor !is IrSimpleFunction -> null
} else if (descriptor.isSuspend) {
DataFlowIR.Node.Parameter(allParameters.size) descriptor.isSuspend -> DataFlowIR.Node.Parameter(allParameters.size)
} else if (doResumeFunctionSymbol in descriptor.overriddenSymbols) { // <this> is a CoroutineImpl inheritor.
doResumeFunctionSymbol in descriptor.overriddenSymbols -> // <this> is a CoroutineImpl inheritor.
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation. templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
} else {
null else -> null
} }
private fun getContinuation() = continuationParameter ?: error("Function $descriptor has no continuation parameter") private fun getContinuation() = continuationParameter ?: error("Function $descriptor has no continuation parameter")
@@ -592,6 +594,23 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
arraySetSymbol -> DataFlowIR.Node.ArrayWrite(expressionToEdge(value.dispatchReceiver!!), arraySetSymbol -> DataFlowIR.Node.ArrayWrite(expressionToEdge(value.dispatchReceiver!!),
expressionToEdge(value.getValueArgument(0)!!), expressionToEdge(value.getValueArgument(1)!!)) expressionToEdge(value.getValueArgument(0)!!), expressionToEdge(value.getValueArgument(1)!!))
createUninitializedInstanceSymbol ->
DataFlowIR.Node.AllocInstance(symbolTable.mapType(value.getTypeArgument(0)!!))
initInstanceSymbol -> {
val thiz = expressionToEdge(value.getValueArgument(0)!!)
val initializer = value.getValueArgument(1) as IrCall
val arguments = listOf(thiz) + initializer.getArguments().map { expressionToEdge(it.second) }
val callee = initializer.symbol.owner as IrConstructor
DataFlowIR.Node.StaticCall(
symbolTable.mapFunction(callee),
arguments,
symbolTable.mapClass(context.ir.symbols.unit.owner),
symbolTable.mapClass(callee.constructedClass),
null
)
}
else -> { else -> {
val callee = value.symbol.owner val callee = value.symbol.owner
val arguments = value.getArguments() val arguments = value.getArguments()
@@ -516,6 +516,15 @@ internal object DFGSerializer {
} }
} }
class AllocInstance(val type: Int) {
constructor(data: ArraySlice) : this(data.readInt())
fun write(result: ArraySlice) {
result.writeInt(type)
}
}
class FieldRead(val receiver: Edge?, val field: Field) { class FieldRead(val receiver: Edge?, val field: Field) {
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data)) constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data))
@@ -578,6 +587,7 @@ internal object DFGSerializer {
VTABLE_CALL, VTABLE_CALL,
ITABLE_CALL, ITABLE_CALL,
SINGLETON, SINGLETON,
ALLOC_INSTANCE,
FIELD_READ, FIELD_READ,
FIELD_WRITE, FIELD_WRITE,
ARRAY_READ, ARRAY_READ,
@@ -593,6 +603,7 @@ internal object DFGSerializer {
var vtableCall : VtableCall? = null var vtableCall : VtableCall? = null
var itableCall : ItableCall? = null var itableCall : ItableCall? = null
var singleton : Singleton? = null var singleton : Singleton? = null
var allocInstance: AllocInstance? = null
var fieldRead : FieldRead? = null var fieldRead : FieldRead? = null
var fieldWrite : FieldWrite? = null var fieldWrite : FieldWrite? = null
var arrayRead : ArrayRead? = null var arrayRead : ArrayRead? = null
@@ -607,6 +618,7 @@ internal object DFGSerializer {
vtableCall != null -> NodeType.VTABLE_CALL vtableCall != null -> NodeType.VTABLE_CALL
itableCall != null -> NodeType.ITABLE_CALL itableCall != null -> NodeType.ITABLE_CALL
singleton != null -> NodeType.SINGLETON singleton != null -> NodeType.SINGLETON
allocInstance != null -> NodeType.ALLOC_INSTANCE
fieldRead != null -> NodeType.FIELD_READ fieldRead != null -> NodeType.FIELD_READ
fieldWrite != null -> NodeType.FIELD_WRITE fieldWrite != null -> NodeType.FIELD_WRITE
arrayRead != null -> NodeType.ARRAY_READ arrayRead != null -> NodeType.ARRAY_READ
@@ -624,6 +636,7 @@ internal object DFGSerializer {
vtableCall ?.write(result) vtableCall ?.write(result)
itableCall ?.write(result) itableCall ?.write(result)
singleton ?.write(result) singleton ?.write(result)
allocInstance?.write(result)
fieldRead ?.write(result) fieldRead ?.write(result)
fieldWrite ?.write(result) fieldWrite ?.write(result)
arrayRead ?.write(result) arrayRead ?.write(result)
@@ -653,6 +666,9 @@ internal object DFGSerializer {
fun singleton(type: Int, constructor: Int?) = fun singleton(type: Int, constructor: Int?) =
Node().also { it.singleton = Singleton(type, constructor) } Node().also { it.singleton = Singleton(type, constructor) }
fun allocInst(type: Int) =
Node().also { it.allocInstance = AllocInstance(type) }
fun fieldRead(receiver: Edge?, field: Field) = fun fieldRead(receiver: Edge?, field: Field) =
Node().also { it.fieldRead = FieldRead(receiver, field) } Node().also { it.fieldRead = FieldRead(receiver, field) }
@@ -679,6 +695,7 @@ internal object DFGSerializer {
NodeType.VTABLE_CALL -> result.vtableCall = VtableCall (data) NodeType.VTABLE_CALL -> result.vtableCall = VtableCall (data)
NodeType.ITABLE_CALL -> result.itableCall = ItableCall (data) NodeType.ITABLE_CALL -> result.itableCall = ItableCall (data)
NodeType.SINGLETON -> result.singleton = Singleton (data) NodeType.SINGLETON -> result.singleton = Singleton (data)
NodeType.ALLOC_INSTANCE -> result.allocInstance = AllocInstance(data)
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data) NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data) NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data)
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data) NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
@@ -873,6 +890,9 @@ internal object DFGSerializer {
is DataFlowIR.Node.Singleton -> is DataFlowIR.Node.Singleton ->
Node.singleton(typeMap[node.type]!!, node.constructor?.let { functionSymbolMap[it]!! }) Node.singleton(typeMap[node.type]!!, node.constructor?.let { functionSymbolMap[it]!! })
is DataFlowIR.Node.AllocInstance ->
Node.allocInst(typeMap[node.type]!!)
is DataFlowIR.Node.FieldRead -> is DataFlowIR.Node.FieldRead ->
Node.fieldRead(node.receiver?.let { buildEdge(it) }, buildField(node.field)) Node.fieldRead(node.receiver?.let { buildEdge(it) }, buildField(node.field))
@@ -1108,6 +1128,10 @@ internal object DFGSerializer {
DataFlowIR.Node.Singleton(types[singleton.type], singleton.constructor?.let { functionSymbols[it] }) DataFlowIR.Node.Singleton(types[singleton.type], singleton.constructor?.let { functionSymbols[it] })
} }
NodeType.ALLOC_INSTANCE -> {
DataFlowIR.Node.AllocInstance(types[it.allocInstance!!.type])
}
NodeType.FIELD_READ -> { NodeType.FIELD_READ -> {
val fieldRead = it.fieldRead!! val fieldRead = it.fieldRead!!
val receiver = fieldRead.receiver?.let { deserializeEdge(it) } val receiver = fieldRead.receiver?.let { deserializeEdge(it) }
@@ -237,6 +237,7 @@ internal object DataFlowIR {
val receiverType: Type?, irCallSite: IrFunctionAccessExpression?) val receiverType: Type?, irCallSite: IrFunctionAccessExpression?)
: Call(callee, arguments, irCallSite) : Call(callee, arguments, irCallSite)
// TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove.
class NewObject(constructor: FunctionSymbol, arguments: List<Edge>, val constructedType: Type, override val irCallSite: IrCall?) class NewObject(constructor: FunctionSymbol, arguments: List<Edge>, val constructedType: Type, override val irCallSite: IrCall?)
: Call(constructor, arguments, irCallSite) : Call(constructor, arguments, irCallSite)
@@ -254,6 +255,8 @@ internal object DataFlowIR {
class Singleton(val type: Type, val constructor: FunctionSymbol?) : Node() class Singleton(val type: Type, val constructor: FunctionSymbol?) : Node()
class AllocInstance(val type: Type) : Node()
class FieldRead(val receiver: Edge?, val field: Field, val ir: IrGetField?) : Node() class FieldRead(val receiver: Edge?, val field: Field, val ir: IrGetField?) : Node()
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge) : Node() class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge) : Node()
@@ -296,6 +299,9 @@ internal object DataFlowIR {
is Node.Singleton -> is Node.Singleton ->
" SINGLETON ${node.type}\n" " SINGLETON ${node.type}\n"
is Node.AllocInstance ->
" ALLOC INSTANCE ${node.type}\n"
is Node.StaticCall -> { is Node.StaticCall -> {
val result = StringBuilder() val result = StringBuilder()
result.appendln(" STATIC CALL ${node.callee}") result.appendln(" STATIC CALL ${node.callee}")
@@ -355,6 +355,10 @@ internal object Devirtualization {
node.constructor?.let { dfs(it) } node.constructor?.let { dfs(it) }
} }
is DataFlowIR.Node.AllocInstance -> {
addInstantiatingClass(node.type)
}
is DataFlowIR.Node.Const -> addInstantiatingClass(node.type) is DataFlowIR.Node.Const -> addInstantiatingClass(node.type)
is DataFlowIR.Node.StaticCall -> is DataFlowIR.Node.StaticCall ->
@@ -918,6 +922,10 @@ internal object Devirtualization {
instanceNode instanceNode
} }
is DataFlowIR.Node.AllocInstance -> {
concreteClass(node.type.resolved())
}
is DataFlowIR.Node.FieldRead -> is DataFlowIR.Node.FieldRead ->
fieldNode(node.field) fieldNode(node.field)