> I think I have demonstrated that Mozilla's insistence on JS and other standards is not holding back the Web as an application platform by any means.
I don't really believe that you have. As simple aggregate counter-evidence, I will point to the popularity, performance, consumer, and developer adoption of mobile platforms.
More specifically:
> To claim that LLVM bitcode is a better target, you need to show that some JIT compilation technique implemented by LLVM/PNaCl is made impossible by JavaScript the language. JS typed arrays provide a C-friendly memory model; I don't know of anything else that's missing. I'd be happy to be educated though.
In the earlier days of Java, a common refrain was that the JVM could get better-than-native performance because it could make runtime decisions about JIT optimization. In reality, the complexity of performing this task generally outweighs the benefits compared to native code, and the JVM hasn't really succeeded outside of specific micro-optimizations. As a whole, the JVM is still slower than most native code.
Your argument seems to be predicated on a similar fallacy. The notion that since you can, in _theory_, optimize JS down to an efficient byte-code (or even AOT compile it), it is as good as an efficient and well-defined byte-code to begin with.
Yet, we have numerous historical examples of how adding more complexity between you and your intended target (eg, performance, versatility) doesn't help you achieve it. JS is an expensive and complicated intermediate.
This is equivalent to selling something at a loss and claiming you'll make it up in volume. You're adding complexity and challenge to an already challenging problem.
> You also assume that Mozilla's insistence on the DOM and other existing standards, rather than PNaCl + Pepper ...
Actually, NaCL and Pepper have nothing to do with the DOM argument. The DOM argument is just an example of where rigorious adherence to what worked for documents is not working for applications.
> Finally, you may be unaware of some limitations in NaCl. Specifically, because of the way NaCl validates code, you can't run a JIT compiler on top of NaCl. So, if you thought that NaCl would be a better target for Java/Python/Ruby/pick your favorite than JS, think again.
You are aware that Mono AOT compiles C#, correct? As does RubyMotion. JIT is not strictly necessary here.
> As simple aggregate counter-evidence, I will point to the popularity, performance, consumer, and developer adoption of mobile platforms.
This only implies that native mobile applications are more popular than mobile Web applications; it doesn't imply any particular reason why. At best, NaCl was still in the research phase when native mobile apps started to catch on, so Mozilla's refusal to get behind NaCl is irrelevant to the popularity of native mobile apps.
> In the earlier days of Java, a common refrain was that the JVM could get better-than-native performance because it could make runtime decisions about JIT optimization. In reality, the complexity of performing this task generally outweighs the benefits compared to native code, and the JVM hasn't really succeeded outside of specific micro-optimizations. As a whole, the JVM is still slower than most native code.
Are you arguing that for optimal performance, applications will always need to be distributed as native machine code? I will be disappointed if it turns out that they do, because that's how we get locked into proprietary platforms, at the CPU level if not at the OS level.
> You are aware that Mono AOT compiles C#, correct? As does RubyMotion. JIT is not strictly necessary here.
Yes, I was aware. Perhaps I overstated the importance of JIT compilation. However, I think we need more data. Some comparative benchmarks between RubyMotion (in the simulator) and a JIT-compiled Ruby (on the same Mac) would be relevant.
(Or did I, from my Throne of Skulls, send my T-1000 back in time to stop NaCl from being used by Apple on the first iPhone? Mwa-hah-hah!)
On Skatepark's planet it seems (a) Android (definitely a mobile platform, now the biggest one by users) has native-speed Dalvik apps; and (b) most developers write those in preference to hybrid or web-only apps.
Not so on Earth. Regarding (a), SpiderMonkey (and I'm pretty sure V8) beat Dalvik on same hardware on standard benchmarks. On (b), when last I checked over 70% of Google Play apps used embedded WebViews.
Only by reading "mobile" as "iOS" do the commenter from another planet's performance assertions even half-way hold up. The historical cause/effect claims just don't make sense (unless I do have backward time travel).
"In the earlier days of Java, a common refrain was that the JVM could get better-than-native performance because it could make runtime decisions about JIT optimization. In reality, the complexity of performing this task generally outweighs the benefits compared to native code, and the JVM hasn't really succeeded outside of specific micro-optimizations. As a whole, the JVM is still slower than most native code."
The JVM is a much higher-level bytecode than asm.js; asm.js is essentially just a JS encoding of LLVM. To name just one example, the JVM's memory model is composed of garbage-collected objects, while asm.js' memory model is a heap and stack as a linear array of bytes. There's a world of difference between the JVM intermediate language and the LLVM/asm.js intermediate language.
The idea that the LLVM intermediate language cannot be compiled into something as efficient as native code is trivially disproven by the fact that this is how clang works: it compiles to LLVM IR and then to native code.
"You are aware that Mono AOT compiles C#, correct? As does RubyMotion. JIT is not strictly necessary here."
Polymorphic inline caching, essential for performance of dynamic languages, requires self-modifying code.
> asm.js is essentially just a JS encoding of LLVM
This seems like a bit of a stretch; how do you encode an indirect branch in JS?
But it looks like an interesting project and I look forward to seeing what they are able to accomplish. I think it may be difficult to get native code performance while also being a secure enough sandbox to run in-process with the browser. LLVM is fast in large part because does not have the requirement of being a sandboxed attack surface. Making it safe will require performance compromises, like guards on loads and stores. Even (P)NaCl, despite its sandboxing, runs in a separate process, limiting the damage if the sandbox is broken out of. JavaScript has traditionally taken the approach of achieving safety by exposing only high-level concepts (objects, attributes, etc); if it aims to support lower-level programming idioms with low overhead that may be at odds with also being highly safe.
It's an interesting design space and I will be curious to watch the project evolve.
"This seems like a bit of a stretch; how do you encode an indirect branch in JS?"
asm.js has a switch instruction to cover most uses of indirect branches. First-class function pointers are being worked on for a future version of the spec. So this should cover the vast majority of use cases of indirect branching. If this is not enough, I could imagine an extension of JavaScript to support e.g. first-class labels. (Note that LLVM did not support first-class labels for a long time, and of course portable C does not.)
"Making it safe will require performance compromises, like guards on loads and stores."
Naturally, but this is also the case with NaCl or PNaCl, unless NaCl drops all of its software fault isolation techniques and starts relying solely on the OS sandbox. I suppose in theory one could compile asm.js in this way if it was really desired. The entry and exit points from asm.js to the DOM are fairly well defined, so in theory one could IPC them as well.
I'm personally skeptical that asm.js adds much more security risk over the JavaScript JIT that already must exist, however; the semantics of asm.js are extremely simple even compared to LLVM (as asm.js is untyped), much less the full semantics of JavaScript.
> In the earlier days of Java, a common refrain was that the JVM could get better-than-native performance because it could make runtime decisions about JIT optimization
In reality, that goal was achieved ;-)
> You are aware that Mono AOT compiles C#, correct?
Java can be compiled straight to native code too. GCJ works like that for instance. The resulting performance from binaries of such compilers is abysmal though.
C# is not really a good example because C# was designed for AOT compilation. For example, most methods in the standard library are not polymorphic and methods in C# are final by default, whereas with Java it's the complete opposite, with methods being virtual by default. With all respect to Mono and Xamarin, it's hardly an epitome of performance.
Also, right now JRuby trumps in performance just about every other Ruby implementation available, including MRI, RubyMotion, Rubinius or IronRuby.
> JIT is not strictly necessary here
For dynamic languages, if you want decent performance, all the known techniques require JIT techniques. One of the most important optimizations the JVM does is inlining of virtual method calls at runtime, something which is impossible to do ahead of time. Another important technique is tracing JIT compilation, used successfully in recent Javascript engines (except V8 I think) and by Lua [1]
All known techniques for optimizing dynamic languages or runtime-polymorphic method dispatch require recompilation of code based on changing conditions.
This ... has not been my experience. And I write a lot of high-performance native and Java code.
> For dynamic languages, if you want decent performance, all the known techniques require JIT techniques.
Then adopt a bytecode standard so that it can be JIT'd. I don't believe that NaCL is the end of the conversation, just that Mozilla has consistently prevented the conversation from starting, and refused to participate in it unless it involves Eich's JavaScript as the baseline implementation language.
So, you want a standard program representation that's amenable to JIT compilation. But why, exactly, does it need to be a bytecode format, rather than source code in a standardized language?
Let me reiterate some of the advantages of JavaScript:
* A performance arms race among JavaScript implementers has been underway for nearly half a decade now. JS thus has a head start in that area over any hypothetical language or bytecode format that might be integrated in a browser.
* JS already has first-class access to the DOM -- the API that all the browsers already have -- as well as all the other up-and-coming APIs.
* There are already JS debuggers, and with source maps, these debuggers can even be made to work with other languages that can be compiled to JS. All JS developers benefit from this, as well as all developers who use languages that compile to JS.
So basically, JS has a head start over NaCl, Dart, or any other potential "clean" replacement.
As far as I can tell, your only objection then is that there's something aesthetically wrong with using a quirky high-level language as a compilation target for other languages. To that I can only say that worse is better. We might as well get on with the business of writing great apps with the tools we have.
I don't really believe that you have. As simple aggregate counter-evidence, I will point to the popularity, performance, consumer, and developer adoption of mobile platforms.
More specifically:
> To claim that LLVM bitcode is a better target, you need to show that some JIT compilation technique implemented by LLVM/PNaCl is made impossible by JavaScript the language. JS typed arrays provide a C-friendly memory model; I don't know of anything else that's missing. I'd be happy to be educated though.
In the earlier days of Java, a common refrain was that the JVM could get better-than-native performance because it could make runtime decisions about JIT optimization. In reality, the complexity of performing this task generally outweighs the benefits compared to native code, and the JVM hasn't really succeeded outside of specific micro-optimizations. As a whole, the JVM is still slower than most native code.
Your argument seems to be predicated on a similar fallacy. The notion that since you can, in _theory_, optimize JS down to an efficient byte-code (or even AOT compile it), it is as good as an efficient and well-defined byte-code to begin with.
Yet, we have numerous historical examples of how adding more complexity between you and your intended target (eg, performance, versatility) doesn't help you achieve it. JS is an expensive and complicated intermediate.
This is equivalent to selling something at a loss and claiming you'll make it up in volume. You're adding complexity and challenge to an already challenging problem.
> You also assume that Mozilla's insistence on the DOM and other existing standards, rather than PNaCl + Pepper ...
Actually, NaCL and Pepper have nothing to do with the DOM argument. The DOM argument is just an example of where rigorious adherence to what worked for documents is not working for applications.
> Finally, you may be unaware of some limitations in NaCl. Specifically, because of the way NaCl validates code, you can't run a JIT compiler on top of NaCl. So, if you thought that NaCl would be a better target for Java/Python/Ruby/pick your favorite than JS, think again.
You are aware that Mono AOT compiles C#, correct? As does RubyMotion. JIT is not strictly necessary here.