[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
@@ -44,7 +44,7 @@ fun createTopDownAnalyzerForJs(
languageVersionSettings: LanguageVersionSettings,
lookupTracker: LookupTracker,
expectActualTracker: ExpectActualTracker,
fallbackPackage: PackageFragmentProvider?
additionalPackages: List<PackageFragmentProvider>
): LazyTopDownAnalyzer {
val storageComponentContainer = createContainer("TopDownAnalyzerForJs", JsPlatform) {
configureModule(moduleContext, JsPlatform, TargetPlatformVersion.NoVersion, bindingTrace)
@@ -62,7 +62,7 @@ fun createTopDownAnalyzerForJs(
}.apply {
val packagePartProviders = mutableListOf(get<KotlinCodeAnalyzer>().packageFragmentProvider)
val moduleDescriptor = get<ModuleDescriptorImpl>()
fallbackPackage?.let { packagePartProviders += it }
packagePartProviders += additionalPackages
moduleDescriptor.initialize(CompositePackageFragmentProvider(packagePartProviders))
}
return storageComponentContainer.get<LazyTopDownAnalyzer>()
@@ -6,12 +6,15 @@
package org.jetbrains.kotlin.js.analyze
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.context.ContextForNewModule
import org.jetbrains.kotlin.context.ModuleContext
import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.frontend.js.di.createTopDownAnalyzerForJs
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
@@ -45,31 +48,55 @@ object TopDownAnalyzerFacadeForJS {
project: Project,
configuration: CompilerConfiguration,
moduleDescriptors: List<ModuleDescriptorImpl>,
friendModuleDescriptors: List<ModuleDescriptorImpl>
friendModuleDescriptors: List<ModuleDescriptorImpl>,
thisIsBuiltInsModule: Boolean = false,
customBuiltInsModule: ModuleDescriptorImpl? = null
): JsAnalysisResult {
require(!thisIsBuiltInsModule || customBuiltInsModule == null) {
"Can't simultaneously use custom built-ins module and set current module as built-ins"
}
val projectContext = ProjectContext(project)
val builtIns = if (thisIsBuiltInsModule || customBuiltInsModule != null) {
object : KotlinBuiltIns(projectContext.storageManager) {}
} else {
JsPlatform.builtIns
}
val moduleName = configuration[CommonConfigurationKeys.MODULE_NAME]!!
val context = ContextForNewModule(ProjectContext(project), Name.special("<$moduleName>"), JsPlatform.builtIns, null)
context.module.setDependencies(
listOf(context.module) +
moduleDescriptors +
listOf(JsPlatform.builtIns.builtInsModule),
friendModuleDescriptors.toSet()
val context = ContextForNewModule(
projectContext,
Name.special("<$moduleName>"),
builtIns,
multiTargetPlatform = null
)
val additionalPackages = mutableListOf<PackageFragmentProvider>()
if (customBuiltInsModule != null) {
builtIns.builtInsModule = customBuiltInsModule
}
if (thisIsBuiltInsModule) {
builtIns.builtInsModule = context.module
additionalPackages += functionInterfacePackageFragmentProvider(context.storageManager, context.module)
}
val dependencies = mutableSetOf(context.module) + moduleDescriptors + builtIns.builtInsModule
context.module.setDependencies(dependencies.toList(), friendModuleDescriptors.toSet())
val moduleKind = configuration.get(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN)
val trace = BindingTraceContext()
trace.record(MODULE_KIND, context.module, moduleKind)
return analyzeFilesWithGivenTrace(files, trace, context, configuration)
return analyzeFilesWithGivenTrace(files, trace, context, configuration, additionalPackages)
}
fun analyzeFilesWithGivenTrace(
files: Collection<KtFile>,
trace: BindingTrace,
moduleContext: ModuleContext,
configuration: CompilerConfiguration
configuration: CompilerConfiguration,
additionalPackages: List<PackageFragmentProvider> = emptyList()
): JsAnalysisResult {
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER) ?: LookupTracker.DO_NOTHING
val expectActualTracker = configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_TRACKER) ?: ExpectActualTracker.DoNothing
@@ -91,7 +118,7 @@ object TopDownAnalyzerFacadeForJS {
languageVersionSettings,
lookupTracker,
expectActualTracker,
packageFragment
additionalPackages + listOfNotNull(packageFragment)
)
analyzerForJs.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
return JsAnalysisResult.success(trace, moduleContext.module)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.js.test
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.ir.backend.js.Result
import org.jetbrains.kotlin.ir.backend.js.compile
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
@@ -13,6 +14,7 @@ import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.MainCallParameters
import org.jetbrains.kotlin.js.facade.TranslationUnit
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TargetBackend
import java.io.File
@@ -112,7 +114,8 @@ abstract class BasicIrBoxTest(
config.configuration,
FqName((testPackage?.let { "$it." } ?: "") + testFunction),
dependencies,
irDependencies
irDependencies,
runtimeResult.moduleDescriptor as ModuleDescriptorImpl
)
compilationCache[outputFile.name.replace(".js", ".meta.js")] = result
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.js.test
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
private const val runtimeDir = "js/js.translator/testData/out/irBox"
@@ -26,6 +27,29 @@ enum class JsIrTestRuntime(
)
}
// Required to compile native builtins with the rest of runtime
private const val builtInsHeader = """@file:Suppress(
"NON_ABSTRACT_FUNCTION_WITH_NO_BODY",
"MUST_BE_INITIALIZED_OR_BE_ABSTRACT",
"EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE",
"PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED",
"WRONG_MODIFIER_TARGET"
)
"""
// Native builtins that were not implemented in JS IR runtime
private val unimplementedNativeBuiltInsDir = KotlinTestUtils.tmpDir("unimplementedBuiltins").also { tmpDir ->
val allBuiltins = listOfKtFilesFrom("core/builtins/native/kotlin").map { File(it).name }
val implementedBuiltIns = listOfKtFilesFrom("libraries/stdlib/js/irRuntime/builtins/").map { File(it).name }
val unimplementedBuiltIns = allBuiltins - implementedBuiltIns
for (filename in unimplementedBuiltIns) {
val originalFile = File("core/builtins/native/kotlin", filename)
val newFile = File(tmpDir, filename)
val sourceCode = builtInsHeader + originalFile.readText()
newFile.writeText(sourceCode)
}
}
private val fullRuntimeSources = listOfKtFilesFrom(
"core/builtins/src/kotlin",
"libraries/stdlib/common/src",
@@ -36,15 +60,8 @@ private val fullRuntimeSources = listOfKtFilesFrom(
"libraries/stdlib/js/runtime",
"libraries/stdlib/unsigned",
"core/builtins/native/kotlin/Annotation.kt",
"core/builtins/native/kotlin/Number.kt",
"core/builtins/native/kotlin/Comparable.kt",
"core/builtins/native/kotlin/Collections.kt",
"core/builtins/native/kotlin/Iterator.kt",
"core/builtins/native/kotlin/CharSequence.kt",
"core/builtins/src/kotlin/Unit.kt",
unimplementedNativeBuiltInsDir.path,
BasicBoxTest.COMMON_FILES_DIR_PATH
) - listOfKtFilesFrom(
"libraries/stdlib/common/src/kotlin/JvmAnnotationsH.kt",
@@ -102,10 +119,6 @@ private val fullRuntimeSources = listOfKtFilesFrom(
val reducedRuntimeSources = fullRuntimeSources - listOfKtFilesFrom(
"libraries/stdlib/unsigned",
"core/builtins/src/kotlin/reflect/KParameter.kt",
"core/builtins/src/kotlin/reflect/KType.kt",
"core/builtins/src/kotlin/reflect/KTypeParameter.kt",
"core/builtins/src/kotlin/reflect/KVisibility.kt",
"libraries/stdlib/common/src/generated/_Arrays.kt",
"libraries/stdlib/common/src/generated/_Collections.kt",
"libraries/stdlib/common/src/generated/_Maps.kt",