On the basis of JavaScript engine: Shapes and Inline Caches

There are five full sections   

1.JavaScript workflow engine: The processing pipeline JavaScript engine, this part will involve the contents of the interpreter / compiler, and will introduce the differences and points in common between the different engines;

2.JavaScript object model;

3. Optimization property access: by engine interspersed introduce the concept of Shapes, Transistion chain tree, ICs and so on is how to optimize the acquired object properties;

4. efficient storage array;

5.Take-aways: to do a full-text content summary, and gave two suggestions.

1. JavaScript engine workflow

All this had to begin from JavaScript code you write. JavaScript parsing engine after its source is converted into an abstract syntax tree (AST). Based on AST, the interpreter will be able to work and produce bytecode. Great! At this engine is executing JavaScript code.

 

 

 

1.1 JavaScript engine interpreter / compiler processes

Now, let's focus on the actual execution of JavaScript code that this part of the process, that is where the code is interpreted and optimized, and discuss some of the differences that exist between the major JavaScript engine.

In general, (all JavaSciript engine) has an interpreter and comprising optimizing compiler process flow. Wherein the interpreter can quickly generate bytecode is not optimized, while optimizing compiler will take longer to eventually generate highly optimized machine code.

 

 

 The general procedure is almost the same with the V8 engine used in the workflow and Node.js in Chrome:

 

 

 

The interpreter is referred to as V8 Ignition, which is responsible for generating and executing bytecode. When it is running bytecode data collection and analysis, and then it can be used to accelerate (code) of the execution speed. When a function becomes hot, such as it is often called, the generated bytecode and analysis of data will be passed to our TurboFan-- optimizing compiler, it generates highly optimized machine code based on the analysis data.

 

 

 

 SpiderMonkey, Firefox and the  use of SpiderNode in Mozilla's JavaScript engine, there are a number of different places. They have two optimizing compiler. Code interpreter to explain Baseline compiler, the partially optimized code compiler can generate. Analysis of data collected when the code is run in conjunction with, IonMonkey compiler can generate highly optimized code. If the attempt fails optimization, IonMonkey will fall back to Baseline stage code.

 

 

 Chakra, and Edge for  Microsoft JavaScript engine Node-ChakraCore two projects, there are two similar compiler optimization settings. Interpreter code optimized to SimpleJIT-- Representative wherein JIT Just-In-Time compiler - it partially optimized code may be generated. Analysis of binding data, FullJIT may generate optimized code deeper.

 

 

 

JavaScriptCore (abbreviated as JSC), Apple's JavaScript engine, Safari and React Native is used for two projects, it reaches the ultimate three different optimizing compiler allows effects. Lower LLInt interpreter passes the code interpreter Baseline to the compiler, and (after Baseline compiler) optimized code will be passed to the compiler DFG, (DFG compiler after treatment) the results of the final pass compiler FTL deal with.

Why do some engine will have more optimizing compilers do? This is completely compromises choice. The interpreter can quickly generate bytecode, the bytecode is usually but not efficient enough. On the other hand, optimizing compiler process takes longer, but it will eventually generate more efficient machine code. In the end is quick access to executable code (interpreter), or take more time but in the end the best performance running code (optimizing compiler), which contains a balance. Some engine selects to add a plurality of different time-consuming optimizing compiler / efficiency characteristic, with higher complexity by more fine-grained control over the cost of such compromise.

We have just highlighted the JavaScript engine in each main difference between interpreter and compiler optimization process. In addition to these differences, all JavaScript engines have the same architecture: that is to have some kind of a parser and interpreter / compiler processes.

2. JavaScript Object Model

For example, JavaScript engine is how to achieve JavaScript object model, and what techniques they use to speed up JavaScript object properties get the speed? It turns out that all the major engines are very similar in the realization of this.

ECMAScript specification is defined as substantially all of the objects mapped to the string key  property attribute dictionary.

 

 

 In addition  , the specification also defines the following properties: [[Value]]

 

  • [[Writable]] Determine whether the property can be re-assigned;

  • [[Enumerable]] Determine whether this property appears in the  cycle; for-in

  • [[Configurable]] Determine whether the property can be deleted.

[[双方括号]]The symbol indicates that looks something special, but that is not directly exposed specification defines a JavaScript representation of the property. You can still in JavaScript by  the specified object's API property values: Object.getOwnPropertyDescriptor

const object = { foo: 42 };
Object.getOwnPropertyDescriptor(object, 'foo');
// → { value: 42, writable: true, enumerable: true, configurable: true }

JavaScript is an object of this definition, the array it?

