DFG: Supported IrFunctionReference

This commit is contained in:
Igor Chevdar
2019-03-25 17:27:03 +03:00
parent 7bf16abf66
commit c5430769de
5 changed files with 93 additions and 34 deletions
@@ -124,6 +124,13 @@ internal class CallGraphBuilder(val context: Context,
} }
} }
} }
body.nodes.filterIsInstance<DataFlowIR.Node.FunctionReference>()
.forEach {
val callee = it.symbol.resolved()
if (callee is DataFlowIR.FunctionSymbol.Declared
&& !directEdges.containsKey(callee))
dfs(callee)
}
} else { } else {
var function = moduleDFG.functions[symbol] var function = moduleDFG.functions[symbol]
var local = true var local = true
@@ -160,6 +167,16 @@ internal class CallGraphBuilder(val context: Context,
} }
} }
} }
body.nodes.filterIsInstance<DataFlowIR.Node.FunctionReference>()
.forEach {
val callee = it.symbol.resolved()
if (moduleDFG.functions.containsKey(callee))
addNode(callee)
if (callee is DataFlowIR.FunctionSymbol.Declared
&& !visitedFunctions.contains(callee))
dfs(callee)
}
} }
} }
} }
@@ -545,8 +545,12 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
when (value) { when (value) {
is IrGetValue -> getNode(value) is IrGetValue -> getNode(value)
is IrVararg, is IrVararg -> DataFlowIR.Node.Const(symbolTable.mapType(value.type))
is IrFunctionReference -> DataFlowIR.Node.Const(symbolTable.mapType(value.type))
is IrFunctionReference -> {
val callee = value.symbol.owner
DataFlowIR.Node.FunctionReference(symbolTable.mapFunction(callee), symbolTable.mapType(value.type))
}
is IrConst<*> -> is IrConst<*> ->
if (value.value == null) if (value.value == null)
@@ -530,6 +530,16 @@ internal object DFGSerializer {
} }
} }
class FunctionReference(val symbol: Int, val type: Int) {
constructor(data: ArraySlice) : this(data.readInt(), data.readInt())
fun write(result: ArraySlice) {
result.writeInt(symbol)
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))
@@ -594,6 +604,7 @@ internal object DFGSerializer {
ITABLE_CALL, ITABLE_CALL,
SINGLETON, SINGLETON,
ALLOC_INSTANCE, ALLOC_INSTANCE,
FUNCTION_REFERENCE,
FIELD_READ, FIELD_READ,
FIELD_WRITE, FIELD_WRITE,
ARRAY_READ, ARRAY_READ,
@@ -611,21 +622,23 @@ internal object DFGSerializer {
var itableCall : ItableCall? = null var itableCall : ItableCall? = null
var singleton : Singleton? = null var singleton : Singleton? = null
var allocInstance: AllocInstance? = null var allocInstance: AllocInstance? = null
var fieldRead : FieldRead? = null var functionReference: FunctionReference? = 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
allocInstance != null -> NodeType.ALLOC_INSTANCE allocInstance != null -> NodeType.ALLOC_INSTANCE
functionReference != null -> NodeType.FUNCTION_REFERENCE
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
@@ -637,19 +650,20 @@ internal object DFGSerializer {
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)
allocInstance?.write(result) allocInstance ?.write(result)
fieldRead ?.write(result) functionReference?.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 {
@@ -679,6 +693,9 @@ internal object DFGSerializer {
fun allocInst(type: Int) = fun allocInst(type: Int) =
Node().also { it.allocInstance = AllocInstance(type) } Node().also { it.allocInstance = AllocInstance(type) }
fun functionReference(symbol: Int, type: Int) =
Node().also { it.functionReference = FunctionReference(symbol, 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) }
@@ -707,12 +724,13 @@ internal object DFGSerializer {
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.ALLOC_INSTANCE -> result.allocInstance = AllocInstance(data)
NodeType.FIELD_READ -> result.fieldRead = FieldRead (data) NodeType.FUNCTION_REFERENCE -> result.functionReference = FunctionReference(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
} }
@@ -913,6 +931,9 @@ internal object DFGSerializer {
is DataFlowIR.Node.AllocInstance -> is DataFlowIR.Node.AllocInstance ->
Node.allocInst(typeMap[node.type]!!) Node.allocInst(typeMap[node.type]!!)
is DataFlowIR.Node.FunctionReference ->
Node.functionReference(functionSymbolMap[node.symbol]!!, 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))
@@ -1162,6 +1183,11 @@ internal object DFGSerializer {
DataFlowIR.Node.AllocInstance(types[it.allocInstance!!.type]) DataFlowIR.Node.AllocInstance(types[it.allocInstance!!.type])
} }
NodeType.FUNCTION_REFERENCE -> {
val functionReference = it.functionReference!!
DataFlowIR.Node.FunctionReference(functionSymbols[functionReference.symbol], types[functionReference.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) }
@@ -254,6 +254,8 @@ internal object DataFlowIR {
class AllocInstance(val type: Type) : Node() class AllocInstance(val type: Type) : Node()
class FunctionReference(val symbol: FunctionSymbol, 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()
@@ -302,6 +304,9 @@ internal object DataFlowIR {
is Node.AllocInstance -> is Node.AllocInstance ->
" ALLOC INSTANCE ${node.type}\n" " ALLOC INSTANCE ${node.type}\n"
is Node.FunctionReference ->
" FUNCTION REFERENCE ${node.symbol}\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}")
@@ -358,6 +358,9 @@ internal object Devirtualization {
is DataFlowIR.Node.StaticCall -> is DataFlowIR.Node.StaticCall ->
dfs(node.callee) dfs(node.callee)
is DataFlowIR.Node.FunctionReference ->
dfs(node.symbol)
is DataFlowIR.Node.FieldRead -> is DataFlowIR.Node.FieldRead ->
if (entryPoint == null && node.field.type.isFinal) if (entryPoint == null && node.field.type.isFinal)
addInstantiatingClass(node.field.type) addInstantiatingClass(node.field.type)
@@ -963,6 +966,10 @@ internal object Devirtualization {
concreteClass(node.type.resolved()) concreteClass(node.type.resolved())
} }
is DataFlowIR.Node.FunctionReference -> {
concreteClass(node.type.resolved())
}
is DataFlowIR.Node.FieldRead -> is DataFlowIR.Node.FieldRead ->
fieldNode(node.field) fieldNode(node.field)