[IR JS BE] update NameTables for working with repl
This commit is contained in:
committed by
romanart
parent
184ae2fa43
commit
24cfd0e88c
@@ -262,12 +262,18 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
|
|||||||
|
|
||||||
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering
|
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering
|
||||||
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
|
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
|
||||||
val charSequenceLengthPropertyGetterSymbol =
|
val charSequenceLengthPropertyGetterSymbol by lazy {
|
||||||
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "length" }.getter!!.symbol
|
with(charSequenceClassSymbol.owner.declarations) {
|
||||||
val charSequenceGetFunctionSymbol =
|
filterIsInstance<IrProperty>().firstOrNull { it.name.asString() == "length" }?.getter ?:
|
||||||
|
filterIsInstance<IrFunction>().first { it.name.asString() == "<get-length>" }
|
||||||
|
}.symbol
|
||||||
|
}
|
||||||
|
val charSequenceGetFunctionSymbol by lazy {
|
||||||
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "get" }.symbol
|
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "get" }.symbol
|
||||||
val charSequenceSubSequenceFunctionSymbol =
|
}
|
||||||
|
val charSequenceSubSequenceFunctionSymbol by lazy {
|
||||||
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence" }.symbol
|
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence" }.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
val jsCharSequenceGet = getInternalFunction("charSequenceGet")
|
val jsCharSequenceGet = getInternalFunction("charSequenceGet")
|
||||||
|
|||||||
+23
-15
@@ -73,7 +73,7 @@ class IrModuleToJsTransformer(
|
|||||||
|
|
||||||
module.files.forEach { StaticMembersLowering(backendContext).lower(it) }
|
module.files.forEach { StaticMembersLowering(backendContext).lower(it) }
|
||||||
|
|
||||||
val namer = NameTables(module.files + additionalPackages)
|
namer.merge(module.files, additionalPackages)
|
||||||
|
|
||||||
val program = JsProgram()
|
val program = JsProgram()
|
||||||
|
|
||||||
@@ -102,25 +102,33 @@ class IrModuleToJsTransformer(
|
|||||||
val exportStatements = ExportModelToJsStatements(internalModuleName, namer)
|
val exportStatements = ExportModelToJsStatements(internalModuleName, namer)
|
||||||
.generateModuleExport(exportedModule)
|
.generateModuleExport(exportedModule)
|
||||||
|
|
||||||
with(rootFunction) {
|
if (generateScriptModule) {
|
||||||
parameters += JsParameter(internalModuleName)
|
with(program.globalBlock) {
|
||||||
parameters += importedJsModules.map { JsParameter(it.internalName) }
|
|
||||||
with(body) {
|
|
||||||
statements += importStatements
|
statements += importStatements
|
||||||
statements += moduleBody
|
statements += moduleBody
|
||||||
statements += exportStatements
|
statements += exportStatements
|
||||||
statements += generateCallToMain(rootContext)
|
|
||||||
statements += JsReturn(internalModuleName.makeRef())
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
with(rootFunction) {
|
||||||
|
parameters += JsParameter(internalModuleName)
|
||||||
|
parameters += importedJsModules.map { JsParameter(it.internalName) }
|
||||||
|
with(body) {
|
||||||
|
statements += importStatements
|
||||||
|
statements += moduleBody
|
||||||
|
statements += exportStatements
|
||||||
|
statements += generateCallToMain(rootContext)
|
||||||
|
statements += JsReturn(internalModuleName.makeRef())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
program.globalBlock.statements += ModuleWrapperTranslation.wrap(
|
program.globalBlock.statements += ModuleWrapperTranslation.wrap(
|
||||||
moduleName,
|
moduleName,
|
||||||
rootFunction,
|
rootFunction,
|
||||||
importedJsModules,
|
importedJsModules,
|
||||||
program,
|
program,
|
||||||
kind = moduleKind
|
kind = moduleKind
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return CompilerResult(program.toString(), dts)
|
return CompilerResult(program.toString(), dts)
|
||||||
}
|
}
|
||||||
|
|||||||
+115
-46
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
|||||||
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.JsLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsMangler
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
import org.jetbrains.kotlin.ir.expressions.IrLoop
|
||||||
import org.jetbrains.kotlin.ir.types.isUnit
|
import org.jetbrains.kotlin.ir.types.isUnit
|
||||||
@@ -21,10 +22,24 @@ import org.jetbrains.kotlin.js.naming.isES5IdentifierStart
|
|||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||||
|
|
||||||
|
fun <T> mapToKey(declaration: T): String {
|
||||||
|
return with(JsMangler) {
|
||||||
|
if (declaration is IrDeclaration && isPublic(declaration)) {
|
||||||
|
declaration.hashedMangle.toString()
|
||||||
|
} else if (declaration is Signature) {
|
||||||
|
declaration.toString().hashMangle.toString()
|
||||||
|
} else "key_have_not_generated"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun JsMangler.isPublic(declaration: IrDeclaration) =
|
||||||
|
declaration.isExported() && declaration !is IrScript && declaration !is IrVariable && declaration !is IrValueParameter
|
||||||
|
|
||||||
class NameTable<T>(
|
class NameTable<T>(
|
||||||
val parent: NameTable<*>? = null,
|
val parent: NameTable<*>? = null,
|
||||||
private val reserved: MutableSet<String> = mutableSetOf(),
|
val reserved: MutableSet<String> = mutableSetOf(),
|
||||||
val sanitizer: (String) -> String = ::sanitizeName
|
val sanitizer: (String) -> String = ::sanitizeName,
|
||||||
|
val mappedNames: MutableMap<String, String> = mutableMapOf()
|
||||||
) {
|
) {
|
||||||
var finished = false
|
var finished = false
|
||||||
val names = mutableMapOf<T, String>()
|
val names = mutableMapOf<T, String>()
|
||||||
@@ -40,6 +55,7 @@ class NameTable<T>(
|
|||||||
assert(!finished)
|
assert(!finished)
|
||||||
names[declaration] = name
|
names[declaration] = name
|
||||||
reserved.add(name)
|
reserved.add(name)
|
||||||
|
mappedNames[mapToKey(declaration)] = name
|
||||||
}
|
}
|
||||||
|
|
||||||
fun declareFreshName(declaration: T, suggestedName: String): String {
|
fun declareFreshName(declaration: T, suggestedName: String): String {
|
||||||
@@ -134,7 +150,12 @@ fun functionSignature(declaration: IrFunction): Signature {
|
|||||||
return ParameterTypeBasedSignature(signature, declarationName)
|
return ParameterTypeBasedSignature(signature, declarationName)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NameTables(packages: List<IrPackageFragment>) {
|
class NameTables(
|
||||||
|
packages: List<IrPackageFragment>,
|
||||||
|
reservedForGlobal: MutableSet<String> = mutableSetOf(),
|
||||||
|
reservedForMember: MutableSet<String> = mutableSetOf(),
|
||||||
|
val mappedNames: MutableMap<String, String> = mutableMapOf()
|
||||||
|
) {
|
||||||
val globalNames: NameTable<IrDeclaration>
|
val globalNames: NameTable<IrDeclaration>
|
||||||
private val memberNames: NameTable<Signature>
|
private val memberNames: NameTable<Signature>
|
||||||
private val localNames = mutableMapOf<IrDeclaration, NameTable<IrDeclaration>>()
|
private val localNames = mutableMapOf<IrDeclaration, NameTable<IrDeclaration>>()
|
||||||
@@ -144,61 +165,108 @@ class NameTables(packages: List<IrPackageFragment>) {
|
|||||||
val stableNamesCollector = StableNamesCollector()
|
val stableNamesCollector = StableNamesCollector()
|
||||||
packages.forEach { it.acceptChildrenVoid(stableNamesCollector) }
|
packages.forEach { it.acceptChildrenVoid(stableNamesCollector) }
|
||||||
|
|
||||||
globalNames = NameTable(reserved = stableNamesCollector.staticNames)
|
globalNames = NameTable(
|
||||||
memberNames = NameTable(reserved = stableNamesCollector.memberNames)
|
reserved = (stableNamesCollector.staticNames + reservedForGlobal).toMutableSet(),
|
||||||
|
mappedNames = mappedNames
|
||||||
|
)
|
||||||
|
|
||||||
|
memberNames = NameTable(
|
||||||
|
reserved = (stableNamesCollector.memberNames + reservedForMember).toMutableSet(),
|
||||||
|
mappedNames = mappedNames
|
||||||
|
)
|
||||||
|
|
||||||
|
mappedNames.addAllIfAbsent(mappedNames)
|
||||||
|
|
||||||
|
val classDeclaration = mutableListOf<IrClass>()
|
||||||
for (p in packages) {
|
for (p in packages) {
|
||||||
for (declaration in p.declarations) {
|
for (declaration in p.declarations) {
|
||||||
generateNamesForTopLevelDecl(declaration)
|
generateNamesForTopLevelDecl(declaration)
|
||||||
|
if (declaration is IrScript) {
|
||||||
|
for (memberDecl in declaration.declarations) {
|
||||||
|
generateNamesForTopLevelDecl(memberDecl)
|
||||||
|
if (memberDecl is IrClass) {
|
||||||
|
classDeclaration += memberDecl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
globalNames.finished = true
|
globalNames.finished = true
|
||||||
|
|
||||||
|
for (declaration in classDeclaration) {
|
||||||
|
acceptDeclaration(declaration)
|
||||||
|
}
|
||||||
|
|
||||||
for (p in packages) {
|
for (p in packages) {
|
||||||
for (declaration in p.declarations) {
|
for (declaration in p.declarations) {
|
||||||
val localNameGenerator = LocalNameGenerator(declaration)
|
acceptDeclaration(declaration)
|
||||||
|
|
||||||
if (declaration is IrClass) {
|
|
||||||
if (declaration.isEffectivelyExternal()) {
|
|
||||||
declaration.acceptChildrenVoid(object : IrElementVisitorVoid {
|
|
||||||
override fun visitElement(element: IrElement) {
|
|
||||||
element.acceptChildrenVoid(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
|
||||||
val parent = declaration.parent
|
|
||||||
if (parent is IrClass && !parent.isEnumClass) {
|
|
||||||
generateNameForMemberFunction(declaration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitField(declaration: IrField) {
|
|
||||||
val parent = declaration.parent
|
|
||||||
if (parent is IrClass && !parent.isEnumClass) {
|
|
||||||
generateNameForMemberField(declaration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
declaration.thisReceiver!!.acceptVoid(localNameGenerator)
|
|
||||||
for (memberDecl in declaration.declarations) {
|
|
||||||
memberDecl.acceptChildrenVoid(LocalNameGenerator(memberDecl))
|
|
||||||
when (memberDecl) {
|
|
||||||
is IrSimpleFunction ->
|
|
||||||
generateNameForMemberFunction(memberDecl)
|
|
||||||
is IrField ->
|
|
||||||
generateNameForMemberField(memberDecl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
declaration.acceptChildrenVoid(localNameGenerator)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun acceptDeclaration(declaration: IrDeclaration) {
|
||||||
|
val localNameGenerator = LocalNameGenerator(declaration)
|
||||||
|
|
||||||
|
if (declaration is IrClass) {
|
||||||
|
if (declaration.isEffectivelyExternal()) {
|
||||||
|
declaration.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||||
|
override fun visitElement(element: IrElement) {
|
||||||
|
element.acceptChildrenVoid(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
|
||||||
|
val parent = declaration.parent
|
||||||
|
if (parent is IrClass && !parent.isEnumClass) {
|
||||||
|
generateNameForMemberFunction(declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitField(declaration: IrField) {
|
||||||
|
val parent = declaration.parent
|
||||||
|
if (parent is IrClass && !parent.isEnumClass) {
|
||||||
|
generateNameForMemberField(declaration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
declaration.thisReceiver!!.acceptVoid(localNameGenerator)
|
||||||
|
for (memberDecl in declaration.declarations) {
|
||||||
|
memberDecl.acceptChildrenVoid(LocalNameGenerator(memberDecl))
|
||||||
|
when (memberDecl) {
|
||||||
|
is IrSimpleFunction ->
|
||||||
|
generateNameForMemberFunction(memberDecl)
|
||||||
|
is IrField ->
|
||||||
|
generateNameForMemberField(memberDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
declaration.acceptChildrenVoid(localNameGenerator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T, K> MutableMap<T, K>.addAllIfAbsent(other: Map<T, K>) {
|
||||||
|
this += other.filter { it.key !in this }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun packagesAdded() = mappedNames.isEmpty()
|
||||||
|
|
||||||
|
fun merge(files: List<IrPackageFragment>, additionalPackages: List<IrPackageFragment>) {
|
||||||
|
val packages = mutableListOf<IrPackageFragment>().also { it.addAll(files) }
|
||||||
|
if (packagesAdded()) packages.addAll(additionalPackages)
|
||||||
|
|
||||||
|
val table = NameTables(packages, globalNames.reserved, memberNames.reserved, mappedNames)
|
||||||
|
|
||||||
|
globalNames.names.addAllIfAbsent(table.globalNames.names)
|
||||||
|
memberNames.names.addAllIfAbsent(table.memberNames.names)
|
||||||
|
localNames.addAllIfAbsent(table.localNames)
|
||||||
|
loopNames.addAllIfAbsent(table.loopNames)
|
||||||
|
|
||||||
|
globalNames.reserved.addAll(table.globalNames.reserved)
|
||||||
|
memberNames.reserved.addAll(table.memberNames.reserved)
|
||||||
|
}
|
||||||
|
|
||||||
private fun generateNameForMemberField(field: IrField) {
|
private fun generateNameForMemberField(field: IrField) {
|
||||||
require(!field.isTopLevel)
|
require(!field.isTopLevel)
|
||||||
require(!field.isStatic)
|
require(!field.isStatic)
|
||||||
@@ -257,12 +325,13 @@ class NameTables(packages: List<IrPackageFragment>) {
|
|||||||
parent = parent.parent
|
parent = parent.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
error("Can't find name for declaration ${declaration.fqNameWhenAvailable}")
|
return mappedNames[mapToKey(declaration)] ?: error("Can't find name for declaration ${declaration.fqNameWhenAvailable}")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNameForMemberField(field: IrField): String {
|
fun getNameForMemberField(field: IrField): String {
|
||||||
val signature = fieldSignature(field)
|
val signature = fieldSignature(field)
|
||||||
val name = memberNames.names[signature]
|
val name = memberNames.names[signature] ?: mappedNames[mapToKey(signature)]
|
||||||
|
|
||||||
require(name != null) {
|
require(name != null) {
|
||||||
"Can't find name for member field $field"
|
"Can't find name for member field $field"
|
||||||
}
|
}
|
||||||
@@ -271,7 +340,7 @@ class NameTables(packages: List<IrPackageFragment>) {
|
|||||||
|
|
||||||
fun getNameForMemberFunction(function: IrSimpleFunction): String {
|
fun getNameForMemberFunction(function: IrSimpleFunction): String {
|
||||||
val signature = functionSignature(function)
|
val signature = functionSignature(function)
|
||||||
val name = memberNames.names[signature]
|
val name = memberNames.names[signature] ?: mappedNames[mapToKey(signature)]
|
||||||
|
|
||||||
// TODO: Fix hack: Coroutines runtime currently relies on stable names
|
// TODO: Fix hack: Coroutines runtime currently relies on stable names
|
||||||
// of `invoke` functions in FunctionN interfaces
|
// of `invoke` functions in FunctionN interfaces
|
||||||
|
|||||||
Reference in New Issue
Block a user