[JS IR BE] Load builtins from code to runtime

Bypass builtins deserialization mechanism in legacy JS backend and load
bultins direcly as kotlin code.

This way we won't have separated IR declarations for Enum, Char, Long

Some "native" builtins are implemented in libraries/stdlib/js/irRuntime/builtins/
Other builtins are moved by MoveExternalDeclarationsToSeparatePlace and
used only in compile-time
This commit is contained in:
Svyatoslav Kuzmich
2019-01-24 18:44:59 +03:00
parent 7e263fd68e
commit 8c89ffbe2d
19 changed files with 1506 additions and 127 deletions
@@ -43,10 +43,10 @@ private fun makeJsPhase(
prerequisite: Set<CompilerPhase<JsIrBackendContext, IrModuleFragment>> = emptySet()
) = makePhase(lowering, description, name, prerequisite)
private val MoveExternalDeclarationsToSeparatePlacePhase = makeJsPhase(
{ _, module -> MoveExternalDeclarationsToSeparatePlace().lower(module) },
name = "MoveExternalDeclarationsToSeparatePlace",
description = "Move `external` declarations into separate place to make the following lowerings do not care about them"
private val MoveBodilessDeclarationsToSeparatePlacePhase = makeJsPhase(
{ _, module -> MoveBodilessDeclarationsToSeparatePlace().lower(module) },
name = "MoveBodilessDeclarationsToSeparatePlace",
description = "Move `external` and `built-in` declarations into separate place to make the following lowerings do not care about them"
)
private val ExpectDeclarationsRemovingPhase = makeJsPhase(
@@ -337,7 +337,7 @@ private val IrToJsPhase = makeJsPhase(
val jsPhases = listOf(
IrModuleStartPhase,
MoveExternalDeclarationsToSeparatePlacePhase,
MoveBodilessDeclarationsToSeparatePlacePhase,
ExpectDeclarationsRemovingPhase,
CoroutineIntrinsicLoweringPhase,
ArrayInlineConstructorLoweringPhase,
@@ -27,7 +27,8 @@ fun compile(
configuration: CompilerConfiguration,
export: FqName? = null,
dependencies: List<ModuleDescriptor> = listOf(),
irDependencyModules: List<IrModuleFragment> = listOf()
irDependencyModules: List<IrModuleFragment> = listOf(),
builtInsModule: ModuleDescriptorImpl? = null
): Result {
val analysisResult =
TopDownAnalyzerFacadeForJS.analyzeFiles(
@@ -35,7 +36,9 @@ fun compile(
project,
configuration,
dependencies.mapNotNull { it as? ModuleDescriptorImpl },
emptyList()
emptyList(),
thisIsBuiltInsModule = builtInsModule == null,
customBuiltInsModule = builtInsModule
)
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
@@ -51,7 +51,7 @@ class JsDefaultArgumentStubGenerator(override val context: JsIrBackendContext) :
private fun resolveInvoke(paramCount: Int): IrSimpleFunction {
assert(paramCount > 0)
val fqn = FqName.fromSegments(listOf("kotlin", "Function$paramCount"))
val functionKlass = context.run { symbolTable.referenceClass(getClass(fqn)) }.owner
val functionKlass = context.run { symbolTable.lazyWrapper.referenceClass(getClass(fqn)) }.owner
return functionKlass.declarations.filterIsInstance<IrSimpleFunction>().first { it.name == Name.identifier("invoke") }
}
}
@@ -8,14 +8,42 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.ir.backend.js.lower.inline.addChild
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.util.isEffectivelyExternal
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class MoveBodilessDeclarationsToSeparatePlace : FileLoweringPass {
private val builtInClasses = listOf(
"String",
"Nothing",
"Array",
"Any",
"ByteArray",
"CharArray",
"ShortArray",
"IntArray",
"LongArray",
"FloatArray",
"DoubleArray",
"BooleanArray",
"Boolean",
"Byte",
"Short",
"Int",
"Float",
"Double"
).map { Name.identifier(it) }.toSet()
private fun isBuiltInClass(declaration: IrDeclaration): Boolean =
declaration is IrClass && declaration.name in builtInClasses
class MoveExternalDeclarationsToSeparatePlace : FileLoweringPass {
private val packageFragment = IrExternalPackageFragmentImpl(object : IrExternalPackageFragmentSymbol {
override val descriptor: PackageFragmentDescriptor
get() = error("Operation is unsupported")
@@ -36,7 +64,7 @@ class MoveExternalDeclarationsToSeparatePlace : FileLoweringPass {
while (it.hasNext()) {
val d = it.next()
if (d.isEffectivelyExternal()) {
if (d.isEffectivelyExternal() || isBuiltInClass(d)) {
it.remove()
packageFragment.addChild(d)
}