Devritualization analysis enhancement
This commit is contained in:
+2
-2
@@ -231,7 +231,8 @@ internal object DataFlowIR {
|
|||||||
: Call(callee, arguments, returnType, irCallSite)
|
: Call(callee, arguments, returnType, irCallSite)
|
||||||
|
|
||||||
// TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove.
|
// 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: IrConstructorCall?)
|
class NewObject(constructor: FunctionSymbol, arguments: List<Edge>,
|
||||||
|
val constructedType: Type, override val irCallSite: IrConstructorCall?)
|
||||||
: Call(constructor, arguments, constructedType, irCallSite)
|
: Call(constructor, arguments, constructedType, irCallSite)
|
||||||
|
|
||||||
open class VirtualCall(callee: FunctionSymbol, arguments: List<Edge>,
|
open class VirtualCall(callee: FunctionSymbol, arguments: List<Edge>,
|
||||||
@@ -252,7 +253,6 @@ internal object DataFlowIR {
|
|||||||
|
|
||||||
class FunctionReference(val symbol: FunctionSymbol, val type: Type, val returnType: Type) : Node()
|
class FunctionReference(val symbol: FunctionSymbol, val type: Type, val returnType: Type) : Node()
|
||||||
|
|
||||||
// TODO: Add type (similar to arrays)?
|
|
||||||
class FieldRead(val receiver: Edge?, val field: Field, val type: Type, val ir: IrGetField?) : Node()
|
class FieldRead(val receiver: Edge?, val field: Field, val type: Type, val ir: IrGetField?) : Node()
|
||||||
|
|
||||||
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge, val type: Type) : Node()
|
class FieldWrite(val receiver: Edge?, val field: Field, val value: Edge, val type: Type) : Node()
|
||||||
|
|||||||
+31
-10
@@ -472,7 +472,7 @@ internal object Devirtualization {
|
|||||||
|
|
||||||
val nodesMap = mutableMapOf<DataFlowIR.Node, Node>()
|
val nodesMap = mutableMapOf<DataFlowIR.Node, Node>()
|
||||||
val constraintGraphBuilder =
|
val constraintGraphBuilder =
|
||||||
ConstraintGraphBuilder(nodesMap, functions, typeHierarchy, instantiatingClasses, allTypes, rootSet)
|
ConstraintGraphBuilder(nodesMap, functions, typeHierarchy, instantiatingClasses, allTypes, rootSet, true)
|
||||||
constraintGraphBuilder.build()
|
constraintGraphBuilder.build()
|
||||||
|
|
||||||
DEBUG_OUTPUT(0) {
|
DEBUG_OUTPUT(0) {
|
||||||
@@ -678,7 +678,8 @@ internal object Devirtualization {
|
|||||||
val typeHierarchy: TypeHierarchy,
|
val typeHierarchy: TypeHierarchy,
|
||||||
val instantiatingClasses: Map<DataFlowIR.Type.Declared, Int>,
|
val instantiatingClasses: Map<DataFlowIR.Type.Declared, Int>,
|
||||||
val allTypes: List<DataFlowIR.Type.Declared>,
|
val allTypes: List<DataFlowIR.Type.Declared>,
|
||||||
val rootSet: List<DataFlowIR.FunctionSymbol>) {
|
val rootSet: List<DataFlowIR.FunctionSymbol>,
|
||||||
|
val useTypes: Boolean) {
|
||||||
|
|
||||||
private val variables = mutableMapOf<DataFlowIR.Node.Variable, Node>()
|
private val variables = mutableMapOf<DataFlowIR.Node.Variable, Node>()
|
||||||
|
|
||||||
@@ -827,7 +828,10 @@ internal object Devirtualization {
|
|||||||
val argument = argumentToConstraintNode(arguments[index])
|
val argument = argumentToConstraintNode(arguments[index])
|
||||||
argument.addEdge(parameter)
|
argument.addEdge(parameter)
|
||||||
}
|
}
|
||||||
return callee.returns
|
return if (!useTypes || returnType == callee.symbol.returnParameter.type.resolved())
|
||||||
|
callee.returns
|
||||||
|
else
|
||||||
|
doCast(function, callee.returns, returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun doCall(callee: DataFlowIR.FunctionSymbol,
|
fun doCall(callee: DataFlowIR.FunctionSymbol,
|
||||||
@@ -853,7 +857,7 @@ internal object Devirtualization {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
calleeConstraintGraph.throws.addEdge(function.throws)
|
calleeConstraintGraph.throws.addEdge(function.throws)
|
||||||
if (receiverType == null)
|
if (!useTypes || receiverType == null || receiverType == callee.parameters[0].type.resolved())
|
||||||
doCall(calleeConstraintGraph, arguments, returnType)
|
doCall(calleeConstraintGraph, arguments, returnType)
|
||||||
else {
|
else {
|
||||||
val receiverNode = argumentToConstraintNode(arguments[0])
|
val receiverNode = argumentToConstraintNode(arguments[0])
|
||||||
@@ -864,6 +868,25 @@ internal object Devirtualization {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun readField(field: DataFlowIR.Field, actualType: DataFlowIR.Type.Declared): Node {
|
||||||
|
val fieldNode = fieldNode(field)
|
||||||
|
val expectedType = field.type.resolved()
|
||||||
|
return if (!useTypes || actualType == expectedType)
|
||||||
|
fieldNode
|
||||||
|
else
|
||||||
|
doCast(function, fieldNode, actualType)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun writeField(field: DataFlowIR.Field, actualType: DataFlowIR.Type.Declared, value: Node) {
|
||||||
|
val fieldNode = fieldNode(field)
|
||||||
|
val expectedType = field.type.resolved()
|
||||||
|
val castedValue = if (!useTypes || actualType == expectedType)
|
||||||
|
value
|
||||||
|
else
|
||||||
|
doCast(function, value, actualType)
|
||||||
|
castedValue.addEdge(fieldNode)
|
||||||
|
}
|
||||||
|
|
||||||
if (node is DataFlowIR.Node.Variable && node.kind != DataFlowIR.VariableKind.Temporary) {
|
if (node is DataFlowIR.Node.Variable && node.kind != DataFlowIR.VariableKind.Temporary) {
|
||||||
var variableNode = variables[node]
|
var variableNode = variables[node]
|
||||||
if (variableNode == null) {
|
if (variableNode == null) {
|
||||||
@@ -983,20 +1006,18 @@ internal object Devirtualization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldRead ->
|
is DataFlowIR.Node.FieldRead ->
|
||||||
doCast(function, fieldNode(node.field), node.type.resolved())
|
readField(node.field, node.field.type.resolved())
|
||||||
|
|
||||||
is DataFlowIR.Node.FieldWrite -> {
|
is DataFlowIR.Node.FieldWrite -> {
|
||||||
val fieldNode = fieldNode(node.field)
|
writeField(node.field, node.field.type.resolved(), edgeToConstraintNode(node.value))
|
||||||
doCast(function, edgeToConstraintNode(node.value), node.type.resolved()).addEdge(fieldNode)
|
|
||||||
constraintGraph.voidNode
|
constraintGraph.voidNode
|
||||||
}
|
}
|
||||||
|
|
||||||
is DataFlowIR.Node.ArrayRead ->
|
is DataFlowIR.Node.ArrayRead ->
|
||||||
doCast(function, fieldNode(constraintGraph.arrayItemField), node.type.resolved())
|
readField(constraintGraph.arrayItemField, node.type.resolved())
|
||||||
|
|
||||||
is DataFlowIR.Node.ArrayWrite -> {
|
is DataFlowIR.Node.ArrayWrite -> {
|
||||||
val fieldNode = fieldNode(constraintGraph.arrayItemField)
|
writeField(constraintGraph.arrayItemField, node.type.resolved(), edgeToConstraintNode(node.value))
|
||||||
doCast(function, edgeToConstraintNode(node.value), node.type.resolved()).addEdge(fieldNode)
|
|
||||||
constraintGraph.voidNode
|
constraintGraph.voidNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user