You can imagine the array into a special set of objects. One difference is the array index array will both special handling. Array index referred to herein is a term specific ECMAScript specification. In JavaScript, the array is limited to a maximum of 2 ^ 32-1 have items. Refers to any valid array index index within the limits, i.e., any integer from 0 to 2 ^ 32-2.

Another difference is that there is a magical array of  attributes. length

const array = ['a', 'b'];
array.length; // → 2
array[2] = 'c';
array.length; // → 3

In this example, array when generating unit of length 2. Then we as an index to 2the location assigned to another element, length attribute will be automatically updated.

JavaScript on the way to define arrays and objects similar. For example, the array includes all the key indices are explicitly represented as a string. The key value is '0' position of the first array element is stored in.

 

 

 

'length' Property happens to be another non-enumeration and non-configurable attributes.

Once an element is added to the array, JavaScript is automatically updated  attribute  property values. 'length' [[Value]]

 

 

 In general, the behavior is very similar to the array of objects.

3. Optimization of property access

Let us deep knowledge of JavaScript engine is how to effectively deal with objects related operations.

JavaScript observation program, visit a property is the most common operation. JavaScript engine enables quick access to property will be crucial.

const object = {
foo: 'bar',
baz: 'qux',
};
// Here, we’re accessing the property `foo` on `object`:
doSomething(object.foo);
// ^^^^^^^^^^
3.1 Shapes

In JavaScript program, multiple objects with the same key attributes are very common. These objects have the same shape.

const object1 = { x: 1, y: 2 };
const object2 = { x: 3, y: 4 };
// `object1` and `object2` have the same shape.

Access the same property with the same shape of the object is also very common:

function logX(object) {
console.log(object.x);
//          ^^^^^^^^
}
const object1 = { x: 1, y: 2 };
const object2 = { x: 3, y: 4 };
logX(object1);
logX(object2);

With this in mind, JavaScript engine can attribute to optimize the shape of the object based on the object of acquisition. It is so achievable.

Suppose we have a property with  and  an object, it uses the dictionary data structures discussed earlier: it contains the key value represented by the string, but they point to the respective attribute values. x y

 

 

 

 

If you visit a property, for example , JavaScript engine will  find the key , and then load the appropriate property values, and returns . object.y JSObject 'y' [[Value]]

But these property values are stored in the memory of how it? Should we store them as a  part of? Suppose we encounter more objects of the same shape later, then in  their store contains a complete dictionary of attribute names and values is very wasteful (space), because all objects with the same shape we have repeated the attribute name . It is too redundant and introduces unnecessary memory usage. As optimization, engine objects  stored separately. JSObject JSObject Shape

 

 

 

 Shape In addition to containing  all the attribute names and the rest outside the properties. Instead,  comprising  an offset value for the inside, in order to know where to find specific JavaScript engine value. Each having the same shape  are pointing to this  example. Each now  only need to store only those values for this object is. [[Value]]Shape JSObject JSObject Shape JSObject

 

 

 

When we have multiple objects, advantages become visible. No matter how many objects as long as they have the same shape, we only need their shape and key attribute information stored once!

All of the JavaScript engine are used as shape optimization, but have different address:

  • Papers call them Hidden Classes (easily confused with class concept in JavaScript)

  • They called V8 Maps (and easily in JavaScript  to confuse the concept) Map

  • They called Chakra Types (easy and JavaScript dynamic type and keyword  confusion) typeof

  • JavaScriptCore call them Structures

  • SpiderMonkey call them Shapes.

3.2 Transition chain with tree

If you have an object with a particular shape, but it Youxiang you add a property, what will happen this time? How to find the JavaScript engine is the new shape?

const object = {};
object.x = 5;
object.y = 6;

In JavaScript engine, the representation of the shapes is referred to as transition chain. The following shows an example:

 

 

 The object does not have any properties in the initialization, so that it points to a null shape. The next statement object added value for  the attribute , the attribute contains a JavaScript engine steering  Shape, and to  the first offset is added at a 0 value . Next, a statement adds a property , then the steering engine comprising another  and  Shape, and the value  attached to (at offset  at). 5 “x” “x” JSObject 5 'y' 'x' 'y' 6 JSObject 1

We do not even need to complete each Shape memory attribute table. Instead, each Shape just need to know it introduced new attributes. For example, in this case, we do not have to last a Shape stored on  it can be found on the earlier of the chain of information, because. To do this, each Shape of Shape will before its connected: 'x'

If you wrote the JavaScript code , the JavaScript engine will look for properties along transition chain until you find the introduction of property Shape. o.x “x” “x”

