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
@@ -619,15 +631,16 @@ internal object DFGSerializer {
result.writeByte(type.ordinal.toByte()) result.writeByte(type.ordinal.toByte())
parameter ?.write(result) parameter ?.write(result)
const ?.write(result) const ?.write(result)
staticCall?.write(result) staticCall ?.write(result)
newObject ?.write(result) newObject ?.write(result)
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)
arrayWrite?.write(result) arrayWrite ?.write(result)
variable ?.write(result) variable ?.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) }
@@ -674,15 +690,16 @@ internal object DFGSerializer {
when (type) { when (type) {
NodeType.PARAMETER -> result.parameter = Parameter (data) NodeType.PARAMETER -> result.parameter = Parameter (data)
NodeType.CONST -> result.const = Const (data) NodeType.CONST -> result.const = Const (data)
NodeType.STATIC_CALL -> result.staticCall = StaticCall(data) NodeType.STATIC_CALL -> result.staticCall = StaticCall (data)
NodeType.NEW_OBJECT -> result.newObject = NewObject (data) NodeType.NEW_OBJECT -> result.newObject = NewObject (data)
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)
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite(data) NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite (data)
NodeType.VARIABLE -> result.variable = Variable (data) NodeType.VARIABLE -> result.variable = Variable (data)
else -> { } else -> { }
} }
@@ -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)