Fixed bug in devirtualization

All final return types of external functions are instantiated
This commit is contained in:
Igor Chevdar
2018-02-22 19:14:42 +03:00
parent b577c05eaa
commit df97ef75c9
@@ -246,7 +246,7 @@ internal object Devirtualization {
.forEach { addInstantiatingClass(it) } .forEach { addInstantiatingClass(it) }
} }
// Traverse call graph from the roots. // Traverse call graph from the roots.
rootSet.forEach { dfs(it) } rootSet.forEach { dfs(it, functions[it]!!.returnType) }
return instantiatingClasses return instantiatingClasses
} }
@@ -275,7 +275,7 @@ internal object Devirtualization {
else -> error("Unreachable") else -> error("Unreachable")
} }
dfs(callee) dfs(callee, virtualCall.returnType)
} }
private fun checkSupertypes(type: DataFlowIR.Type.Declared, private fun checkSupertypes(type: DataFlowIR.Type.Declared,
@@ -310,12 +310,19 @@ internal object Devirtualization {
.forEach { checkSupertypes(it, inheritor, seenTypes) } .forEach { checkSupertypes(it, inheritor, seenTypes) }
} }
private fun dfs(symbol: DataFlowIR.FunctionSymbol) { private fun dfs(symbol: DataFlowIR.FunctionSymbol, returnType: DataFlowIR.Type) {
val resolvedFunctionSymbol = symbol.resolved() val resolvedFunctionSymbol = symbol.resolved()
if (resolvedFunctionSymbol is DataFlowIR.FunctionSymbol.External) { if (resolvedFunctionSymbol is DataFlowIR.FunctionSymbol.External) {
DEBUG_OUTPUT(1) { println("Function $resolvedFunctionSymbol is external") } DEBUG_OUTPUT(1) { println("Function $resolvedFunctionSymbol is external") }
val resolvedReturnType = returnType.resolved()
if (resolvedReturnType.isFinal) {
DEBUG_OUTPUT(1) { println("Adding return type as it is final") }
addInstantiatingClass(resolvedReturnType)
}
return return
} }
if (!visited.add(resolvedFunctionSymbol)) return if (!visited.add(resolvedFunctionSymbol)) return
@@ -330,17 +337,18 @@ internal object Devirtualization {
when (node) { when (node) {
is DataFlowIR.Node.NewObject -> { is DataFlowIR.Node.NewObject -> {
addInstantiatingClass(node.returnType) addInstantiatingClass(node.returnType)
dfs(node.callee) dfs(node.callee, node.returnType)
} }
is DataFlowIR.Node.Singleton -> { is DataFlowIR.Node.Singleton -> {
addInstantiatingClass(node.type) addInstantiatingClass(node.type)
node.constructor?.let { dfs(it) } node.constructor?.let { dfs(it, node.type) }
} }
is DataFlowIR.Node.Const -> addInstantiatingClass(node.type) is DataFlowIR.Node.Const -> addInstantiatingClass(node.type)
is DataFlowIR.Node.StaticCall -> dfs(node.callee) is DataFlowIR.Node.StaticCall ->
dfs(node.callee, node.returnType)
is DataFlowIR.Node.VirtualCall -> { is DataFlowIR.Node.VirtualCall -> {
if (node.receiverType == DataFlowIR.Type.Virtual) if (node.receiverType == DataFlowIR.Type.Virtual)