f15 Subj : Re: Whats about a JIT? To : Clemens Eisserer From : Brendan Eich Date : Sat Oct 18 2003 11:32 am Clemens Eisserer wrote: > Hi again! > >> Well, there is already at least one JIT for JS, that is a JVM running >> Rhino which is a pure Java implementation based on early SpiderMonkey >> code. Rhino by default translate JS into JVM byte code which is then >> is executed diectly by JVM. > > > Wow, Rhino is faster than SpiderMonkey, that beats all :-) > > Of course, if the JS is converted to Java-Bytecode before execution, the > code can benefit from the Sun-JIT, which is the best JIT I know! Those two paragraphs are not unrelated, as the "Of course" seems to imply. The reason for Rhino beating SM is precisely the great Java JITs (there are others than Sun's). > Hmm, another point is, that it would be even hard to implement a working > JIT. Building a fast JIT is another thing :( > > I think about a soft-jit which does only fast and easy optimizations, > because most JSs run only < 5 times would be the best ide. JS has few "easy optimizations". Because types are dynamic, the JIT must be willing to compile and cache code specialized to assume that a loop control variable, e.g., is always a 32-bit integer. Consider the recent example (a bogo-benchmark, see below, but never mind): function myFunc() { var time = (new Date()).getTime(); var length = 0; for (var i = 0; i < 200000; i++) length += String(i).length; time = (new Date()).getTime() - time; print("time: "+time+"ms length="+length); } (Note that I've eliminated the unused vars sub and string, changed while to for as indicated by canonical [init;cond;update] for-loop structure, and used i++ instead of i = i + 1.) The JIT will need to do enough flow graph analysis to see that i is set only in the [init] and [update] parts of the for loop, that it starts at 0, and that the [cond] part constrains i to be <= 200000. Given that analysis, it can then generate native machine code to optimize i to be loaded and stored as a native 32-bit integer. Similar things could be done for length and time, although whether they are implemented using SpiderMonkey bytecode and jsvals, or via native double types, probably doesn't matter for performance. Also, the JIT may want to cache code that knows that String(i) calls the standard String class constructor as a type conversion function. But if it can assume that String(i) converts an integer in [0,200000) to its string literal form (possibly with a runtime check before the loop, which uncaches the specialized code and falls back on JS bytecode, if the String global function object has been redefined by some script that ran previously against the global object), then the JIT can and should partially evaluate String(0).length, String(1).length, ... String(10).length, etc. -- and fully evaluate the loop at compile time. So we need a better benchmark. See bug http://bugzilla.mozilla.org/show_bug.cgi?id=121414. Note also that although a JS JIT might be "nice to have", it hardly seems like a high priority for all the JS embeddings with which I am familiar, compared to things like better GC implementation. Most JS embeddings do not spend long in the JS interpreter. They don't run explosive combinatorial or numerical code. Also: given Mono, Parrot (the new Perl/Python/Ruby dynamic language JIT'ing runtie, under construction), and other efforts I'm forgetting, why would anyone want to do an ad-hoc JIT for SpiderMonkey? Perhaps licensing requirements may force the issue, but I'd much rather see someone check out Parrot, and do a SpiderMonkey front end to Parrot back end if that makes sense. /be . 0