This is the 102nd original article without water. If you want to get more original articles, please search the official account and follow us.
V8 performs JS procedures

preface

This article is intended to give a brief introduction to the process of executing JS in V8. By understanding the process of executing JS in V8, we can understand what JS code rendering does in the browser. Of course, I am also in the gradual exploration of V8, if there is any improper place in the article, but also hope not stingy correction, rational communication.

As we all know, the machine (CPU) can only recognize the machine code (binary code), for JS code, it is not recognized, so when the code as a page appears on the screen, it must be done a lot of translation work.

V8 performs JavaScript procedures

As shown in the figure above, we will break it down step by step:

JS TO AST

After the V8 engine gets the JS code, the Parser performs lexical parsing and parsing on it.

Lexical analysis

The JS code is divided into the corresponding Token. The Token is the smallest unit that can be split. The fixed type represents the type/attribute, and the value represents the corresponding value, as shown below.

#### Syntax Analysis

After lexical analysis and conversion to Token, the parser continues to generate corresponding AST according to the generated Token. AST is believed to be one of the hot words, whether it is the representation of virtual DOM in Vue or React. Or Babel’s representation of JS translation is first converted into the corresponding AST, and the AST structure after parsing by the parser is shown in the figure below:

As you can see, a very small piece of code becomes much more complicated after being parsed into an AST. The AST in the figure is just simplified data. The whole AST actually has many parameters, which will become more complicated.

The bytecode

After the Parser parses the JS code into the AST, the interpreter initiates the bytecode (also known as intermediate code) from the AST. As mentioned above, the CPU can only recognize the machine code, but not the bytecode. This raises the question, if the CPU can’t recognize the bytecode, why put a step in the middle to expend resources to convert the bytecode? Isn’t it much less efficient?

In the field of computer science, there is no escaping the two concepts of time and space when talking about efficiency. Most of the optimization is about space for time and time for space. How to balance the two and achieve the highest efficiency is a problem worthy of further study.

Previous version of the V8 engine perform JS, for one, is not turn bytecode this step, directly from the AST into machine code, this process is called the compilation process, so every time to get the JS file, first will be compiled, and the process is a waste of time, it is a headache, need a solution.

A web page opened for the first time, closed again to open, in most cases, or the original JS file consistent, unless the developer modified the code, but this can be temporarily not considered, after all, which website will not be a day idle, constantly modify, upload replacement.

Cache machine code

According to this idea, since the vast majority of cases, the file will not change, the compiled machine code can consider caching off, in this way, the next time you open or refresh the page to save the process of compiling, can be directly carried out, storage machine was divided into two kinds of circumstances, when a browser is not closed, storage directly to the local browser’s memory, One is that the browser is closed and stored directly on disk, which is exactly what the early V8 did, typically sacrificing space for time.

The problem with caching

Consider a problem. As can be seen from the figure above, after converting a small code fragment into an AST, it becomes much larger. A problem caused by the large file size is that it needs more memory to store. This means that a JS file of dozens of KB will reach dozens of MB, which is terrible. The original multi-process architecture of Chrome has already taken up a lot of memory. Again, no matter how well configured the computer is, it will not be happy to enjoy Chrome, after all, the user experience is good. Although V8 caches compiled code, reducing compilation time and improving time efficiency, it costs too much memory, so it is necessary for the Chrome team to optimize this.

Inert compilation

Of course, the introduction of other technologies takes time to develop and optimize, and as a technical architecture is created, it is necessary to make up for the disadvantages. In earlier versions of V8, lazy compilation was introduced in order to solve the memory footprint and startup speed.

Before ES6, there were only global scopes and function scopes. The idea behind lazy compilation is that when V8 starts, only the globally scoped code is compiled and cached, while the function scoped code is compiled when called. Similarly, the compiled code inside the function is not cached.

Problems with lazy compilation

Introduced inert compiled in compilation speed and cache on the point of view, has been promoted, everything seems to be very perfect, right, looks, but designed, you will never know the user how to use, in ES6 and Vue, such as the React before any of these popular, most developers will use jQuery, As well as similar products such as RequireJS, JQ plugins have various references, various plugins or methods wrapped by the developer themselves, which are usually wrapped as a function in order not to pollute other users’ variables. The problem is that lazy compilation does not save the machine code and understand the compiled function after the function is compiled. If a plugin is too big to compile until it uses a function, the compilation time will be slow, and the developer will have finished the lazy compilation and blocked the path.

