Front-end capability model-V8 JS engine

Source: Internet
Author: User
Tags access properties

first, WebKit kernel and V8
In Chrome, use WebKit for HTML rendering, using V8 as the JS engine. Chrome and WebKit are open source, but Chrome keeps webkit distance, and chrome encapsulates a layer called WebKit Glue on WebKit. In the glue layer, most types of structures and interfaces are similar to WebKit, and Chrome relies on WebKit components to invoke only the interfaces of the WebKit glue layer, rather than calling the types in WebKit directly.     According to Chrome's own documentation, although we re-use WebKit to achieve page rendering, but through the WebKit glue middle layer, to a certain extent greatly reduce the coupling with WebKit, Blink is a good alternative to webkit rendering engine. V8 has given full play to the knowledge gained by developing hotspots and Strongtalk.
Second, Android WebKit
Android WebKit includes the Java layer and the C layer, both of which are communicated by the Java Native interface, as shown in the following example:


Third, WebViewWebView is a view module in the Java layer, usually inserted in the Android Native app HTML page is also built on the WebView, including the page browser, the processing of requests. This is why WebView's mirror rate is higher than the Android WebKit itself, a lot of native app in the development, some of the high-update module, will choose to use WebView to render HTML pages, so that the content can be updated easily.
There is also a webview module in the C layer, the WebView module in the C layer is responsible for initializing and constructing the WebView object, which is then assigned to the Java layer's webview. The two will then be able to communicate.

iv. differences between Safari and chrome cores


JS engine early slow has a certain historical reason, at that time only used in the Web page a few animation, interactive operation, browser development priority to improve the speed of rendering engine, JS processing speed is not very important. With the emergence of the rich application blowout, the reliance on JS and the demand is more and more high, the performance problem is once again called the network application developers most concerned.

v. JavaScript differs from C + +, Java
1) Problems with the language itself
C + + and Java use static types (typing). When the code compiles, declaring the variable type, JS needs to check the data type during execution, so the static type occupies a performance advantage.
2) The difference of object variables and methods in JS, C + +, Java
Illustrated by the legend:



C + +, Java handles the variables and methods of object, storing them in the array with the displacement values in their name 1:1 corresponding arrays. The variable type to be accessed is known in advance, so you can access variables and methods using only arrays and displacements.
JS, individual objects have their own properties and methods and other tables. Each time a program accesses a property or a calling method, it must check the type of the object and perform appropriate processing.
Many JavaScript engines use a hash table (hash table) to access properties and find methods. In other words, each time a property is accessed or a method is searched, the string is used as the key to find the object hash table (key), such as:



Internal JavaScript processing when attributes are accessed in the graph: Use the string foo of the object X hash table as a keyword to search for foo content. The Search hash table is a sequential action that contains the position within the array from the hash (hashing) value, and then see if the key value (key) for that position is equal. It is then possible to use an array of displacements to directly read the data, which is more time-consuming to access.
Other languages that use dynamic types, as well as Smalltalk and Ruby. These languages are basically search hash tables, but they use classes to shorten the search time. However, JS does not have a class, except that numbers indicates a numeric value, strings is a string, and several other basic types, leaving objects as object type. Classes cannot be declared, so explicit types cannot be used to expedite processing.
six, V8 engine acceleration technology
The flexibility of JS allows you to add or delete properties and methods on an object at any time. The industry generally believes that dynamic languages are more difficult to accelerate than static languages. V8 has used several techniques to achieve accelerated objectives:
1) JIT compile (JIT Compile): Generate machine language without bytecode (bytecode)
From a performance perspective, V8 has 4 main features, first of all, it generates machine language at execution time in the form of a compile method called prompt (Just-in-time, JIT). This is a common way to improve the speed of interpretation, and this method can be found in Java. V8 has already practiced this technology earlier than the SpiderMonkey JavaScript engine in Firefox, or the competitive engine such as Safari's JavaScriptCore.
The V8 JIT compiler does not produce an intermediate code when it produces machine language. For example, in the Java compiler, the original code is first converted to a class file represented by the Virtual intermediate language (called bytecode, bytecode). The Java compiler and bytecode compilers produce bytecode, not machine language. The Java VM interprets bytecode sequentially in execution. This execution mode is called the bytecode interpreter (bytecode interpreter). Firefox's SpiderMonkey has an internal bytecode compiler and byte interpreter that converts the JS source code into its own signature byte code for execution. Such as:


