Fixed bug in devirtualization
In a library fields of objects might be initialized by some of users with unknown type.
This commit is contained in:
+22
-4
@@ -172,7 +172,7 @@ internal object Devirtualization {
|
|||||||
|
|
||||||
val voidNode = addNode { Node.Ordinary(it, { "Void" }) }
|
val voidNode = addNode { Node.Ordinary(it, { "Void" }) }
|
||||||
val virtualNode = addNode { Node.Source(it, VIRTUAL_TYPE_ID, { "Virtual" }) }
|
val virtualNode = addNode { Node.Source(it, VIRTUAL_TYPE_ID, { "Virtual" }) }
|
||||||
val arrayItemField = DataFlowIR.Field(null, symbolTable.mapClass(context.irBuiltIns.anyClass.owner), 1, "Array\$Item")
|
val arrayItemField = DataFlowIR.Field(null, symbolTable.mapClassReferenceType(context.irBuiltIns.anyClass.owner), 1, "Array\$Item")
|
||||||
val functions = mutableMapOf<DataFlowIR.FunctionSymbol, Function>()
|
val functions = mutableMapOf<DataFlowIR.FunctionSymbol, Function>()
|
||||||
val concreteClasses = mutableMapOf<DataFlowIR.Type.Declared, Node>()
|
val concreteClasses = mutableMapOf<DataFlowIR.Type.Declared, Node>()
|
||||||
val externalFunctions = mutableMapOf<DataFlowIR.FunctionSymbol, Node>()
|
val externalFunctions = mutableMapOf<DataFlowIR.FunctionSymbol, Node>()
|
||||||
@@ -363,6 +363,14 @@ internal object Devirtualization {
|
|||||||
is DataFlowIR.Node.StaticCall ->
|
is DataFlowIR.Node.StaticCall ->
|
||||||
dfs(node.callee)
|
dfs(node.callee)
|
||||||
|
|
||||||
|
is DataFlowIR.Node.FieldRead ->
|
||||||
|
if (entryPoint == null && node.field.type.isFinal)
|
||||||
|
addInstantiatingClass(node.field.type)
|
||||||
|
|
||||||
|
is DataFlowIR.Node.FieldWrite ->
|
||||||
|
if (entryPoint == null && node.field.type.isFinal)
|
||||||
|
addInstantiatingClass(node.field.type)
|
||||||
|
|
||||||
is DataFlowIR.Node.VirtualCall -> {
|
is DataFlowIR.Node.VirtualCall -> {
|
||||||
if (node.receiverType == DataFlowIR.Type.Virtual)
|
if (node.receiverType == DataFlowIR.Type.Virtual)
|
||||||
continue@nodeLoop
|
continue@nodeLoop
|
||||||
@@ -676,7 +684,19 @@ internal object Devirtualization {
|
|||||||
constraintGraph.concreteClasses.getOrPut(type) { sourceNode(concreteType(type)) { "Class\$$type" } }
|
constraintGraph.concreteClasses.getOrPut(type) { sourceNode(concreteType(type)) { "Class\$$type" } }
|
||||||
|
|
||||||
private fun fieldNode(field: DataFlowIR.Field) =
|
private fun fieldNode(field: DataFlowIR.Field) =
|
||||||
constraintGraph.fields.getOrPut(field) { ordinaryNode { "Field\$$field" } }
|
constraintGraph.fields.getOrPut(field) {
|
||||||
|
val fieldNode = ordinaryNode { "Field\$$field" }
|
||||||
|
if (entryPoint == null) {
|
||||||
|
// TODO: This is conservative.
|
||||||
|
val fieldType = field.type.resolved()
|
||||||
|
// Some user of our library might place some value into the field.
|
||||||
|
if (fieldType.isFinal)
|
||||||
|
concreteClass(fieldType).addEdge(fieldNode)
|
||||||
|
else
|
||||||
|
constraintGraph.virtualNode.addEdge(fieldNode)
|
||||||
|
}
|
||||||
|
fieldNode
|
||||||
|
}
|
||||||
|
|
||||||
private var stack = mutableListOf<DataFlowIR.FunctionSymbol>()
|
private var stack = mutableListOf<DataFlowIR.FunctionSymbol>()
|
||||||
|
|
||||||
@@ -898,8 +918,6 @@ internal object Devirtualization {
|
|||||||
}
|
}
|
||||||
// And throw anything.
|
// And throw anything.
|
||||||
receiverNode.addCastEdge(Node.CastEdge(function.throws, virtualTypeFilter))
|
receiverNode.addCastEdge(Node.CastEdge(function.throws, virtualTypeFilter))
|
||||||
// And write to some array anything. TODO: This is conservative.
|
|
||||||
receiverNode.addCastEdge(Node.CastEdge(fieldNode(constraintGraph.arrayItemField), virtualTypeFilter))
|
|
||||||
|
|
||||||
if (callees.isEmpty() && returnType.isFinal && entryPoint == null) {
|
if (callees.isEmpty() && returnType.isFinal && entryPoint == null) {
|
||||||
// If we are in a library and facing final return type with no possible callees -
|
// If we are in a library and facing final return type with no possible callees -
|
||||||
|
|||||||
Reference in New Issue
Block a user