DFG: Refactored types representation
This commit is contained in:
+44
-31
@@ -204,13 +204,26 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExternalType(val hash: Long, val name: String?) {
|
class TypeBase(val isFinal: Boolean, val isAbstract: Boolean, val correspondingValueType: ValueType?, val name: String?) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readLong(), data.readNullableString())
|
constructor(data: ArraySlice) : this(data.readBoolean(), data.readBoolean(),
|
||||||
|
data.readNullableInt()?.let { ValueType.values()[it] }, data.readNullableString())
|
||||||
|
|
||||||
|
fun write(result: ArraySlice) {
|
||||||
|
result.writeBoolean(isFinal)
|
||||||
|
result.writeBoolean(isAbstract)
|
||||||
|
result.writeNullableInt(correspondingValueType?.ordinal)
|
||||||
|
result.writeNullableString(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ExternalType(val hash: Long, val base: TypeBase) {
|
||||||
|
|
||||||
|
constructor(data: ArraySlice) : this(data.readLong(), TypeBase(data))
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeLong(hash)
|
result.writeLong(hash)
|
||||||
result.writeNullableString(name)
|
base.write(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,16 +237,14 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DeclaredType(val isFinal: Boolean, val isAbstract: Boolean, val correspondingValueType: ValueType?,
|
class DeclaredType(val base: TypeBase, val index: Int, val superTypes: IntArray,
|
||||||
val index: Int, val superTypes: IntArray, val vtable: IntArray, val itable: Array<ItableSlot>) {
|
val vtable: IntArray, val itable: Array<ItableSlot>) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readBoolean(), data.readBoolean(), data.readNullableInt()?.let { ValueType.values()[it] },
|
constructor(data: ArraySlice) : this(TypeBase(data), data.readInt(), data.readIntArray(),
|
||||||
data.readInt(), data.readIntArray(), data.readIntArray(), data.readArray { ItableSlot(this) })
|
data.readIntArray(), data.readArray { ItableSlot(this) })
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeBoolean(isFinal)
|
base.write(result)
|
||||||
result.writeBoolean(isAbstract)
|
|
||||||
result.writeNullableInt(correspondingValueType?.ordinal)
|
|
||||||
result.writeInt(index)
|
result.writeInt(index)
|
||||||
result.writeIntArray(superTypes)
|
result.writeIntArray(superTypes)
|
||||||
result.writeIntArray(vtable)
|
result.writeIntArray(vtable)
|
||||||
@@ -241,25 +252,23 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PublicType(val hash: Long, val intestines: DeclaredType, val name: String?) {
|
class PublicType(val hash: Long, val intestines: DeclaredType) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readLong(), DeclaredType(data), data.readNullableString())
|
constructor(data: ArraySlice) : this(data.readLong(), DeclaredType(data))
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeLong(hash)
|
result.writeLong(hash)
|
||||||
intestines.write(result)
|
intestines.write(result)
|
||||||
result.writeNullableString(name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrivateType(val index: Int, val intestines: DeclaredType, val name: String?) {
|
class PrivateType(val index: Int, val intestines: DeclaredType) {
|
||||||
|
|
||||||
constructor(data: ArraySlice) : this(data.readInt(), DeclaredType(data), data.readNullableString())
|
constructor(data: ArraySlice) : this(data.readInt(), DeclaredType(data))
|
||||||
|
|
||||||
fun write(result: ArraySlice) {
|
fun write(result: ArraySlice) {
|
||||||
result.writeInt(index)
|
result.writeInt(index)
|
||||||
intestines.write(result)
|
intestines.write(result)
|
||||||
result.writeNullableString(name)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,11 +289,11 @@ internal object DFGSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun external(hash: Long, name: String?) = Type(ExternalType(hash, name), null, null, false)
|
fun external(hash: Long, base: TypeBase) = Type(ExternalType(hash, base), null, null, false)
|
||||||
|
|
||||||
fun public(hash: Long, intestines: DeclaredType, name: String?) = Type(null, PublicType(hash, intestines, name), null, false)
|
fun public(hash: Long, intestines: DeclaredType) = Type(null, PublicType(hash, intestines), null, false)
|
||||||
|
|
||||||
fun private(index: Int, intestines: DeclaredType, name: String?) = Type(null, null, PrivateType(index, intestines, name), false)
|
fun private(index: Int, intestines: DeclaredType) = Type(null, null, PrivateType(index, intestines), false)
|
||||||
|
|
||||||
fun virtual() = Type(null, null, null, true)
|
fun virtual() = Type(null, null, null, true)
|
||||||
|
|
||||||
@@ -764,11 +773,12 @@ internal object DFGSerializer {
|
|||||||
.sortedBy { it.value }
|
.sortedBy { it.value }
|
||||||
.map {
|
.map {
|
||||||
|
|
||||||
|
fun buildTypeBase(type: DataFlowIR.Type) =
|
||||||
|
TypeBase(type.isFinal, type.isAbstract, type.correspondingValueType, type.name)
|
||||||
|
|
||||||
fun buildTypeIntestines(type: DataFlowIR.Type.Declared) =
|
fun buildTypeIntestines(type: DataFlowIR.Type.Declared) =
|
||||||
DeclaredType(
|
DeclaredType(
|
||||||
type.isFinal,
|
buildTypeBase(type),
|
||||||
type.isAbstract,
|
|
||||||
type.correspondingValueType,
|
|
||||||
type.symbolTableIndex,
|
type.symbolTableIndex,
|
||||||
type.superTypes.map { typeMap[it]!! }.toIntArray(),
|
type.superTypes.map { typeMap[it]!! }.toIntArray(),
|
||||||
type.vtable.map { functionSymbolMap[it]!! }.toIntArray(),
|
type.vtable.map { functionSymbolMap[it]!! }.toIntArray(),
|
||||||
@@ -779,11 +789,11 @@ internal object DFGSerializer {
|
|||||||
when (type) {
|
when (type) {
|
||||||
DataFlowIR.Type.Virtual -> Type.virtual()
|
DataFlowIR.Type.Virtual -> Type.virtual()
|
||||||
|
|
||||||
is DataFlowIR.Type.External -> Type.external(type.hash, type.name)
|
is DataFlowIR.Type.External -> Type.external(type.hash, buildTypeBase(type))
|
||||||
|
|
||||||
is DataFlowIR.Type.Public -> Type.public(type.hash, buildTypeIntestines(type), type.name)
|
is DataFlowIR.Type.Public -> Type.public(type.hash, buildTypeIntestines(type))
|
||||||
|
|
||||||
is DataFlowIR.Type.Private -> Type.private(type.index, buildTypeIntestines(type), type.name)
|
is DataFlowIR.Type.Private -> Type.private(type.index, buildTypeIntestines(type))
|
||||||
|
|
||||||
else -> error("Unknown type $type")
|
else -> error("Unknown type $type")
|
||||||
}
|
}
|
||||||
@@ -930,14 +940,17 @@ internal object DFGSerializer {
|
|||||||
val public = it.public
|
val public = it.public
|
||||||
val private = it.private
|
val private = it.private
|
||||||
when {
|
when {
|
||||||
external != null -> DataFlowIR.Type.External(external.hash, external.name)
|
external != null ->
|
||||||
|
DataFlowIR.Type.External(external.hash, external.base.isFinal, external.base.isAbstract,
|
||||||
|
external.base.correspondingValueType, external.base.name)
|
||||||
|
|
||||||
public != null -> {
|
public != null -> {
|
||||||
val symbolTableIndex = public.intestines.index
|
val symbolTableIndex = public.intestines.index
|
||||||
if (symbolTableIndex >= 0)
|
if (symbolTableIndex >= 0)
|
||||||
++module.numberOfClasses
|
++module.numberOfClasses
|
||||||
DataFlowIR.Type.Public(public.hash, public.intestines.isFinal, public.intestines.isAbstract,
|
DataFlowIR.Type.Public(public.hash, public.intestines.base.isFinal,
|
||||||
public.intestines.correspondingValueType, module, symbolTableIndex, public.name).also {
|
public.intestines.base.isAbstract, public.intestines.base.correspondingValueType,
|
||||||
|
module, symbolTableIndex, public.intestines.base.name).also {
|
||||||
publicTypesMap.put(it.hash, it)
|
publicTypesMap.put(it.hash, it)
|
||||||
allTypes += it
|
allTypes += it
|
||||||
}
|
}
|
||||||
@@ -947,9 +960,9 @@ internal object DFGSerializer {
|
|||||||
val symbolTableIndex = private!!.intestines.index
|
val symbolTableIndex = private!!.intestines.index
|
||||||
if (symbolTableIndex >= 0)
|
if (symbolTableIndex >= 0)
|
||||||
++module.numberOfClasses
|
++module.numberOfClasses
|
||||||
DataFlowIR.Type.Private(privateTypeIndex++, private.intestines.isFinal,
|
DataFlowIR.Type.Private(privateTypeIndex++, private.intestines.base.isFinal,
|
||||||
private.intestines.isAbstract, private.intestines.correspondingValueType,
|
private.intestines.base.isAbstract, private.intestines.base.correspondingValueType,
|
||||||
module, symbolTableIndex, private.name).also {
|
module, symbolTableIndex, private.intestines.base.name).also {
|
||||||
allTypes += it
|
allTypes += it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-17
@@ -46,11 +46,14 @@ import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
|||||||
|
|
||||||
internal object DataFlowIR {
|
internal object DataFlowIR {
|
||||||
|
|
||||||
abstract class Type {
|
abstract class Type(val isFinal: Boolean, val isAbstract: Boolean,
|
||||||
|
val correspondingValueType: ValueType?, val name: String?) {
|
||||||
// Special marker type forbidding devirtualization on its instances.
|
// Special marker type forbidding devirtualization on its instances.
|
||||||
object Virtual : Declared(false, true, null, null, -1)
|
object Virtual : Declared(false, true, null, null, -1, "\$VIRTUAL")
|
||||||
|
|
||||||
class External(val hash: Long, val name: String? = null) : Type() {
|
class External(val hash: Long, isFinal: Boolean, isAbstract: Boolean,
|
||||||
|
correspondingValueType: ValueType?, name: String? = null)
|
||||||
|
: Type(isFinal, isAbstract, correspondingValueType, name) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other !is External) return false
|
if (other !is External) return false
|
||||||
@@ -67,16 +70,17 @@ internal object DataFlowIR {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Declared(val isFinal: Boolean, val isAbstract: Boolean, val correspondingValueType: ValueType?,
|
abstract class Declared(isFinal: Boolean, isAbstract: Boolean, correspondingValueType: ValueType?,
|
||||||
val module: Module?, val symbolTableIndex: Int) : Type() {
|
val module: Module?, val symbolTableIndex: Int, name: String?)
|
||||||
|
: Type(isFinal, isAbstract, correspondingValueType, name) {
|
||||||
val superTypes = mutableListOf<Type>()
|
val superTypes = mutableListOf<Type>()
|
||||||
val vtable = mutableListOf<FunctionSymbol>()
|
val vtable = mutableListOf<FunctionSymbol>()
|
||||||
val itable = mutableMapOf<Long, FunctionSymbol>()
|
val itable = mutableMapOf<Long, FunctionSymbol>()
|
||||||
}
|
}
|
||||||
|
|
||||||
class Public(val hash: Long, isFinal: Boolean, isAbstract: Boolean, correspondingValueType: ValueType?,
|
class Public(val hash: Long, isFinal: Boolean, isAbstract: Boolean, correspondingValueType: ValueType?,
|
||||||
module: Module, symbolTableIndex: Int, val name: String? = null)
|
module: Module, symbolTableIndex: Int, name: String? = null)
|
||||||
: Declared(isFinal, isAbstract, correspondingValueType, module, symbolTableIndex) {
|
: Declared(isFinal, isAbstract, correspondingValueType, module, symbolTableIndex, name) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other !is Public) return false
|
if (other !is Public) return false
|
||||||
@@ -94,8 +98,8 @@ internal object DataFlowIR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Private(val index: Int, isFinal: Boolean, isAbstract: Boolean, correspondingValueType: ValueType?,
|
class Private(val index: Int, isFinal: Boolean, isAbstract: Boolean, correspondingValueType: ValueType?,
|
||||||
module: Module, symbolTableIndex: Int, val name: String? = null)
|
module: Module, symbolTableIndex: Int, name: String? = null)
|
||||||
: Declared(isFinal, isAbstract, correspondingValueType, module, symbolTableIndex) {
|
: Declared(isFinal, isAbstract, correspondingValueType, module, symbolTableIndex, name) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (other !is Private) return false
|
if (other !is Private) return false
|
||||||
@@ -477,21 +481,25 @@ internal object DataFlowIR {
|
|||||||
if (descriptor.module.name == Name.special("<forward declarations>") || descriptor.isObjCClass())
|
if (descriptor.module.name == Name.special("<forward declarations>") || descriptor.isObjCClass())
|
||||||
return Type.Virtual
|
return Type.Virtual
|
||||||
|
|
||||||
val name = descriptor.fqNameSafe.asString()
|
|
||||||
if (descriptor.module != irModule.descriptor)
|
|
||||||
return classMap.getOrPut(descriptor) { Type.External(name.localHash.value, takeName { name }) }
|
|
||||||
|
|
||||||
classMap[descriptor]?.let { return it }
|
|
||||||
|
|
||||||
val isFinal = descriptor.isFinal()
|
val isFinal = descriptor.isFinal()
|
||||||
val isAbstract = descriptor.isAbstract()
|
val isAbstract = descriptor.isAbstract()
|
||||||
val correspondingValueType = descriptor.defaultType.correspondingValueType
|
val correspondingValueType = descriptor.defaultType.correspondingValueType
|
||||||
|
val name = descriptor.fqNameSafe.asString()
|
||||||
|
if (descriptor.module != irModule.descriptor)
|
||||||
|
return classMap.getOrPut(descriptor) {
|
||||||
|
Type.External(name.localHash.value, isFinal, isAbstract, correspondingValueType, takeName { name })
|
||||||
|
}
|
||||||
|
|
||||||
|
classMap[descriptor]?.let { return it }
|
||||||
|
|
||||||
val placeToClassTable = correspondingValueType == null
|
val placeToClassTable = correspondingValueType == null
|
||||||
val symbolTableIndex = if (placeToClassTable) module.numberOfClasses++ else -1
|
val symbolTableIndex = if (placeToClassTable) module.numberOfClasses++ else -1
|
||||||
val type = if (descriptor.isExported())
|
val type = if (descriptor.isExported())
|
||||||
Type.Public(name.localHash.value, isFinal, isAbstract, correspondingValueType, module, symbolTableIndex, takeName { name })
|
Type.Public(name.localHash.value, isFinal, isAbstract, correspondingValueType,
|
||||||
|
module, symbolTableIndex, takeName { name })
|
||||||
else
|
else
|
||||||
Type.Private(privateTypeIndex++, isFinal, isAbstract, correspondingValueType, module, symbolTableIndex, takeName { name })
|
Type.Private(privateTypeIndex++, isFinal, isAbstract, correspondingValueType,
|
||||||
|
module, symbolTableIndex, takeName { name })
|
||||||
|
|
||||||
classMap[descriptor] = type
|
classMap[descriptor] = type
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user