Introducing bytecode

Well, developers are out of the game, so the V8 team has to change their mind and introduce bytecode. First of all, we need to understand what bytecode is. Bytecode is actually the abstraction of machine code, and the mutual composition of various bytecodes can realize all functions required by JS. Of course, first of all, bytecode takes much, much smaller memory than machine code, which is basically tens or even a few hundredths of the memory where the machine code is located. In this way, the memory consumed by bytecode caching is still acceptable.

One question is, if the CPU can’t read bytecode, is it necessary to convert it to machine code? How else to do it? The answer is yes. After converting the AST to bytecode, it will convert the bytecode to machine code at execution time. This execution process is definitely slower than executing machine code directly, so it will be slower in execution, but the JS source code will be converted to bytecode through the parser, and then converted to bytecode through the interpreter. This process is faster than the compiler directly JS source code to machine code, the whole process seems, the whole time is not much difference, but it reduces a lot of memory occupation, why not.

The compiler

Hot code

In the code, often can have the same part of the code, is called many times, every time the same part of the code if need to turn the interpreter binary code to execute, efficiency, will be a little waste, so there will be special in V8 module monitoring module, to monitor whether the same code is called many times, if be called multiple times, then will be marked as hot code, What does that do?

Optimized compiler

Turbofan, or optimized compiler, is a familiar word to those of you who are interested in mobile phones. From Huawei to Xiaomi, Turbofan has been featured in product launches over the past few years. Its main feature is software computing power that can be used to optimize a range of features for greater efficiency.

Then continued hot code, when there is hot code V8 will borrow the TurboFan for hot code byte code into machine code and cache, as a result, when called again hot code, not need to transfer the bytecode machine code, of course, hot code is relatively small, so the cache will not take up too much memory, And improve the efficiency of execution, the same here is the sacrifice of space for time.

The optimization

JS language is a dynamic language, very flexible, object structure and properties can be changed during the runtime, imagine a question, if the hot code is executed in a certain time, one of the properties is suddenly modified, then the hot code compiled into machine code can continue to execute? The answer is absolutely not. At this point, the de-optimization of the optimized compiler is used, which reverses the hot code back to the AST, where the interpreter reinterprets the modified code and repeats the optimized compiler step if the code is marked as hot code again.

conclusion

From the analysis of the process, V8 JS execution process, not only use the interpreter, but also use the optimized compiler. This combination of the two is known In the industry as JIT (Just-in-Time). Using this combination to process JS is mainly to take advantage of the small files formed by AST and the high execution efficiency of the compiled hot code by optimizing the compiler. The two combine to give play to their respective advantages and maximize the efficiency as far as possible.

V8 do, far more than these, here also is just a simple summary and analyze the main process on something, if refined to each point, there are many concepts, such as inline cache, hidden properties, fast, slow, create objects, and the author written before recycling, etc., are doing too much, not name one by one.

Open source works

  • Politics gathers cloud front tabloids

Open source address www.zoo.team/openweekly/ (there is WeChat communication group on the homepage of the tabloid official website)

, recruiting

ZooTeam, a young, passionate and creative front-end team, is affiliated to the R&D Department of ZooTeam, based in the picturesque city of Hangzhou. There are more than 40 front-end partners in the team, with an average age of 27. Nearly 30% of them are full stack engineers, no problem young storm group. The members are not only “old” soldiers from Ali and netease, but also fresh graduates from Zhejiang University, University of Science and Technology of China and Hangzhou Electric University. In addition to daily business connection, the team also carries out technical exploration and practical practice in the directions of material system, engineering platform, construction platform, performance experience, cloud application, data analysis and visualization, promotes and lands a series of internal technical products, and continues to explore the new boundary of the front-end technical system.

If you want to change what you’ve been doing, you want to start doing it. If you want to change the way you’ve been told you need to think a little bit, you can’t break it. If you want to change, you have the power to do it, but you don’t need to; If you want to change what you want to do, you need a team to support it, but there is no place for you to bring people. If you want to change the established pace, it will be “5 years and 3 years experience”; If you want to change the original savvy is good, but there is always a layer of window paper fuzzy… If you believe in the power of belief, the ability of ordinary people to do extraordinary things, to meet better people. If you want to be a part of the take-off process and personally drive the growth of a front end team that has a deep business understanding, a sound technology system, technology that creates value, and influence that spills over, I think we should talk. Anytime, waiting for you to write something down and send it to [email protected]