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

Already on GitHub? Sign in to your account

Support for asm.js #32

Open
akrymski opened this Issue Nov 27, 2013 · 7 comments

Comments

Projects
None yet
4 participants

Does the compiled JS code take advantage of asm.js support in Firefox? I don't see any "use asm.js" annotation in generated code.

See: http://jlongster.com/Compiling-LLJS-to-asm.js,-Now-Available-

I think writing LLJS is nicer & easier than writing C and compiling via ECMAScripten but the later provides asm.js support dramatically improving performance as I understand?

There's a fork with asm.js support: https://github.com/jlongster/LLJS

Owner

mbebenita commented Nov 28, 2013

We started work on LLJS before asm.js was a thing. We are planning to support asm.js in the future but the problem is that asm.js doesn't let you use high level JS constructs as LLJS does, so we would have to automatically extract parts of the program that can run in asm.js and leave the rest in JS.

Why would you want to use higher level constructs in LLJS? Personally I'd rather write a module in LLJS that I can invoke from regular JS - that's all that most would want to do - like TypeScript. The great benefit over emscripten is the easy interop with regular JS (essentially being able to invoke JS functions and exporting certain LLJS functions).

I think the ultimate goal would be to get a language like TypeScript (minus the dynamic bits) to compile to asm.js. See this discussion: http://typescript.codeplex.com/discussions/438243

Unlike TS, LLJS has done the hard bit already - heap & memory management. Adding convenient sugar such as ES6 classes is the easier bit.

Here's an example of what people are trying to achieve that LLJS+asm.js would be perfect for: http://stackoverflow.com/questions/17564972/handwriting-asm-js-how-can-you-track-javascript-objects-in-the-heap

Could we have simple interop between JS & LLJS instead that allows you to call LLJS from JS code in a way that automatically converts arguments to their typed versions (as defined in LLJS function definition)? ie a transparent bridge between JS => LLJS and back. You could even support passing of objects/hashes by mapping them to a HashTable struct in LLJS for example. This would mean there's overhead in calling unmanaged code and back, which is normal in python / C# for example. So you'd be able to execute JS callbacks from LLJS, but not create new JS objects from LLJS functions for example, which I think is to be expected and a good trade-off. After all LLJS is for writing high performance code. For example, in LLJS:

function void insert(Map *document, function *callback) { // a Map is now an instance of LLJS Map struct }

which can be called from regular JS as follows: db.insert({ id: 1, value: 2 }, function(err, success) { ... })

For example I've tried writing an in-memory database with BTrees for indices in JS for my webmail project (www.post.fm) and obviously the performance isn't great as you don't get proper structs + pointers.

Owner

mbebenita commented Nov 29, 2013

You don't necessarily want to use higher level constructs in LLJS, but if you want it to act as a bridge between JS and asm.js code it needs to be able to talk both JS and asm.js. The discussion in that thread is interesting, and it's exactly the same problem we ran into. Our motivating use case for LLJS was to build fast and space efficient data structures, but the biggest problem there is dealing with memory management. There is no way to wrap a LLJS C like data structure with JS friendly API. Freeing malloc'ed memory requires that we detect when JS objects are GC'ed, and that is not possible ATM.

The other way around, hanging on to JS object references from the asm.js heap can be done with a shadow heap and other table based tricks.

The JS <-> LLJS <-> asm.js interface needs to be very efficient, otherwise it doesn't pay off to migrate small parts of your program to LLJS/asm.js.

Instead of freeing malloc'ed memory when JS objects are GC'ed, why not simply return clones of those objects as hashes? If you export an LLJS function, then it must return a basic JS-compatible type (a primitive or a Map) never a pointer to a struct. Or you could let the compiler serialize structs to JSON and de-serialize them in JS - as a way of passing structs around (this is the current recommended way for cloning JS objects anyhow).

Equally passing JS objects into LLJS should convert them to a Map data-structure with boxed objects of type String & Number & Function allocated on the heap. That's the most inefficient bit as type information is not available to the compiler, but I don't think it's horrible anyhow as that's the fastest way to clone JS objects on most browsers.

I don't think such an interface will be inefficient - python and others have a lot more work to do when calling into C code. I think the use case is ultimately writing whole libraries in LLJS, not a single function that is called in a loop (that's what straight asm.js can be used for). A 3D engine or a NoSQL database could be good examples, where the overhead of calling into those "native" libs isn't an issue at all. And frankly if you're expecting passing hashes around to be fast - you're doing it wrong. You can always pass numeric IDs into asm.js code if that's your overhead.

jslegers commented Jun 22, 2017 edited

Being able to write code in LLJS and convert is to asm.js sounds awesome to me. However, with no new submits in 5 years, it looks like LLJS has been abandoned. Right?

Does any of you know any alternative approaches for writing code in either ordinary JavaScript or a language closely related to JavaScript and convert it to asm.js?

I was intrigued by both TypeScript or Flow, but the core dev team of neither language seems to show any interest whatsoever in offering the ability to convert it to asm.js. Also, This project appears to have been abandoned. And with no activity on LLJS in 5 years either, I'm not sure where else to look.

Those also interested in converting staticly typed variations of JavaScript to asm.js, WebAssembly or C might want to take a look at ThinScript or TurboScript.

ThinScript compiles to JavaScript, WebAssembly, and C. TurboScript compiles only to JavaScript and WebAssembly.

Both languages have been inspired by TypeScript.

I'd like to thank @RReverser for pointing me in the direction of these two languages.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment