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

GHCJS for the JVM #472

Closed
mmhelloworld opened this issue Mar 3, 2016 · 6 comments
Closed

GHCJS for the JVM #472

mmhelloworld opened this issue Mar 3, 2016 · 6 comments

Comments

@mmhelloworld
Copy link

Hi,

First, thank you all for this cool project! It is really great that Haskell can be compiled to JS and it also enables Haskell running on the JVM via Nashorn, Java's JavaScript engine.

The following program can be compiled with GHCJS and run on the JVM via jjs, Nashorn JavaScript runner:

{-# LANGUAGE JavaScriptFFI #-}

module Main where

foreign import javascript unsafe "console={log: function(s) { java.lang.System.out.print(s); }}"
  setupConsole :: IO ()

foreign import javascript unsafe "java.lang.System.exit($1)"
  sysexit :: Int -> IO ()

main = do
  setupConsole
  putStrLn "Hello from Haskell!"
  sysexit 0
$ ghcjs -o Main Main.hs
[1 of 1] Compiling Main             ( Main.hs, Main.js_o )
Linking Main.jsexe (Main)

$ which jjs
~/bin/jdk/bin/jjs

$ jjs Main.jsexe/all.js
Hello from Haskell!

It works! As we can see from the above code, we have to define console.log as Nashorn doesn't provide one by default. The main issue is that the JVM keeps on running so I had to add sysexit to terminate the JVM. I looked up GHCJS sources and found this flag GHCJS_TRACE_SCHEDULER from thread.js. With that flag enabled, I can see that the following lines keep on repeating which seems to be the cause for the JVM not exiting:

sched: <no thread> -> scheduling next main loop wakeup
sched: <no thread> -> sched: scheduler: 0
sched: <no thread> -> sched: no other runnable threads
sched: <no thread> -> sched: pausing
sched: <no thread> -> scheduling next main loop wakeup
sched: <no thread> -> sched: scheduler: 0
sched: <no thread> -> sched: no other runnable threads
sched: <no thread> -> sched: pausing
sched: <no thread> -> scheduling next main loop wakeup
sched: <no thread> -> sched: scheduler: 0
sched: <no thread> -> sched: no other runnable threads
sched: <no thread> -> sched: pausing

Any idea how to fix this so that the JVM exits normally? Are there any other things that I need to be aware of to make this work for the JVM?

P.S: Sorry if this is not the right forum to ask these kind of questions. I have also posted this on StackOverflow here but haven't got any answer so far.

@luite
Copy link
Member

luite commented Mar 3, 2016

Oh I was planning to answer your question there, but it's been a rather long day.

There is some detection of what platform the code is running on:
https://github.com/ghcjs/shims/blob/4df1808d03117ddcd45f276f0ddd85c73e59506a/src/platform.js#L17-L50

And this is used to exit the process:
https://github.com/ghcjs/shims/blob/4df1808d03117ddcd45f276f0ddd85c73e59506a/src/thread.js#L1097-L1119

Defining GHCJS_BROWSER disables the platform detection and just leaves the code paths intended for the browser. There is other platform specific code, for example file i/o and child process control are node.js specific and use h$isNode.

@mmhelloworld
Copy link
Author

Thank you! After removing the flag GHCJS_BROWSER for ghcjs and modifying the h$exitProcess to call java.lang.System.exit(0), the JVM exits correctly. Can I send a pull request for this? I am going to add h$isJvm platform detection similar to others.

@3noch
Copy link

3noch commented Mar 4, 2016

This is just amazing. 😲

@mmhelloworld
Copy link
Author

@3noch thanks!

@luite How do I test my changes in shims? I've checked out both shims and ghcjs locally and I have read "Hacking GHCJS" wiki page but I am still missing something that I couldn't get my changes in shim to integrate with ghcjs. Any suggestions?

@luite
Copy link
Member

luite commented Mar 4, 2016

See the shims subdirectory in your ghcjs library directory (ghcjs --print-libdir). If you did a development install (ghcjs-boot --dev) it's a git repo, otherwise it's just a plain subdirectory.

mmhelloworld added a commit to mmhelloworld/shims that referenced this issue Mar 5, 2016
@mmhelloworld
Copy link
Author

Awesome! It works finally. I have created a pull request here with shims for the JVM. Thank you for your help!

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

3 participants