The programming language system first uses the parser to convert the original code into an abstract syntax tree (abstract syntax tree, AST). There are several ways to deal with it before. The bytecode compiler compiles the abstract syntax tree into intermediate code and executes it in the compiler. Mixed mode such as Java JIT compiles part of this intermediate code into machine language to improve processing performance. Chrome does not use intermediate code, and JIT compiles the machine language directly from the abstract syntax tree. There are also abstract syntax tree interpreters that parse the abstract syntax tree directly.
In fact, Java VMS currently use a hotspot-based JIT compiler. It plays the role of the bytecode interpreter to parse the code, convert the frequently executed chunks of code into machine language and then execute, which is the mixed mode (hybrid model).
BYTE-code interpreter, mixed mode, etc., with the advantages of simple fabrication and excellent portability. As long as the original code that the engine can compile, the bytecode can be executed on any CPU architecture, which is why the technology is called a "virtual machine (VM)". Even in a mixed mode that produces machine code, it can be developed by the interpreter that writes the bytecode, and then the machine language generator is implemented. By using simple bit codes, it is much easier to optimize the output in the case of machine code generation.
Instead of converting the original program into an intermediate language, V8 directly produces the machine language and executes the abstract syntax. Without a virtual machine, and because no intermediate representation is required, program processing starts earlier. However, it also loses the benefits of virtual machines, such as high portability (portability) and ease of optimization, such as byte-code interpreter and mixed mode.
2) Garbage collection management: a subtle implementation of Java standard features
The second key feature is that V8 uses garbage collection management (garbage collection, gc*) as "precise gc*", whereas most JS engines, Ruby, and other language compilers use conservative gc* (conservative GC). Because conservative GC practice is much simpler. Although the precise GC is more complex, it also has a performance advantage. The Oracle (Sun) Java VM is using the exact GC.
Garbage collection (GC) garbage collection Management: automatically detects and frees memory space that is reserved by the program but is no longer in use. Conservative (Conservative) GC: There is no separate management of memory recycling that strictly manages the indicator and numeric values. This method is if it can be an indicator, then look at it as an indicator, even if it is a numeric value.     This method prevents an object from being accidentally reclaimed, but it cannot release possible storage. Although the exact GC itself is efficient, advanced algorithms based on accurate GC, such as generational (generational) GC, copy GC, and markup and thin processing (mark-and-compact processing), have significant performance improvements.     The generational (generational) GC promotes GC efficiency by separating the "young generational" objects (often collected) and the old generational (older generational) objects (objects that are relatively long-lived). V8 uses a generational (generational) GC to replicate the GC with light (LIGHT-LOAD) on new generational (generational) processing, and to use markup and thin GC on the old GC, because it needs to move objects within the memory space. This is hard to do in a conservative GC. In the object's replication, compression (compaction) (called Defrag on hard disk) and similar actions, the address of the object changes, and for this reason, the most common way is to use "handle" (handles) to refer to the address indirectly. However, instead of using a handle (handles), V8 overrides all data referenced by the object. Not using handles (handles) makes the implementation more difficult, but it improves performance because there are fewer indirect references. The Java VM hotspot also uses the same technology.
3) Embedded cache: JS is not available, V8 use hidden class skillsV8 can now produce the right machine language for both x86 and arm architectures, although V8 has the inherent speed of dynamic languages without the traditional optimizations in C + + or java. One good example is the inline cache, a technique that avoids hash table searches when method calls and attribute accesses are available. It can cache the previous search results immediately, so it is called "inline".          This technology has been known for some time and has been used in languages such as Smalltalk, Java, and Ruby.     The embedded cache assumes that the object has a type, but not in JS, until the V8 appears, and this is why the JS engine has signed no embedded cache reason. To break this limit, V8 parses the program operation at execution time and assigns a temporary class to the object using a "hidden class" (hidden classes). With hidden classes, even JS can use inline caching. But these classes are a technique for improving execution speed, not an extension of the language specification. So they can't be referenced in the JS code.
Other JavaScript engines, unlike V8, store object properties in a hash table, but V8 store them in an array. Displacement information-Specifies the position of an individual attribute in the array-is stored in the hash table of the hidden class. Objects of the same hidden class have the same property name. If you know the object class, you can manipulate the Access property by using the displacement array. This is much faster than searching the hash table.
However, in dynamic languages such as JS, it is difficult to know the object type beforehand. For example, the object type P and Q call the lengthsquared () function. The properties of the object type P and q are different, the hidden classes are different, so the parameter (arguments) type of the lengthsquared () function code cannot be determined.
To read the object properties in a function, you must first examine the object's hidden class and then search the class's hash table to find out the displacement of the property. The array is then accessed using the displacement.          Although accessing attributes in an array, the need to search the hash table first destroys the advantage of using arrays. However, from different points of view, the situation is different. In a real-world program, there are not many cases where the dependency code performs the judging type. For example, the lengthsquared () function even assumes that most of the values that are passed as parameters are point class objects, which are generally correct.
function lengthsquared (p) {return p.x * p.x + p.y * P.Y;          } function Labeledlocation (name, x, y) {this.name = name;          this.x = x;     This.y = y;     } var p = new Point (10, 20);     var q = new Labeledlocation ("Hello", 10, 20);     var plen = lengthsquared (p); var Qlen = lengthsquared (q);
It is not possible to judge whether the parameter is a point type or a labeledlocation type of the lengthsqurared () function before execution.
Inline caching is an acceleration technique designed to take advantage of the local (local) category approach in the program. For programmatic property access, V8 generates a command string to search for the Hidden class list, which is called the premonomorphic stub. This stub is intended to be accessed in the Function property. The premonomorphic stub has two messages: hidden classes for search and displacement from hidden. Finally, new code is generated to cache this information.
object* find_x_for_p_premorphic (object* p) {class* Klass = P->get_class ();          int offset = Klass->lookup_offset ("x");          Update_cache (Klass, offset);     Return p->properties[offset]; }
The premonomorphic stub in pseudo-code (pseudocode) Gets the attribute offset from the hidden class. Lengthsquared () function

