Fixed bug in devirtualization
All final return types of external functions are instantiated
This commit is contained in:
+14
-6
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user