However, if you just can not create a transition chain it? For example, if you have two empty object, and each object you add a different attribute?

const object1 = {};
object1.x = 5;
const object2 = {};
object2.y = 6;

In this case we will have to branch operations, then we end up with a transition tree instead of transition chain:

 

 

 

Here, we create an empty object , and then add a property to it . We ultimately obtained contains a single value , and two Shapes: empty and contains only attributes Shape Shape. a 'x' JSObject x

The second example is an empty object from  the beginning, but after being added to a different property . We shape the final form two chains, a total of three shape. b 'y'

Does this mean that we always need to start with an empty shape it? It is not. Engine for literal objects contain attributes will apply some optimization. Let's say we start adding either from an empty object literal  property, either have a property that already contains  an object literal: x x

const object1 = {};
object1.x = 5;
const object2 = { x: 6 };

In the first example, we start with an empty shape, then turned to include  shape, which, as we have seen before us. x

In  one example, having a property to directly generate  the object is significant, not from the empty object and then transition connection. object2 x

 

 

 

 

Attribute contains  literal object from the group consisting  shape begins to be effectively empty skip shape. SpiderMonkey and V8 (at least) to do so. This optimization transition shortened chain, and is configured such that an object from the literal more efficient. 'x' 'x'

Benedikt Bowen  surprising polymorphism in React applications discussed how these subtleties affect actual performance.

3.3 Inline Caches (ICs)

Shapes main motivation behind the concept of Inline Caches or ICs. ICs are key factors have contributed to the rapid run JavaScript! JavaScript engines use ICs to remember where to find information about object properties, to reduce the number of costly lookup.

There is a function that takes an object and removed from the attribute  values: getX x

function getX(o) {
   return o.x;
}

If we execute this function in JSC, it generates byte code as follows:

 

 

 

A command  (from the first parameter ) in the load attribute  values and stored into the address  of. We returned the second instruction stored  content. get_by_idarg1 'x' loc0 loc0

JSC also  instructions embedded Inline Cache, which consists of two uninitialized slots. get_by_id

 

 

 Now let's say we use the object  to call  a function. As we know, this object contains a property  of Shape, Shape memory properties of the  offsets and other properties. When you execute the first function,  instruction looks for the property , and found that the offset value is stored in its  place. {x:'a'} getX 'x' xget_by_id 'x' 0

 

 Embedded in the  shape and offset of the IC memory instruction attribute: get_by_id

 

 For subsequent operation, only the IC Shape contrast, if it is the same as before, only the attribute value is loaded from the memory offset. Specifically, if the shape before the JavaScript engine to see an object to be recorded through the IC, it is no longer necessary contact with the attribute information - but can skip expensive lookup attribute information (the process). Each time this attribute much faster than Find.

4. efficient storage array

For an array, the array storage attributes such as indexes, etc. are very common. The value of the property is referred to as array elements. Characteristic storage properties of each array each array element (property attributes) would be a wasteful storage. On the contrary, because the array index default attribute is writable, enumerable and configurable, JavaScript engines use this to separate array elements with other naming attributes are stored.

Consider this array:

 const array = [
'#jsconfeu',
];

Engine stores the length of the array ( 1), and comprising a point  and  Shape characteristic properties. offset 'length'

 

 This've seen similar before us ...... but an array of values ​​stored where?

 

 

 

Each has a separate array elements backing store, which contains the attribute values ​​for all of the array index. JavaScript engine does not have to store any attribute characteristics to the array elements, because they are usually writable, enumerable and configurable.

So if it is not the usual situation? If you change the properties of the array elements, how to do?

// Please don’t ever do this!
const array = Object.defineProperty(
[],
'0',
{
  value: 'Oh noes!!1',
  writable: false,
  enumerable: false,
  configurable: false,
}
);

The above code fragment defines a named  attribute (which happens to be an array index), but the characteristic ( ) is provided to a non-default value. '0'value

In this case the edge, JavaScript engine will all elements backing store the dictionary as a subscript of an array mapped to the property characteristics.

 

 Even if only one array element having a non-default attribute, backing store processing of the entire array will enter this slow and inefficient mode. Avoid using the array index Object.defineProperty

5. Take-aways

We have learned is how to store the JavaScript engine and an array of objects, and Shapes and how IC is optimized for their common operations. Based on this knowledge, we have identified a number of practical JavaScript coding skills help to improve the performance of:

  • Always initialize the object in the same way, to ensure that they will not come to a different shape direction.

  • Do not confuse the array element attribute property (property attributes), to ensure efficient storage and manipulation thereof.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin www.cnblogs.com/zhouyideboke/p/11818741.html