[WASM] Minor refactorings
This commit is contained in:
+2
-2
@@ -206,7 +206,7 @@ class BodyGenerator(
|
|||||||
|
|
||||||
//ClassITable and VTable load
|
//ClassITable and VTable load
|
||||||
body.buildGetGlobal(context.referenceGlobalVTable(klass.symbol))
|
body.buildGetGlobal(context.referenceGlobalVTable(klass.symbol))
|
||||||
if (klass.hasInterfaceForClass()) {
|
if (klass.hasInterfaceSuperClass()) {
|
||||||
body.buildGetGlobal(context.referenceGlobalClassITable(klass.symbol))
|
body.buildGetGlobal(context.referenceGlobalClassITable(klass.symbol))
|
||||||
} else {
|
} else {
|
||||||
body.buildRefNull(WasmHeapType.Simple.Data)
|
body.buildRefNull(WasmHeapType.Simple.Data)
|
||||||
@@ -249,7 +249,7 @@ class BodyGenerator(
|
|||||||
|
|
||||||
//ClassITable and VTable load
|
//ClassITable and VTable load
|
||||||
body.buildGetGlobal(context.referenceGlobalVTable(klassSymbol))
|
body.buildGetGlobal(context.referenceGlobalVTable(klassSymbol))
|
||||||
if (klass.hasInterfaceForClass()) {
|
if (klass.hasInterfaceSuperClass()) {
|
||||||
body.buildGetGlobal(context.referenceGlobalClassITable(klassSymbol))
|
body.buildGetGlobal(context.referenceGlobalClassITable(klassSymbol))
|
||||||
} else {
|
} else {
|
||||||
body.buildRefNull(WasmHeapType.Simple.Data)
|
body.buildRefNull(WasmHeapType.Simple.Data)
|
||||||
|
|||||||
+88
-60
@@ -5,20 +5,56 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature
|
import org.jetbrains.kotlin.ir.util.isOverridableOrOverrides
|
||||||
import org.jetbrains.kotlin.backend.wasm.lower.wasmSignature
|
|
||||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.ir.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.eraseGenerics
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
|
||||||
import org.jetbrains.kotlin.ir.util.isInterface
|
import org.jetbrains.kotlin.ir.util.isInterface
|
||||||
import org.jetbrains.kotlin.ir.util.isOverridableOrOverrides
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
data class WasmSignature(
|
||||||
|
val name: Name,
|
||||||
|
val extensionReceiverType: IrType?,
|
||||||
|
val valueParametersType: List<IrType>,
|
||||||
|
val returnType: IrType,
|
||||||
|
// Needed for bridges to final non-override methods
|
||||||
|
// that indirectly implement interfaces. For example:
|
||||||
|
// interface I { fun foo() }
|
||||||
|
// class C1 { fun foo() {} }
|
||||||
|
// class C2 : C1(), I
|
||||||
|
val isVirtual: Boolean,
|
||||||
|
) {
|
||||||
|
override fun toString(): String {
|
||||||
|
val er = extensionReceiverType?.let { "(er: ${it.render()}) " } ?: ""
|
||||||
|
val parameters = valueParametersType.joinToString(", ") { it.render() }
|
||||||
|
val nonVirtual = if (!isVirtual) "(non-virtual) " else ""
|
||||||
|
return "[$nonVirtual$er$name($parameters) -> ${returnType.render()}]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IrSimpleFunction.wasmSignature(irBuiltIns: IrBuiltIns): WasmSignature =
|
||||||
|
WasmSignature(
|
||||||
|
name,
|
||||||
|
extensionReceiverParameter?.type?.eraseGenerics(irBuiltIns),
|
||||||
|
valueParameters.map { it.type.eraseGenerics(irBuiltIns) },
|
||||||
|
returnType.eraseGenerics(irBuiltIns),
|
||||||
|
isOverridableOrOverrides
|
||||||
|
)
|
||||||
|
|
||||||
|
class VirtualMethodMetadata(
|
||||||
|
val function: IrSimpleFunction,
|
||||||
|
val signature: WasmSignature
|
||||||
|
)
|
||||||
|
|
||||||
class ClassMetadata(
|
class ClassMetadata(
|
||||||
val klass: IrClass,
|
val klass: IrClass,
|
||||||
@@ -36,27 +72,23 @@ class ClassMetadata(
|
|||||||
// Virtual methods in Wasm order
|
// Virtual methods in Wasm order
|
||||||
// TODO: Collect interface methods separately
|
// TODO: Collect interface methods separately
|
||||||
val virtualMethods: List<VirtualMethodMetadata> = run {
|
val virtualMethods: List<VirtualMethodMetadata> = run {
|
||||||
val virtualFunctions =
|
val virtualFunctions = klass.declarations
|
||||||
klass.declarations
|
.asSequence()
|
||||||
.filterVirtualFunctions()
|
.filterVirtualFunctions()
|
||||||
.map {
|
.mapTo(mutableListOf()) { VirtualMethodMetadata(it, it.wasmSignature(irBuiltIns)) }
|
||||||
VirtualMethodMetadata(
|
|
||||||
it,
|
val superClassVirtualMethods = superClass?.virtualMethods
|
||||||
it.wasmSignature(irBuiltIns)
|
if (superClassVirtualMethods.isNullOrEmpty()) return@run virtualFunctions
|
||||||
)
|
|
||||||
}
|
val result = mutableListOf<VirtualMethodMetadata>()
|
||||||
|
|
||||||
val signatureToVirtualFunction = virtualFunctions.associateBy { it.signature }
|
val signatureToVirtualFunction = virtualFunctions.associateBy { it.signature }
|
||||||
|
superClassVirtualMethods.mapTo(result) { signatureToVirtualFunction[it.signature] ?: it }
|
||||||
|
|
||||||
val superSignatures = superClass?.virtualMethodsSignatures.orEmpty()
|
val superSignatures = superClassVirtualMethods.mapTo(mutableSetOf()) { it.signature }
|
||||||
|
virtualFunctions.filterTo(result) { it.signature !in superSignatures }
|
||||||
|
|
||||||
val newVirtualMethods = virtualFunctions.filter { it.signature !in superSignatures }
|
result
|
||||||
val superVirtualMethods = superClass?.virtualMethods.orEmpty().map {
|
|
||||||
signatureToVirtualFunction[it.signature] ?: it
|
|
||||||
}
|
|
||||||
val orderedVirtualFunctions = superVirtualMethods + newVirtualMethods
|
|
||||||
|
|
||||||
orderedVirtualFunctions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -69,64 +101,60 @@ class ClassMetadata(
|
|||||||
if (functions.size > 1) {
|
if (functions.size > 1) {
|
||||||
val funcList = functions.joinToString { " ---- ${it.fqNameWhenAvailable} \n" }
|
val funcList = functions.joinToString { " ---- ${it.fqNameWhenAvailable} \n" }
|
||||||
// TODO: Check in FE
|
// TODO: Check in FE
|
||||||
error(
|
error("Class ${klass.fqNameWhenAvailable} has ${functions.size} methods with the same signature $sig\n $funcList")
|
||||||
"Class ${klass.fqNameWhenAvailable} has ${functions.size} methods with the same signature $sig\n $funcList"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val virtualMethodsSignatures: Set<WasmSignature> =
|
|
||||||
virtualMethods.map { it.signature }.toSet()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class InterfaceMetadata(
|
class InterfaceMetadata(val iFace: IrClass, irBuiltIns: IrBuiltIns) {
|
||||||
val iface: IrClass,
|
val methods: List<VirtualMethodMetadata> = iFace.declarations
|
||||||
irBuiltIns: IrBuiltIns
|
.asSequence()
|
||||||
) {
|
.filterIsInstance<IrSimpleFunction>()
|
||||||
val methods: List<VirtualMethodMetadata> =
|
.filter { !it.isFakeOverride && it.visibility != DescriptorVisibilities.PRIVATE && it.modality != Modality.FINAL }
|
||||||
iface.declarations
|
.mapTo(mutableListOf()) { VirtualMethodMetadata(it, it.wasmSignature(irBuiltIns)) }
|
||||||
.filterIsInstance<IrSimpleFunction>()
|
|
||||||
.filter { !it.isFakeOverride && it.visibility != DescriptorVisibilities.PRIVATE && it.modality != Modality.FINAL }
|
|
||||||
.map {
|
|
||||||
VirtualMethodMetadata(
|
|
||||||
it,
|
|
||||||
it.wasmSignature(irBuiltIns)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun IrClass.allSuperInterfaces(): List<IrClass> {
|
||||||
class VirtualMethodMetadata(
|
fun allSuperInterfacesImpl(currentClass: IrClass, result: MutableList<IrClass>) {
|
||||||
val function: IrSimpleFunction,
|
for (superType in currentClass.superTypes) {
|
||||||
val signature: WasmSignature
|
allSuperInterfacesImpl(superType.classifierOrFail.owner as IrClass, result)
|
||||||
)
|
}
|
||||||
|
if (currentClass.isInterface) result.add(currentClass)
|
||||||
fun IrClass.allSuperInterfaces(): List<IrClass> =
|
|
||||||
superTypes.map {
|
|
||||||
it.classifierOrFail.owner as IrClass
|
|
||||||
}.flatMap {
|
|
||||||
(if (it.isInterface) listOf(it) else emptyList()) + it.allSuperInterfaces()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<IrDeclaration>.filterVirtualFunctions(): List<IrSimpleFunction> =
|
return mutableListOf<IrClass>().also {
|
||||||
asSequence()
|
allSuperInterfacesImpl(this, it)
|
||||||
.filterIsInstance<IrSimpleFunction>()
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Sequence<IrDeclaration>.filterVirtualFunctions(): Sequence<IrSimpleFunction> =
|
||||||
|
this.filterIsInstance<IrSimpleFunction>()
|
||||||
.filter { it.dispatchReceiverParameter != null }
|
.filter { it.dispatchReceiverParameter != null }
|
||||||
.map { it.realOverrideTarget }
|
.map { it.realOverrideTarget }
|
||||||
.filter { it.isOverridableOrOverrides }
|
.filter { it.isOverridableOrOverrides }
|
||||||
.distinct()
|
.distinct()
|
||||||
.toList()
|
|
||||||
|
|
||||||
fun IrClass.getSuperClass(builtIns: IrBuiltIns): IrClass? =
|
fun IrClass.getSuperClass(builtIns: IrBuiltIns): IrClass? =
|
||||||
when (this) {
|
when (this) {
|
||||||
builtIns.anyClass.owner -> null
|
builtIns.anyClass.owner -> null
|
||||||
else -> {
|
else -> superTypes
|
||||||
superTypes
|
.map { it.classifierOrFail.owner as IrClass }
|
||||||
.map { it.classifierOrFail.owner as IrClass }
|
.singleOrNull { !it.isInterface } ?: builtIns.anyClass.owner
|
||||||
.singleOrNull { !it.isInterface } ?: builtIns.anyClass.owner
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrClass.allFields(builtIns: IrBuiltIns): List<IrField> =
|
fun IrClass.allFields(builtIns: IrBuiltIns): List<IrField> =
|
||||||
getSuperClass(builtIns)?.allFields(builtIns).orEmpty() + declarations.filterIsInstance<IrField>()
|
getSuperClass(builtIns)?.allFields(builtIns).orEmpty() + declarations.filterIsInstance<IrField>()
|
||||||
|
|
||||||
|
fun IrClass.hasInterfaceSuperClass(): Boolean {
|
||||||
|
var superClass: IrClass? = null
|
||||||
|
for (superType in superTypes) {
|
||||||
|
val typeAsClass = superType.classifierOrFail.owner as IrClass
|
||||||
|
if (typeAsClass.isInterface) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
superClass = typeAsClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return superClass?.hasInterfaceSuperClass() ?: false
|
||||||
|
}
|
||||||
-1
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
package org.jetbrains.kotlin.backend.wasm.ir2wasm
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.wasm.lower.wasmSignature
|
|
||||||
import org.jetbrains.kotlin.backend.wasm.utils.*
|
import org.jetbrains.kotlin.backend.wasm.utils.*
|
||||||
import org.jetbrains.kotlin.config.AnalysisFlags.allowFullyQualifiedNameInKClass
|
import org.jetbrains.kotlin.config.AnalysisFlags.allowFullyQualifiedNameInKClass
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||||
|
|||||||
+2
-35
@@ -5,16 +5,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.wasm.lower
|
package org.jetbrains.kotlin.backend.wasm.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrBuiltIns
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmSignature
|
||||||
|
import org.jetbrains.kotlin.backend.wasm.ir2wasm.wasmSignature
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.BridgesConstruction
|
import org.jetbrains.kotlin.ir.backend.js.lower.BridgesConstruction
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.eraseGenerics
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
|
||||||
import org.jetbrains.kotlin.ir.util.isOverridableOrOverrides
|
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
|
|
||||||
class WasmBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruction<JsCommonBackendContext>(context) {
|
class WasmBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruction<JsCommonBackendContext>(context) {
|
||||||
override fun getFunctionSignature(function: IrSimpleFunction): WasmSignature =
|
override fun getFunctionSignature(function: IrSimpleFunction): WasmSignature =
|
||||||
@@ -25,32 +21,3 @@ class WasmBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruc
|
|||||||
override fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin =
|
override fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin =
|
||||||
IrDeclarationOrigin.BRIDGE
|
IrDeclarationOrigin.BRIDGE
|
||||||
}
|
}
|
||||||
|
|
||||||
data class WasmSignature(
|
|
||||||
val name: Name,
|
|
||||||
val extensionReceiverType: IrType?,
|
|
||||||
val valueParametersType: List<IrType>,
|
|
||||||
val returnType: IrType,
|
|
||||||
// Needed for bridges to final non-override methods
|
|
||||||
// that indirectly implement interfaces. For example:
|
|
||||||
// interface I { fun foo() }
|
|
||||||
// class C1 { fun foo() {} }
|
|
||||||
// class C2 : C1(), I
|
|
||||||
val isVirtual: Boolean,
|
|
||||||
) {
|
|
||||||
override fun toString(): String {
|
|
||||||
val er = extensionReceiverType?.let { "(er: ${it.render()}) " } ?: ""
|
|
||||||
val parameters = valueParametersType.joinToString(", ") { it.render() }
|
|
||||||
val nonVirtual = if (!isVirtual) "(non-virtual) " else ""
|
|
||||||
return "[$nonVirtual$er$name($parameters) -> ${returnType.render()}]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IrSimpleFunction.wasmSignature(irBuiltIns: IrBuiltIns): WasmSignature =
|
|
||||||
WasmSignature(
|
|
||||||
name,
|
|
||||||
extensionReceiverParameter?.type?.eraseGenerics(irBuiltIns),
|
|
||||||
valueParameters.map { it.type.eraseGenerics(irBuiltIns) },
|
|
||||||
returnType.eraseGenerics(irBuiltIns),
|
|
||||||
isOverridableOrOverrides
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user