Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How does the JS engine execute the process?

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article introduces you how the JS engine implementation process is, the content is very detailed, interested friends can refer to, hope to be helpful to you.

Preface

The reason why I highly recommend it is:

The basic principle of JavaScript engine is described vividly in the form of motion diagram.

Having been in touch with the front end for so long, you have been dealing with JS every day, and you must think JavaScript is cool as much as I do. But how can the machine really understand the code you write?

From the above thinking points, this article is led to:

Take you to the basics of the JavaScript engine to see how it handles our human-friendly JS code and turns it into something that machines can understand.

As a developer of JavaScript, it is definitely a good thing to clearly understand its process.

Basic concept

Before we do that, we need to know some basics of the JS engine.

What is the JS engine and what does it do for us?

We all know that the code we wrote, processed and handed over to CPU, is unrecognizable and cannot be executed. CPU knows its own instruction set, which corresponds to assembly code. It is impossible to write these instruction sets, so it appears:

The JavaScirpt engine compiles JS code into assembly code corresponding to different CPU (Intel, ARM, MIPS, etc.) so that we don't have to flip through each CPU instruction set manual.

Of course, compiling code is not its only function, such as code execution, memory allocation, and garbage collection mechanisms.

Having a general understanding of it, what are our common JS engines? I found that the most famous one must be V8. As for some others, you can check the information if you are interested.

For example, there is also:

SpiderMonkey (Mozilla)

JavaScriptCore (Apple)

Chakra (Microsoft)

IOT:duktape 、 JerryScript

The content of V8 is too much and the space is limited. Follow up and write an article to talk about.

It is so famous that the knowledge introduced in this article is mainly based on Node.js and the V8 engine used by Chromium-based browsers.

Main flow chart

There are a lot of details, so the main analysis is the main process, as shown in the figure:

From the picture, we can summarize a few points:

Generate abstract syntax tree

Lexical analysis

Grammar analysis

Generate bytecode

Execute the code

Real-time compilation

Inline cache

Generate abstract syntax tree

The HTML parser encountered a script tag with the source. The code for this source is loaded from the network, cache, or installed service workers. The response is the requested script as a byte stream that is processed by the byte stream decoder. The byte stream decoder decodes the byte stream that is being downloaded.

Decode

Lexical analysis

The first stage of generating an abstract syntax tree is word segmentation (tokenize), also known as lexical analysis.

The byte stream decoder first creates a token (token) from the code byte stream.

Note: tokens can be understood as the smallest single character or string that cannot be further divided grammatically.

For example, 0066 is decoded to fmeme0075, decoded to uPower006e, decoded to nmeme0063, decoded to cmeme0074, decoded to tmemorial0069, decoded to iPower006f, decoded to oPower006e, decoded to n, followed by a space. And then you will find that together they are function.

This is a reserved keyword in JavaScript.

A token is created and sent to the parser. The same is true of the rest of the byte flow, as shown in the following figure:

Lexical analysis

Grammar analysis

The second stage is parsing (parse), also known as parsing.

The engine uses two parsers: a pre-parser and a parser. To reduce the time it takes to load a Web site, the engine tries to avoid parsing code that doesn't need to be used immediately.

The pre-parser handles the code that may be used later, while the parser handles the code that is needed immediately!

If a function is called only after the user clicks a button, there is no need to compile the code immediately in order to load the site.

If the user finally clicks the button and needs that code, it will be sent to the parser.

The parser creates a node based on the tags it receives from the byte stream decoder. With these nodes, it creates an abstract syntax tree or AST, as shown in the figure:

Grammar analysis

What's worth thinking about is, what on earth is AST? (what kind of data structure is it? are there these concepts in babel?)

Next, it's time for the interpreter, which browses the AST and generates bytecode based on the information contained in the AST. Once the bytecode is fully generated, the AST is deleted, thus clearing the memory space. Finally, we have something that the machine can work.

Generate bytecode

We just mentioned that the interpreter browses the AST and generates bytecode based on the information contained in the AST, so what does it do?

Roughly speaking, you can understand it like this:

The AST is passed to the interpreter (interpreter), traverses the entire AST, and the bytecode is generated. When the bytecode is generated, the AST is deleted to save memory space. In the end, we got a bytecode closer to the machine code.

The bytecode here is a kind of code between AST and machine code, and it still needs to be converted into machine code by an interpreter before it can be executed.

Let's take a look at its process through a picture:

Generate bytecode

Code execution

Once we have the bytecode, we can move on to the execution phase.

Even if compiling

Although bytecode is fast, it can be faster. When this bytecode runs, the information is generated.

It can detect whether certain behaviors occur frequently, as well as the data types used. Maybe you've been calling a function dozens of times: it's time to optimize it so that it runs faster. The bytecode, along with the generated type feedback, is sent to the optimization compiler. The optimization compiler receives bytecode and type feedback and generates highly optimized machine code from it.

This technique is also known as just-in-time compilation (JIT:Just In Time), and the optimized compiler mentioned above is also called the JIT compiler.

For details, you can refer to the following figure:

Timely compilation

Inline cache

JavaScript is a dynamically typed language, which means that the type of data can be constantly changing. If the JavaScript engine checks the data type of a value every time, it will be very slow.

According to the appeal, the engine has a technology called inline caching (inline caching).

The process goes like this:

To reduce the time it takes to interpret the code, the optimized machine code only deals with what the engine has seen when running bytecode. If we use a piece of code repeatedly and return the same data type over and over again, the optimized machine code can be simply reused to speed up.

However, because JavaScript is dynamically typed, it is possible that the same code suddenly returns different types of data. If this happens, the machine code will be unoptimized and the engine will return to interpreting the generated bytecode. Suppose a function has been called 100 times and has always returned the same value so far. It will assume that it will also return this value when you call it for the 101st time.

Suppose we have the following function sum, which (so far) has been called with a numeric value as an argument, as shown in the figure:

If this is true, there is no need for dynamic lookup, it can reuse the optimized machine code. Otherwise, if the assumption is incorrect, it will revert to the original bytecode instead of the optimized machine code. For example, the next time we call it, we pass a string instead of a number. Because JavaScript is dynamically typed, we can do this without any errors!

As shown in the figure:

This means that the number 2 will be forced into a string, and the function will return the string "12". It goes back to executing the interpreted bytecode and updates the type feedback.

The above is how the execution process of the JS engine is, and the editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

About how the JS engine execution process is shared here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report