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 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.
|
|
||||||
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
doResumeFunctionSymbol in descriptor.overriddenSymbols -> // <this> is a CoroutineImpl inheritor.
|
||||||
} else {
|
templateParameters[descriptor.dispatchReceiverParameter!!] // It is its own continuation.
|
||||||
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()
|
||||||
|
|||||||
+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) {
|
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,
|
||||||
@@ -586,49 +596,52 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Node {
|
class Node {
|
||||||
var parameter : Parameter? = null
|
var parameter : Parameter? = null
|
||||||
var const : Const? = null
|
var const : Const? = null
|
||||||
var staticCall : StaticCall? = null
|
var staticCall : StaticCall? = null
|
||||||
var newObject : NewObject? = null
|
var newObject : NewObject? = null
|
||||||
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 fieldRead : FieldRead? = null
|
var allocInstance: AllocInstance? = null
|
||||||
var fieldWrite : FieldWrite? = null
|
var fieldRead : FieldRead? = null
|
||||||
var arrayRead : ArrayRead? = null
|
var fieldWrite : FieldWrite? = null
|
||||||
var arrayWrite : ArrayWrite? = null
|
var arrayRead : ArrayRead? = null
|
||||||
var variable : Variable? = null
|
var arrayWrite : ArrayWrite? = null
|
||||||
|
var variable : Variable? = null
|
||||||
|
|
||||||
val type get() = when {
|
val type get() = when {
|
||||||
parameter != null -> NodeType.PARAMETER
|
parameter != null -> NodeType.PARAMETER
|
||||||
const != null -> NodeType.CONST
|
const != null -> NodeType.CONST
|
||||||
staticCall != null -> NodeType.STATIC_CALL
|
staticCall != null -> NodeType.STATIC_CALL
|
||||||
newObject != null -> NodeType.NEW_OBJECT
|
newObject != null -> NodeType.NEW_OBJECT
|
||||||
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
|
||||||
fieldRead != null -> NodeType.FIELD_READ
|
allocInstance != null -> NodeType.ALLOC_INSTANCE
|
||||||
fieldWrite != null -> NodeType.FIELD_WRITE
|
fieldRead != null -> NodeType.FIELD_READ
|
||||||
arrayRead != null -> NodeType.ARRAY_READ
|
fieldWrite != null -> NodeType.FIELD_WRITE
|
||||||
arrayWrite != null -> NodeType.ARRAY_WRITE
|
arrayRead != null -> NodeType.ARRAY_READ
|
||||||
variable != null -> NodeType.VARIABLE
|
arrayWrite != null -> NodeType.ARRAY_WRITE
|
||||||
else -> NodeType.UNKNOWN
|
variable != null -> NodeType.VARIABLE
|
||||||
|
else -> NodeType.UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
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)
|
||||||
fieldRead ?.write(result)
|
allocInstance?.write(result)
|
||||||
fieldWrite?.write(result)
|
fieldRead ?.write(result)
|
||||||
arrayRead ?.write(result)
|
fieldWrite ?.write(result)
|
||||||
arrayWrite?.write(result)
|
arrayRead ?.write(result)
|
||||||
variable ?.write(result)
|
arrayWrite ?.write(result)
|
||||||
|
variable ?.write(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -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) }
|
||||||
|
|
||||||
@@ -672,19 +688,20 @@ internal object DFGSerializer {
|
|||||||
val type = enumValues<NodeType>()[data.readByte().toInt()]
|
val type = enumValues<NodeType>()[data.readByte().toInt()]
|
||||||
val result = Node()
|
val result = Node()
|
||||||
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.FIELD_READ -> result.fieldRead = FieldRead (data)
|
NodeType.ALLOC_INSTANCE -> result.allocInstance = AllocInstance(data)
|
||||||
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite(data)
|
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data)
|
||||||
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
|
NodeType.FIELD_WRITE -> result.fieldWrite = FieldWrite (data)
|
||||||
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite(data)
|
NodeType.ARRAY_READ -> result.arrayRead = ArrayRead (data)
|
||||||
NodeType.VARIABLE -> result.variable = Variable (data)
|
NodeType.ARRAY_WRITE -> result.arrayWrite = ArrayWrite (data)
|
||||||
else -> { }
|
NodeType.VARIABLE -> result.variable = Variable (data)
|
||||||
|
else -> { }
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -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) }
|
||||||
|
|||||||
+6
@@ -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}")
|
||||||
|
|||||||
+8
@@ -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)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user