With an interpreter, the JavaScript source is compiled to some bytecode, then the bytecode is executed in a loop, instruction by instruction.
With a compiler (not jit), the whole bytecode would be further fully compiled to some C apis before being executed, making it effectively an "ahead of time" compilation.
The catch is : since the code never was executed, there is very little static information to work with, so the compiled output is often just a giant unrolled interpret loop. The compiled version can be like 10% faster on very hot JavaScript loops compared to the interpreted version.
> With a compiler (not jit), the whole bytecode would be further fully compiled to some C apis before being executed, making it effectively an "ahead of time" compilation.
This hinges at least on the question of what you mean by "the whole bytecode". If the source is made up of N functions, and you compile all N functions ("the whole bytecode" of the entire program) to machine code before you know if any of them will be executed: Yes, I'd agree that that's a form of ahead of time compilation. Is this what full-codegen used to do?
On the other hand, if the source is made up of N functions, and you only compile "the whole bytecode" of each of them to machine code one by one, only those that will actually be executed, and only when you are preparing to actually execute them: That's JIT compilation. Even if it is the very first execution (i.e., you have never even interpreted), even if the compilation doesn't use fancy profiling or sophisticated code generation or whatnot.
> since the code never was executed, there is very little static information to work with, so the compiled output is often just a giant unrolled interpret loop
I think you mean "dynamic" information. And "the compiled output is often just a giant unrolled interpret loop" is pretty much the definition of what a baseline JIT compiler produces.
By "the entire thing", do you mean an entire file, without knowing if all functions in it will be used? I'm just baffled because there are several posts here from V8 developers, and quotes from the FAQ, saying things of the form "this is like FullCodeGen, except X", and the "X" is never "FullCodeGen was not a JIT". Which suggests to me that the people closest to development of these things don't think of them in the same terms as you do, which is why I'm trying to understand your terms.
> By "the entire thing", do you mean an entire file, without knowing if all functions in it will be used?
Yes. Afaik full-codegen had no way to discover that.
> and the "X" is never "FullCodeGen was not a JIT". Which suggests to me that the people closest to development of these things don't think of them in the same terms as you do, which is why I'm trying to understand your terms.
If you look at the langage they used, they’d always call full-codegen a compiler or baseline compiler. Not a jit. Because there was nothing to gather time-of-use information from. And full-codegen didn’t keep parse information around which is why crankshaft had to separately re-parse everything, full-codegen could not hand it the source or bytecode of functions to optimise.
With an interpreter, the JavaScript source is compiled to some bytecode, then the bytecode is executed in a loop, instruction by instruction.
With a compiler (not jit), the whole bytecode would be further fully compiled to some C apis before being executed, making it effectively an "ahead of time" compilation.
The catch is : since the code never was executed, there is very little static information to work with, so the compiled output is often just a giant unrolled interpret loop. The compiled version can be like 10% faster on very hot JavaScript loops compared to the interpreted version.