Let’s Understand Chrome V8 — Chapter 10: Ignition Execution Unit

灰豆 Huidou
3 min readJul 29, 2022

Welcome to other chapters of Let’s Understand Chrome V8

Execution is responsible for executing the bytecode. In this paper, we’ll talk about the workflow from S to E and several kernel functions.

Our test case:

Workflow

The GetSharedFunctionInfoForScript() compiles JS source code into bytecodes.

In the 17th line of code, lookup compilation_cache, cache hit indicates that there are already bytecodes, and don’t need to recompile. The 26th line of code indicates that cache miss, so call the CompileToplevel on the 37th line to generate bytecodes.

Bytecode needs to be bound to a context before execution, as below:

After binding, we get an important member — JSFunction, which is the input expected by the execution.

The above function is the entrance for executing JS. Line 19 compiles the JS to bytecode. Line 22 executes the bytecode. Debug line 22 to step into the Run(realm).

The 8th line casts this pointer to JSFunction. For our case, the variable fun is console.log(JsPrint(6)), then call the 12th line — call().

In call(), the Invoke() will be called which is below.

Line 18 gets the address of the builtin, its index is 40, and its name is JSEntry. This builtin builds the execution environment for bytecodes. Then step into line 25, where the bytecode is executed. After that, we can only debug the assembly code, but c++. Figure 1 is the call stack.

Before stepping into bytecodes, Generate_JSEntryVariant will be called.

Look at the 30th line of code, the generator function of the 40th builtin is B, and its analysis method refers to my previous paper. Figure 2 shows the corresponding assembly code.

You can also see a bit of C++ in Figure 2, but this is the last chance to see C++. After that, only the assembly code.

Our case uses the console.log which is a global function. It is below.

RUNTIME_FUNCTION(Runtime_DeclareGlobals) is a runtime function defined by a macro template. The function checks the parameters and then calls DeclareGlobals() to perform the corresponding operation.

In our case, DeclareGlobals() lookup the global object console, then takes out the log() from the console, and gets the address of console.log(). Finally, pass the parameter JsPrint(6) into log() which will start a new compilation and execution.

Okay, that wraps it up for this share. I’ll see you guys next time, take care!

My blog is cncyclops.com. Please reach out to me if you have any issues.

WeChat: qq9123013 Email: v8blink@outlook.com

--

--