skip to Main Content

I’m currently researching how the V8 engine processes JavaScript source code. However, something has caught my attention. In all these medium articles, they explain it as follows:

source code -> parser -> abstract syntax tree (AST) -> interpreter -> bytecode

They say that when bytecode is generated, the code is executed at that stage. Is there no baseline compiler? I know that there is an optimizing compiler that collects profiling data, etc., but why is there no mention of a baseline compiler?

I came across an article called ‘Sparkplug’ on this website: https://v8.dev/blog/sparkplug. Is Sparkplug the baseline compiler?

To summarize:

  • Does the V8 engine have a baseline compiler? If not, how is bytecode executed? Doesn’t it need to be translated into machine code?
  • Why is bytecode needed?

I am curious whether there is a baseline compiler or not.

2

Answers


  1. Chosen as BEST ANSWER

    If I were to summarize it, can we say the following about the working logic in basic terms?

    The source code goes to the V8 engine and is checked by a parser for syntax and other checks. If there are no errors, a syntax tree (AST) is created. If there are syntax errors, we receive an error at this stage. Once the AST is created, the Ignition component in V8 generates bytecode. There are three execution models: the interpreter interprets the code and produces specific outputs, the baseline compiler translates it to machine code, or the optimizing compiler converts it to machine code based on profiling information (such as functions marked as hot during the second execution).

    Additionally, the interpreter does not compile/translate bytecode into machine code. It executes its own outputs corresponding to the bytecode.

    This is how I understand it at a basic level. Is there any incorrect part in my explanation? I would be grateful for your response.

    However, I have some questions that I'm curious about:

    -Doesn't Ignition generate the bytecode? -Isn't Ignition the interpreter? -You mentioned that the interpreter's code can be machine code, bytecode, or JavaScript code. If the interpreter outputs JavaScript code, are these processes performed again? The answer seems a bit contradictory... I'm speaking based on my basic knowledge of how computers execute machine code.


  2. Yes, Sparkplug is a "baseline" or non-optimizing compiler.

    The V8 architecture is changing all the time, and I’m sure this answer will soon be out of date. I believe the addition of a non-optimizing compiler is a recent development, so this might be why you have heard V8 didn’t have one. But this is my understanding of the current architecture.

    The V8 engine has multiple ways to execute code. It has an interpreter, a baseline compiler (Sparkplug), and an optimizing compiler. The reason for the multiple strategies is a tradeoff between how long it takes to compile code and how long it takes to execute code. A slower compiler can generate more optimized code. But if a block of code is only executed once or a few times, an optimizing compiler might actually be a lot slower than an interpreter. So the engine shifts strategy based on how many times the code is executed.

    But in all cases, the source code is first compiled into bytecode. The interpreter and the compilers all use this bytecode as input.

    So the flow is more correctly illustrated like:

    source code -> parser -> AST -> bytecode -|-> interpreter
                                              |-> baseline compiler -> machine code
                                              |-> optimizing compiler -> machine code
    

    The term "compiler" is used both for the part transforming the source code into bytecode, and the parts transforming bytecode into machine code.

    Bytecode is an intermediate format between source code and machine code. It is much lower level than source code, but not CPU specific like machine code. Bytecode is used because parsing source code is expensive, so there is no reason to do it more than once.

    The interpreter does not compile the bytecode to machine code. It reads the bytecode instructions one at a time and executes the corresponding code. This has some overhead in reading and decoding each bytecode instruction, but the advantage is there is no separate compilation pass necessary, so it will be extremely fast to get started.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search