DFG: Supported createUninitializedInstance/initInstance functions
This commit is contained in:
+28
-9
@@ -355,7 +355,6 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
val thrownValues = mutableListOf<IrExpression>()
|
||||
val catchParameters = mutableSetOf<VariableDescriptor>()
|
||||
|
||||
private val returnableBlocks = mutableMapOf<FunctionDescriptor, IrReturnableBlock>()
|
||||
private val suspendableExpressionStack = mutableListOf<IrSuspendableExpression>()
|
||||
|
||||
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 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 scheduleImplProducerClassSymbol = context.ir.symbols.functions[0]
|
||||
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 templateParameters = allParameters.withIndex().associateBy({ it.value }, { DataFlowIR.Node.Parameter(it.index) })
|
||||
|
||||
private val continuationParameter = if (descriptor !is IrSimpleFunction) {
|
||||
null
|
||||
} else if (descriptor.isSuspend) {
|
||||
DataFlowIR.Node.Parameter(allParameters.size)
|
||||
} else if (doResumeFunctionSymbol in descriptor.overriddenSymbols) { // <this> is a CoroutineImpl inheritor.
|
||||
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
||||
} else {
|
||||
null
|
||||
private val continuationParameter = when {
|
||||
descriptor !is IrSimpleFunction -> null
|
||||
|
||||
descriptor.isSuspend -> DataFlowIR.Node.Parameter(allParameters.size)
|
||||
|
||||
doResumeFunctionSymbol in descriptor.overriddenSymbols -> // <this> is a CoroutineImpl inheritor.
|
||||
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
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!!),
|
||||
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 -> {
|
||||
val callee = value.symbol.owner
|
||||
val arguments = value.getArguments()
|
||||
|
||||
+74
-50
@@ -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) {
|
||||
|
||||
constructor(data: ArraySlice) : this(data.readNullable { Edge(this) }, Field(data))
|
||||
@@ -578,6 +587,7 @@ internal object DFGSerializer {
|
||||
VTABLE_CALL,
|
||||
ITABLE_CALL,
|
||||
SINGLETON,
|
||||
ALLOC_INSTANCE,
|
||||
FIELD_READ,
|
||||
FIELD_WRITE,
|
||||
ARRAY_READ,
|
||||
@@ -586,49 +596,52 @@ internal object DFGSerializer {
|
||||
}
|
||||
|
||||
class Node {
|
||||
var parameter : Parameter? = null
|
||||
var const : Const? = null
|
||||
var staticCall : StaticCall? = null
|
||||
var newObject : NewObject? = null
|
||||
var vtableCall : VtableCall? = null
|
||||
var itableCall : ItableCall? = null
|
||||
var singleton : Singleton? = null
|
||||
var fieldRead : FieldRead? = null
|
||||
var fieldWrite : FieldWrite? = null
|
||||
var arrayRead : ArrayRead? = null
|
||||
var arrayWrite : ArrayWrite? = null
|
||||
var variable : Variable? = null
|
||||
var parameter : Parameter? = null
|
||||
var const : Const? = null
|
||||
var staticCall : StaticCall? = null
|
||||
var newObject : NewObject? = null
|
||||
var vtableCall : VtableCall? = null
|
||||
var itableCall : ItableCall? = null
|
||||
var singleton : Singleton? = null
|
||||
var allocInstance: AllocInstance? = null
|
||||
var fieldRead : FieldRead? = null
|
||||
var fieldWrite : FieldWrite? = null
|
||||
var arrayRead : ArrayRead? = null
|
||||
var arrayWrite : ArrayWrite? = null
|
||||
var variable : Variable? = null
|
||||
|
||||
val type get() = when {
|
||||
parameter != null -> NodeType.PARAMETER
|
||||
const != null -> NodeType.CONST
|
||||
staticCall != null -> NodeType.STATIC_CALL
|
||||
newObject != null -> NodeType.NEW_OBJECT
|
||||
vtableCall != null -> NodeType.VTABLE_CALL
|
||||
itableCall != null -> NodeType.ITABLE_CALL
|
||||
singleton != null -> NodeType.SINGLETON
|
||||
fieldRead != null -> NodeType.FIELD_READ
|
||||
fieldWrite != null -> NodeType.FIELD_WRITE
|
||||
arrayRead != null -> NodeType.ARRAY_READ
|
||||
arrayWrite != null -> NodeType.ARRAY_WRITE
|
||||
variable != null -> NodeType.VARIABLE
|
||||
else -> NodeType.UNKNOWN
|
||||
parameter != null -> NodeType.PARAMETER
|
||||
const != null -> NodeType.CONST
|
||||
staticCall != null -> NodeType.STATIC_CALL
|
||||
newObject != null -> NodeType.NEW_OBJECT
|
||||
vtableCall != null -> NodeType.VTABLE_CALL
|
||||
itableCall != null -> NodeType.ITABLE_CALL
|
||||
singleton != null -> NodeType.SINGLETON
|
||||
allocInstance != null -> NodeType.ALLOC_INSTANCE
|
||||
fieldRead != null -> NodeType.FIELD_READ
|
||||
fieldWrite != null -> NodeType.FIELD_WRITE
|
||||
arrayRead != null -> NodeType.ARRAY_READ
|
||||
arrayWrite != null -> NodeType.ARRAY_WRITE
|
||||
variable != null -> NodeType.VARIABLE
|
||||
else -> NodeType.UNKNOWN
|
||||
}
|
||||
|
||||
fun write(result: ArraySlice) {
|
||||
result.writeByte(type.ordinal.toByte())
|
||||
parameter ?.write(result)
|
||||
const ?.write(result)
|
||||
staticCall?.write(result)
|
||||
newObject ?.write(result)
|
||||
vtableCall?.write(result)
|
||||
itableCall?.write(result)
|
||||
singleton ?.write(result)
|
||||
fieldRead ?.write(result)
|
||||
fieldWrite?.write(result)
|
||||
arrayRead ?.write(result)
|
||||
arrayWrite?.write(result)
|
||||
variable ?.write(result)
|
||||
parameter ?.write(result)
|
||||
const ?.write(result)
|
||||
staticCall ?.write(result)
|
||||
newObject ?.write(result)
|
||||
vtableCall ?.write(result)
|
||||
itableCall ?.write(result)
|
||||
singleton ?.write(result)
|
||||
allocInstance?.write(result)
|
||||
fieldRead ?.write(result)
|
||||
fieldWrite ?.write(result)
|
||||
arrayRead ?.write(result)
|
||||
arrayWrite ?.write(result)
|
||||
variable ?.write(result)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -653,6 +666,9 @@ internal object DFGSerializer {
|
||||
fun singleton(type: Int, constructor: Int?) =
|
||||
Node().also { it.singleton = Singleton(type, constructor) }
|
||||
|
||||
fun allocInst(type: Int) =
|
||||
Node().also { it.allocInstance = AllocInstance(type) }
|
||||
|
||||
fun fieldRead(receiver: Edge?, field: Field) =
|
||||
Node().also { it.fieldRead = FieldRead(receiver, field) }
|
||||
|
||||
@@ -672,19 +688,20 @@ internal object DFGSerializer {
|
||||
val type = enumValues<NodeType>()[data.readByte().toInt()]
|
||||
val result = Node()
|
||||
when (type) {
|
||||
NodeType.PARAMETER -> result.parameter = Parameter (data)
|
||||
NodeType.CONST -> result.const = Const (data)
|
||||
NodeType.STATIC_CALL -> result.staticCall = StaticCall(data)
|
||||
NodeType.NEW_OBJECT -> result.newObject = NewObject (data)
|
||||
NodeType.VTABLE_CALL -> result.vtableCall = VtableCall(data)
|
||||
NodeType.ITABLE_CALL -> result.itableCall = ItableCall(data)
|
||||
NodeType.SINGLETON -> result.singleton = Singleton (data)
|
||||
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
|
||||
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite(data)
|
||||
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
|
||||
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite(data)
|
||||
NodeType.VARIABLE -> result.variable = Variable (data)
|
||||
else -> { }
|
||||
NodeType.PARAMETER -> result.parameter = Parameter (data)
|
||||
NodeType.CONST -> result.const = Const (data)
|
||||
NodeType.STATIC_CALL -> result.staticCall = StaticCall (data)
|
||||
NodeType.NEW_OBJECT -> result.newObject = NewObject (data)
|
||||
NodeType.VTABLE_CALL -> result.vtableCall = VtableCall (data)
|
||||
NodeType.ITABLE_CALL -> result.itableCall = ItableCall (data)
|
||||
NodeType.SINGLETON -> result.singleton = Singleton (data)
|
||||
NodeType.ALLOC_INSTANCE -> result.allocInstance = AllocInstance(data)
|
||||
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
|
||||
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data)
|
||||
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
|
||||
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite (data)
|
||||
NodeType.VARIABLE -> result.variable = Variable (data)
|
||||
else -> { }
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -873,6 +890,9 @@ internal object DFGSerializer {
|
||||
is DataFlowIR.Node.Singleton ->
|
||||
Node.singleton(typeMap[node.type]!!, node.constructor?.let { functionSymbolMap[it]!! })
|
||||
|
||||
is DataFlowIR.Node.AllocInstance ->
|
||||
Node.allocInst(typeMap[node.type]!!)
|
||||
|
||||
is DataFlowIR.Node.FieldRead ->
|
||||
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] })
|
||||
}
|
||||
|
||||
NodeType.ALLOC_INSTANCE -> {
|
||||
DataFlowIR.Node.AllocInstance(types[it.allocInstance!!.type])
|
||||
}
|
||||
|
||||
NodeType.FIELD_READ -> {
|
||||
val fieldRead = it.fieldRead!!
|
||||
val receiver = fieldRead.receiver?.let { deserializeEdge(it) }
|
||||
|
||||
+6
@@ -237,6 +237,7 @@ internal object DataFlowIR {
|
||||
val receiverType: Type?, irCallSite: IrFunctionAccessExpression?)
|
||||
: 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?)
|
||||
: Call(constructor, arguments, irCallSite)
|
||||
|
||||
@@ -254,6 +255,8 @@ internal object DataFlowIR {
|
||||
|
||||
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 FieldWrite(val receiver: Edge?, val field: Field, val value: Edge) : Node()
|
||||
@@ -296,6 +299,9 @@ internal object DataFlowIR {
|
||||
is Node.Singleton ->
|
||||
" SINGLETON ${node.type}\n"
|
||||
|
||||
is Node.AllocInstance ->
|
||||
" ALLOC INSTANCE ${node.type}\n"
|
||||
|
||||
is Node.StaticCall -> {
|
||||
val result = StringBuilder()
|
||||
result.appendln(" STATIC CALL ${node.callee}")
|
||||
|
||||
+8
@@ -355,6 +355,10 @@ internal object Devirtualization {
|
||||
node.constructor?.let { dfs(it) }
|
||||
}
|
||||
|
||||
is DataFlowIR.Node.AllocInstance -> {
|
||||
addInstantiatingClass(node.type)
|
||||
}
|
||||
|
||||
is DataFlowIR.Node.Const -> addInstantiatingClass(node.type)
|
||||
|
||||
is DataFlowIR.Node.StaticCall ->
|
||||
@@ -918,6 +922,10 @@ internal object Devirtualization {
|
||||
instanceNode
|
||||
}
|
||||
|
||||
is DataFlowIR.Node.AllocInstance -> {
|
||||
concreteClass(node.type.resolved())
|
||||
}
|
||||
|
||||
is DataFlowIR.Node.FieldRead ->
|
||||
fieldNode(node.field)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user