Skip to content

Commit a71cd7b

Browse files
olme04qurbonzoda
authored andcommitted
Support JS IR
* share klib resolving logic between JS IR and Native * minor cleanup of buildscripts * add support for JS IR in integration tests * add support for JS IR in example
1 parent 48427fa commit a71cd7b

File tree

11 files changed

+237
-206
lines changed

11 files changed

+237
-206
lines changed

examples/kotlin-multiplatform/build.gradle

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,13 @@ allOpen {
1010
}
1111

1212
kotlin {
13-
jvm {
14-
compilations.all {
15-
kotlinOptions {
16-
jvmTarget = '1.8'
17-
}
18-
}
19-
}
20-
21-
js {
22-
nodejs { }
23-
}
24-
25-
macosX64 { }
26-
macosArm64 { }
27-
linuxX64 { }
28-
mingwX64 { }
13+
jvm()
14+
js('jsIr', IR) { nodejs() }
15+
js('jsLegacy', LEGACY) { nodejs() }
16+
macosX64 {}
17+
macosArm64 {}
18+
linuxX64 {}
19+
mingwX64 {}
2920

3021
sourceSets.all {
3122
languageSettings {
@@ -42,7 +33,12 @@ kotlin {
4233

4334
jvmMain {}
4435

45-
jsMain {}
36+
jsMain {
37+
dependsOn(commonMain)
38+
39+
jsIrMain.dependsOn(it)
40+
jsLegacyMain.dependsOn(it)
41+
}
4642

4743
nativeMain {
4844
dependsOn(commonMain)
@@ -108,7 +104,8 @@ benchmark {
108104
register("jvm") {
109105
jmhVersion = "1.21"
110106
}
111-
register("js")
107+
register("jsIr")
108+
register("jsLegacy")
112109
register("macosX64")
113110
register("macosArm64")
114111
register("linuxX64")

integration/build.gradle.kts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ fun IncludedBuild.classpath() = projectDir.resolve("build/createClasspathManifes
5252
val createClasspathManifest by tasks.registering {
5353
dependsOn(plugin.task(":createClasspathManifest"))
5454
dependsOn(artifactsTask("jvm"))
55-
dependsOn(artifactsTask("js"))
55+
dependsOn(artifactsTask("jsIr"))
56+
dependsOn(artifactsTask("jsLegacy"))
5657
dependsOn(artifactsTask("metadata"))
5758
dependsOn(artifactsTaskNativeKlibs())
5859

@@ -64,7 +65,8 @@ val createClasspathManifest by tasks.registering {
6465
resolve("plugin-classpath.txt").writeText(plugin.classpath().resolve("plugin-classpath.txt").readText())
6566
resolve("runtime-metadata.txt").writeText(artifactsTask("metadata").archiveFilePath)
6667
resolve("runtime-jvm.txt").writeText(artifactsTask("jvm").archiveFilePath)
67-
resolve("runtime-js.txt").writeText(artifactsTask("js").archiveFilePath)
68+
resolve("runtime-jsIr.txt").writeText(artifactsTask("jsIr").archiveFilePath)
69+
resolve("runtime-jsLegacy.txt").writeText(artifactsTask("jsLegacy").archiveFilePath)
6870
resolve("runtime-native.txt").writeText(artifactsTaskNativeKlibs().klibs())
6971
}
7072
}

integration/src/main/kotlin/kotlinx/benchmark/integration/ProjectBuilder.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ private val buildScript = run {
4141
4242
def benchmarkRuntimeMetadata = files(${readFileList("runtime-metadata.txt")})
4343
def benchmarkRuntimeJvm = files(${readFileList("runtime-jvm.txt")})
44-
def benchmarkRuntimeJs = files(${readFileList("runtime-js.txt")})
44+
def benchmarkRuntimeJsIr = files(${readFileList("runtime-jsIr.txt")})
45+
def benchmarkRuntimeJsLegacy = files(${readFileList("runtime-jsLegacy.txt")})
4546
def benchmarkRuntimeNative = files(${readFileList("runtime-native.txt")})
4647
""".trimIndent()
4748
}

integration/src/test/kotlin/kotlinx/benchmark/integration/ReportFormatTest.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class ReportFormatTest : GradleTest() {
88
@Test
99
fun testReportFormatFileNames() {
1010
val formats = listOf(null, "json", "csv", "scsv", "text")
11+
val targets = listOf("jsIr", "jsLegacy", "jvm", "native")
1112

1213
val runner = project("kotlin-multiplatform", true) {
1314
formats.forEach { format ->
@@ -20,13 +21,13 @@ class ReportFormatTest : GradleTest() {
2021
}
2122
}
2223

23-
formats.forEach {
24-
val name = it ?: "jsonDefault"
25-
val ext = it ?: "json"
24+
formats.forEach { format ->
25+
val name = format ?: "jsonDefault"
26+
val ext = format ?: "json"
2627
runner.run("${name}Benchmark")
2728
val reports = reports(name)
28-
assertEquals(3, reports.size)
29-
assertEquals(setOf("js.$ext", "jvm.$ext", "native.$ext"), reports.map(File::getName).toSet())
29+
assertEquals(targets.size, reports.size)
30+
assertEquals(targets.map { "$it.$ext" }.toSet(), reports.map(File::getName).toSet())
3031
}
3132
}
3233
}

integration/src/test/resources/templates/kotlin-multiplatform/build.gradle

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,9 @@ import org.jetbrains.kotlin.konan.target.KonanTarget
22
import org.jetbrains.kotlin.konan.target.HostManager
33

44
kotlin {
5-
jvm {
6-
compilations.all {
7-
kotlinOptions.jvmTarget = '1.8'
8-
}
9-
}
10-
11-
js {
12-
nodejs()
13-
}
5+
jvm()
6+
js('jsIr', IR) { nodejs() }
7+
js('jsLegacy', LEGACY) { nodejs() }
148

159
if (HostManager.hostIsLinux) linuxX64('native')
1610
if (HostManager.hostIsMingw) mingwX64('native')
@@ -28,9 +22,14 @@ kotlin {
2822
implementation(benchmarkRuntimeJvm)
2923
}
3024
}
31-
jsMain {
25+
jsIrMain {
26+
dependencies {
27+
implementation(benchmarkRuntimeJsIr)
28+
}
29+
}
30+
jsLegacyMain {
3231
dependencies {
33-
implementation(benchmarkRuntimeJs)
32+
implementation(benchmarkRuntimeJsLegacy)
3433
}
3534
}
3635
nativeMain {
@@ -45,7 +44,8 @@ kotlin {
4544
benchmark {
4645
targets {
4746
register("jvm")
48-
register("js")
47+
register("jsIr")
48+
register("jsLegacy")
4949
register("native")
5050
}
5151
}

plugin/main/src/kotlinx/benchmark/gradle/JsMultiplatformTasks.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package kotlinx.benchmark.gradle
22

33
import org.gradle.api.*
44
import org.jetbrains.kotlin.gradle.plugin.mpp.*
5+
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
6+
import org.jetbrains.kotlin.gradle.targets.js.ir.*
57

68
fun Project.processJsCompilation(target: JsBenchmarkTarget) {
79
project.logger.info("Configuring benchmarks for '${target.name}' using Kotlin/JS")
@@ -21,6 +23,11 @@ private fun Project.createJsBenchmarkCompileTask(target: JsBenchmarkTarget): Kot
2123
val benchmarkCompilation =
2224
compilation.target.compilations.create(BenchmarksPlugin.BENCHMARK_COMPILATION_NAME) as KotlinJsCompilation
2325

26+
(compilation.target as KotlinJsTargetDsl).apply {
27+
//force to create executable: required for IR, do nothing on Legacy
28+
binaries.executable(benchmarkCompilation)
29+
}
30+
2431
benchmarkCompilation.apply {
2532
val sourceSet = kotlinSourceSets.single()
2633
sourceSet.kotlin.setSrcDirs(files("$benchmarkBuildDir/sources"))
@@ -58,6 +65,7 @@ private fun Project.createJsBenchmarkGenerateSourceTask(
5865
group = BenchmarksPlugin.BENCHMARKS_TASK_GROUP
5966
description = "Generate JS source files for '${target.name}'"
6067
title = target.name
68+
ir = target.compilation is KotlinJsIrCompilation
6169
inputClassesDirs = compilationOutput.output.allOutputs
6270
inputDependencies = compilationOutput.compileDependencyFiles
6371
outputResourcesDir = file("$benchmarkBuildDir/resources")

plugin/main/src/kotlinx/benchmark/gradle/JsNodeTasks.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ package kotlinx.benchmark.gradle
33
import kotlinx.benchmark.gradle.BenchmarksPlugin.Companion.RUN_BENCHMARKS_TASKNAME
44
import org.gradle.api.*
55
import org.jetbrains.kotlin.gradle.plugin.mpp.*
6+
import org.jetbrains.kotlin.gradle.targets.js.dsl.*
7+
import org.jetbrains.kotlin.gradle.targets.js.ir.*
68
import org.jetbrains.kotlin.gradle.targets.js.nodejs.*
7-
import org.jetbrains.kotlin.gradle.targets.js.npm.*
89

910
fun Project.createJsBenchmarkExecTask(
1011
config: BenchmarkConfiguration,
@@ -18,12 +19,19 @@ fun Project.createJsBenchmarkExecTask(
1819
group = BenchmarksPlugin.BENCHMARKS_TASK_GROUP
1920
description = "Executes benchmark for '${target.name}'"
2021

21-
val executableFile = compilation.compileKotlinTask.outputFile
22-
args("-r", "source-map-support/register")
23-
args(executableFile.absolutePath)
24-
workingDir = compilation.npmProject.dir
25-
26-
onlyIf { executableFile.exists() }
22+
nodeArgs.addAll(listOf("-r", "source-map-support/register"))
23+
24+
val executableFile = when (val kotlinTarget = compilation.target) {
25+
is KotlinJsIrTarget -> {
26+
val binary = kotlinTarget.binaries.executable(compilation)
27+
.first { it.mode == KotlinJsBinaryMode.PRODUCTION } as JsIrBinary
28+
binary.linkSyncTask.map {
29+
it.destinationDir.resolve(binary.linkTask.get().outputFileProperty.get().name)
30+
}
31+
}
32+
else -> compilation.compileKotlinTaskProvider.map { it.outputFileProperty.get() }
33+
}
34+
inputFileProperty.set(project.layout.file(executableFile))
2735

2836
val reportFile = setupReporting(target, config)
2937
args(writeParameters(target.name, reportFile, traceFormat(), config))

plugin/main/src/kotlinx/benchmark/gradle/JsSourceGeneratorTask.kt

Lines changed: 55 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import org.gradle.api.*
44
import org.gradle.api.file.*
55
import org.gradle.api.tasks.*
66
import org.gradle.workers.*
7-
import org.jetbrains.kotlin.builtins.*
87
import org.jetbrains.kotlin.config.*
98
import org.jetbrains.kotlin.descriptors.*
109
import org.jetbrains.kotlin.descriptors.impl.*
@@ -25,6 +24,9 @@ open class JsSourceGeneratorTask
2524
@Input
2625
lateinit var title: String
2726

27+
@Input
28+
var ir: Boolean = false
29+
2830
@InputFiles
2931
@PathSensitive(PathSensitivity.RELATIVE)
3032
lateinit var inputClassesDirs: FileCollection
@@ -44,23 +46,11 @@ open class JsSourceGeneratorTask
4446
cleanup(outputSourcesDir)
4547
cleanup(outputResourcesDir)
4648

47-
inputClassesDirs.files.forEach { lib ->
49+
inputClassesDirs.files.forEach { lib: File ->
4850
generateSources(lib)
4951
}
5052
}
5153

52-
private fun load(lib: File): List<ModuleDescriptor> {
53-
val configuration = CompilerConfiguration()
54-
val languageVersionSettings = configuration.languageVersionSettings
55-
val storageManager = LockBasedStorageManager("Inspect")
56-
57-
val dependencies = inputDependencies.flatMap {
58-
loadDescriptors(it, languageVersionSettings, storageManager)
59-
}
60-
return loadDescriptors(lib, languageVersionSettings, storageManager, dependencies)
61-
}
62-
63-
6454
private fun generateSources(lib: File) {
6555
val modules = load(lib)
6656
modules.forEach { module ->
@@ -74,42 +64,61 @@ open class JsSourceGeneratorTask
7464
}
7565
}
7666

67+
private fun load(lib: File): List<ModuleDescriptor> {
68+
val storageManager = LockBasedStorageManager("Inspect")
69+
return if (ir) {
70+
loadIr(lib, storageManager)
71+
} else {
72+
loadLegacy(lib, storageManager)
73+
}
74+
}
75+
76+
private fun loadIr(lib: File, storageManager: StorageManager): List<ModuleDescriptor> {
77+
//skip processing of empty dirs (fail if not to do it)
78+
if (lib.listFiles() == null) return emptyList()
79+
val dependencies = inputDependencies.files.filterNot { it.extension == "js" }.toSet()
80+
val module = KlibResolver.JS.createModuleDescriptor(lib, dependencies, storageManager)
81+
return listOf(module)
82+
}
83+
84+
private fun loadLegacy(lib: File, storageManager: StorageManager): List<ModuleDescriptor> {
85+
val dependencies = inputDependencies.flatMap {
86+
loadDescriptors(it, storageManager)
87+
}
88+
return loadDescriptors(lib, storageManager, dependencies)
89+
}
90+
7791
private fun loadDescriptors(
7892
lib: File,
79-
languageVersionSettings: LanguageVersionSettings,
80-
storageManager: LockBasedStorageManager,
93+
storageManager: StorageManager,
8194
dependencies: List<ModuleDescriptorImpl> = listOf()
82-
): List<ModuleDescriptorImpl> {
83-
val modules = KotlinJavascriptMetadataUtils.loadMetadata(lib)
84-
val builtIns = org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices.builtIns
85-
return modules.map { metadata ->
86-
val skipCheck = languageVersionSettings.getFlag(AnalysisFlags.skipMetadataVersionCheck)
87-
assert(metadata.version.isCompatible() || skipCheck) {
88-
"Expected JS metadata version " + JsMetadataVersion.INSTANCE + ", but actual metadata version is " + metadata.version
89-
}
90-
91-
val module = ModuleDescriptorImpl(
92-
Name.special("<" + metadata.moduleName + ">"),
93-
storageManager,
94-
builtIns
95-
)
96-
val (header, body) = KotlinJavascriptSerializationUtil.readModuleAsProto(
97-
metadata.body,
98-
metadata.version
99-
)
100-
val provider = createKotlinJavascriptPackageFragmentProvider(
101-
storageManager,
102-
module,
103-
header,
104-
body,
105-
metadata.version,
106-
CompilerDeserializationConfiguration(languageVersionSettings),
107-
LookupTracker.DO_NOTHING
108-
)
109-
module.setDependencies(listOf(module, builtIns.builtInsModule) + dependencies)
110-
module.initialize(provider)
111-
module
95+
): List<ModuleDescriptorImpl> = KotlinJavascriptMetadataUtils.loadMetadata(lib).map { metadata ->
96+
val skipCheck = LanguageVersionSettingsImpl.DEFAULT.getFlag(AnalysisFlags.skipMetadataVersionCheck)
97+
assert(metadata.version.isCompatible() || skipCheck) {
98+
"Expected JS metadata version " + JsMetadataVersion.INSTANCE + ", but actual metadata version is " + metadata.version
11299
}
100+
101+
val module = ModuleDescriptorImpl(
102+
Name.special("<" + metadata.moduleName + ">"),
103+
storageManager,
104+
JsPlatformAnalyzerServices.builtIns
105+
)
106+
val (header, body) = KotlinJavascriptSerializationUtil.readModuleAsProto(
107+
metadata.body,
108+
metadata.version
109+
)
110+
val provider = createKotlinJavascriptPackageFragmentProvider(
111+
storageManager,
112+
module,
113+
header,
114+
body,
115+
metadata.version,
116+
CompilerDeserializationConfiguration(LanguageVersionSettingsImpl.DEFAULT),
117+
LookupTracker.DO_NOTHING
118+
)
119+
module.setDependencies(listOf(module, JsPlatformAnalyzerServices.builtIns.builtInsModule) + dependencies)
120+
module.initialize(provider)
121+
module
113122
}
114123

115124
}

0 commit comments

Comments
 (0)