[JS IR] Context to NameTables for stable names in additional exported declarations

[JS IR] BridgesConstruction with generic without cast

^KT-44469 fixed
This commit is contained in:
Ilya Goncharov
2021-01-22 18:42:34 +03:00
parent f186047101
commit d88d1d048e
7 changed files with 41 additions and 22 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
@@ -43,7 +44,7 @@ import org.jetbrains.kotlin.ir.util.*
// fun foo(t: Any?) = foo(t as Int) // Constructed bridge // fun foo(t: Any?) = foo(t as Int) // Constructed bridge
// } // }
// //
abstract class BridgesConstruction(val context: JsCommonBackendContext) : DeclarationTransformer { abstract class BridgesConstruction<T : JsCommonBackendContext>(val context: T) : DeclarationTransformer {
private val specialBridgeMethods = SpecialBridgeMethods(context) private val specialBridgeMethods = SpecialBridgeMethods(context)
@@ -115,11 +116,7 @@ abstract class BridgesConstruction(val context: JsCommonBackendContext) : Declar
specialMethodInfo: SpecialMethodWithDefaultInfo? specialMethodInfo: SpecialMethodWithDefaultInfo?
): IrFunction { ): IrFunction {
val origin = val origin = getBridgeOrigin(bridge)
if (bridge.hasStableJsName())
JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME
else
JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME
// TODO: Support offsets for debug info // TODO: Support offsets for debug info
val irFunction = context.irFactory.buildFun { val irFunction = context.irFactory.buildFun {
@@ -179,6 +176,8 @@ abstract class BridgesConstruction(val context: JsCommonBackendContext) : Declar
return irFunction return irFunction
} }
abstract fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin
// TODO: get rid of Unit check // TODO: get rid of Unit check
private fun IrBlockBodyBuilder.irCastIfNeeded(argument: IrExpression, type: IrType): IrExpression = private fun IrBlockBodyBuilder.irCastIfNeeded(argument: IrExpression, type: IrType): IrExpression =
if (argument.type.classifierOrNull == type.classifierOrNull) argument else irAs(argument, type) if (argument.type.classifierOrNull == type.classifierOrNull) argument else irAs(argument, type)
@@ -194,7 +193,7 @@ abstract class BridgesConstruction(val context: JsCommonBackendContext) : Declar
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 BridgesConstruction.FunctionAndSignature) return false if (other !is BridgesConstruction<*>.FunctionAndSignature) return false
return signature == other.signature return signature == other.signature
} }
@@ -87,7 +87,7 @@ class ExportedDefaultParameterStub(val context: JsIrBackendContext) : Declaratio
return null return null
} }
if (!declaration.hasStableJsName()) { if (!declaration.hasStableJsName(context)) {
return null return null
} }
@@ -5,12 +5,21 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.utils.Signature import org.jetbrains.kotlin.ir.backend.js.utils.Signature
import org.jetbrains.kotlin.ir.backend.js.utils.hasStableJsName
import org.jetbrains.kotlin.ir.backend.js.utils.jsFunctionSignature import org.jetbrains.kotlin.ir.backend.js.utils.jsFunctionSignature
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
class JsBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruction(context) { class JsBridgesConstruction(context: JsIrBackendContext) : BridgesConstruction<JsIrBackendContext>(context) {
override fun getFunctionSignature(function: IrSimpleFunction): Signature = override fun getFunctionSignature(function: IrSimpleFunction): Signature =
jsFunctionSignature(function) jsFunctionSignature(function, context)
override fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin =
if (bridge.hasStableJsName(context))
JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME
else
JsLoweredDeclarationOrigin.BRIDGE_WITHOUT_STABLE_NAME
} }
@@ -27,7 +27,7 @@ class IrModuleToJsTransformer(
private val backendContext: JsIrBackendContext, private val backendContext: JsIrBackendContext,
private val mainArguments: List<String>?, private val mainArguments: List<String>?,
private val generateScriptModule: Boolean = false, private val generateScriptModule: Boolean = false,
var namer: NameTables = NameTables(emptyList()), var namer: NameTables = NameTables(emptyList(), context = backendContext),
private val fullJs: Boolean = true, private val fullJs: Boolean = true,
private val dceJs: Boolean = false, private val dceJs: Boolean = false,
private val multiModule: Boolean = false, private val multiModule: Boolean = false,
@@ -64,7 +64,7 @@ class IrModuleToJsTransformer(
eliminateDeadDeclarations(modules, backendContext) eliminateDeadDeclarations(modules, backendContext)
// Use a fresh namer for DCE so that we could compare the result with DCE-driven // Use a fresh namer for DCE so that we could compare the result with DCE-driven
// TODO: is this mode relevant for scripting? If yes, refactor so that the external name tables are used here when needed. // TODO: is this mode relevant for scripting? If yes, refactor so that the external name tables are used here when needed.
val namer = NameTables(emptyList()) val namer = NameTables(emptyList(), context = backendContext)
namer.merge(modules.flatMap { it.files }, additionalPackages) namer.merge(modules.flatMap { it.files }, additionalPackages)
generateWrappedModuleBody(modules, exportedModule, namer) generateWrappedModuleBody(modules, exportedModule, namer)
} else null } else null
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.backend.common.ir.isTopLevel import org.jetbrains.kotlin.backend.common.ir.isTopLevel
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBreak import org.jetbrains.kotlin.ir.expressions.IrBreak
@@ -105,13 +106,13 @@ fun fieldSignature(field: IrField): Signature {
return BackingFieldSignature(field) return BackingFieldSignature(field)
} }
fun jsFunctionSignature(declaration: IrFunction): Signature { fun jsFunctionSignature(declaration: IrFunction, context: JsIrBackendContext?): Signature {
require(!declaration.isStaticMethodOfClass) require(!declaration.isStaticMethodOfClass)
require(declaration.dispatchReceiverParameter != null) require(declaration.dispatchReceiverParameter != null)
val declarationName = declaration.getJsNameOrKotlinName().asString() val declarationName = declaration.getJsNameOrKotlinName().asString()
if (declaration.hasStableJsName()) { if (declaration.hasStableJsName(context)) {
return StableNameSignature(declarationName) return StableNameSignature(declarationName)
} }
@@ -148,7 +149,8 @@ class NameTables(
packages: List<IrPackageFragment>, packages: List<IrPackageFragment>,
reservedForGlobal: MutableSet<String> = mutableSetOf(), reservedForGlobal: MutableSet<String> = mutableSetOf(),
reservedForMember: MutableSet<String> = mutableSetOf(), reservedForMember: MutableSet<String> = mutableSetOf(),
val mappedNames: MutableMap<String, String>? = null val mappedNames: MutableMap<String, String>? = null,
private val context: JsIrBackendContext? = null
) { ) {
val globalNames: NameTable<IrDeclaration> val globalNames: NameTable<IrDeclaration>
private val memberNames: NameTable<Signature> private val memberNames: NameTable<Signature>
@@ -250,7 +252,13 @@ class NameTables(
val packages = mutableListOf<IrPackageFragment>().also { it.addAll(files) } val packages = mutableListOf<IrPackageFragment>().also { it.addAll(files) }
if (packagesAdded()) packages.addAll(additionalPackages) if (packagesAdded()) packages.addAll(additionalPackages)
val table = NameTables(packages, globalNames.reserved, memberNames.reserved, mappedNames) val table = NameTables(
packages,
globalNames.reserved,
memberNames.reserved,
mappedNames,
context
)
globalNames.names.addAllIfAbsent(table.globalNames.names) globalNames.names.addAllIfAbsent(table.globalNames.names)
memberNames.names.addAllIfAbsent(table.memberNames.names) memberNames.names.addAllIfAbsent(table.memberNames.names)
@@ -274,7 +282,7 @@ class NameTables(
} }
private fun generateNameForMemberFunction(declaration: IrSimpleFunction) { private fun generateNameForMemberFunction(declaration: IrSimpleFunction) {
when (val signature = jsFunctionSignature(declaration)) { when (val signature = jsFunctionSignature(declaration, context)) {
is StableNameSignature -> memberNames.declareStableName(signature, signature.name) is StableNameSignature -> memberNames.declareStableName(signature, signature.name)
is ParameterTypeBasedSignature -> memberNames.declareFreshName(signature, signature.suggestedName) is ParameterTypeBasedSignature -> memberNames.declareFreshName(signature, signature.suggestedName)
} }
@@ -327,7 +335,7 @@ class NameTables(
} }
fun getNameForMemberFunction(function: IrSimpleFunction): String { fun getNameForMemberFunction(function: IrSimpleFunction): String {
val signature = jsFunctionSignature(function) val signature = jsFunctionSignature(function, context)
val name = memberNames.names[signature] ?: mappedNames?.get(mapToKey(signature)) val name = memberNames.names[signature] ?: mappedNames?.get(mapToKey(signature))
// TODO Add a compiler flag, which enables this behaviour // TODO Add a compiler flag, which enables this behaviour
@@ -24,7 +24,7 @@ import org.jetbrains.kotlin.name.Name
fun TODO(element: IrElement): Nothing = TODO(element::class.java.simpleName + " is not supported yet here") fun TODO(element: IrElement): Nothing = TODO(element::class.java.simpleName + " is not supported yet here")
fun IrFunction.hasStableJsName(): Boolean { fun IrFunction.hasStableJsName(context: JsIrBackendContext?): Boolean {
if ( if (
origin == JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME || origin == JsLoweredDeclarationOrigin.BRIDGE_WITH_STABLE_NAME ||
(this as? IrSimpleFunction)?.isMethodOfAny() == true // Handle names for special functions (this as? IrSimpleFunction)?.isMethodOfAny() == true // Handle names for special functions
@@ -52,7 +52,7 @@ fun IrFunction.hasStableJsName(): Boolean {
else -> true else -> true
} }
return (isEffectivelyExternal() || getJsName() != null || isExported(null)) && namedOrMissingGetter return (isEffectivelyExternal() || getJsName() != null || isExported(context)) && namedOrMissingGetter
} }
fun IrFunction.isEqualsInheritedFromAny() = fun IrFunction.isEqualsInheritedFromAny() =
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound
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.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
@@ -18,12 +19,14 @@ import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
class WasmBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruction(context) { class WasmBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruction<JsCommonBackendContext>(context) {
override fun getFunctionSignature(function: IrSimpleFunction): WasmSignature = override fun getFunctionSignature(function: IrSimpleFunction): WasmSignature =
function.wasmSignature(context.irBuiltIns) function.wasmSignature(context.irBuiltIns)
// Dispatch receiver type must be casted when types are different. // Dispatch receiver type must be casted when types are different.
override val shouldCastDispatchReceiver: Boolean = true override val shouldCastDispatchReceiver: Boolean = true
override fun getBridgeOrigin(bridge: IrSimpleFunction): IrDeclarationOrigin =
IrDeclarationOrigin.BRIDGE
} }
data class WasmSignature( data class WasmSignature(