Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Wasmer Things: An Upside Down Guide To WebAssembly (Wasm I/O)

Wasmer Things: An Upside Down Guide To WebAssembly (Wasm I/O)

Edoardo Vacchi

March 27, 2023
Tweet

More Decks by Edoardo Vacchi

Other Decks in Programming

Transcript

  1. @evacchi @mastodon.social Transpilers • CoffeeScript (2009) • Dart (2011) •

    TypeScript (2012) • AtScript (2014) • BabelJS (2014)
  2. @evacchi @mastodon.social Transpilers • CoffeeScript (2009) • Dart (2011) •

    TypeScript (2012) • AtScript (2014) • BabelJS (2014) Elm Scala.js Haxe ClojureScript React/JSX Svelte
  3. @evacchi @mastodon.social JVM • Source Code compiled into Bytecode •

    Stack-based VM • Client / Server • Bytecode “interpreted” by the JVM (Interpreter + JIT)
  4. @evacchi @mastodon.social CLR (.NET) • Source Code compiled into Bytecode

    (CIL) • Stack-based VM • Client / Server • Bytecode “interpreted” by the CLR (Interpreter + JIT)
  5. @evacchi @mastodon.social Bringing the Web up to Speed with WebAssembly

    (PLDI’17) • JVM bytecode verification takes more than 150 pages to describe (WebAssembly fits on one page) • It took a decade of research to hash out the details of correct JVM verification • JVM, CIL, Android Dalvik, allow bytecode to create irreducible loops and unbalanced locking structures, features which usually cause optimizing JITs to give up “
  6. @evacchi @mastodon.social What About LLVM ? “The LLVM Project is

    a collection of modular and reusable compiler and toolchain technologies. “Despite its name, LLVM has little to do with traditional virtual machines. “The name "LLVM" itself is not an acronym; it is the full name of the project. llvm.org
  7. @evacchi @mastodon.social Bringing the Web up to Speed with WebAssembly

    (PLDI’17) We investigated reusing another compiler IR which has a binary format. In fact, LLVM bitcode is the binary format used by PNaCl. “
  8. @evacchi @mastodon.social Bringing the Web up to Speed with WebAssembly

    (PLDI’17) Disadvantages with LLVM bitcode in particular are that 1. it is not entirely stable, 2. it has undefined behavior which had to be corrected in PNaCl, 3. it was found to be less compact than a stack machine, 4. it essentially requires every consumer to either include LLVM or reimplement a fairly complex LLVM IR decoder/verifier, and 5. the LLVM backend is notoriously slow. “
  9. @evacchi @mastodon.social Bringing the Web up to Speed with WebAssembly

    (PLDI’17) Other compiler IRs have similar, sometimes worse, properties. In general, compiler IRs are better suited to optimization and transformation, and not as compact, verifiable code formats. “
  10. @evacchi @mastodon.social WebAssembly [...] offers • compact representation, • efficient

    validation and compilation, and • safe low to no-overhead execution. Bringing the Web up to Speed with WebAssembly (PLDI’17) “
  11. @evacchi @mastodon.social Rather than committing to a specific programming model,

    WebAssembly is • an abstraction over modern hardware • making it language-, hardware-, and platform-independent, • with use cases beyond just the Web. Bringing the Web up to Speed with WebAssembly (PLDI’17) “
  12. @evacchi @mastodon.social Supported languages Language Browser Other WASI Rust ✅

    ✅ ✅ C++ ✅ ✅ ✅ C ✅ ✅ ✅ Swift ✅ ✅ ✅ Zig ✅ ✅ ✅ AssemblyScript ✅ ✅ ✅ https://www.fermyon.com/wasm-languages/webassembly-language-support
  13. @evacchi @mastodon.social Language Browser CLI WASI Go ✅ ✅ ✅

    Erlang (BEAM) ⏳ ⏳ ⏳ Haskell ✅ ✅ ✅ Lisp ⏳ ⏳ ⏳ Lua ✅ ❌ ❌ Perl ✅ ❌ ❌ Python ⏳ ✅ ✅ Ruby ✅ ✅ ✅ Java ⏳ ⏳ ⏳
  14. @evacchi @mastodon.social A “Structured” Stack Machine • WebAssembly code can

    be considered a structured stack machine; • a machine where most computations use a stack of values, • but control flow is expressed in structured constructs such as blocks, ifs, and loops. • virtual instruction set architecture (virtual ISA) https:/ /github.com/WebAssembly/design/blob/main/Rationale.md
  15. JVM Bytecode int exp(int); Code: 0: iload_1 1: iconst_2 2:

    iadd 3: iconst_3 4: imul 5: ireturn ( x + 2 ) * 3 (local.get $x) (i32.const 2) i32.add (i32.const 3) i32.mul
  16. Wasm Bytecode (local.get $x) (i32.const 2) i32.add (i32.const 3) i32.mul

    (i32.mul (i32.add (local.get $x) (i32.const 2)) (i32.const 3)) ( x + 2 ) * 3 Wasm Text Format (WAT)
  17. @evacchi @mastodon.social Bringing the Web up to Speed with WebAssembly

    (PLDI’17) • JVM, CIL, Android Dalvik, allow bytecode to create irreducible loops and unbalanced locking structures, features which usually cause optimizing JITs to give up • In contrast, the structured control flow of WebAssembly makes validation and compilation fast and simple • and paves the way for structured locking and exception constructs in the future “
  18. Unstructured Control Flow void print(boolean x) { if (x) {

    System.out.println(1); } else { System.out.println(0); } } void print(boolean); Code: 0: iload_1 1: ifeq 14 4: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 7: iconst_1 8: invokevirtual #13 // Method java/io/PrintStream.println:(I)V 11: goto 21 14: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 17: iconst_0 18: invokevirtual #13 // Method java/io/PrintStream.println:(I)V 21: return
  19. @evacchi @mastodon.social Structured Control Flow (module ;; import the browser

    console object, you'll need to pass this in from JavaScript (import "console" "log" (func $log (param i32))) (func (i32.const 0) ;; change to positive number (true) if you want to run the if block (call 0)) (func (param i32) local.get 0 (if (then i32.const 1 call $log ;; should log '1' ) (else i32.const 0 call $log ;; should log '0' ))) (start 1) ;; run the first function automatically ) https://developer.mozilla.org/en-US/docs/WebAssembly/Reference/Control_flow/if...else
  20. @evacchi @mastodon.social Structured Control Flow (module (type (;0;) (func (param

    i32))) (type (;1;) (func)) (import "console" "log" (func (;0;) (type 0))) (func (;1;) (type 1) i32.const 1 call 0) (func (;2;) (type 0) (param i32) local.get 0 if ;; label = @1 i32.const 1 call 0 else i32.const 0 call 0 end) (start 1))