The premonomorphic stub is called when the permonomorphic stub calls a property in the function.
object* find_x_for_p_monomorphic (object* p) {if (Cached_klass = = P->get_class ()) {return P-&gt          ;p Roperties[cached_offset];          } else {return lookup_property_on_monomorphic (p, "X"); }     }
The pseudo-code of the monomorphic stub handles the displacements in the direct embed code as constants used to access the attributes. Hidden classes with Property objects are compared to cache-hidden classes before the table is searched. If the match does not need to search again, and can use the buffer displacement to access the property. If the hidden class does not match, the displacement is judged in a general way through the hidden class hash table.
The newly generated code is called the monomorphic stub. The word "inline" means that the displacement required to query the hidden class is embedded in the resulting code in an immediate, usable form. When the monomorphic stub is first called, it rewrites the function from the first address called in the Pre-monomorphic stub address into a monomorphic stub address. Since then, using a high-speed monomorphic stub, class comparison and array access can be used to handle property access.



When the monomorphic stub is called, it re-writes the function from the first address in the Premonomorphic stub address to the monomorphic stub address.
If there is only one object with attributes, the monomorphic stub will be highly efficient. However, if the type is more, the cache error will be more frequent, thereby reducing the efficiency of the monomorphic stub.
When a cache error occurs, V8 is resolved by generating another code called the Megamorphic stub. Monomorphic stubs corresponding to individual classes are written in a hash table, which is searched and called stubs at execution time. If there is no monomorphic stub for the type, the displacement is searched from the type hash table.
object* find_x_for_p_megamorphic (object* p) {class* Klass = P->get_class ();          Inline processing of the actual search stub* Stub = klass->lookup_cached_stub ("x");          if (NULL! = Stub) {return (*stub) (p);          } else {return lookup_property_on_megamorphic (p, "X"); }} The megamorphic stub in the pseudo-code is stored in the hash table with the monomorphic stub corresponding to the type, and is searched and called out at execution time. If the corresponding monomorphic stub cannot be found, the displacement is searched in the type hash table.
When a cache error occurs with the monomorphic stub, the monomorphic stub overrides the first address that the function calls from the monomorphic stub address with the megamorphic stub address. In terms of code search, the performance of the megamorphic stub is lower than the monomorphic stub, but the Megamorphic code is much faster than premonomorphic stubs with cache updates, code generation, and other ancillary processing.
Covering multiple kinds of inline caches is called multi-morphological inline caching (polymorphic inline cache). The V8 embedded cache system is used to call methods and store properties.

4) Hide class storage type conversion information
Hidden classes bring interesting challenges to the JS language specification without classes, and are the most unique techniques V8 use to speed up the process.          They deserve more in-depth exploration. There are two main reasons for building a class in V8, i.e. (1) categorizing objects with the same property names, and (2) identifying objects with different property names. Objects in the previous class have exactly the same object descriptions, which can speed up property access.
In V8, classes that meet the classification criteria are configured on various JS objects. The object references the configured class. However, these classes exist only in V8 as a convenience, so they are "hidden".


If the object's description is the same, the hidden class will be the same. In this example, both the object P and Q belong to the same hidden class, which mentions that you can add or delete attributes in JS at any time. When this happens, however, the collation condition (the attribute with the same name) is destroyed. The V8 is addressed by the new classes needed to establish the property changes. The object of the property change is included in the new level through a program called type conversion (class transition).

