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,6 +622,7 @@ 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 functionReference: FunctionReference? = 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
@@ -626,6 +638,7 @@ internal object DFGSerializer {
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
@@ -644,7 +657,8 @@ internal object DFGSerializer {
vtableCall ?.write(result) vtableCall ?.write(result)
itableCall ?.write(result) itableCall ?.write(result)
singleton ?.write(result) singleton ?.write(result)
allocInstance?.write(result) allocInstance ?.write(result)
functionReference?.write(result)
fieldRead ?.write(result) fieldRead ?.write(result)
fieldWrite ?.write(result) fieldWrite ?.write(result)
arrayRead ?.write(result) arrayRead ?.write(result)
@@ -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,6 +724,7 @@ 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.FUNCTION_REFERENCE -> result.functionReference = FunctionReference(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)
@@ -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)