Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running wasm modules in wasmer #575

Closed
dazraf opened this issue Sep 24, 2021 · 6 comments
Closed

Running wasm modules in wasmer #575

dazraf opened this issue Sep 24, 2021 · 6 comments

Comments

@dazraf
Copy link

dazraf commented Sep 24, 2021

Hi,

I'm working on integrating JVM languages with the wasmer runtime and CLI and I'm trying out TeaVM to this end. The intention is to use wasmer as a general purpose wasm execution library so that wasm modules, written in JVM languages, can be hosted in server-side processes in a language agnostic manner.

The challenge I'm facing is what to do with TeaVM's wasm-runtime.js. Does anyone have an experience of attempting to achieve the same?

Thank you,
dazraf

@jcaesar
Copy link

jcaesar commented Sep 26, 2021

Heh, I started trying this last week.

About the imports: those are normally provided by JavaScript, and normally you'd have to make an equivalent implementation in your host system (Rust or whatever you're using wasmer through).
But here

  • I've never seen logString being called, so maybe you can just get away with stubbing it out.
  • There's also this .c file with a purpose I don't understand - maybe it could be used instead?

Short demo of what I have so far: https://github.com/jcaesar/wastea
So I can invoke an exported function, and have that invoke an imported function and pass around some ints, but trying to invoke System.out.println crashes. :(

Further discussion: #568 (comment)

@konsoletyper
Copy link
Owner

I've never seen logString being called, so maybe you can just get away with stubbing it out.

It's called to print uncaught exceptions. Run main() method that contains throw new Exception() and see the result. You can look at reference implementation in JS to see how TeaVM objects are laid out:

1.Every object has a 32-bit header (bit 31 is a GC mark bit, bit 30 is a old generation flag, bit 29 reserved, bits 28-0 are address of class divided by 8), you can simply skip it.
2. java.lang.String class has two fields, first is pointer to array of chars.
3. Arrays is an object (so you need to skip 4 bytes) with first 32 bits of its content used to encode length, further bytes are data.

But you can take existing exports that parse strings in heap for you (i.e. teavm_stringData, teavm_arrayLength, teavm_charArrayData).

There's also this .c file with a purpose I don't understand - maybe it could be used instead?

No, it's for debugging purposes only. I lacked full gdb power when developed initial wasm implementation (not checked current state of wasm debuggers), so came up with idea to generate C code right from wasm AST I generate to produce wasm binaries. You can see .wasm.c files generated together with .wasm file if you enable generation of debug information in TeaVM.

So I can invoke an exported function, and have that invoke an imported function and pass around some ints, but trying to invoke System.out.println crashes. :(

@jcaesar did you try writing your logic in main method and calling it instead of running custom export?

@dazraf
Copy link
Author

dazraf commented Sep 26, 2021

@jcaesar thank you for the project link and reply. Great work.
@konsoletype thank you for your guidance and your superb work with TeaVM. A fantastic achievement.

I'm a newcomer to wasm, so please forgive any misunderstandings I still have. I turned to TeaVM after my initial search and trial with GraalVM failed - their implementation is far too unstable. My work is specifically in the area of decentralised multi-network ledgers and I'm looking at wasm as a common bytecode/vm for contract definition and execution. My firm's clients vary from startups to tier-1 financial services - hence support for a wide range of languages (including JVM languages) being a key requirement.

From my naive perspective (and with recollections of previous interface issues such as Java JNI vs Microsoft RNI) it seems to me that what may be incredibly useful for the entire wasm community is a standard 'core' ABI, containing common functions (each ABI has a logging facility, as an example). That way wasm modules built from disparate languages can co-exist in the wide range of application environments.

I recently found WASI which is a subgroup of the WebAssembly CG has an extensive (very large?) ABI that's documented here. I wonder if there's any scope in TeaVM to support WASI? Are there alternative efforts to standardise?

Thanks and regards,
dazraf

@jcaesar
Copy link

jcaesar commented Sep 26, 2021

did you try writing your logic in main method and calling it instead of running custom export?

Ty, That works, even if I leave my logic as is and just call the empty main method first.
That would be another point on my wish/todo-list: do whatever needs doing in (start …), make calling (export "start") optional (esp. since that first requires allocating a String[] for argv).

It's called to print uncaught exceptions. Run main() method that contains throw new Exception() and see the result.

That I cannot reproduce.

I just get some nasty stack trace.
Error: RuntimeError { source: Trap(UnreachableCodeReached), wasm_trace: [FrameInfo { module_name: "<module>", func_index: 112, function_name: None, func_start: SourceLoc(15500), instr: SourceLoc(15734) }, FrameInfo { module_name: "<module>", func_index: 12, function_name: None, func_start: SourceLoc(3119), instr: SourceLoc(3729) }, FrameInfo { module_name: "<module>", func_index: 119, function_name: None, func_start: SourceLoc(16937), instr: SourceLoc(16958) }, FrameInfo { module_name: "<module>", func_index: 122, function_name: None, func_start: SourceLoc(17032), instr: SourceLoc(17067) }, FrameInfo { module_name: "<module>", func_index: 118, function_name: None, func_start: SourceLoc(16573), instr: SourceLoc(16795) }, FrameInfo { module_name: "<module>", func_index: 281, function_name: None, func_start: SourceLoc(42126), instr: SourceLoc(42129) }], native_trace:    0: <unknown>
   1: <unknown>
   2: <unknown>
   3: <unknown>
   4: <unknown>
   5: <unknown>
   6: <unknown>
   7: <unknown>
   8: <unknown>
   9: <unknown>
  10: <unknown>
  11: <unknown>
 }
I guess I'll have to find out how to use source maps in wasmer (if that's even possible yet…).

@dicej
Copy link

dicej commented Jul 25, 2022

In case it's of interest, I've recently been experimenting with using TeaVM to build Spin apps: https://github.com/dicej/spin-http-java. Spin is based on Wasmtime rather than Wasmer, but model is generally the same.

I expect that once the component model is fully implemented it will be pretty straightforward to host TeaVM modules in non-browser contexts by virtualizing things like teavm.logString. One could even write a general-purpose TeaVM-to-WASI virtualizer that works for any TeaVM-generated module -- without needing to add specific support to TeaVM itself.

One thing that would need to change in TeaVM is to make the heap offset and data segment offset configurable so that there is room to allocate the buffers needed for canonical ABI marshalling of e.g. strings, lists, etc.

@dicej
Copy link

dicej commented Aug 5, 2022

See #610 for a patch which adds a WASI target, suitable for building modules which Wasmer, Wasmtime and other WASI-compatible runtimes can execute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants