Skip to content

Instantly share code, notes, and snippets.

View tanishiking's full-sized avatar
🎓

Rikito Taniguchi tanishiking

🎓
View GitHub Profile
$ wasm-tools parse itoa.wat -o itoa.wasm
import { readFileSync } from "node:fs";
const wasmBuffer = readFileSync("itoa.wasm");
const importObj = {}
const wasmModule = await WebAssembly.instantiate(wasmBuffer, importObj, { builtins: ['js-string'] });
const { test } = wasmModule.instance.exports;

LoopInvariantCodeMotion - wasm-opt

Flattening

TL;DR: We would need running --flatten pass before --licm to make LICM work.

;; test.wat
(module
  (global $x (mut i32) (i32.const 0))
  (func (export "test")
 (result i32)

How to proceed the development to standalone wasm

We (I?) want to make the scala-js wasm backend generate wasm binaries that can run on stand-alone wasm runtime. However, that requires a lot of changes, and most of them are not self-contained (for example, WASI preview 1/2 support alone doesn't mean anything to users).

It's not desirable to add such non-self-contained changes to the main branch of scala-js. Only changes that are meaningful to users should be merged into the main branch.

Therefore, if we use the main branch as the target branch for stand-alone wasm development, we'll inevitably end up holding a gigantic changes locally and submitting extremely large pull requests. This puts a significant burden on reviewers and is undesirable. We want to proceed with frequent reviews and agreements among tanishiking, sjrd, and gzm0 on changes.

Wasm-Native String

I attempted to implement a String representation in our Wasm backend using an i16 array with WasmGC. However, we cannot simply switch the String representation from a JS String to an i16 array, as we still rely on JS Strings for JS interoperation. The plan is to allow these two String representations to coexist, using i16 arrays wherever possible while retaining JS Strings where necessary. This way, we should be able to keep the test suites passing, start using i16 arrays, and gradually remove JS interoperation.

To achieve this, we need to convert between JS Strings and i16 array Strings. The main idea is to

  • convert an i16 array String to a JS String when upcasting String into Any and
  • convert a JS String into an i16 array when down casting from Any to String
  • Additionally, we must handle conversions between JS Strings and i16 arrays when passing Strings between non-JS and JS classes (because we keep using JSStrings inside the JSClasses).
  • Select from JSClass fro
@tanishiking
tanishiking / bench.md
Last active July 26, 2024 05:49
Scala.js wasm backend benchmark
wasm js wasm / js
sha512 12368.78034 69356.554 0.1783361431
sha512int 12078.89027 18342.09272 0.6585339229
queens 3.299606497 9.262363477 0.3562380709
list 76.06484363 142.8739845 0.5323911412
richards 92.35085892 130.1592505 0.7095220552
cd 40129.51947 62085.45494 0.6463594332
gcbench 111415.1666 135005.6104 0.8252632331
tracerFloat 1048.518644 1280.901067 0.8185789445
@tanishiking
tanishiking / README.md
Created June 26, 2024 03:29
amm-intellij-example

amm-intellij-example

Screenshot 2023-04-21 at 17 22 49

Screenshot 2023-04-21 at 17 20 36

Not sure why ivy imports are marked red, but everything works fine 👍

diff --git a/sample/src/main/scala/Sample.scala b/sample/src/main/scala/Sample.scala
index 2bd374c..c861535 100644
--- a/sample/src/main/scala/Sample.scala
+++ b/sample/src/main/scala/Sample.scala
@@ -17,6 +17,7 @@ object Main {
def main(args: Array[String]): Unit = {
println("hello world")
+ val foo = new Foo
}

Why

WebAssembly interacts with the external environment through imported and exported functions. If it's a simple function that takes an integer and returns an integer, there is no problem.

However, when trying to use complex data types (such as strings or arrays), the limitation of WebAssembly 1.0 having only 4 types (i32, i64, f32, f64) becomes an issue.

To represent strings or user-defined types, we have to represent it using these 4 types, and there are no predefined rules on how to represent them in linear memory. The consumers of these modules need to understand how these data structures are laid out in linear memory and implement glue code accordingly.