The following describes the basic concepts of parsing, generating bytecode to JIT. The following describes the implementation of the tool against the javascriptcore source code.
From JS script to byte code
First, the lexer, parser, and bytecode are generated by the programexecutable initialization process. In jsc api evaluate (), the programexecutable is created and the script code is specified. When interpreter is passed in, the un‑programcodeblock obtained through codecache is the code block after bytecode is generated.
Is the sequence diagram of codecache calling parser and bytecodegenerator:
Lexer is called in the parser process, for example:
Observe the relationships between several classes from the class diagram:
About codeblock, unwritable codeblock, and scriptexecutable
Codeblock can be understood as a code management class. It can be divided into globalcodeblock, programcodeblock, functioncodeblock, and evalcodeblock by type. It also has a similar inheritance system with the corresponding un‑codeblock and scriptexecutable, as shown below:
Un‑codeblock stores the compiled bytecode, while codeblock is used for llint and JIT.
Programexecutable can be understood as the general manager of the script currently executed. It can be seen from its name that it represents an executable program.
Their functions are easy to understand.
About the slow path of llint
As mentioned above, llint is an offlineasm-based assembly language. Here we will only introduce its slow path. to handle some operations, you need to call some C functions for extension processing when llint executes the command. For example, the JIT statistical function to be described later, llint provides an interface to call C functions, call all the called C functions as slow path, as shown in:
The code can be seen in lowlevelinterpreterxxx. ASM. So we can see the macro with slow_path in the C function declaration.
JIT optimization trigger
First, JSC uses the Counter-based hotspot detection method. As mentioned above, the JIT is triggered after a function or loop is executed several times. The number of times can be set through thresholdforoptimizesoon in JSC: options. Then, when llint executes the loop bytecode command loop_hint and function return command ret, it will call slow.
The C function in path is used to count and judge the number of times. The process is as follows:
The result returned by checkifjitthresholdreached () is used to determine whether jitcompile is performed. Once JIT compilation is performed, optimization is performed for different functions or code segments based on the current codeblock type. The following shows how to perform JIT compilation for a frequently used function:
The counting function is not directly implemented by codeblock, but managed by executioncounter. The main relationships are as follows:
Reprinted please indicate the source: http://blog.csdn.net/horkychen
Reference: WebKit Research
You can download the related UML diagram here: WebKit documentation on GitHub
Series indexes:
Basics (1) JSC and WebCore
Basics (ii) interpreter basics and JSC Core Components
Basic (3) code implementation from script code to JIT compilation
Basic (4) page parsing and JavaScript element execution
Advanced Article (1) SSA (Static Single Assignment)
Advanced (ii) type inference)
Advanced (iii) register allocation & trampoline