I recently started some web development, with ASP.NET and some Javascript, and something is confusing me alot.
I always read that JavaScript used to be interpreted until JIT slowly made it so chunks are compiled to machine code (which made browsers alot faster).
This makes no sense to me. How can JavaScript compile to native machine code, if traditional JavaScript apps don't target the machine/CPU to begin with?
I understand if an electron.js app gets compiled to machine code using the NodeJS runtime. That I get. Because it natively compiles to machine code and as far as I understand it, doesn't run in a browser.
If traditional JavaScript apps run in a browser, why must it be compiled to machine code? The browser is responsible for running the code, not the CPU. The CPU runs the browser itself. I actually don't see how the native OS can influence anything that happens in the browser at all or vise versa. Seems like a security issue as well.
Sorry if it's a stupid question, but I can't find any resource that will go beyond saying "Javascript uses JIT"
Thank you!
Lauren
At the end of the day, the CPU has to run the code.
JIT-compiling it down to machine code is one way to make that faster.
How can JavaScript compile to native machine code, if traditional JavaScript apps don't target the machine/CPU to begin with?
It is not "Javascript" that is doing it, it is the browser (or rather, the Javascript execution engine inside the browser), and since it is "JIT" it knowns exactly which CPU to target (this is not done in a generic way, this is done for the specific CPU that the browser is currently running on).
So, yes, there is some mismatch, since Javascript will not use low-level primitive types that the CPU can work with directly, which is why there is a lot of indirection and speculative type inference guess-work. The resulting machine code is much different than you would get from hand-coded assembly, but it can still be a net positive. To help with this, WASM was developed, which is closer to "normal" machine code.
Other intermediate, non-CPU specific formats like JVM bytecode or CLR bytecode or LLVM bitcode are in a similar situation (in that can also be compiled to machine code they do not themselves target directly) -- but they have been "lowered" already from language source code to something close to machine code.
Seems like a security issue as well.
Yes, it can be. The browser has to be careful in what it is doing here, and the OS should sandbox the browser as much as possible.
Executing instructions is easier than running an interpreter, and JIT seeks to take advantage of this for a performance boost. All programs running on your computer become machine code at some point, the only question is which instructions are be executed.
let x=0;
for (let i=0;i<100;++i) {
x+=2;
}
Since it is clear that there are no side effects in a block of code like this, it is faster to compile instructions directly, rather than interpreting each line.
// NIOS 2 assembly, sorry its the only one i know
movi r2,0
movi r3,0
movi r4,100
loop:
addi r2,2
addi r3,1
blt r3,r4,loop
Executing this will be faster than executing the parsing logic for each individual instruction.
TLDR: All programs are always running CPU instructions, so it is faster to minimize the number of instructions by skipping the parsing stage when possible
Related
The major JavaScript engines of web browsers and nodeJS have had just-in-time compilers for years.
I was just watching a video on Compiler Explorer showing the assembly code output by many compilers for various CPUs.
This reminded me that I've been curious about the code generated by the JS engines' jits.
Do any of those engines have ways for us to see that low-level generated code?
(If this is out of place on SO please feel free to migrate it to the correct SE site.)
For V8, there is a flag --print-opt-code, which prints generated optimized assembly code for each function that gets optimized. Note that functions only get optimized when they're "hot", not right away, so for a short "hello, world" style program the flag won't print anything. You can make functions "hot" by calling them a lot.
In older versions, there was a --print-code flag for unoptimized code, but since the baseline (non-optimizing) compiler has been replaced by an interpreter, there is no unoptimized code any more. You can print the generated bytecode with --print-bytecode.
If you're using Chrome, you can specify flags to be passed to V8 by wrapping them in --js-flags, e.g. --js-flags="--print-opt-code".
One thing you can always do is interrupt your program while it's running, using a debugger.
If it's spending most of its time in JIT-compiled code, then chances are the current instruction-pointer value (RIP) will be inside some JIT-compiled machine code, which your debugger will disassemble for you. (Or at least the part after the current RIP: x86 machine code uses variable-length instructions, so there's no reliable way to go backwards. You might single-step until you reach a backwards branch to get to the top of a loop.)
But without any way to figure out which function name you're seeing JITed asm for, this is probably not very useful unless you only have one hot loop (e.g. in an artificial test / microbenchmark).
Having the JIT engine print the asm as it generates it (#jmrk's answer) is much more usable; I only mention this technique because it works without any support from the JIT engine, so it can work on anything.
Is it possible to compile assembly or x86/x64 code to JavaScript?
Or asm -> llvm-ir -> js?
UPD:
So my final question is:
I have asm listing (excerpt)
push %rbp
mov %rsp,%rbp
sub $0x10,%rsp
mov 0x5e41(%rip),%eax
lea 0x601a(%rip),%rdx
cltq
movzbl (%rdx,%rax,1),%eax
test %al,%al
jne loc_0040121b
movl $0x0,-0x4(%rbp)
jmp loc_00401206
Can I run it in browser without modifications with help of emscriptten or any other tool?
I want to run executable(small program) in browser without access to original source code
So, you actually don't want to compile assembly to js, as you don't have the source. Which is good, as it doesn't make any sense anyway, asm is not like high-level languages having some variables and affecting platform trough some API, in asm basically any instruction can change state of platform a lot, and "variables" is the whole accessible memory.
A way how it makes sense:
You want to execute some machine code already prepared for some target platform (CPU + OS).
"In browser" (directly) it's not possible, browser doesn't process machine code of that CPU, neither does it provide the OS API/ABI/syscall. That executable needs the target OS, so it's instructions have the desired effect.
You can run emulator of that OS written in JS, and run the binary inside the emulator. Search for example for web-online dosbox (running old DOS games in browser, with reasonable speed and not-worst-accuracy, most of them actually being playable and looking as they should).
How to create emulator of your target platform is a bit too broad question and takes somewhat more effort, like decades in some cases. But you may be lucky, that there already exists emulator of your target OS, and has JS port and license allowing you to use it.
There's also second option: if it's really small program, it would be very likely simpler to rewrite it from scratch in JS and in OS/browser agnostic way.
edit: about machine code -> llvm ir:
Let's say simply "no". (although probably like 50% of machine code would be reasonably easy to translate, but the other half would require the translator to fully understand what the code does, which is fully NP problem (or not possible at all)).
I have a quite big JavaScript for HTML page for a device.
But it's a bit slow. I tried compressing JavaScript files but it's still not satisfactory.
So I was thinking, is it possible to make it as a Just in Time that is compiled converted to machine code and use it? (Hope my understanding is correct) I use a WebKit based browser.
Anybody please who have done this, please provide links to "How To" pages or info about the same.
Both Safari and Chrome do JIT compilation of Javascript already. In fact, the only browser in widespread use that doesn't is IE8 and earlier. This is one of the main reasons why IE8 is so much slower than the competition these days.
But reading between the lines of your question, my guess is that you're not quite understanding what JIT compilation is. JIT compilation happens on the browser; you don't need to change your code in any way at all in order for the browser to be able to do JIT compilation on it for you.
What it sounds like you're actually thinking of is bytecode compilation, such as Java does. This bytecode is effectively a half-way compiled language which is then itself JIT compiled when you run the program. If this is what you're thinking of, I can confirm that this is not an option for browser-based Javascript code.
Google have been toying with a technology called 'Native Client' (NaCl), which would allow you to provide compiled code to the browser, but this is not available yet except in development versions of Chrome.
In any case, compiling may make your code run quicker, but it wouldn't solve the fundamental issue of why it's running slowly, which is likely to be a far better thing to resolve. (even compiled code will perform badly if it has bottlenecks; compilation in itself doesn't magically make slow code better)
If you want to find out why your script is running slowly, I recommend using a profiling tool, such as the one built into Firebug or Chrome's Developer Tools. This will help you identify the parts of your code which are running slowly.
You could also try the YSlow tool, which can also give useful information on javascript performance.
You also state that you've compressed your script to try to get it to go faster. Compressing the script will help it to download quicker (because it's a smaller file), but it won't do anything for the speed that the code runs at.
Is it possible to run JavaScript code in parallel in the browser? I'm willing to sacrifice some browser support (IE, Opera, anything else) to gain some edge here.
If you don't have to manipulate the dom, you could use webworkers ... there's a few other restrictions but check it out # http://ejohn.org/blog/web-workers/
Parallel.js of parallel.js.org (see also github source) is a single file JS library that has a nice API for multithreaded processing in JavaScript. It runs both in web browsers and in Node.js.
Perhaps it would be better to recode your JavaScript in something that generally runs faster, rather than trying to speed up the Javascript by going parallel. (I expect you'll find the cost of forking parallel JavaScript activities is pretty high, too, and that may well wipe out any possible parallel gain; this is common problem with parallel programming).
Javascript is interpreted in most browsers IIRC, and it is dynamic on top of it which means it, well, runs slowly.
I'm under the impression you can write Java code and run it under browser plugins. Java is type safe and JIT compiles to machine code. I'd expect that any big computation done in Javascript would run a lot faster in Java. I'm not specifically suggesting Java; any compiled language for which you can get a plug in would do.
As an alternative, Google provides Closure, a JavaScript compiler. It is claimed to be a compiler, but looks like an optimizer to me and I don't know much it "optimizes". But, perhaps you can use that. I'd expect the Closure compiler to be built into Chrome (but I don't know for a fact) and maybe just running Chrome would get your JavaScript compiler "for free".
EDIT: After reading about what about Closure does, as compiler guy I'm not much impressed. It looks like much of the emphasis is on reducing code size which minimizes download time but not necessarily performance. The one good thing they do in function inlining. I doubt that will help as much as switching to a truly compiled langauge.
EDIT2: Apparantly the "Closure" compiler is different than the engine than runs JavaScript in Chrome. I'm told, but don't know this for a fact, that the Chrome engine has a real compiler.
Intel is coming up with an open-source project codenamed River Trail check out http://www.theregister.co.uk/2011/09/17/intel_parallel_javascript/
I’ve noticed that after making a change to a javascript file, clearing the cache, and reloading; one function in particular runs in about 90ms, the next time I load the page, it runs in 40ms, the next time I run it, it runs in 20ms … then never gets faster.
It kind of looks like IE is compiling my javascript and caching that compiled version somewhere, similar to how SQLServer processes queries.
Is that what is happening?
Does anybody know where I can find a clarification of how browsers process javascript?
You may want to check out Eric Lippert's comment to Peter Torr's blog post Compiled, interpreted, whatever:
JScript Classic acts like a compiled language in the sense that before any JScript Classic program runs, we fully syntax check the code, generate a full parse tree, and generate a bytecode. We then run the bytecode through a bytecode interpreter. In that sense, JScript is every bit as "compiled" as Java. The difference is that JScript does not allow you to persist or examine our proprietary bytecode. Also, the bytecode is much higher-level than the JVM bytecode -- the JScript Classic bytecode language is little more than a linearization of the parse tree, whereas the JVM bytecode is clearly intended to operate on a low-level stack machine.
The post and the comment are from September 2003, but judging from Ralph Sommerer's On JavaScript performance in IE8 post, they haven't changed much in the underlying JScript engine:
Unless the JavaScript engine used in IE (and elsewhere) employs some sort of compilation to native code, it will always lag behind its competitors with respect to performance. From what I gather in their Channel9 appearance they have made improvements in bytecode execution, but their main targets were JavaScript native objects (Array, String, ...) and JavaScript-DOM-interaction.
IE8 is not open-source, so one can only make hypotheses; however, open-source browsers (such as Chromium, Firefox, Webkit) do work roughly as you say, as do many other interpreters in non-browser and not necessarily JS settings (compile new sources when first seen or reloaded, cache or save the compiled version for faster execution in the future), so it seems very reasonable that IE's Javascript approach should be very much the same, as you surmised.
I know you asked about IE8, but here is V8 - Google's engine. Includes videos on how V8 works.
http://code.google.com/p/v8/