BRIEF SUMMARY ON HOW THE JIT WORKS
7 min read
What is the JIT
Just in time compilation (JIT) is a hybrid of compilation and interpretation that converts all of the source code into machine code before immediately executing it. Because of this, we can compile ahead of time, but there isn't a portable file to run, therefore execution occurs right away.
To illustrate. You speak only English and you are in Germany with friend who speaks both german and english and you two visit a restaurant, the waitress speaks only german. What ever you will have to order in the restaurant you will have to tell your friend so he interprets to the waiter so she can take your order. In this case you are programmer, english is your high-level language the waiter is the computer and german is the machine code your friend is the JS engine because he serves as the middle man between the waiter and you.
A more detailed explanation
Baseline compilers The warm section of codes are compiled into Bytecode which is run by an interpreter also the baseline compiler optimizes code producing "stubs" for each instruction that is being inspected, the baseline compilation will also make an effort to optimize the code.
Optimizing compilers When a code becomes extremely hot, the monitor sends it to the optimizing compiler. This will generate a faster version of the function. Ok as you know a stub is created for every function, for the hot code it contains a whole lot of element hence multiple stubs for each of the specific function is created which have quite some similarities, so for the optimizing compiler to work faster it makes some presumption, some examples of such presumptions are
Weather or weather not an element is an array.
Weather or weather not the values of giving data structure are integers, alphabets or alpha-numeric data.
If the returned value from certain functions are strings or any other data type.
Of course this assumption aren't always right, an array might have 200 data the 190 being strings and the remaining 10 numbers, so the compiled code are checked before they run to see whether the assumptions are correct. If true the compiled code runs else the JIT discards the optimized code and the execution is reversed back to the baseline Compiler. Normally optimization makes a code faster but its like taking a shortcut, if the gates to the short cuts are closed and you have to turn back to take the normal route making your journey much longer than it actually was.
To further let me give you a common example (Type specialization)
As regards the image above we have a variable arr which is an array that is undefined, if it was array with 1000 integers immediately the code is warm the baseline compiler starts creating stubs for that operations. The sum += arr[i] will have its own stub too but this line is polymorphic by polymorphic i mean the value of arr[i] could be any value of any type and not just an integer so a stub is created for every possible type combination. This implies that the JIT must ask several questions before creating a stub. Is i an integer? Is sum an integer? Is the result a string? Is arr actually an array? Is arr[i] a string? The above is a set of question which each iteration of the loop will ask and we would agree this will be slow especially when dealing with a lot of data and thats where the optimizing compiler comes in so you don't have to repeat those checks in order for your code to be much quicker. Is arr an array? YES Is i an integer? YES (all data in arr is confirmed to be an integer) now everything is stubbed So any question which isn't stubbed by the optimized compiler is then ran singly for each ilteration.
Thanks for making it to the end of this article, feel free to ask any question and if there is a topic you would need me to write on do well to contact me on Twitter or Linkedin.
Do well to like and Share this article if you found it helpful✌️.