[DCE] Reference public external functions + test

This commit is contained in:
Igor Chevdar
2019-12-12 15:23:37 +03:00
parent 06e77303a5
commit 724a05ce6a
5 changed files with 25 additions and 17 deletions
@@ -326,13 +326,14 @@ internal object DFGSerializer {
}
}
class ExternalFunctionSymbol(val hash: Long, val name: String?) {
class ExternalFunctionSymbol(val hash: Long, val name: String?, val isExported: Boolean) {
constructor(data: ArraySlice) : this(data.readLong(), data.readNullableString())
constructor(data: ArraySlice) : this(data.readLong(), data.readNullableString(), data.readBoolean())
fun write(result: ArraySlice) {
result.writeLong(hash)
result.writeNullableString(name)
result.writeBoolean(isExported)
}
}
@@ -379,8 +380,8 @@ internal object DFGSerializer {
}
companion object {
fun external(base: FunctionSymbolBase, hash: Long, name: String?) =
FunctionSymbol(base, ExternalFunctionSymbol(hash, name), null, null)
fun external(base: FunctionSymbolBase, hash: Long, name: String?, isExported: Boolean) =
FunctionSymbol(base, ExternalFunctionSymbol(hash, name, isExported), null, null)
fun public(base: FunctionSymbolBase, hash: Long, index: Int, bridgeTarget: Int?, name: String?) =
FunctionSymbol(base, null, PublicFunctionSymbol(hash, index, bridgeTarget, name), null)
@@ -876,7 +877,7 @@ internal object DFGSerializer {
val bridgeTarget = (symbol as? DataFlowIR.FunctionSymbol.Declared)?.let { functionSymbolMap[it] }
when (symbol) {
is DataFlowIR.FunctionSymbol.External ->
FunctionSymbol.external(buildFunctionSymbolBase(symbol), symbol.hash, symbol.name)
FunctionSymbol.external(buildFunctionSymbolBase(symbol), symbol.hash, symbol.name, symbol.isExported)
is DataFlowIR.FunctionSymbol.Public ->
FunctionSymbol.public(buildFunctionSymbolBase(symbol), symbol.hash,
@@ -1051,7 +1052,7 @@ internal object DFGSerializer {
val private = it.private
when {
external != null ->
DataFlowIR.FunctionSymbol.External(external.hash, attributes, null, external.name)
DataFlowIR.FunctionSymbol.External(external.hash, attributes, null, external.name, external.isExported)
public != null -> {
val symbolTableIndex = public.index
@@ -132,7 +132,7 @@ internal object DataFlowIR {
var escapes: Int? = null
var pointsTo: IntArray? = null
class External(val hash: Long, attributes: Int, irFunction: IrFunction?, name: String? = null)
class External(val hash: Long, attributes: Int, irFunction: IrFunction?, name: String? = null, val isExported: Boolean)
: FunctionSymbol(attributes, irFunction, name) {
override fun equals(other: Any?): Boolean {
@@ -609,7 +609,7 @@ internal object DataFlowIR {
val escapesBitMask = (escapesAnnotation?.getValueArgument(0) as? IrConst<Int>)?.value
@Suppress("UNCHECKED_CAST")
val pointsToBitMask = (pointsToAnnotation?.getValueArgument(0) as? IrVararg)?.elements?.map { (it as IrConst<Int>).value }
FunctionSymbol.External(name.localHash.value, attributes, it, takeName { name }).apply {
FunctionSymbol.External(name.localHash.value, attributes, it, takeName { name }, it.isExported()).apply {
escapes = escapesBitMask
pointsTo = pointsToBitMask?.let { it.toIntArray() }
}
@@ -64,14 +64,18 @@ internal object Devirtualization {
val exportedFunctions =
if (entryPoint != null)
listOf(moduleDFG.symbolTable.mapFunction(entryPoint).resolved())
else
// In a library every public function and every function accessible via virtual call belongs to the rootset.
moduleDFG.symbolTable.functionMap.values.filterIsInstance<DataFlowIR.FunctionSymbol.Public>() +
moduleDFG.symbolTable.classMap.values
.filterIsInstance<DataFlowIR.Type.Declared>()
.flatMap { it.vtable + it.itable.values }
.filterIsInstance<DataFlowIR.FunctionSymbol.Declared>()
.filter { moduleDFG.functions.containsKey(it) }
else {
// In a library every public function and every function accessible via virtual call belongs to the rootset.
moduleDFG.symbolTable.functionMap.values.filter {
it is DataFlowIR.FunctionSymbol.Public
|| (it as? DataFlowIR.FunctionSymbol.External)?.isExported == true
} +
moduleDFG.symbolTable.classMap.values
.filterIsInstance<DataFlowIR.Type.Declared>()
.flatMap { it.vtable + it.itable.values }
.filterIsInstance<DataFlowIR.FunctionSymbol.Declared>()
.filter { moduleDFG.functions.containsKey(it) }
}
// TODO: Are globals initializers always called whether they are actually reachable from roots or not?
val globalInitializers =
moduleDFG.symbolTable.functionMap.values.filter { it.isGlobalInitializer } +
@@ -1123,6 +1123,7 @@ __attribute__((swift_name("ValuesKt")))
+ (BOOL)testInterfaceTypeCheckX:(id)x __attribute__((swift_name("testInterfaceTypeCheck(x:)")));
+ (int32_t)testAbstractInterfaceCallX:(id<ValuesIAbstractInterface>)x __attribute__((swift_name("testAbstractInterfaceCall(x:)")));
+ (int32_t)testAbstractInterfaceCall2X:(id<ValuesIAbstractInterface2>)x __attribute__((swift_name("testAbstractInterfaceCall2(x:)")));
+ (void)fooA:(ValuesKotlinAtomicReference *)a __attribute__((swift_name("foo(a:)")));
@property (class, readonly) double dbl __attribute__((swift_name("dbl")));
@property (class, readonly) float flt __attribute__((swift_name("flt")));
@property (class, readonly) int32_t integer __attribute__((swift_name("integer")));
@@ -830,4 +830,6 @@ object GH3525 : GH3525Base() {
class TestStringConversion {
lateinit var str: Any
}
}
fun foo(a: kotlin.native.concurrent.AtomicReference<*>) {}