How is JS executed

A: Single thread, scripting language, DOM manipulation… Q: Ok, do you know how JS is executed? A:… -_ – | |

doubt

I was wondering why Java needs to compile, but JS doesn’t. Originally, programming languages were divided into static and dynamic languages:

Static languages: such as C++, Go, etc., all need to compile (AOT) in advance into machine code and then execute, this process is mainly completed by the compiler; Dynamic languages, such as JavaScript, Python, etc., are compiled and executed (JIT) only at runtime, through the interpreter;

V8 performs JS processes

Parser Generates abstract Syntax tree (AST)

Once you start downloading Javascript files in Chrome, the Parser starts parsing the code in parallel on a separate thread. The process of AST generation can be divided into two processes: semantic analysis and semantic analysis.

1. Lexical analysis

It’s basically converting a char stream, which is our code line by line, into a token stream, which is the smallest single character or string that is syntactically non-divisible.

To see the Token Stream in detail, I used Recast to simulate browser parsing JS.

Install esprima

npm i  recast --save

Copy the code

Create a new file recast.js

const recast = require("recast");

const code = 'const LK = 1';

const ast = recast.parse(code);

console.log(ast);

Copy the code

Perform the node recast. Js

node recast.js

Copy the code

I intercept tokens objects. You can see that the JS code is split into key-value pairs of Type and value.

2. Semantic analysis

The purpose of semantic analysis is to combine the grammatical units from word segmentation and analyze and determine the relations among them. In simple terms, semantic analysis can be understood as the identification of statements and expressions. Semantic analysis is a recursive process, so it converts an array of segmented words into a tree representation (hence the T in AST). It also validates the syntax and throws syntax errors if there are any.

As you can see, just a JS code is parsed JSON for the tree, each reader can turn the AST at https://esprima.org/demo/parse.html online.

Ignition generates bytecode

Bytecode is an abstraction of machine code that can be viewed as the small building blocks that together make up any JavaScript functionality. Bytecode takes up less memory than machine code, which is an important reason why V8 uses bytecode. Bytecode cannot be run directly on the processor; it must be converted to machine code by the interpreter before it can be executed.

As you can see from the figure above, Ignition takes the AST from the previous step and generates bytecode through a bytecode generator with a few columns of optimization. In the process:

  • Register Optimizer: a Register Optimizer is designed to avoid unnecessary loading and storage of registers.
  • Peephole Optimizer: Finds portions of direct code that can be reused and merges them.
  • 5. dead-code Elimination: eliminate unnecessary code and reduce the size of bytecode;

TurboFan (TurboFan

Ignition executes the bytecode generated in the previous step and records information such as how many times the code has been run. If the same code has been run many times, it is flagged as “HotSpot” and sent to the compiler TurboFan. TurboFan then compiles it into more efficient machine code and stores it. The next time it executes the code, it replaces the bytecode with the current machine code, making the code much more efficient. In addition, when TurboFan decides that a piece of code is no longer hot code, it performs de-tuning, throws away the optimized machine code, and returns to Ignition

Improve JS code performance by parsing, interpreting, and compiling V8

I. Analysis process

  • Remove excess code. Reduce the browser request JS file time, reduce the parsing process and subsequent process time.
  • Lazy loading of unnecessary JS [optimized first screen loading]. Avoid loading and compiling JavaScript code that would delay the initial display of the page. Once the page is fully loaded, we can start loading these features again so that they are available as soon as the user starts interacting with the page. Google recommends this lazy loading in 50ms so that it does not affect the user’s interaction with the page.
  • Write js code correctly. Reduce the cost of semantic analysis throwing up problems.

Second, explain the process

V8 is compiled in JIT mode. JIT must be a strongly typed language. Before compilation, binary files that can be executed by the CPU are directly generated by compilation.

  • Provide default types when declaring variables to speed UP JIT intervention.
  • Do not easily change the type of a variable, which will increase the cost of type handling at compile time.

3. Compilation process

  • Always use the least computationally complex algorithm and the best data structure to solve the task.

  • Rewrite the algorithm to get the same results and fewer calculations.

  • Avoid recursive calls.

  • Add variables, calculations, and calls to repeating functions.

  • Decompose and simplify mathematical formulas.

  • Use search arrays: Use them to get values based on one another, rather than using switch/case statements.

  • Make the condition always more likely to be true to take better advantage of the processor’s speculative execution.

  • If you can, replace some operations with bit-level operators, because these operators have short processing cycles.

AST application

A, Babel

Babel is a javascript compiler that compiles ES6 syntax into ES5.

1, parsing,

Parse the code into an abstract syntax tree using the parser Babylon.

2,

Depth-first traverse of the abstract syntax tree with babel-traverse Plugin. Add, update, and remove nodes that need to be translocated directly on AST objects. For example, if an arrow function needs to be translocated to a normal function, a new AST tree can be obtained.

3. Generate

Generate ES5 code from the AST tree via babel-Generator.

Vue template compilation process

Vue provides two versions, one is Runtime + Compiler, the other is Runtime only, the former contains the compiled code, the compilation process is put at Runtime, the latter does not contain the compiled code, Use webpack’s vue-loader to compile the render function from the template. Regardless of which version you use, there is always a step to compiling the template into the Render function.

1, parsing,

The template string is parsed into AST. The parser is implemented by VUE itself. During the parsing process, regular expressions are used to parse the template sequentially.

2,

Not all data in the Vue template is responsive, and many data will never change after the first rendering, so the DOM generated by this part of data will not change, so we can skip the comparison of them in the process of patch. In this stage, the generated AST tree will be deeply traversed to detect whether each of its sub-trees is a static node. If it is a static node, they will never need to change the DOM generation, which will greatly optimize the update of the template at runtime.

3. Generate

The AST generates the render function using the generate method.

Reference link: juejin.cn/post/684490…