From e7f721bc63142717859180e7df6574283faaf7d5 Mon Sep 17 00:00:00 2001 From: Igor Chevdar Date: Mon, 3 Jun 2019 16:25:20 +0300 Subject: [PATCH] Devritualization analysis enhancement --- .../backend/konan/optimizations/DataFlowIR.kt | 4 +- .../konan/optimizations/Devirtualization.kt | 41 ++++++++++++++----- 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index fd67a6ceeca..b76c1d469db 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -231,7 +231,8 @@ internal object DataFlowIR { : Call(callee, arguments, returnType, irCallSite) // TODO: It can be replaced with a pair(AllocInstance, constructor Call), remove. - class NewObject(constructor: FunctionSymbol, arguments: List, val constructedType: Type, override val irCallSite: IrConstructorCall?) + class NewObject(constructor: FunctionSymbol, arguments: List, + val constructedType: Type, override val irCallSite: IrConstructorCall?) : Call(constructor, arguments, constructedType, irCallSite) open class VirtualCall(callee: FunctionSymbol, arguments: List, @@ -252,7 +253,6 @@ internal object DataFlowIR { 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 FieldWrite(val receiver: Edge?, val field: Field, val value: Edge, val type: Type) : Node() diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt index 6c883309c7e..19664fe9d9d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/Devirtualization.kt @@ -472,7 +472,7 @@ internal object Devirtualization { val nodesMap = mutableMapOf() val constraintGraphBuilder = - ConstraintGraphBuilder(nodesMap, functions, typeHierarchy, instantiatingClasses, allTypes, rootSet) + ConstraintGraphBuilder(nodesMap, functions, typeHierarchy, instantiatingClasses, allTypes, rootSet, true) constraintGraphBuilder.build() DEBUG_OUTPUT(0) { @@ -678,7 +678,8 @@ internal object Devirtualization { val typeHierarchy: TypeHierarchy, val instantiatingClasses: Map, val allTypes: List, - val rootSet: List) { + val rootSet: List, + val useTypes: Boolean) { private val variables = mutableMapOf() @@ -827,7 +828,10 @@ internal object Devirtualization { val argument = argumentToConstraintNode(arguments[index]) 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, @@ -853,7 +857,7 @@ internal object Devirtualization { } } else { calleeConstraintGraph.throws.addEdge(function.throws) - if (receiverType == null) + if (!useTypes || receiverType == null || receiverType == callee.parameters[0].type.resolved()) doCall(calleeConstraintGraph, arguments, returnType) else { 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) { var variableNode = variables[node] if (variableNode == null) { @@ -983,20 +1006,18 @@ internal object Devirtualization { } is DataFlowIR.Node.FieldRead -> - doCast(function, fieldNode(node.field), node.type.resolved()) + readField(node.field, node.field.type.resolved()) is DataFlowIR.Node.FieldWrite -> { - val fieldNode = fieldNode(node.field) - doCast(function, edgeToConstraintNode(node.value), node.type.resolved()).addEdge(fieldNode) + writeField(node.field, node.field.type.resolved(), edgeToConstraintNode(node.value)) constraintGraph.voidNode } is DataFlowIR.Node.ArrayRead -> - doCast(function, fieldNode(constraintGraph.arrayItemField), node.type.resolved()) + readField(constraintGraph.arrayItemField, node.type.resolved()) is DataFlowIR.Node.ArrayWrite -> { - val fieldNode = fieldNode(constraintGraph.arrayItemField) - doCast(function, edgeToConstraintNode(node.value), node.type.resolved()).addEdge(fieldNode) + writeField(constraintGraph.arrayItemField, node.type.resolved(), edgeToConstraintNode(node.value)) constraintGraph.voidNode }