To configure a new class: type conversion
The object that the property is changing is classified as a new class. When Object P adds a new attribute z, the object P is classified as a new class. V8 to resolve this problem by storing the transformation information inside the class. When the hidden class point has the X and Y properties, the new attribute z is added to the point-level object p. When the new attribute z is added to the object p, V8 stores the "new attribute Z, build Point2 class" information in the point-level internal table.
Storing class transformation information in a class when a new attribute z is added to the object p, V8 records "Join attribute Z, establish class Point2" on the table within the point class (step 1). When the object Q of the same point class joins the attribute Z, V8 searches the point class table first. If it finds out that the Point2 class has been added to attribute Z, the object q is set to the Point2 class (step 2). Such as:



When new attribute z is added to Object Q, which is also point level, V8 searches for a point-level table and discovers that the Point2 level has been added to attribute Z. When a class is found in a table, the object q is set to the class (POINT2) instead of creating a new Class (step 2), which achieves the object's purpose of generalizing the same property name.
However, this method means that the empty object corresponding to the hidden class will have a large conversion table. V8 is handled by creating hidden classes for each constructor. If the constructor is different, even if the object's statement (layout) is identical, a new hidden class is created for it.
5) Characteristics of machine language
As mentioned above, V8 uses such as inline caching to achieve the natural speed of a dynamic language at design time. Create a machine language generation module that uses the stub of the inline cache to closely link with the JIT compiler.
Some frequently used methods are also written in machine languages to achieve the same effect as inline outreach, making them "intrinsic". The V8 source lists the candidate lists for intrinsic conversions.
V8 contains shell programs that can be used to check the machine language produced by V8. The resulting instruction string can be compared with the V8 code in order to show its characteristics.
For example, when executing the JS function shown in Figure 14a, a x86 machine language instruction string is generated as shown. This function is called in the 39th instruction, which is a [n+one] addition. In JS, the [+] operand indicates the addition of the numeric variable and the continuity of the string. The compiler does not generate code to determine which of these is the calling function to be responsible for judging.


V8 Machine language addition processing from JS code is converted to the machine language of the function call (A, B).
If the function changes slightly, then the function call disappears, but there is an addition and branch instruction (JNZ if it is not 0). When using integers as operands of the [+] operator, the V8 compiler produces a command string with an "add" instruction without calling the function. A function is called if the operand ([n]) is found to be an indicator (pointer), such as a number object or a string object. "Addition" only occurs when the operands of the two "+" operations are integers. In this case, execution is faster because a function call can be skipped.



Slightly modified JS, the resulting machine language.
Additionally, the 0x2 is added with an "addition" instruction because the least significant bit (least significant bit, LSB) is used to distinguish between integers (0) and indicators (1). Add 0x2 (10 in binary) just as if the value is plus 1,lsb.     In the JO Command Overflow (overflow) processing, the test and JNZ instructions are used to determine the indicator and skip downstream processing. This kind of trick is everywhere in the compiler. However, the generation of machine code also reveals compiler limitations. Traditionally optimized compilers can produce exactly the same machine language for the above two graphs, due to the constant rounding relationship. However, the V8 compiler generates code in the abstract syntax tree unit, so there is no optimization when processing extends multiple nodes. This is also evident in the large number of push and pop instructions.



The machine language produced by the C language is displayed, because the language specification between C and JS is different, so the machine language is different, and the compiler performance is irrelevant. The C compiler produces a much cleaner machine language from C code than V8 (A, b), mostly due to differences in C and JS language specifications. Note 1: When the overflow signal appears, the Jo command jumps to a specific address. The test instruction reflects the logical and result into 0 and symbol indicators. The jnz instruction jumps to a specific address unless the 0 signal appears.
Abstract syntax tree: The data representing the schema of the program in the tree schema.
Seven, familiar with JS object-oriented
JS has no classes, but to make it easier to familiarize yourself with the class (object-oriented code), you can use the new operand to build the object, just as in Java, a special constructor constructor is defined after the new operand.     However, even without constructors, you can create objects and set properties, and the properties and methods of JS objects can be added and deleted at any time. In addition to using dot notation (dot notation) to access the JS attribute, you can also use parentheses to suggest hashing (hashing) access or a variable-specific property name string. The JS object design is explicitly shown from these examples in order to use a hash table.
A) define the constructor [Point]function Point (x, y) {//] This refers to its own this.x = x; This.y = y;}
b) When adding new and called build functions, the object var p = new Point (10, 20);
c) No build function can also build object var p = {x:10, y:20};
d) Be free to add properties P.z = 30 on the object;
e) Use dot tag access attribute var y = p.y;
f) Use the hash of parentheses (hashing) to access var y = p["y"];
g) You can also use variables for hashing (hashing) to access var name = "Y";p [name];



Front-end capability model-V8 JS engine

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.