当前位置:网站首页>Chrome browser engine blink & V8

Chrome browser engine blink & V8

2020-11-09 10:50:00 InfoQ

{"type":"doc","content":[{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":" background "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" This article is the second in my front-end technology series on how browsers work . Browser engine ( Also known as layout engine or rendering engine ) Is an important part of the browser . The most important job of browser engine is to make HTML Resources in text and other pages are transformed into pages that interact with users ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Besides the browser engine , Layout engine and rendering engine are two other related concepts , Theoretically , The two engines can be implemented independently , But in reality , It is often rare to separate the two ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In addition to the layout and rendering engine , The browser engine also follows "},{"type":"link","attrs":{"href":"https://en.wikipedia.org/wiki/Content_Security_Policy","title":null},"content":[{"type":"text","text":" Document security policy (Content Security Policy)"}]},{"type":"text","text":" To ensure that sites are independent of each other ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Running JavaScript Code function , Basically, mainstream browsers use separate engines , At first JavaScript Language is only used in browsers , But now JavaScript It can be used almost anywhere , This needs to be JavaScript The engine can be used independently of the browser ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" And like "},{"type":"link","attrs":{"href":"https://en.wikipedia.org/wiki/Electron_(software_framework)","title":null},"content":[{"type":"text","text":"Electron framework"}]},{"type":"text","text":" Such a technology is integration Chromium Rendering engine and Nodejs The implementation of the ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" I want to put V8 As detailed as possible , There will be more coverage , Can be read over and over again :)."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":" Common browser engines "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The browser engine is Web A series of standards in platform technology (HTML、CSS、ECMAScript、WebGL、Web Storage wait ) The concrete realization of , Different browser engines follow the same standard , It also implements additional functions ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Gecko yes Mozilla The browser engine for , stay Firefox Use in ,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#333333","name":"user"}}],"text":"SpiderMonkey yes Firefox Of JavaScript engine ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Apple by Safari The browser created Webkit engine ,Webkit The engine has built-in "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#333333","name":"user"}}],"text":"JavaScriptCore engine . although Apple Allow in IOS Other browsers can be used on the device instead Safari, But what is used is through App Store Distributed browsers must use Webkit engine . for example ,Opera Mini The browser IOS Use on equipment Webkit engine , And on other devices Blink engine ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Google First use Webkit As Chrome Browser engine , Later, with Webkit The engine created Blink engine , All based on Chromium Products derived from open source browsers use blink engine . And the famous V8 The engine is Chromium-based Browser's JavaScript engine ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Microsoft Defending your own EdgeHTML engine , As the old Trident An alternative to the engine . new Edge The browser is already in use Chromium Of Blink The engine is on , and EdgeHTML The engine is only in window 10 Upper "},{"type":"link","attrs":{"href":"https://en.wikipedia.org/wiki/Universal_Windows_Platform","title":null},"content":[{"type":"text","text":"Universal Windows Platform"}]},{"type":"text","text":" Is used in ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c2/c2d5a491c0b230edf39337130cd12f67.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" If the world is united for a long time, it must be divided , Long period of division , With Edge And joined in Blink Camps , Basically Webkit Kernel and Webkit The derivation of the kernel Blink Has dominated the browser market . So far , only Chrome Has a market share of 60% . Next , Let's talk about it Blink and V8 engine ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"Chromium & Blink"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Broadly speaking ,Blink All rendering work in the browser tab is realized , These include :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Realized Web Standards in the platform , for example HTML standard , Include DOM、CSS etc. ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Built in V8 The engine is used to run JavaScript."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Get resources from the network stack "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" structure DOM Trees "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Computing styles and layouts "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Built in "},{"type":"link","attrs":{"href":"https://chromium.googlesource.com/chromium/src/+/HEAD/cc/README.md","title":null},"content":[{"type":"text","text":"Chrome Compositor"}],"marks":[{"type":"underline"}]},{"type":"text","text":" And the ability to draw graphics "}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" With the help of "},{"type":"link","attrs":{"href":"https://chromium.googlesource.com/chromium/src/+/HEAD/content/public/README.md","title":null},"content":[{"type":"text","text":"Content public APIs"}],"marks":[{"type":"underline"}]},{"type":"text","text":",Blink Can be built into many things like Chromium,Android WebView and Opera In such an application ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":" process / Thread Architecture "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" process "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Chromium Have a multi process architecture .Chromium There is a browser process and multiple rendering processes with sandbox capabilities .Blink Run in the rendering process ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" From a security point of view , It's very important to keep sites separate from each other , This is called the "},{"type":"text","marks":[{"type":"strong"}],"text":" Site isolation (Site Isolation)"},{"type":"text","text":". Theoretically speaking , A rendering process should be responsible for rendering at most one site . But actually , When a user opens many tabs , Rendering process and site 1 Yes 1 It takes up a lot of memory . So a rendering process can be more than one iframe Or shared by the tab , That is to say, more than one page iframe May be rendered by more than one rendering process , And on multiple pages iframe It can also be rendered by the same rendering process ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" therefore , stay iframe, There is no one-to-one relationship between the tab and the rendering process ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" because Blink Run in the sandbox in the rendering process , When Blink Need to access files or videos or access user information (cookie、password etc. ) Must communicate with the browser process . This communication between different processes is "},{"type":"link","attrs":{"href":"https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md","title":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"Mojo"}]},{"type":"text","text":" Realization . With Chromium Constantly evolving towards a service-oriented architecture ,Blink Can pass Mojo To reduce the dependence of the sender and receiver on the concrete implementation in the process of message delivery ( Services may be in multiple processes , It may also be in the same process , Message delivery is different )"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/24/240541c94b8227856e0c4062a8f9db7e.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Mojo"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Mojo It's a collection of Libraries , Used to provide an in-process or cross process communication scheme , It includes platform independent generic IPC programme 、 news IDL Formatting and binding libraries that can be integrated with different languages ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/d9/d990029007862acd8e71392f766b48ee.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Message pipe"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One "},{"type":"text","marks":[{"type":"strong"}],"text":" News channel (Message pipe)"},{"type":"text","text":" Build two of them "},{"type":"text","marks":[{"type":"strong"}],"text":" Endpoint (endpoint)"},{"type":"text","text":" The passage between . Each endpoint has a queue for receiving messages , You can also send a message to another endpoint , And the message channel is bidirectional ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Mojom"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Mojom The file describes the type of message ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" With message channels and message types , An endpoint in a channel can be specified as "},{"type":"codeinline","content":[{"type":"text","text":"Remote"}],"marks":[{"type":"strong"}]},{"type":"text","text":", It can send Mojom The type of message defined in the file . The other endpoint can be specified as "},{"type":"codeinline","content":[{"type":"text","text":"Receiver"}],"marks":[{"type":"strong"}]},{"type":"text","text":", For receiving messages ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" Threads "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Blink Contains a main thread , Multiple Worker Threads , There are other threads ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Almost all the important work runs on the main thread . Including running JavaScript( except Workers),DOM Generate ,CSS Style and layout calculation, etc , Therefore, the key to the optimization of interactive performance is mainly around the main thread ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Blink Would be Web workers,Service workers Create separate threads . Even though it's running JavaScript, But the main thread and worker The running environment of threads is not shared , Data needs to be delivered through messages ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Blink and V8 It's possible to create others for audio and video , Database and garbage collection (GC) And so on ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" For inter thread communication , Will use PostTask Provided api. Except for real performance reasons , Using shared memory for communication is not recommended , This is also Blink Do not use thread locks (MutexLocks) Why ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/89/89ab6c79bbfa58c540f5ebc72be974b5.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"Page, Frame, Document, DOMWindow"}]},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" Concept "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One "},{"type":"text","marks":[{"type":"strong"}],"text":" page (Page)"},{"type":"text","text":" Represents a browser tab , A single rendering process may be responsible for rendering multiple pages ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One "},{"type":"text","marks":[{"type":"strong"}],"text":" box (Frame)"},{"type":"text","text":" Represents the main frame or a iframe, One "},{"type":"text","marks":[{"type":"strong"}],"text":" The page contains at least one box ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One "},{"type":"text","marks":[{"type":"strong"}],"text":"DOMWindow"},{"type":"text","text":" representative JavaScript Medium window object , Each box has only one "},{"type":"text","marks":[{"type":"strong"}],"text":"DOMWindow"},{"type":"text","text":"."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One "},{"type":"text","marks":[{"type":"strong"}],"text":"Document"},{"type":"text","text":" representative JavaScript Medium window.document object , Each box has only one "},{"type":"text","marks":[{"type":"strong"}],"text":"Document."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One "},{"type":"text","marks":[{"type":"strong"}],"text":"ExecutionContext"},{"type":"text","text":" Abstract A from the main thread Document, stay worker Abstract in thread WorkerGlobalScope."}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Rendering Progress : page = 1 :N"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" page : box = 1 :M"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Frame : DOMWindow : Document ( or ExecutionContext) In any case it is 1 : 1 : 1 , But sometimes the citation relationship changes ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" Cross process iframes(OOPIF)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Although site isolation makes pages more secure , But it adds complexity . Site isolation is dedicated to creating a rendering process for each site , example "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Such as ,"},{"type":"link","attrs":{"href":"https://mail.example.com","title":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"https://mail.example.com"}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" and "},{"type":"link","attrs":{"href":"https://chat.example.com","title":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"https://chat.example.com"}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Belong to the same site , and "},{"type":"link","attrs":{"href":"https://noodles.com","title":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"https://noodles.com"}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" and "},{"type":"link","attrs":{"href":"https://pumpkins.com","title":null},"content":[{"type":"text","text":"https://pumpkins.com"}],"marks":[{"type":"underline"}]},{"type":"text","text":" It doesn't belong to the same site . If there is a cross site iframe It may be hosted by multiple rendering processes ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" From the perspective of the main frame , The main frame is "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"LocalFrame,iframe It is RemoteFrame. from iframe From the perspective of , The main frame is RemoteFrame, and iframe It is LocalFrame."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"LocalFrame and RemoteFrame Communication is managed by the browser process ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"Web IDL binding "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Web IDL (Web Interface definition language) Is for description Web How the standards defined in the platform are implemented by the browser interface definition language , The implementation of the interfaces defined in these standards through the browser ,Web Developers can use JavaScript Object to call these standard functions .Blink While implementing these standards , Also need to V8 Medium JavaScript Provide calls Blink Way , This is it. Web IDL Bindings. Through to Web IDL Implementation and Bindings The existence of , It's like in JavaScript Access to the first child node of a node in "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" The function of (node."},{"type":"text","text":"firstChild)"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":". At the same time of realizing the general standard , The browser also implements its own unique function definition , General standards are defined in "},{"type":"link","attrs":{"href":"https://heycam.github.io/webidl/","title":null},"content":[{"type":"text","text":"the Web IDL spec"}],"marks":[{"type":"underline"}]},{"type":"text","text":", and Blink Self definition is defined in "},{"type":"link","attrs":{"href":"https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/IDLExtendedAttributes.md","title":null},"content":[{"type":"text","text":"Blink-specific IDL extended attributes"}],"marks":[{"type":"underline"}]},{"type":"text","text":" in ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Usually in idl When the file is built ,"},{"type":"link","attrs":{"href":"https://chromium.googlesource.com/chromium/src/+/master/third_party/blink/renderer/bindings/IDLCompiler.md","title":null},"content":[{"type":"text","marks":[{"type":"underline"}],"text":"the IDL compiler"}]},{"type":"text","text":" Will automatically generate for the specific implementation class Blink-V8 The binding of . When in JavaScript Call in node.firstChild when ,V8 Would call V8Node::firstChildAttributeGetterCallback() , And then call Node::firstChild() ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":" Rendering pipeline "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Rendering pipeline Defined from HTML The process from characters to displaying pixels on the screen ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/59/59f93c4bc67cf902dcaad2524f5d709f.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" You can read the previous article about this part ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"V8"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 yes Google Open source , High performance JavaScript and WebAssembly engine , Use C++ Language implementation .V8 Engines are used in Chrome、Nodejs And other applications .V8 The engine can run independently , It can also run on any C++ In the program ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One V8 An example of is called Isolate, every last isolate All have independence GC Stack space of . That means a Isolate Medium JavaScript Object cannot directly access another Isolate Objects in the ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" stay Chrome in , Each rendering process has a V8 Isolate, All sites processed by the same rendering process JavaScript The code is in the same Isolate Run in . But for the Web worker, every last worker Have your own Isolate."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" stay Isolate in , There is one or more JavaScript Context (JavaScript content).Chrome For each iframe Create a JavaScript Environmental Science . Besides , Every Chrome extension For one iframe All have their own JavaScript Environmental Science ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Blink Usually use ScriptState Object as JavaScript References to the environment ,blink::ScriptState And v8::Context with 1 : 1 The relationship between ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":" Execution pipeline "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JavaScript The running of the script needs to go through a series of processes ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/a5/a5595e9e68069bbe5d22c63c9ab8b324.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" To run JavaScript Scripts can be... From the network or cache "},{"type":"text","marks":[{"type":"strong"}],"text":" load ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Through to JavaScript The analysis of script text can generate data used to describe the structured source code ,"},{"type":"text","marks":[{"type":"strong"}],"text":" Abstract syntax tree (AST)."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Next "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Ignition Interpreter "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Will AST Into smaller ones "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":" Bytecode "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":", Each line of instruction in bytecode represents the operation on the register , When bytecode is born AST Will be abandoned to save space , Subsequent execution and optimization are based on bytecode ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" When the interpreter executes bytecode ,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Object Shapes"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Will try to cache the type of the object in the code to generate "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Type Feedback"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":", When you access these objects, you try to get them from the cache , If it can't be found, find and update the cache dynamically ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"TurboFan"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" yes V8 Code optimization compiler in , It evaluates whether the function needs to be further optimized into machine code to improve performance , Functions that need to be optimized are compiled into "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Optimized Code"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" But when the compiled function is found that the data type of the variable in the function is different from the previous cache type , You need to abandon the optimized code and go back to bytecode for reinterpretation and execution ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Let's look at each process one by one ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" load (Loading)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Loading is V8 obtain JavaScript The process of script text ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/33/33980d9f58ed08dcbca52989379c4b24.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 Not responsible for downloading resources , So these resources may come from the Internet 、 cache , It may also come from Service worker."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 You can download the file at the same time for the next analysis work ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 Have the ability of script hot loading :"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Warm Load"},{"type":"text","text":": When V8 When you run the same script again , It will cache the compiled results of the script in the hard disk ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Hot Load:"},{"type":"text","text":" On the third visit ,V8 You can skip the analysis and compilation process and read the previously compiled results directly from the hard disk ."}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" analysis (Parsing)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4f/4f9f1c010a79037cd568d8145b75bfd9.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The analysis is to JavaScript Script text is converted to "},{"type":"text","marks":[{"type":"strong"}],"text":" Abstract syntax tree (Abstract Syntax Tree) The process of ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":" Lexical analysis "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" Lexical analysis (lexical analysis)"},{"type":"text","text":" Is to convert a series of characters into "},{"type":"text","marks":[{"type":"strong"}],"text":" Mark (token)"},{"type":"text","text":" The process of . there "},{"type":"text","marks":[{"type":"strong"}],"text":" Mark "},{"type":"text","text":" Is the smallest unit of source code , The process of converting the input character stream into a tag is called "},{"type":"text","marks":[{"type":"strong"}],"text":" Tokenization (tokenization)"},{"type":"text","text":", In the process , The lexical analyzer also classifies these tags ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Common label categories are :"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" identifier (identifier):x,color,UP"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" keyword (keyword):if,var,return"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Separator (separator):(,}, ;"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The operator (operator):*,=,>"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Literal (literal):\"Hello world\", true, 666"}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" notes (comment):// A single , /* Multiple lines */"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"Scanner"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The scanner is in the first stage of lexical analysis , It is usually implemented based on state machine , You can switch between recognizable tags . Each tag can represent a character or a sequence of multiple characters . A lot of times , You can infer the type of the tag from the first non empty character , And then process the following characters one by one , Until the occurrence of a character that does not belong to the type of markup character set ( The longest consistency principle )."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" The scanner only deals with utf-16 Character set for , There is a character set conversion process before the scanner gets the character ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":5},"content":[{"type":"text","text":"Evaluator"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The evaluator is in the second stage of lexical analysis , Used to define some semantic words as "},{"type":"text","marks":[{"type":"strong"}],"text":" value (value)"},{"type":"text","text":", One "},{"type":"text","marks":[{"type":"strong"}],"text":" semantics ("},{"type":"text","marks":[{"type":"color","attrs":{"color":"#202122","name":"user"}},{"type":"strong"}],"text":"lexeme"},{"type":"text","marks":[{"type":"strong"}],"text":")"},{"type":"text","text":" It's a combination of tag type and value . Some tags have value , For example, identifier type tags , And some tags have no value , For example, separator type tags ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" for example , It's like this in the source code :"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"net_worth_future = (assets – liabilities);"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The generated semantic tags may look like this :"}]},{"type":"codeblock","attrs":{"lang":null},"content":[{"type":"text","text":"IDENTIFIER net_worth_future\nEQUALS\nOPEN_PARENTHESIS\nIDENTIFIER assets\nMINUS\nIDENTIFIER liabilities\nCLOSE_PARENTHESIS\nSEMICOLON"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":" Syntax analysis "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" Syntax analysis ("},{"type":"text","marks":[{"type":"color","attrs":{"color":"#202122","name":"user"}},{"type":"strong"}],"text":"syntactic analysis, Also called parsing"},{"type":"text","marks":[{"type":"strong"}],"text":")"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#202122","name":"user"}}],"text":" It's based on some given "},{"type":"text","text":" Formal grammar "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#202122","name":"user"}}],"text":" By word sequence ( Such as English word sequence ) The process of analyzing and determining the grammatical structure of a structured input text ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" parsers "},{"type":"text","text":"(parser) The function of is to check grammar 、 And according to the input word sequence to generate a hierarchical data structure ( It's usually a syntax tree 、 Abstract grammar tree, etc )"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":" Abstract syntax tree and scope "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" Abstract syntax tree (Abstract Syntax Tree)"},{"type":"text","text":" Is an abstract representation of the structure of the source code . It represents the syntax structure of programming language in the form of tree , Each node in the tree represents a structure in the source code ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here we take a piece of code as an example "}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function sayHi () {\n var str = \"hello world\";\n return str;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Turn it into AST The structure of the latter is like this "}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/7e/7e62d86a0d4c4277bc91ad76a679f88d.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"FunctionLiteral"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" representative sayHi function ,Block For the body of a function ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Sinister "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"VariableDeclaration"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" On behalf of the variable str Statement of ,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}},{"type":"strong"}],"text":"Assignment"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}}],"text":" For assignment ,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}},{"type":"strong"}],"text":"ReturnStatement"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}}],"text":" representative return sentence ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" there "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}},{"type":"strong"}],"text":"VariableProxy"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}}],"text":" Represents a reference to a variable , At this stage, we don't know which variable to refer to ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In this stage of analysis, in addition to generating AST, Also analyze the scope ."}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1a/1ac03cdfbd40f995afbd50da9ee3b5a8.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Through analysis , The global scope contains functions sayHi Statement of , and sayHi The scope of the function contains variables str Statement of . And two "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}},{"type":"strong"}],"text":"VariableProxy"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#323232","name":"user"}}],"text":" The referenced variables can also be determined ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#202122","name":"user"}}],"text":"V8 There are two kinds of analyzers :Preparser and Full parser.Preparser Parsers can delay functions that don't need to be analyzed immediately to reduce the time required for code startup .Preparser It only deals with parsing and error checking without generating an abstract syntax tree ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 At this stage, there are various optimization methods for scanning various types of markers , Interested students can continue reading "},{"type":"link","attrs":{"href":"https://v8.dev/blog/scanner","title":null},"content":[{"type":"text","text":"Blazingly fast parsing, part 1: optimizing the scanner"}]},{"type":"text","text":"."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here we recommend a website for analyzing abstract syntax trees :"},{"type":"link","attrs":{"href":"https://astexplorer.net/","title":null},"content":[{"type":"text","text":"AST Explorer"}]},{"type":"text","text":". In all kinds of lint Custom rule ,babel、webpack Plug in code analysis 、 It's helpful in the generated scenarios ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" explain (I"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"nterpreting"},{"type":"text","text":")"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The explanation phase will AST Convert to bytecode (bytecode). Thanks to the "},{"type":"link","attrs":{"href":"https://en.wikipedia.org/wiki/Just-in-time_compilation","title":null},"content":[{"type":"text","text":" Just in time compilation (just-in-time (JIT) compilation)"}]},{"type":"text","text":" technology , Include V8 Modern browsers inside JavaScript The engine combines "},{"type":"text","marks":[{"type":"strong"}],"text":" Precompile (AOT)"},{"type":"text","text":" High performance and interpretation flexibility ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" At first , The code is first quickly compiled by the compiler into machine code that has not been optimized , At the same time, the code that needs to be optimized is recompiled by a more advanced compiler . This improves the speed of operation , But it's also a waste of resources ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One of the most significant problems is that the compiled machine code will take up a lot of memory , Even if some code may only be executed once . To solve these problems ,V8 The team came up with a new JavaScript Interpreter ,"},{"type":"link","attrs":{"href":"https://v8.dev/docs/ignition","title":null},"content":[{"type":"text","text":"Ignition"}]},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" With the help of "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Ignition"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":",V8 Can be AST First, it's converted to simpler bytecode , Compared with the previous machine code, its size is reduced to 50% to 25% Space ."}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/35/355cb34cfd38811ba0c6e19ab7e7025c.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" from "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Ignition"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Generated "},{"type":"text","text":" Bytecodes are used as data sources by compilers and debugging tools for optimization , When bytecode is generated , The abstract syntax tree can be discarded to save memory . While generating bytecode , Also add some metadata to bytecode , Such as the location of the source code and the processing functions used to execute bytecode ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Next we use d8 Take a close look at bytecode, Here we'll take the following JavaScript Put it in the name of bytecode.js In the file of , And run d8 Debugging tools for ."}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function sayHi () {\n var str = 'hello world'\n return str\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" You can get the following results "}]},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"# d8 --print-bytecode bytecode.js\n[generated bytecode for function: (0x300d082d25e5 )]\nParameter count 1\nRegister count 2\nFrame size 16\n 0x300d082d26ae @ 0 : 12 00 LdaConstant [0]\n 0x300d082d26b0 @ 2 : 26 fa Star r0\n 0x300d082d26b2 @ 4 : 27 fe f9 Mov , r1\n 0x300d082d26b5 @ 7 : 62 3e 01 fa 02 CallRuntime [DeclareGlobals], r0-r1\n 0x300d082d26ba @ 12 : 0d LdaUndefined \n 0x300d082d26bb @ 13 : ab Return \nConstant pool (size = 1)\n0x300d082d2681: [FixedArray] in OldSpace\n - map: 0x300d08042201 \n - length: 1\n 0: 0x300d082d2631 \nHandler Table (size = 0)\nSource Position Table (size = 0)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The first 6 Go to the first place 11 The output of the line is the transformed bytecode . Among them LdaConstant、Star、Mov What's waiting for is the instruction . There are many instructions corresponding to bytecode , Here we intercept a part of , More instructions and explanations can be found in v8 Source code file for src/interpreter/interpreter-generator.cc View in ."}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/3e/3e63d210cef55982c21198790116dca3.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Before you start to analyze the code, you need to introduce "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#333333","name":"user"}},{"type":"strong"}],"text":" accumulator (Accumulator)"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#333333","name":"user"}}],"text":", The accumulator is V8 A special register in the , Used to store intermediate results "},{"type":"text","text":"."}]},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"LdaConstant [0]\nStar r0\nMov , r1\nCallRuntime [DeclareGlobals], r0-r1\nLdaUndefined \nReturn "}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"LdaConstant [0]"},{"type":"text","text":" Represents taking from the constant pool 0 And put it in the accumulator ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Star r0"},{"type":"text","text":" Indicates that the contents of the accumulator are stored in r0 In the register ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Mov , r1"},{"type":"text","text":" It means that you will The contents of the register are placed in r1 In the register ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"CallRuntime [DeclareGlobals], r0-r1"},{"type":"text","text":" To express with r0 and r1 The contents of the register are called as parameters DeclareGlobals function ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"LdaUndefined"},{"type":"text","text":" For and on behalf of Undefined Load into accumulator ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Return"},{"type":"text","text":" Represents the contents of the returned accumulator ."}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JavaScript Objects are allocated in the heap , It can't be embedded directly into bytecode . So in bytecode , Use array subscripts to represent JavaScript The location of the reference to the object ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" We modify the source code a little bit , Then analyze the more complex bytecode "}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function sayHi () {\n console.log(str)\n var str = 'hello world'\n}\n\nsayHi()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"[generated bytecode for function: (0x3da0082d25e5 )]\nParameter count 1\nRegister count 3\nFrame size 24\n 0x3da0082d26b2 @ 0 : 12 00 LdaConstant [0]\n 0x3da0082d26b4 @ 2 : 26 f9 Star r1\n 0x3da0082d26b6 @ 4 : 27 fe f8 Mov , r2\n 0x3da0082d26b9 @ 7 : 62 3e 01 f9 02 CallRuntime [DeclareGlobals], r1-r2\n 0x3da0082d26be @ 12 : 13 01 00 LdaGlobal [1], [0]\n 0x3da0082d26c1 @ 15 : 26 f9 Star r1\n 0x3da0082d26c3 @ 17 : 5d f9 02 CallUndefinedReceiver0 r1, [2]\n 0x3da0082d26c6 @ 20 : 26 fa Star r0\n 0x3da0082d26c8 @ 22 : ab Return \nConstant pool (size = 2)\n0x3da0082d2681: [FixedArray] in OldSpace\n - map: 0x3da008042201 \n - length: 2\n 0: 0x3da0082d2631 \n 1: 0x3da0082d25b1 \nHandler Table (size = 0)\nSource Position Table (size = 0)\n[generated bytecode for function: sayHi (0x3da0082d2641 )]\nParameter count 1\nRegister count 3\nFrame size 24\n 0x3da0082d280a @ 0 : 13 00 00 LdaGlobal [0], [0]\n 0x3da0082d280d @ 3 : 26 f8 Star r2\n 0x3da0082d280f @ 5 : 28 f8 01 02 LdaNamedProperty r2, [1], [2]\n 0x3da0082d2813 @ 9 : 26 f9 Star r1\n 0x3da0082d2815 @ 11 : 5a f9 f8 fa 04 CallProperty1 r1, r2, r0, [4]\n 0x3da0082d281a @ 16 : 12 02 LdaConstant [2]\n 0x3da0082d281c @ 18 : 26 fa Star r0\n 0x3da0082d281e @ 20 : 0d LdaUndefined \n 0x3da0082d281f @ 21 : ab Return \nConstant pool (size = 3)\n0x3da0082d27d5: [FixedArray] in OldSpace\n - map: 0x3da008042201 \n - length: 3\n 0: 0x3da00824a15d \n 1: 0x3da00824a1d1 \n 2: 0x3da0082d278d \nHandler Table (size = 0)\nSource Position Table (size = 0)\nundefined"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here we mainly look at the second byte code "}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"LdaGlobal [0], [0]"},{"type":"text","text":" Represents subscript from constant pool to 0 Read the content and store it in the accumulator , That is to say console. And the second one. [0] representative "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#333333","name":"user"}},{"type":"strong"}],"text":" Feedback vector slot (feedback vector slot)"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#333333","name":"user"}}],"text":" The corresponding position in , Aim to help the following optimization compiler to provide optimization information ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Star r2"},{"type":"text","text":" Represents that the contents of the accumulator are stored in r2 In the register , here r2 What is stored in console."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"LdaNamedProperty r2, [1], [2]"},{"type":"text","text":" Representative acquisition r2 The object in the register is in the constant pool 1 The attribute of the sign position . Constant pool 1 The number is stored in log,LdaNamedProperty r2, [1] That is to say console.log, And stored in the accumulator ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"Star r1"},{"type":"text","text":" Put... In the accumulator console.log Store in r1 In the register ."}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"CallProperty1 r1, r2, r0, [4]"},{"type":"text","text":" Represents a call to r1 In register console.log, With r2、r0 The contents of the register are parameters .r2 Medium is console, When we find out r0 Until the first 32 Line is the only way to store constants hello world, So call console.log Will print out the undefined."}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" perform (Execution)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/92/924f8c01fa3254e222075be8ed2d223f.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JavaScript Is a dynamic language , A single line of simple attribute access can contain complex semantics ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Object.foo It could be a simple property access , It may also call Getter, You may even need to traverse the prototype chain to find ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" This dynamism takes more time to find properties , It will slow down the speed of operation . To improve performance ,V8 Cache the results of the first analysis , When the property is accessed again, it is read directly from the cache ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 Would call GetProperty(object, \"foo\", feedback_cache), If feedback Cache for object.foo To skip any search step ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Object Shapes"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Object Shapes It's also called Hidden Classes or Maps, Represents the JavaScript Structure of objects , How attributes and elements are stored ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JavaScript As a dynamic language, it is easy to add or delete attributes in an object after instantiation ."}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"class Point {\n constructor(x, y) {\n this.x = x\n this.y = y\n }\n}\n\nconst point = new Point(1, 1)\npoint.version = '1.0.0'"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" image Java Such a static language , The attribute structure of an object can be determined before compilation , So the values of these properties can be stored in a continuous memory space , The offset between attributes can be calculated by the type of the property . But because of JavaScript The dynamics of , Property lookup is slower than static languages ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" To solve this problem ,V8 Use "},{"type":"text","marks":[{"type":"strong"}],"text":"Hidden Classes"},{"type":"text","text":" To describe the structure of an object ."}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"let point = { x:1, y:1, '2': '1', in: {} };\npoint.out = {};\npoint[1] = 1;"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" utilize d8 Debugging tools run the above code can get the following results ."}]},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"DebugPrint: 0xe4a08148b69: [JS_OBJECT_TYPE]\n - map: 0x0e4a083074d5 [FastProperties]\n - prototype: 0x0e4a082c3c69 \n - elements: 0x0e4a08148bc5 [HOLEY_ELEMENTS]\n - properties: 0x0e4a08148cc9 \n - All own properties (excluding elements): {\n 0xe4a082d25c5: [String] in OldSpace: #x: 1 (const data field 0), location: in-object\n 0xe4a082d25d5: [String] in OldSpace: #y: 1 (const data field 1), location: in-object\n 0xe4a082d25f5: [String] in OldSpace: #in: 0x0e4a08148c1d (const data field 2), location: in-object\n 0xe4a082d2605: [String] in OldSpace: #out: 0x0e4a08148c6d (const data field 3), location: properties[0]\n }\n - elements: 0x0e4a08148bc5 {\n 0: 0x0e4a08042429 \n 1: 1\n 2: 0x0e4a08044939 \n 3-19: 0x0e4a08042429 \n }\n0xe4a083074d5: [Map]\n - type: JS_OBJECT_TYPE\n - instance size: 24\n - inobject properties: 3\n - elements kind: HOLEY_ELEMENTS\n - unused property fields: 2\n - enum length: invalid\n - stable_map\n - back pointer: 0x0e4a083074ad \n - prototype_validity cell: 0x0e4a082d277d \n - instance descriptors (own) #4: 0x0e4a08148c89 \n - prototype: 0x0e4a082c3c69 \n - constructor: 0x0e4a082c38a1 \n - dependent code: 0x0e4a080421b5 \n - construction counter: 0"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"map "},{"type":"text","text":" It describes point Details of the type of object "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"prototype "},{"type":"text","text":" It describes point A prototype reference to an object "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"elements "},{"type":"text","text":" Used to hold attributes of element types "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"properties "},{"type":"text","text":" Used to hold properties of named types "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"in-object "},{"type":"text","text":" The value representing the property is stored directly in the object "}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" stay JavaScript Object type , Attributes can be divided into "},{"type":"text","marks":[{"type":"strong"}],"text":" Named properties (Named properties) And elements (Elements)."},{"type":"text","text":" Named properties are properties whose property names are non numeric , And element attributes are attributes like array subscripts ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/b5/b5251530f458f909f9338984faa9e210.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Hidden Class Named attributes and elements are stored in different spaces , They can be stored in either an array or a dictionary . stay JavaScript Each object in has a Hidden Class Used to describe the type information of an object ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" And when you have the type information of these objects , Multiple objects with the same attribute name and number can share one type information ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" After the object is initialized , The modification of attributes in the object will form new type information ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/4c/4c5ef65684116513b5ebe57d7f306ddd.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" When the attributes of the object are added in different order ,v8 Create a new branch ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/65/658cec5e92b474411d3c0ac047760a0a.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" At the same time, the storage location of attributes will also change ."}]},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"0xe4a082d25f5: [String] in OldSpace: #in: 0x0e4a08148c1d (const data field 2), location: in-object\n0xe4a082d2605: [String] in OldSpace: #out: 0x0e4a08148c6d (const data field 3), location: properties[0]"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here we focus on point Object in and out attribute , We found that when the object is initialized, the definition of in Properties are stored inside the object (in-object), After the object is initialized out Attributes are added to properties in , And access in-object The properties of are faster than properties Properties in ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" So the dynamic modification of attributes will result in New Hidden Class And the change of attribute storage location . In the actual development, try not to add or delete the attributes in the object dynamically after the object is initialized ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" With type information , visit JavaScript The properties of the object can be quickly located by the coordinate offset as in the static language ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":"Inline Cache"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 adopt "},{"type":"text","marks":[{"type":"strong"}],"text":" inline caching (Inline Cache)"},{"type":"text","text":" Policy optimizes the performance of access objects ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"IC Create a function called "},{"type":"text","marks":[{"type":"strong"}],"text":" Feedback vector ("},{"type":"text","marks":[{"type":"color","attrs":{"color":"#333333","name":"user"}},{"type":"strong"}],"text":"FeedBack Vector"},{"type":"text","marks":[{"type":"strong"}],"text":")"},{"type":"text","text":" Is used to store information about objects and their properties ."}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"function load(o) {\n return o.x\n}\n\nload({ x: 10 })"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" here IC It's stored in the feedback vector "},{"type":"codeinline","content":[{"type":"text","text":"{ x: 10 }"}]},{"type":"text","text":" Object type information and x Attribute information ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/35/35c891a284d1b7b32508a7dc56cf26f4.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The feedback vector is similar to the database table structure ,0 Represents the position in the table "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"LOAD_IC Represents the type of operation "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"Monomorphic The state of the current feedback vector is "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":" Singlet "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":", Status is IC A very important concept in , In addition to the singlet, there's "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":" polymorphic (Polymorphic)"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" and "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D5156","name":"user"}},{"type":"strong"}],"text":" Complex state (M"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"egamorphic"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D5156","name":"user"}},{"type":"strong"}],"text":")"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D5156","name":"user"}}],"text":". In the process of function running, with the change of parameter type , The state may change ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#4D5156","name":"user"}}],"text":"Map The type information of the object is stored in ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Bitfield Put the information of the object properties in the ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" With the feedback vector ,load When the function is called repeatedly, if the parameter type does not change , You can go through bitfield Quickly find the value in the attribute by using the attribute information stored in , Avoid repeated dynamic queries ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" When the type of the parameter changes :"}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"load({ x: 100 })\nload({ y: 1, z: 2 })"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" You need to cache both types . here , The state in the feedback vector will go from "},{"type":"text","marks":[{"type":"strong"}],"text":" Singlet "},{"type":"text","text":" become "},{"type":"text","marks":[{"type":"strong"}],"text":" polymorphic ,"},{"type":"text","text":" The structure of the feedback vector also changes ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1c/1cd9e8b08fbf8612f26188df973d65e5.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Feedback vector from the original storage of a type information into an array structure to store multiple types of information ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Next we pass d8 Tools and Indicium Tools to analyze IC Change process of ."}]},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"class Test {\n constructor(a, b, c, d, e) {\n if (a) {\n this.a = a;\n }\n\n if (b) {\n this.b = b;\n }\n\n if (c) {\n this.c = c;\n }\n\n if (d) {\n this.d = d;\n }\n\n if (e) {\n this.e = e;\n }\n }\n}\n\nconst util = {\n merge(test) {\n return test.a + test.b + test.c + test.d + test.e;\n }\n};\n\nlet rst;\n\nconsole.time('Test');\nconst test1 = new Test(1);\nfor (let i = 0; i < 10e6; i++) {\n rst = util.merge(test1);\n}\n\nconst test2 = new Test(null, 1);\nfor (let i = 0; i < 10e6; i++) {\n rst = util.merge(test2);\n}\n\nconst test3 = new Test(null, null, 1);\nfor (let i = 0; i < 10e6; i++) {\n rst = util.merge(test3);\n}\n\nconst test4 = new Test(null, null, null, 1);\nfor (let i = 0; i < 10e6; i++) {\n rst = util.merge(test4);\n}\n\nconst test5 = new Test(null, null, null, null, 1);\nfor (let i = 0; i < 10e6; i++) {\n rst = util.merge(test5);\n}\nconsole.timeEnd('Test');"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here we are Test In the process of instantiation, dynamically add a, b, c, d, e Attribute to create 5 Medium type information . And record 5 The running time of the secondary cycle ."}]},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"d8 ic.js --trace-maps --trace_ic --log-source-code\nconsole.timeEnd: Test, 12668.593000"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/31/3156ab34f61eddeaf58446ce4c1ce7cd.png","alt":null,"title":"image.png","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" adopt Indicium Analysis of the log , We found that calling merge Function time , The state of the feedback vector changes from 0 To "},{"type":"text","marks":[{"type":"strong"}],"text":" Complex state "},{"type":"text","text":" Changed the 3 Time ."}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"merge The first time the function is called, the empty feedback vector is put into { a: 1 } Type information for , At this point, the state of the feedback vector changes from 0 become "},{"type":"text","marks":[{"type":"strong"}],"text":" Singlet "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" On the second call { b: 1 } Is put into the feedback vector , The parameter type has changed , The state of the feedback vector changes from "},{"type":"text","marks":[{"type":"strong"}],"text":" Singlet "},{"type":"text","text":" become "},{"type":"text","marks":[{"type":"strong"}],"text":" polymorphic "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Third 、 Four times it was { c: 1 } and { d: 1 } The type information of is put into the feedback vector , state "},{"type":"text","marks":[{"type":"strong"}],"text":" polymorphic "},{"type":"text","text":" become "},{"type":"text","marks":[{"type":"strong"}],"text":" polymorphic "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" When the fifth object { e: 1 } Is passed in function merge when , The type information stored in the feedback vector has reached 5 Kind of , here V8 No longer cache type information to optimize running speed , Status from "},{"type":"text","marks":[{"type":"strong"}],"text":" polymorphic "},{"type":"text","text":" become "},{"type":"text","marks":[{"type":"strong"}],"text":" Complex state "}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" When the object in the feedback vector is only 1 When the type information is, the state is singlet ,2-4 Species time is polymorphic , exceed 4 After planting, it becomes a complex state ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Now we're going to code Test In the constructor if Get rid of , Let's Test The constructed object structure remains consistent , Rerun the debug command to get the following results ."}]},{"type":"codeblock","attrs":{"lang":"shell"},"content":[{"type":"text","text":"console.timeEnd: Test, 560.487000"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/82/82e7ca527db7da311af1a8acdc993bc5.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" We find that while running time is greatly reduced , The state of the feedback vector is changed from the original 4 The change becomes 1 Kind of ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":" Through to IC Analysis of , In actual development , Minimize the number of types of function arguments ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":" Optimize (Optimizing)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The optimization process is V8 utilize "},{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" The process by which a compiler compiles bytecode into machine code ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/69/694362e2487221a69a2ade93ef1a7aaf.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" It's a \"Sea-of-nodes\" Graph based compilers , It will be in the code "},{"type":"text","marks":[{"type":"strong"}],"text":" data 、 Process control and side effects depend on "},{"type":"text","text":" Express in the form of nodes . Through different stages of optimization , Compiling code into machine code ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/2b/2b0f1150e44813a150c927d897c083b1.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In the process of explaining ,TurboFan Individual functions will be selected for optimization to ensure that the optimization is meaningful . Compared to previous compilers ,"},{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" With "},{"type":"text","marks":[{"type":"strong"}],"text":"Ignition"},{"type":"text","text":" Generated bytecode as data source , And there's no need to rebuild AST structure ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" The optimization process can be seen in the figure below "}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/79/791b3b3527370d1fd892d38218f38ceb.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" stay "},{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" In the process of compiling bytecode into machine code , It has also been simplified "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/05/05df35d2e21b2a963b777c737c87f44d.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" adopt "},{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" Further optimization of bytecode , Give Way JavaScript Functions in code can run at the same speed as compiled languages ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The reason "},{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" It can be compiled like a static language JavaScript It needs to be built on "},{"type":"text","marks":[{"type":"strong"}],"text":"Type Feedback"},{"type":"text","text":" On , That is to say, compilation is meaningful only when the object type information in the function remains unchanged . So when the optimized function finds that the data type changes during the running process, it needs to abandon the optimized code , Go back to the explain execution process, execute and update the type information ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":" memory management "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 The garbage collector is called "},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Orinoco"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":"."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In a garbage collection process ,"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Orinoco"},{"type":"text","text":" Access all the objects in the program through the object reference , The memory occupied by objects that cannot be accessed by the collector will be recycled ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"javascript"},"content":[{"type":"text","text":"window.obj = new Object()\nwindow.obj = new Object()"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/8e/8ecc1d7957478e0cabeb0ff6c099aa95.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" because obj Points to a new object , So the red dotted line in the picture will be recycled ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}},{"type":"strong"}],"text":"Orinoco"},{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Divide the heap space of objects into new ones 、 The old two generations . The newly created objects are placed in the new generation , Objects that live longer are stored in older generations ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The maximum storage space of the new generation can reach 32M, And the old generation can achieve 2G."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Except for the storage space of the object , You also need to allocate separate memory space for the code to be executed ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"JavaScript The object in is by "},{"type":"text","marks":[{"type":"strong"}],"text":"Orinoco"},{"type":"text","text":" Recycling , Other such as DOM Things like that are made up of Blink The garbage collector "},{"type":"text","marks":[{"type":"strong"}],"text":"Oilpan"},{"type":"text","text":" Handle , therefore V8 adopt "},{"type":"text","marks":[{"type":"strong"}],"text":"Orinoco"},{"type":"text","text":" Solved cross JS/C++ Object reference access function ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 There are different garbage collection strategies :"}]},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Minor GC(Scavenge) Used in the Cenozoic era "}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Major GC(Full Mark-Compact) For the entire heap space "}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Minor GC"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" The memory space in the new generation is divided into two equally large spaces , A place to put a newly created object , The other is empty ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c8/c8466ea9f03a74902e0b8e6b66ec5dab.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" When Minor GC When triggered, the accessible objects in the object area will be copied to the free area , Then new object areas and free areas are formed ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/5e/5eb3591ac7c65430000ac5616ffe06e1.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" If an object experiences twice Minor GC If they survive, they will be copied into the old generation ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Major GC"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Major GC There are several stages "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":" Mark (Marking)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" This stage V8 Will try to access all objects to mark those "},{"type":"text","marks":[{"type":"strong"}],"text":" Accessible "},{"type":"text","text":" and "},{"type":"text","marks":[{"type":"strong"}],"text":" inaccessible "},{"type":"text","text":" The object of ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" compaction (Compaction)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"color","attrs":{"color":"#000000","name":"user"}}],"text":" Compaction is the process of defragmentation , Because copying objects is a costly operation , therefore V8 It only compacts the highly fragmented pages (Page) ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/84/844508a47c1be703417bd1cde0368ad8.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" During compaction , Objects from the already fragmented page will be copied to the new page ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":4},"content":[{"type":"text","text":" eliminate (Sweep)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Clearing this phase will clear the memory of objects that cannot be accessed in the page , At the same time Free List Update these blank areas in . This process and the compaction process basically start at the same time , For inaccessible objects that do not need to be compacted, the memory space is cleared directly ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f9/f9bd42379623133fd77ea39427f248f5.png","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Major GC Will run Blink Oilpan GC The process , therefore Oilpan Objects that need to be cleared in the Major GC Destroyed in the process ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"State of GC in V8"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" If GC The work is done entirely on the main thread , It may have an impact on the user experience ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" It is often difficult to combine low latency with high throughput for garbage collection , In order that the garbage collection process does not block other work on the main thread ,V8 The whole garbage collection process is divided into several stages in an incremental way , These different stages of the recycling process can be interspersed in the main thread of other work gaps . meanwhile , Use multithreading parallel way to make garbage collection work on non main thread ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Minor GC"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In the new generation GC In the process ,V8 take GC Tasks are assigned to helper threads . Each thread receives some pointers , And immediately start accessing these objects and copying them to the free space . Because it is possible to access the same object during the execution of tasks by multiple threads , So these tasks have to be atomic and synchronized . When a thread moves an object , The object's pointer is updated to the new location , When other threads access the object, the location has changed ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/ed/ed657eb15946a66327d3bdac5bb4426f.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":3},"content":[{"type":"text","text":"Major GC"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" When the heap space is close to the limit , Parallel tagging starts running in the helper thread , And Minor GC The difference is that this part of the work is entirely in the help thread , The main thread is only responsible for summarizing ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/fa/fab5a6b9a3ee08634d91a945f467a42a.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" When the marking work in the helper thread is finished , The main thread will pause JavaScript And quickly confirm that all surviving objects have been marked , And then with a part of the help thread to complete the compaction work at the same time , meanwhile , The other part of the thread will start to clean up the objects that need to be destroyed and set up the Free List Update this part of the space ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Through years of evolution , current V8 Garbage collection has improved significantly . In the development process , In most cases, we don't need to think about garbage collection , But through the study of this part of the content , Can let us better grasp the principle of garbage collection , And these principles are universal in different languages ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":" summary "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Blink As Chrome Is running in the rendering process , Responsible for almost all the work that happens in the browser tab ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Blink In the realization of Web The standard defined in the specification also implements the category of Chrome Unique function ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 yes Blink Of JavaScript engine , Responsible for operation JavaScript Script ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" One JavaScript The script runs through loading 、 analysis 、 Explain to perform 、 Optimization and inverse optimization several processes , among "},{"type":"text","marks":[{"type":"strong"}],"text":"Ignition"},{"type":"text","text":" Responsible for converting abstract syntax tree into bytecode to save storage space ,"},{"type":"text","marks":[{"type":"strong"}],"text":"TurboFan"},{"type":"text","text":" According to the object type information, the bytecode of some functions is compiled into machine code to speed up the execution . If the object type is changed during the running of compiled function, it will be executed in bytecode interpretation phase ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"V8 Divide memory into new generations 、 The old generation and code space store newly created objects respectively 、 Long lived objects and executable code ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Recycling in the new generation Scavenge Strategy , Quickly release objects that are no longer alive during the exchange of two spaces of the same size ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" And another kind. Full Mark-Compact The strategy is responsible for the garbage collection of the whole heap , After marking in different threads - compaction - Cleaning ensures that the garbage collection process can achieve high throughput with low latency ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Here we are , This article is finally coming to an end , I hope this article can help you build Blink and V8 Summary view of , Light up a new skill tree for your front-end knowledge system ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" In the last related materials, I have been studying V8 Documents and videos referenced in the process , Here we present ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":" Last, last , Thanks for reading ."}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":" Related information "}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://docs.google.com/presentation/d/1sJj-JnSvM71zq-N_CT8qqsLngdW8fgOMiJdd2ylLojs/edit#slide=id.g26e94b78b8_0_9","title":null},"content":[{"type":"text","text":"Life of a script"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://v8.dev/blog/trash-talk","title":null},"content":[{"type":"text","text":"V8 Trash talk"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.youtube.com/watch?v=Scxz6jVS4Ls&feature=emb_logo","title":null},"content":[{"type":"text","text":"Orinoco: The new V8 Garbage Collector Peter Marshall"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.chromium.org/blink/blink-gc","title":null},"content":[{"type":"text","text":"Chromium blink-gc"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://darksi.de/d.sea-of-nodes/","title":null},"content":[{"type":"text","text":"Sea of Nodes"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://benediktmeurer.de/2017/03/01/v8-behind-the-scenes-february-edition","title":null},"content":[{"type":"text","text":"V8: Behind the Scenes (February Edition feat. A tale of TurboFan)"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.youtube.com/watch?v=u7zRSm8jzvA","title":null},"content":[{"type":"text","text":"V8 and How It Listens to You"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://v8.dev/blog/system-analyzer","title":null},"content":[{"type":"text","text":"Indicium: V8 runtime tracer tool"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://v8.dev/docs/d8","title":null},"content":[{"type":"text","text":"d8"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://erdem.pl/2019/08/v-8-function-optimization","title":null},"content":[{"type":"text","text":"V8 function optimization"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://v8.dev/blog/fast-properties","title":null},"content":[{"type":"text","text":"Fast properties in V8"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775","title":null},"content":[{"type":"text","text":"Understanding V8’s Bytecode"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://github.com/lazyparser/v8-internals","title":null},"content":[{"type":"text","text":"V8 Internals: Porting to RISC-V Build & Run, Igni-on Bytecodes"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.youtube.com/watch?v=J9HAvlW7BqA","title":null},"content":[{"type":"text","text":"Understanding Why The New V8 Is So Fast, One Demo At A Time"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://www.youtube.com/watch?v=r5OWCtuKiAk&feature=emb_logo","title":null},"content":[{"type":"text","text":"BlinkOn 6 Day 1 Talk 2: Ignition - an interpreter for V8"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://v8.dev/blog/ignition-interpreter","title":null},"content":[{"type":"text","text":"Firing up the Ignition interpreter"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://docs.google.com/presentation/d/1OqjVqRhtwlKeKfvMdX6HaCIu9wpZsrzqpIVIwQSuiXQ/edit#slide=id.g1357e6d1a4_0_58","title":null},"content":[{"type":"text","text":"Ignition: An Interpreter for V8 [BlinkOn]"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://docs.google.com/document/d/1aitSOucL0VHZa9Z2vbRJSyAIsAz24kX8LFByQ5xQnUg/edit#","title":null},"content":[{"type":"text","text":"How Blink works"}]}]}]},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md","title":null},"content":[{"type":"text","text":"Mojo"}]}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}

版权声明
本文为[InfoQ]所创,转载请带上原文链接,感谢