This first line on Wikipedia is what most of us know about V8, and about lots of other things. Here I’ll try to provide a simple explanation of what V8 actually does. As for the other things, next time, just read the entire first paragraph in Wikipedia, what the hack, you only live once, dive into the second one.
- Compiles and executes JS code
- Handling call stack — running your JS functions in some order
- Managing memory allocation for objects — the memory heap
- Garbage collection — of objects which are no longer in use
- Provide all the data types, operators, objects and functions
- Provide the event loop, but this is sometimes implemented by the browser as well
- Know anything about the Document Object Model (DOM) — which is provided by the browser, and obviously irrelevant to Node.js for example
On the runtime, V8 is mainly managing the heap memory allocation and the single threaded call stack. The call stack is mainly a list of function to execute, by calling order. Every function which calls another function will be inserted one after the other directly, and callbacks will be sent to the end. This is actually why calling a function with setTimeout of zero milliseconds sends it to the end of the current line and doesn’t call it straight away (0 milliseconds).
Other Key Components:
JS Interpreter — Ignition & Optimization Compiler — TurboFan & Crankshaft
JIT compilation result machine code can take a large amount of memory, while it might be executed once. This is solved by the Ignition, which is executing code with less memory overhead.
WebAssembly — Liftoff
Achieving great performance is also key in the browser, and this is the task Liftoff is used for — generating machine code. Not using the complex multi-tier compilation, Liftoff is a simpler code generator, which generates code for each opcode (a single portion of machine code, specifying an operation to be performed) at a time. Liftoff generates code much faster than TurboFan (~10x) which is obviously less performant (~50%). To read more, see the V8 Dev Blog.
Garbage Collection — Orinoco
Running over the memory heap, looking for disconnected memory allocations is the Orinoco. Implementing a generational garbage collector, moving objects within the young generation, from the young to the old generation, and within the old generation. These moves leave holes, and Orinoco performs both evacuation and compaction to free space for more objects.
Another optimization performed by Orinoco is in the way it searches through the heap to find all pointers that contain the old location of the objects moved and update them with the new location. This is made using a data structure called remembered set.
On top of these, black allocation is added, which basically means the garbage collection process automatically marks living objects in black in order to speed up the iterative marking process.