[HN Gopher] ChowJS: An AOT JavaScript engine for game consoles
       ___________________________________________________________________
        
       ChowJS: An AOT JavaScript engine for game consoles
        
       Author : matpow2
       Score  : 110 points
       Date   : 2021-09-16 12:02 UTC (10 hours ago)
        
 (HTM) web link (mp2.dk)
 (TXT) w3m dump (mp2.dk)
        
       | supermatt wrote:
       | Just wondering aloud: Due to issues like no JIT on iOS, do
       | platforms like react-native use AOT JS compilation? If not, why
       | not?
        
         | joshum97 wrote:
         | Here's the relevant section: > In most cases, React Native will
         | use JavaScriptCore, the JavaScript engine that powers Safari.
         | Note that on iOS, JavaScriptCore does not use JIT due to the
         | absence of writable executable memory in iOS apps.
        
           | kiliancs wrote:
           | Since recently, it's possible to use Hermes
           | https://reactnative.dev/blog/2021/03/12/version-0.64
        
             | whizzter wrote:
             | iirc the Hermes has AOT'd bytecode but not real native
             | execution, from what I read they couldn't get the
             | performance up enough to offset the size cost vs their
             | bytecode and for many regular React-native apps absolute
             | performance isn't as important as not being waaay too
             | bloated.
        
       | ridiculous_fish wrote:
       | I am reading correctly that this makes deliberately unsound
       | optimizations? For example it seems to assume that `console.log`
       | or `print` will never change, and there's no deopt check?
       | 
       |  _edit:_ I missed the section titled  "Configurable
       | optimizations" where it addresses this.
        
         | whizzter wrote:
         | Not 100% on how they do everything but remember that this is
         | mostly a tool for porting JS games, soundness isn't a top
         | priority really, rather running real-world game code is and
         | that code doesn't always do too much funky stuff.
         | 
         | As such I'd guess that they have an initial pass that just
         | looks for bad patterns (eval,etc) and totally ignores
         | optimizing those, next up you look for other things (like
         | writes to named properties, if nobody ever writes to a .log
         | property it's probably fairly safe since the main task is AOT
         | compiling code). There's probably a switch-es to enable a safer
         | mode for various things where a fast-path is the default but
         | fallbacks would work,etc.
        
           | ridiculous_fish wrote:
           | Agreed, there's a lot of optimizations you can unlock if you
           | ignore JS misfeatures like modifying Array.prototype. But
           | it's important for compilers to be precise about the
           | semantics they implement. I just saw the section about
           | enabling checks for when the assumptions are violated, that's
           | a good thing to have.
        
       | puppet-master wrote:
       | Is this open source?
        
       | eyelidlessness wrote:
       | This is super interesting, and something I've been thinking about
       | from a different (non-game) angle: build tools. It's cool that
       | ESBuild/SWC (and coming soon Bun[1]) exist as fast native
       | compilers. But most of the rest of the JS tooling world is
       | written in JS, and often performs expensive (and frequently
       | redundant) parsing to AST.
       | 
       | This code is often very static, its biggest performance hit is
       | usually cold start before the JIT. And it's increasingly common
       | that the code is written in TypeScript, which has tons of static
       | analysis potential.
       | 
       | It would make a ton of sense to have a generalized AOT compiler
       | for these tools. And it would be good for the ecosystem, allowing
       | higher build performance overall while preserving portability
       | between underlying bundlers.
       | 
       | I know there's a get in touch section (which I'll avail myself
       | of), but if the author's reading I'd be curious if this is a use
       | case you're considering.
       | 
       | 1: https://bun.sh/
        
       | Leszek wrote:
       | This is very cool. The splitting of logic between startup/warmup
       | and execution is crucial here, to be able to get all that type
       | inference and those speculative optimisations without hitting the
       | limits of static analysis of the JS code. I wonder if the
       | speculative optimisations could be further strengthened by taking
       | advantage of e.g. Typescript type annotations.
        
         | Leszek wrote:
         | Though, I don't see any discussion here on failed speculation /
         | deoptimisation, and I do see discussion of disabling individual
         | optimisation passes. I guess the generated optimized code
         | assumes that all the speculative types collected during startup
         | stay stable? This makes sense in a highly controlled
         | environment like a game engine, though it makes the project
         | less amenable for general purpose use (which is fine).
        
       | sillycross wrote:
       | Interesting post. Seems similar to the approach of HPHPC for PHP,
       | where the code is first run offline in a simulated environment to
       | collect type information, and then use these speculations to
       | generate static-typed code ahead-of-time.
       | 
       | Would be interested to see a performance comparison with V8 JIT
       | (instead of V8 interpreter).
        
         | divs1210 wrote:
         | AFAIK Graal native-image also does something similar.
        
           | chrisseaton wrote:
           | For Java, yes. They're working on JavaScript and Ruby etc,
           | but not sure it's quite there yet.
        
           | sillycross wrote:
           | Java is static-typed already and only has a low degree of
           | dynamism, so the importance of doing so is much less (only to
           | reduce the initialization time I believe).
        
             | chrisseaton wrote:
             | There's a lot of interfaces and virtual calls in Java. Not
             | sure if you're considering that dynamic or not, but I would
             | would. Graal does some pretty intense whole-universe
             | points-to analysis which enables monomorphisation,
             | devirtualisation, scalar replacement, etc.
        
             | CountHackulus wrote:
             | Java is yes, but the JVM runs other things and things like
             | JRuby use the JVM bytecode for invoke_dynamic. There were a
             | few things rewritten to use that bytecode from what I
             | remember but it's been a while since I've worked in that
             | area.
        
       | whizzter wrote:
       | Fun to see, I literally wrote my thesis on the same subject a
       | bunch of years ago (Sadly didn't have an excellent option like
       | QuickJS as a base things on back then).
       | 
       | First off, unlike many AOT JS compilers that has gotten exposure
       | in the past this one actually seems realistic. The performance
       | numbers don't see overly fantastic so they actually DO seem to
       | implement JS properly rather than some overly optimisic JS-alike
       | thing (the fact that they have QuickJS as an underlying base is
       | also a plus).
       | 
       | So for porting this is probably a pretty good choice and should
       | produce something working, the bad part is that even if
       | performance is better than a plain interpreter it'll suffer
       | compared to what you can get with a proper JIT unless you tune
       | your code heavily for the constraints of a compiler like this. I
       | hope they have some seamless option for moving code to C/C++ (so
       | you can run some perf critical stuff in C via WASM on the web and
       | have an easy way to move the code to regular native code on the
       | ported platform).
        
         | [deleted]
        
         | jarrell_mark wrote:
         | Agreed, being able to compile to webassembly would be really
         | nice.
        
       | fabiospampinato wrote:
       | Super cool! I don't really work on anything that needs to be
       | executed in a no-JIT environment, but I wonder if something like
       | this could be useful in a regular browser environment too.
       | 
       | Like there must be a way to throw enough compute at the problem
       | and get back faster code, I'm thinking with an AOT step code
       | could be faster on cold executions and perhaps warm up faster too
       | and/or have a bit lower memory usage? Perhaps TS types could be
       | leveraged too. IMO that's an under explored area.
        
       | fwsgonzo wrote:
       | Very interesting and thanks for doing this! This is exactly what
       | I need for a special case in an environment where changing page
       | tables is not allowed. Static executables with AOT optimized code
       | is preferred, for performance reasons. Thanks for doing this!
       | 
       | Is there a way to interface with the C API from JavaScript now? I
       | am very familiar with QuickJS already so I know that providing
       | functionality is very easy already, but I was wondering since you
       | compile to machine code if it would make sense to allow doing it
       | the other way too?
       | 
       | Another peculiar thing on my wishlist is the ability to have a
       | leaky GC. That is, a GC that doesn't do anything at all. In my
       | special environment there's a phase where the whole environment
       | is run at the highest performance possible and then immediately
       | dropped. What actually happens is the env is reset to an
       | "initialized" state after processing ends.
       | 
       | Also, does it support Linux? I think that it does because many
       | consoles are "based" on that these days, although perhaps that is
       | abstracted away.
        
         | gavinray wrote:
         | I'm also curious about C API access from JS.
         | 
         | One thing I was hopeful about when I first read of Deno was
         | ability to interop with native code by making FFI/bindings
         | available in Rust, and then package to a native binary.
         | 
         | That didn't pan out, and I don't blame them, but I'm still
         | hoping to be able to write native executables/shared libs in
         | TypeScript and use C FFI.
        
           | reilly3000 wrote:
           | This is way outside the realm of my expertise, but I'm
           | curious how a FFI would be better than just calling
           | child_process.exec for accessing a C binary. I suppose that
           | may not be efficient inside of a game loop, but I don't
           | understand why, so long as it was done within a promise.
        
       | nvmletsdoit wrote:
       | Technically cool.
       | 
       | JS should be erased from the earth, tho. ( Expecially for gaming
       | :'D )
        
         | capableweb wrote:
         | That people can comment on random stuff on the internet is
         | technically cool.
         | 
         | But your post is so low quality that I'm wondering that maybe
         | we shouldn't be able to.
         | 
         | Try to actually write your point of view instead of just
         | farting out words with your keyboards. Let's debate and talk
         | JS, if that's what you want, but right now you're not setting
         | things up for debate, your are trying to start a flame war.
        
         | [deleted]
        
       ___________________________________________________________________
       (page generated 2021-09-16 23:01 UTC)