kotl.in/wasm-intro

Repo: GitHib/Kotlin| Branch: wasm/intro | wasm_intro.md


Kotlin/Wasm Internals 101

Disclaimers & Notes

  • Recording?
  • Ask questions on the go.
  • Shortcuts.
  • As deep as I can, as much as we have time and energy.
  • Only about the new frontend (aka K2 aka FIR) + Wasm backend.
  • Live demo.

High level

Typical user project / Gradle

2 groups of tasks:

  • Development
  • Production

Tips:

  • name of tasks in Gradle could be abbreviated, e.g. use wasmJsBrProdRun instead of wasmJsBrowserProductionRun

Development

Goals:

Production

Goals:

  • Runtime performance.

  • Size.

  • Small/local optimizations.

  • Remove Unreachable Declarations (aka DCE in the code)

    • dce, wasm part
    • dce, common & js part
    • Relatively cheap.
    • Use some knowledge about kotlin.
      • Service exports, e.g. for functions.
      • @AssociatedObject (internal feature/API used by kotlinx-serialization)
      • Instantiated classes.
      • Reflection (...::class, KClass<...>)?
    • No de-virtualization.
    • Reachability graph could be dumped.
  • Run Binaryen

Simplified Diagram:

[Sources]     [Dependencies (.klib files)]
      |         |
       \       / \
        v     v   \
       Kompiler    \
          |         \
          v          |
      [.klib file]   |
          |         /
          v        v
     Kompiler (to produce executable)  + addition lowrings in Prod, including DCE
          |         |
          |         |<Optional>
          v         |
    [.wasm, .mjs]  [.wat]   !! Dev build stops here.
       |
       v
    Binaryen                // Run by Gradle plugin
       |
       v
   [.wasm optimized]        !! In Prod build.

Compiler

Pipeline

Simplified Diagram:

    [Sources] & [klibs]
        |
        v
    Frontend (new frontend aka K2 aka FIR)
        |
        v
      [FIR]
        |
        v
      FIR2IR
        |
        v
       [IR] <aka backend IR>
        |
        v
    Compiler plugins
        |
        v
       [IR] <IR>                  !! IR could be serialized to .klib here
        |
..............................................
        |
        v
    Wasm Backend (Lowerings)¹
        |
        v
       [IR lowered/simplified]
        |
        v
       ir2wasm²
        |
        v
     [Wasm IR]--------+
        |             |
        v             |
  WasmIrToBinary³  WasmIrToText⁴
        |             |
        v             v
    [~.wasm]       [~.wat]

1: WasmLoweringPhases.kt:538 2: ir2wasm 3: WasmIrToBinary.kt 4: WasmIrToText.kt

TODO Operators.kt

Project

Paths:

Tests

Test running infrastructure is generated from files (or directories) located in special places.

codegen

fun box() = "OK"

If you add a new test-data file you need to regenerate tests with gradle task generateTests or run configuration in IDE. ./gradlew generateTests

Example: FirWasmJsCodegenBoxTestGenerated.java

Run & Debug tests

./gradlew :wasm:wasm.tests:test ./gradlew :wasm:wasm.tests:testFir

Try to run something. E.g. size tests.

  • Navigate or Run with find class/symbol

Kotlin Test data Helper https://github.com/demiurg906/test-data-helper-plugin

TODO Tips:

  • IRs
  • dump
  • custom renderers
  • compare files/dirs

Directives

compiler/tests-common-new/tests/org/jetbrains/kotlin/test/directives/WasmEnvironmentConfigurationDirectives.kt most popular ones?

*.properties

gradle.properties:123

#kotlin.test.junit5.maxParallelForks=1 gradle.properties:106

Publish

TODO ./gradlew install

defaultSnapshotVersion gradle.properties:27 2.1.255-SNAPSHOT 2..255-SNAPSHOT

Troubleshooting:

  • Stop gradle daemons ./gradlew --stop
  • To change debug level -i or -d

Useful Links

Tips & tricks

  • run test from search symbol
  • find action
  • run anything
  • file patterns