Planet Chromium

December 15, 2017

Google Chrome Releases

Stable Channel Update for Chrome OS

The Stable channel has been updated to 63.0.3239.86 (Platform version: 10032.71.1) for most Chrome OS devices. This build contains a number of bug fixes and security updates. Systems will be receiving updates over the next several days.

If you find new issues, please let us know by visiting our forum or filing a bug. Interested in switching channels? Find out how. You can submit feedback using ‘Report an issue...’ in the Chrome menu (3 vertical dots in the upper right corner of the browser).

Grace Kihumba
Google Chrome

by Grace Kihumba (noreply@blogger.com) at December 15, 2017 02:41 PM

Dev Channel Update for Desktop

The dev channel has been updated to 65.0.3294.5 for Mac and Linux, and 65.0.3294.5/.6 for Windows.


A partial list of changes is available in the log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Krishna Govind
Google Chrome

by Krishna Govind (noreply@blogger.com) at December 15, 2017 01:48 PM

December 14, 2017

Google Chrome Releases

Beta Channel Update for Chrome OS

The Beta channel has been updated to 64.0.3282.24 (Platform version: 10176.13.1) for most Chrome OS devices. This build contains a number of bug fixes, security updates and feature enhancements. Systems will be receiving updates over the next several days.

If you find new issues, please let us know by visiting our forum or filing a bug. Interested in switching channels? Find out how. You can submit feedback using ‘Report an issue...’ in the Chrome menu (3 vertical dots in the upper right corner of the browser).


Kevin Bleicher

Google Chrome

by Kevin Bleicher (noreply@blogger.com) at December 14, 2017 04:33 PM

Chromium Blog

Chrome 64 Beta: stronger pop-up blocker, Resize Observer, and import.meta

Unless otherwise noted, changes described below apply to the newest Chrome Beta channel release for Android,
Chrome OS, Linux, Mac, and Windows.


Stronger pop-up blocker
1 out of every 5 user feedback reports submitted on Chrome for desktop mention some type of
unwanted content. Examples include links to third-party websites disguised as play buttons or other
site controls, or transparent overlays on websites that capture all clicks and open new tabs or
windows. In this release, Chrome's pop-up blocker now prevents sites with these types of abusive
experiences from opening new tabs or windows. Site owners can use the Abusive Experiences
Report in Google Search Console to see if any of these abusive experiences have been found on
their site and improve their user experience.

 
Two types of abusive experiences where a deceptive site control appears to do one thing, but has a different behavior when clicked. One looks like a play button on a video but sends the user to an unwanted download when clicked (left), and the other looks like a close button but instead opens unwanted pop-up windows (right).

Resize Observer
Traditionally, responsive web applications have used CSS media queries or window.onresize to
build responsive components that adapt content to different viewport sizes. However, both of these
are global signals and require the overall viewport to change in order for the site to respond
accordingly. Chrome now supports the Resize Observer API to give web applications finer
control to observe changes to sizes of elements on a page.

const ro = new ResizeObserver((entries) => {
 for (const entry of entries) {
   const cr = entry.contentRect;
   console.log('Element:', entry.target);
   console.log(`Element size: ${cr.width}px × ${cr.height}px`);
   console.log(`Element padding: ${cr.top}px / ${cr.left}px`);
 }
});

// Observe one or multiple elements
ro.observe(someElement);
The code snippet above uses the Resize Observer API to observe changes to an element.

import.meta
Developers writing JavaScript modules often want access to host-specific metadata about the
current module. To make this easier, Chrome now supports the import.meta property within
modules that exposes the module URL via import.meta.url. Library authors might want to
access the URL of the module being bundled into the library to more easily resolve resources
relative to the module file as opposed to the current HTML document. In the future, Chrome plans to
add more properties to import.meta.

Other features in this release

Blink > Animation

  • The offset-path property can be used to animate an element by specifying the geometry of the path that an element moves along.

Blink>Fonts

Blink>Input

Blink>JavaScript

  • To improve developer experience, Chrome now supports named captures in regular expressions, allowing developers to assign meaningful names to portions of a string that a regular expression matches.
  • Chrome now supports the Unicode property escapes \p{…} and \P{…} for regular expressions that have the u flag set, allowing developers to create more powerful Unicode-aware regular expressions.
  • To assist with local-aware formatting of strings produced by internationalization formatters, developers can now use Intl.NumberFormat.prototype.formatToParts() to format a number to a list of tokens and their type. Thanks to Igalia for helping make this happen!

Blink>Media

Blink>Network

  • Developers can now use the cache option to specify the cache mode of a Request.
  • Developers can now use Request.prototype.cache to view the cache mode of a Request and determine whether a request is a reload request.  

Blink>Permissions API

  • To better align with the Permissions API spec, the Permissions API can now be used to query the status of the camera and microphone permissions.

Blink>Scroll

  • In Focus Management APIs, developers can now focus an element without scrolling to it by using the preventScroll attribute.

Blink>SVG

Blink>WebAudio

  • AudioWorklet, an API that exposes low-level audio processing capability to support custom AudioNodes, is now available in origin trials and the experimental flag.

Blink>WebRTC

  • To align with the WebRTC 1.0 spec, RTCPeerConnection now supports addTrack() for single stream use cases, as well as removeTrack(), getSenders(), ontrack, and a minimal version of the RTCRtpSender interface.

Blink>WindowDialog

  • To improve interoperability and end user experience, window.alert() no longer brings a backgrounded tab to the foreground but instead shows the alert when the user switches to the background tab.

UI>Notifications

Deprecations and interoperability improvements

Blink> CSS

Blink> DOM

Blink> Performance APIs


For a complete list of all features (including experimental features) in this release, see the
Chrome 64 milestone hotlist.  
Posted by Charles Harrison, Pop-Up Popping Engineer

by Chrome Blog (noreply@blogger.com) at December 14, 2017 03:02 PM

Google Chrome Releases

Stable Channel Update for Desktop

The stable channel has been updated to 63.0.3239.108 for Windows, Mac and Linux which will roll out over the coming days/weeks.

Security Fixes and Rewards
Note: Access to bug details and links may be kept restricted until a majority of users are updated with a fix. We will also retain restrictions if the bug exists in a third party library that other projects similarly depend on, but haven’t yet fixed.

This update includes 2 security fixes. Below, we highlight fixes that were contributed by external researchers. Please see the Chrome Security Page for more information.

[$7500][788453] High CVE-2017-15429: UXSS in V8. Reported by Anonymous on 2017-11-24.


We would also like to thank all security researchers that worked with us during the development cycle to prevent security bugs from ever reaching the stable channel.

As usual, our ongoing internal security work was responsible for a wide range of fixes:

  • [794792] Various fixes from internal audits, fuzzing and other initiatives 
Many of our security bugs are detected using AddressSanitizer, MemorySanitizer, UndefinedBehaviorSanitizer, Control Flow Integrity, libFuzzer, or AFL.

A list of all changes is available in the log.Interested in switching release channels? Find out how.  If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Krishna Govind
Google Chrome

by Krishna Govind (noreply@blogger.com) at December 14, 2017 02:26 PM

Stable Channel Update for Desktop

The Chrome team is delighted to announce the promotion of Chrome 63 to the stable channel for Windows, Mac and Linux. This will roll out over the coming days/weeks.


Chrome 63.0.3239.84 contains a number of fixes and improvements -- a list of changes is available in the log. Watch out for upcoming Chrome and Chromium blog posts about new features and big efforts delivered in 63.


Security Fixes and Rewards
Note: Access to bug details and links may be kept restricted until a majority of users are updated with a fix. We will also retain restrictions if the bug exists in a third party library that other projects similarly depend on, but haven’t yet fixed.


This update includes 37 security fixes. Below, we highlight fixes that were contributed by external researchers. Please see the Chrome Security Page for more information.


[$10500][778505] Critical CVE-2017-15407: Out of bounds write in QUIC. Reported by Ned Williamson on 2017-10-26
[$6337][762374] High CVE-2017-15408: Heap buffer overflow in PDFium. Reported by Ke Liu of Tencent's Xuanwu LAB on 2017-09-06
[$5000][763972] High CVE-2017-15409: Out of bounds write in Skia. Reported by Anonymous on 2017-09-11
[$5000][765921] High CVE-2017-15410: Use after free in PDFium. Reported by Luật Nguyễn (@l4wio) of KeenLab, Tencent on 2017-09-16
[$5000][770148] High CVE-2017-15411: Use after free in PDFium. Reported by Luật Nguyễn (@l4wio) of KeenLab, Tencent on 2017-09-29
[$3500][727039] High CVE-2017-15412: Use after free in libXML. Reported by Nick Wellnhofer on 2017-05-27
[$500][766666] High CVE-2017-15413: Type confusion in WebAssembly. Reported by Gaurav Dewan(@007gauravdewan) of Adobe Systems India Pvt. Ltd. on 2017-09-19
[$3337][765512] Medium CVE-2017-15415: Pointer information disclosure in IPC call. Reported by Viktor Brange of Microsoft Offensive Security Research Team on 2017-09-15
[$2500][779314] Medium CVE-2017-15416: Out of bounds read in Blink. Reported by Ned Williamson on 2017-10-28
[$2000][699028] Medium CVE-2017-15417: Cross origin information disclosure in Skia . Reported by Max May on 2017-03-07
[$1000][765858] Medium CVE-2017-15418: Use of uninitialized value in Skia. Reported by Kushal Arvind Shah of Fortinet's FortiGuard Labs on 2017-09-15
[$1000][780312] Medium CVE-2017-15419: Cross origin leak of redirect URL in Blink. Reported by Jun Kokatsu (@shhnjk) on 2017-10-31
[$500][777419] Medium CVE-2017-15420: URL spoofing in Omnibox. Reported by WenXu Wu of Tencent's Xuanwu Lab on 2017-10-23
[$TBD][774382] Medium CVE-2017-15422: Integer overflow in ICU. Reported by Yuan Deng of Ant-financial Light-Year Security Lab on 2017-10-13
[$500][778101] Low CVE-2017-15423: Issue with SPAKE implementation in BoringSSL. Reported by Greg Hudson on 2017-10-25
[$N/A][756226] Low CVE-2017-15424: URL Spoof in Omnibox. Reported by Khalil Zhani on 2017-08-16
[$N/A][756456] Low CVE-2017-15425: URL Spoof in Omnibox. Reported by xisigr of Tencent's Xuanwu Lab on 2017-08-17
[$N/A][756735] Low CVE-2017-15426: URL Spoof in Omnibox. Reported by WenXu Wu of Tencent's Xuanwu Lab on 2017-08-18
[$N/A][768910] Low CVE-2017-15427: Insufficient blocking of JavaScript in Omnibox. Reported by Junaid Farhan (fb.me/junaid.farhan.54) on 2017-09-26


We would also like to thank all security researchers that worked with us during the development cycle to prevent security bugs from ever reaching the stable channel.

As usual, our ongoing internal security work was responsible for a wide range of fixes:
  • [792099] Various fixes from internal audits, fuzzing and other initiatives

Many of our security bugs are detected using AddressSanitizer, MemorySanitizer, UndefinedBehaviorSanitizer, Control Flow Integrity, libFuzzer, or AFL.


A list of all changes is available in the log.Interested in switching release channels? Find out how.  If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.




Krishna Govind
Google Chrome

by Krishna Govind (noreply@blogger.com) at December 14, 2017 02:19 PM

Beta Channel Update for Desktop

The Chrome team is excited to announce the promotion of Chrome 64 to the beta channel for Windows, Mac and Linux. Chrome 64.0.3282.24 contains our usual under-the-hood performance and stability tweaks, but there are also some cool new features to explore - please head to the Chromium blog to learn more!

A full list of changes in this build is available in the log. Interested in switching release channels?  Find out how here. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Abdul Syed


Google Chrome

by Abdul Syed (noreply@blogger.com) at December 14, 2017 12:36 PM

V8 JavaScript Engine

Announcing the Web Tooling Benchmark

JavaScript performance has always been important to the V8 team, and in this post we would like to discuss a new JavaScript Web Tooling Benchmark that we have been using recently to identify and fix some performance bottlenecks in V8. You may already be aware of V8’s strong commitment to Node.js and this benchmark extends that commitment by specifically running performance tests based on common developer tools built upon Node.js. The tools in the Web Tooling Benchmark are the same ones used by developers and designers today to build modern web sites and cloud-based applications. In continuation of our ongoing efforts to focus on real-world performance rather than artificial benchmarks, we created the benchmark using actual code that developers run every day.

The Web Tooling Benchmark suite was designed from the beginning to cover important developer tooling use cases for Node.js. Because the V8 team focuses on core JavaScript performance, we built the benchmark in a way that focuses on the JavaScript workloads and excludes measurement of Node.js-specific I/O or external interactions. This makes it possible to run the benchmark in Node.js, in all browsers, and in all major JavaScript engine shells, including ch (ChakraCore), d8 (V8), jsc (JavaScriptCore) and jsshell (SpiderMonkey). Even though the benchmark is not limited to Node.js, we are excited that the Node.js benchmarking working group is considering using the tooling benchmark as a standard for Node performance as well (nodejs/benchmarking#138).

The individual tests in the tooling benchmark cover a variety of tools that developers commonly use to build JavaScript-based applications, for example:

See the in-depth analysis for details on all the included tests.

Based on past experience with other benchmarks like Speedometer, where tests quickly become outdated as new versions of frameworks become available, we made sure it is straight-forward to update each of the tools in the benchmarks to more recent versions as they are released. By basing the benchmark suite on npm infrastructure, we can easily update it to ensure that it is always testing the state of the art in JavaScript development tools. Updating a test case is just a matter of bumping the version in the package.json manifest.

We created a tracking bug and a spreadsheet to contain all the relevant information that we have collected about V8’s performance on the new benchmark up to this point. Our investigations have already yielded some interesting results. For example, we discovered that V8 was often hitting the slow path for instanceof (v8:6971), incurring a 3–4× slowdown. We also found and fixed performance bottlenecks in certain cases of property assignments of the form of obj[name] = val where obj was created via Object.create(null). In these cases, V8 would fall off the fast-path despite being able to utilize the fact that obj has a null prototype (v8:6985). These and other discoveries made with the help of this benchmark improve V8, not only in Node.js, but also in Chrome.

We not only looked into making V8 faster, but also fixed and upstreamed performance bugs in the benchmark’s tools and libraries whenever we found them. For example, we discovered a number of performance bugs in Babel where code patterns like

value = items[items.length - 1];
lead to accesses of the property "-1", because the code didn’t check whether items is empty beforehand. This code pattern causes V8 to go through a slow-path due to the "-1" lookup, even though a slightly modified, equivalent version of the JavaScript is much faster. We helped to fix these issues in Babel (babel/babel#6582, babel/babel#6581 and babel/babel#6580). We also discovered and fixed a bug where Babel would access beyond the length of a string (babel/babel#6589), which triggered another slow-path in V8. Additionally we optimized out-of-bounds reads of arrays and strings in V8. We’re looking forward to continue working with the community on improving the performance of this important use case, not only when run on top of V8, but also when run on other JavaScript engines like ChakraCore.

Our strong focus on real-world performance and especially on improving popular Node.js workloads is shown by the constant improvements in V8’s score on the benchmark over the last couple of releases:


Since V8 5.8, which is the last V8 release before switching to the Ignition+TurboFan architecture, V8’s score on the tooling benchmark has improved by around 60%.

Over the last several years, the V8 team has come to recognize that no one JavaScript benchmark — even a well-intentioned, carefully crafted one — should be used as a single proxy for a JavaScript engine’s overall performance. However, we do believe that the new Web Tooling Benchmark highlights areas of JavaScript performance that are worth focusing on. Despite the name and the initial motivation, we have found that the Web Tooling Benchmark suite is not only representative of tooling workloads, but is representative of a large range of more sophisticated JavaScript applications that are not tested well by front end-focused benchmarks like Speedometer. It is by no means a replacement for Speedometer, but rather a complementary set of tests.

The best news of all is that given how the Web Tooling Benchmark is constructed around real workloads, we expect that our recent improvements in benchmark scores will translate directly into improved developer productivity through less time waiting for things to build. Many of these improvements are already available in Node.js: at the time of writing, Node 8 LTS is at V8 6.1 and Node 9 is at V8 6.2.

The latest version of the benchmark is hosted at https://v8.github.io/web-tooling-benchmark/.

Benedikt Meurer, @bmeurer, JavaScript Performance Juggler

by Benedikt Meurer (noreply@blogger.com) at December 14, 2017 04:34 AM

V8 Release 6.3

Every six weeks, we create a new branch of V8 as part of our release process. Each version is branched from V8’s git master immediately before a Chrome Beta milestone. Today we’re pleased to announce our newest branch, V8 version 6.3, which is in beta until its release in coordination with Chrome 63 Stable in several weeks. V8 v6.3 is filled with all sorts of developer-facing goodies. This post provides a preview of some of the highlights in anticipation of the release.


Speed

Jank Busters III hit the shelves as part of the Orinoco project. Concurrent marking (70-80% of marking is done on a non-blocking thread) is shipped.

The parser now does not need to preparse a function a second time. This translates to a 14 % median improvement in parse time on our internal startup top25 benchmark.

string.js has been completely ported to CodeStubAssembler. Thanks a lot to @peterwmwong for his awesome contributions! As a developer this means that builtin string functions like String#trim are a lot faster starting with 6.3.

Object.is()'s performance is now roughly on-par with alternatives. In general, 6.3 continues the path to better the ES2015+ performance. Beside other items we boosted the speed of polymorphic access to symbols, polymorphic inlining of constructor calls and (tagged) template literals.

 V8's performance over the past six releases

Weak optimized function list is gone. More information can be found in the dedicated blog post.

The mentioned items are a non-exhaustive list of speed improvements. Lot's of other performance-related work has happened.

Memory consumption

Write barriers are switched over to using the CodeStubAssembler. This saves around 100kb of memory per isolate.

ECMAScript language features

V8 shipped the following stage 3 features: Dynamic module import via import(), Promise.prototype.finally() and async iterators/generators.

With dynamic module import it is very straightforward to import modules based on runtime conditions. This comes in handy when an application should lazy-load certain code modules.

Promise.prototype.finally introduces a way to easily clean up after a promise is settled.

Iterating with async functions got more ergonomic with the introduction of async iterators/generators.

Inspector/Debugging

In Chrome 63 block coverage is also supported in the DevTools UI. Please note that the inspector protocol already supports block coverage since V8 6.2.

V8 API

Please check out our summary of API changes. This document is regularly updated a few weeks after each major release.

Developers with an active V8 checkout can use git checkout -b 6.3 -t branch-heads/6.3 to experiment with the new features in V8 6.3. Alternatively you can subscribe to Chrome’s Beta channel and try the new features out yourself soon.

Posted by the V8 team

by Michael Hablich (noreply@blogger.com) at December 14, 2017 04:34 AM

December 13, 2017

Google Chrome Releases

Dev Channel Update for Chrome OS

The Dev channel has been updated to 64.0.3282.24 (Platform version: 10176.13.1) for most Chrome OS devices. This build contains a number of bug fixes, security updates and feature enhancements.  A list of changes can be found here.

If you find new issues, please let us know by visiting our forum or filing a bug. Interested in switching channels? Find out how. You can submit feedback using ‘Report an issue...’ in the Chrome menu (3 vertical dots in the upper right corner of the browser). 


Kevin Bleicher
Google Chrome

by Kevin Bleicher (noreply@blogger.com) at December 13, 2017 04:24 PM

V8 JavaScript Engine

JavaScript code coverage

What is it?

Code coverage provides information about whether, and optionally how often certain parts of an application have been executed. It’s commonly used to determine how thoroughly a test suite exercises a particular codebase.

Why is it useful?

As a JavaScript developer, you may often find yourself in a situation in which code coverage could be useful. For instance:

  • Interested in the quality of your test suite? Refactoring a large legacy project? Code coverage can show you exactly which parts of your codebase is covered.
  • Want to quickly know if a particular part of the codebase is reached? Instead of instrumenting with console.log for printf-style debugging or manually stepping through the code, code coverage can display live information about which parts of your applications have been executed.
  • Or maybe you’re optimizing for speed and would like to know which spots to focus on? Execution counts can point out hot functions and loops.

JavaScript code coverage in V8

Earlier this year, we added native support for JavaScript code coverage to V8. The initial release in version 5.9 provided coverage at function granularity (showing which functions have been executed), which was later extended to support coverage at block granularity in 6.2 (likewise, but for individual expressions).

Function granularity (left) and block granularity (right)

For JavaScript developers

There are currently two primary ways to access coverage information. For JavaScript developers, Chrome DevTools’ Coverage tab exposes JS (and CSS) coverage ratios and highlights dead code in the Sources panel.

Block coverage in the DevTools Coverage pane. Covered lines are highlighted in green, uncovered in red.

Thanks to Benjamin Coe, there is also ongoing work to integrate V8’s code coverage information into the popular Istanbul.js code coverage tool.

An Istanbul.js report based on V8 coverage data.

For embedders

Embedders and framework authors can hook directly into the Inspector API for more flexibility. V8 offers two different coverage modes:

  1. Best-effort coverage collects coverage information with minimal impact on runtime performance, but might lose data on garbage-collected (GC) functions.

  2. Precise coverage ensures that no data is lost to the GC, and users can choose to receive execution counts instead of binary coverage information; but performance might be impacted by increased overhead (see the next section for more details). Precise coverage can be collected either at function or block granularity.

The Inspector API for precise coverage is as follows:

A conversation through the Inspector protocol might look like this:

// The embedder directs V8 to begin collecting precise coverage.
{ "id": 26, "method": "Profiler.startPreciseCoverage",
"params": { "callCount": false, "detailed": true }}
// Embedder requests coverage data (delta since last request).
{ "id": 32, "method":"Profiler.takePreciseCoverage" }
// The reply contains collection of nested source ranges.
{ "id": 32, "result": { "result": [{
"functions": [
{
"functionName": "fib",
"isBlockCoverage": true, // Block granularity.
"ranges": [ // An array of nested ranges.
{
"startOffset": 50, // Byte offset, inclusive.
"endOffset": 224, // Byte offset, exclusive.
"count": 1
}, {
"startOffset": 97,
"endOffset": 107,
"count": 0
}, {
"startOffset": 134,
"endOffset": 144,
"count": 0
}, {
"startOffset": 192,
"endOffset": 223,
"count": 0
},
]},
"scriptId": "199",
"url": "file:///coverage-fib.html"
}
]
}}

// Finally, the embedder directs V8 to end collection and
// free related data structures.
{"id":37,"method":"Profiler.stopPreciseCoverage"}

Similarly, best-effort coverage can be retrieved using Profiler.getBestEffortCoverage().

Behind the scenes

As stated in the previous section, V8 supports two main modes of code coverage: best-effort and precise coverage. Read on for an overview of their implementation.

Best-effort coverage

Both best-effort and precise coverage modes heavily reuse other V8 mechanisms, the first of which is called the invocation counter. Each time a function is called through V8’s Ignition interpreter, we increment an invocation counter on the function’s feedback vector. As the function later becomes hot and tiers up through the optimizing compiler, this counter is used to help guide inlining decisions about which functions to inline; and now, we also rely on it to report code coverage.

The second reused mechanism determines the source range of functions. When reporting code coverage, invocation counts need to be tied to an associated range within the source file. For example, in the example below, we not only need to report that function f has been executed exactly once, but also that f’s source range begins at line 1 and ends in line 3.

function f() {
console.log('Hello World');
}

f();

Again we got lucky and were able to reuse existing information within V8. Functions already knew their start- and end positions within source code due to Function.prototype.toString, which needs to know the function’s location within the source file to extract the appropriate substring.

When collecting best-effort coverage, these two mechanisms are simply tied together: first we find all live function by traversing the entire heap. For each seen function we report the invocation count (stored on the feedback vector, which we can reach from the function) and source range (conveniently stored on the function itself).

Note that since invocation counts are maintained regardless of whether coverage is enabled, best-effort coverage does not introduce any runtime overhead. It also does not use dedicated data structures and thus neither needs to be explicitly enabled or disabled.

So why is this mode called best-effort, what are its limitations? Functions that go out of scope may be freed by the garbage collector. This means that associated invocation counts are lost, and in fact we completely forget that these functions ever existed. Ergo ‘best-effort’: even though we try our best, the collected coverage information may be incomplete.

Precise coverage (function granularity)

In contrast to the best-effort mode, precise coverage guarantees that the provided coverage information is complete. To achieve this, we add all feedback vectors to V8’s root set of references once precise coverage is enabled, preventing their collection by the GC. While this ensures no information is lost, it increases memory consumption by keeping objects alive artificially.

The precise coverage mode can also provide execution counts. This adds another wrinkle to the precise coverage implementation. Recall that the invocation counter is incremented each time a function is called through V8’s interpreter, and that functions can tier up and be optimized once they become hot. But optimized functions no longer increment their invocation counter, and thus the optimizing compiler must be disabled for their reported execution count to remain accurate.

Precise coverage (block granularity)

Block-granularity coverage must report coverage that is correct down to the level of individual expressions. For example, in the following piece of code, block coverage could detect that the else branch of the conditional expression : c is never executed, while function granularity coverage would only know that the function f (in its entirety) is covered.

function f(a) {
return a ? b : c;
}

f(true);

You may recall from the previous sections that we already had function invocation counts and source ranges readily available within V8. Unfortunately, this was not the case for block coverage and we had to implement new mechanisms to collect both execution counts and their corresponding source ranges.

The first aspect is source ranges: assuming we have an execution count for a particular block, how can we map them to a section of the source code? For this, we need to collect relevant positions while parsing the source files. Prior to block coverage, V8 already did this to some extent. One example is the collection of function ranges due to Function.prototype.toString as described above. Another is that source positions are used to construct the backtrace for Error objects. But neither of these is sufficient to support block coverage; the former is only available for functions, while the latter only stores positions (e.g. the position of the if token for if-else statements), not source ranges.

We therefore had to extend the parser to collect source ranges. To demonstrate, consider an if-else statement:

if (cond) {
/* Then branch. */
} else {
/* Else branch. */
}

When block coverage is enabled, we collect the source range of the then and else branches and associate them with the parsed IfStatement AST node. The same is done for other relevant language constructs.

After collecting source range collection during parsing, the second aspect is tracking execution counts at runtime. This is done by inserting a new dedicated IncBlockCounter bytecode at strategic positions within the generated bytecode array. At runtime, the IncBlockCounter bytecode handler simply increments the appropriate counter (reachable through the function object).

In the above example of an if-else statement, such bytecodes would be inserted at three spots: immediately prior to the body of the then branch, prior to the body of the else branch, and immediately after the if-else statement (such continuation counters are needed due to possibility of non-local control within a branch).

Finally, reporting block-granularity coverage works similarly to function-granularity reporting. But in addition to invocations counts (from the feedback vector), we now also report the collection of interesting source ranges together with their block counts (stored on an auxiliary data structure that hangs off the function).

If you’d like to learn more about the technical details behind code coverage in V8, see the coverage and block coverage design documents.

Conclusion

We hope you’ve enjoyed this brief introduction to V8’s native code coverage support. Please give it a try and don’t hesitate to let us know what works for you, and what doesn’t. Say hello on Twitter (@schuay and @hashseed) or file a bug at crbug.com/v8/new.

Coverage support in V8 has been a team effort, and thanks are in order to everyone that has contributed: Benjamin Coe, Jakob Gruber, Yang Guo, Marja Hölttä, Andrey Kosyakov, Alexey Kozyatinksiy, Ross McIlroy, Ali Sheikh, Michael Starzinger. Thank you!

by Jakob Gruber (noreply@blogger.com) at December 13, 2017 01:41 AM

December 12, 2017

Google Chrome Releases

Dev Channel Update for Desktop

The dev channel has been updated to 64.0.3282.24 for Mac and Linux, and 64.0.3282.24/25 for Windows.


A partial list of changes is available in the log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Abdul Syed
Google Chrome

by Abdul Syed (noreply@blogger.com) at December 12, 2017 12:28 PM

December 08, 2017

Google Chrome Releases

Dev Channel Update for Desktop

The dev channel has been updated to 64.0.3282.14 for Mac and Linux, and 64.0.3282.14/15 for Windows.


A partial list of changes is available in the log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Abdul Syed
Google Chrome

by Abdul Syed (noreply@blogger.com) at December 08, 2017 11:52 AM

December 06, 2017

Google Chrome Releases

Dev Channel Update for Chrome OS

The Dev channel has been updated to 64.0.3282.11 (Platform version: 10176.5.0) for most Chrome OS devices. This build contains a number of bug fixes, security updates and feature enhancements.  A list of changes can be found here.

If you find new issues, please let us know by visiting our forum or filing a bug. Interested in switching channels? Find out how. You can submit feedback using ‘Report an issue...’ in the Chrome menu (3 vertical dots in the upper right corner of the browser). 


Kevin Bleicher
Google Chrome

by Kevin Bleicher (noreply@blogger.com) at December 06, 2017 03:59 PM

Beta Channel Update for Desktop

The beta channel has been updated to 63.0.3239.84 for Windows, Mac, and Linux.


A partial list of changes is available in the log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.


Krishna Govind
Google Chrome

by Krishna Govind (noreply@blogger.com) at December 06, 2017 12:11 PM

December 05, 2017

Google Chrome Releases

Chrome for Android Update

Good news, everyone!  Chrome 63 (63.0.3239.83) for Android has been released and will be available on Google Play over the course of the next few weeks.  This release improves autocompletion in the address bar, making it even easier to get to your favorite websites. We've also included stability and performance improvements.

A list of the changes in this build is available in the Git log.

If you find a new issue, please let us know by filing a bug. More information about Chrome for Android is available on the Chrome site.

Estelle Yomba
Google Chrome

by Estelle Yomba (noreply@blogger.com) at December 05, 2017 05:16 PM

November 30, 2017

Google Chrome Releases

Dev Channel Update for Chrome OS

The Dev channel has been updated to 64.0.3280.5 (Platform version: 10172.0.0) for most Chrome OS devices. This build contains a number of bug fixes, security updates and feature enhancements.  A list of changes can be found here.

If you find new issues, please let us know by visiting our forum or filing a bug. Interested in switching channels? Find out how. You can submit feedback using ‘Report an issue...’ in the Chrome menu (3 vertical dots in the upper right corner of the browser). 


Kevin Bleicher
Google Chrome

by Kevin Bleicher (noreply@blogger.com) at November 30, 2017 04:22 PM

Chromium Blog

Reducing Chrome crashes caused by third-party software

Roughly two-thirds of Windows Chrome users have other applications on their machines that interact with Chrome, such as accessibility or antivirus software. In the past, this software needed to inject code in Chrome in order to function properly; unfortunately, users with software that injects code into Windows Chrome are 15% more likely to experience crashes. With Chrome extensions and Native Messaging, there are now modern alternatives to running code inside of Chrome processes. Starting in July 2018, Chrome 68 will begin blocking third-party software from injecting code into Chrome on Windows.

These changes will take place in three phases. In April 2018, Chrome 66 will begin showing affected users a warning after a crash, alerting them that other software is injecting code into Chrome and guiding them to update or remove that software.

In Chrome 66 a warning will be shown to users with third-party software that injects into Chrome.


In July 2018, Chrome 68 will begin blocking third-party software from injecting into Chrome processes. If this blocking prevents Chrome from starting, Chrome will restart and allow the injection, but also show a warning that guides the user to remove the software. Finally, in January 2019, Chrome 72 will remove this accomodation and always block code injection.

While most software that injects code into Chrome will be affected by these changes, there are some exceptions. Microsoft-signed code, accessibility software, and IME software will not be affected. As with all Chrome changes, developers are encouraged to use Chrome Beta for early testing.

Fewer crashes means more happy users, and we look forward to continuing to make Chrome better for everyone.

Posted by Chris Hamilton, Chrome Stability Team

by Chrome Blog (noreply@blogger.com) at November 30, 2017 10:33 AM

November 29, 2017

Google Chrome Releases

Beta Channel Update for Chrome OS

The Beta channel has been updated to 63.0.3239.70 (Platform version: 10032.59.0 ) for most Chrome OS devices. This build contains a number of bug fixes, security updates and feature enhancements. A list of changes can be found here.


If you find new issues, please let us know by visiting our forum or filing a bug. Interested in switching channels? Find out how. You can submit feedback using ‘Report an issue...’ in the Chrome menu (3 vertical dots in the upper right corner of the browser). 

Grace Kihumba
Google Chrome

by Grace Kihumba (noreply@blogger.com) at November 29, 2017 07:33 PM

Chrome Beta for Android Update

Ladies and gentlemen, behold!  Chrome Beta 63 (63.0.3239.71) for Android has been released and is available in Google Play.  A partial list of the changes in this build is available in the Git log.  Details on new features will soon be available on the Chromium blog, and developers should check out our updates related to the web platform here.

If you find a new issue, please let us know by filing a bug. More information about Chrome for Android is available on the Chrome site.

Estelle Yomba
Google Chrome

by Estelle Yomba (noreply@blogger.com) at November 29, 2017 05:45 PM

Beta Channel Update for Desktop

The beta channel has been updated to 63.0.3239.70 for Windows, Mac, and Linux.


A partial list of changes is available in the log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.


Krishna Govind
Google Chrome

by Krishna Govind (noreply@blogger.com) at November 29, 2017 11:11 AM

V8 JavaScript Engine

Orinoco: young generation garbage collection

JavaScript objects in V8 are allocated on a heap managed by V8’s garbage collector. In previous blog posts we have already talked about how we reduce garbage collection pause times (more than once) and memory consumption. In this blog post we introduce the parallel Scavenger, one of the latest features of Orinoco, V8’s mostly concurrent and parallel garbage collector and discuss design decisions and alternative approaches we implemented on the way.

V8 partitions its managed heap into generations where objects are initially allocated in the “nursery” of the young generation. Upon surviving a garbage collection, objects are copied into the intermediate generation, which is still part of the young generation. After surviving another garbage collection, these objects are moved into the old generation (see Figure 1). V8 implements two garbage collectors: one that frequently collects the young generation, and one that collects the full heap including both the young and old generation. Old-to-young generation references are roots for the young generation garbage collection. These references are recorded to provide efficient root identification and reference updates when objects are moved.

Figure 1: Generational garbage collection

Since the young generation is relatively small (up to 16MiB in V8) it fills up quickly with objects and requires frequent collections. Until M62, V8 used a Cheney semispace copying garbage collector (see below) that divides the young generation into two halves. During JavaScript execution only one half of the young generation is available for allocating objects, while the other half remains empty. During a young garbage collection, live objects are copied from one half to the other half, compacting the memory on the fly. Live objects that have already been copied once are considered part of the intermediate generation and are promoted to the old generation.

Starting with M62, V8 switched the default algorithm for collecting the young generation to a parallel Scavenger, similar to Halstead’s semispace copying collector with the difference that V8 makes use of dynamic instead of static work stealing across multiple threads. In the following we explain three algorithms: a) the single-threaded Cheney semispace copying collector, b) a parallel Mark-Evacuate scheme, and c) the parallel Scavenger.

Single-threaded Cheney’s Semispace Copy

Until M62, V8 used Cheney’s semispace copying algorithm which is well-suited for both single-core execution and a generational scheme. Before a young generation collection, both semispace halves of memory are committed and assigned proper labels: the pages containing the current set of objects are called from-space while the pages that objects are copied to are called to-space.

The Scavenger considers references in the call stack and references from the old to the young generation as roots. Figure 2 illustrates the algorithm where initially the Scavenger scans these roots and copies objects reachable in the from-space that have not yet been copied to the to-space. Objects that have already survived a garbage collection are promoted (moved) to the old generation. After root scanning and the first round of copying, the objects in the newly allocated to-space are scanned for references. Similarly, all promoted objects are scanned for new references to from-space. These three phases are interleaved on the main thread. The algorithm continues until no more new objects are reachable from either to-space or the old generation. At this point the from-space only contains unreachable objects, i.e., it only contains garbage.

Processing
Figure 2: Cheney’s semispace copying algorithm used for young generation garbage collections in V8

Parallel Mark-Evacuate

We experimented with a parallel Mark-Evacuate algorithm based on the V8’s full Mark-Sweep-Compact collector. The main advantage is leveraging the already existing garbage collection infrastructure from the full Mark-Sweep-Compact collector. The algorithm consists of three phases: marking, copying, and updating pointers, as shown in Figure 3. To avoid sweeping pages in the young generation to maintain free lists, the young generation is still maintained using a semispace that is always kept compact by copying live objects into to-space during garbage collection. The young generation is initially marked in parallel. After marking, live objects are copied in parallel to their corresponding spaces. Work is distributed based on logical pages. Threads participating in copying keep their own local allocation buffers (LABs) which are merged upon finishing copying. After copying, the same parallelization scheme is applied for updating inter-object pointers. These three phases are performed in lockstep, i.e., while the phases themselves are performed in parallel, threads have to synchronize before continuing to the next phase.

Processing
Figure 3: Young Generation Parallel Mark-Evacuate garbage collection in V8

Parallel Scavenge

The parallel Mark-Evacuate collector separates the phases of computing liveness, copying live objects, and updating pointers. An obvious optimization is to merge these phases, resulting in an algorithm that marks, copies, and updates pointers at the same time. By merging those phases we actually get the parallel Scavenger used by V8, which is a version similar to Halstead’s semispace collector with the difference that V8 uses dynamic work stealing and a simple load balancing mechanism for scanning the roots (see Figure 4). Like the single-threaded Cheney algorithm, the phases are: scanning for roots, copying within the young generation, promoting to the old generation, and updating pointers. We found that the majority of the root set is usually the references from the old generation to the young generation. In our implementation, remembered sets are maintained per-page, which naturally distributes the roots set among garbage collection threads. Objects are then processed in parallel. Newly found objects are added to a global work list from which garbage collection threads can steal. This work list provides fast task local storage as well as global storage for sharing work. A barrier makes sure that tasks do not prematurely terminate when the sub graph currently processed is not suitable for work stealing (e.g. a linear chain of objects). All phases are performed in parallel and interleaved on each task, maximizing the utilization of worker tasks.

Processing
Figure 4: Young generation parallel Scavenger in V8

Results and outcome

The Scavenger algorithm was initially designed having optimal single-core performance in mind. The world has changed since then. CPU cores are often plentiful, even on low-end mobile devices. More importantly, often these cores are actually up and running. To fully utilize these cores, one of the last sequential components of V8’s garbage collector, the Scavenger, had to be modernized.

The big advantage of a parallel Mark-Evacuate collector is that exact liveness information is available. This information can e.g. be used to avoid copying at all by just moving and relinking pages that contain mostly live objects which is also performed by the full Mark-Sweep-Compact collector. In practice, however, this was mostly observable on synthetic benchmarks and rarely showed up on real websites. The downside of the parallel Mark-Evacuate collector is the overhead of performing three separate lockstep phases. This overhead is especially noticeable when the garbage collector is invoked on a heap with mostly dead objects, which is the case on many real-world webpages. Note that invoking garbage collections on heaps with mostly dead objects is actually the ideal scenario, as garbage collection is usually bounded by the size of live objects.

The parallel Scavenger closes this performance gap by providing performance that is close to the optimized Cheney algorithm on small or almost empty heaps while still providing a high throughput in case the heaps get larger with lots of live objects.

V8 supports, among many other platforms, as Arm big.LITTLE. While offloading work on little cores benefits battery lifetime, it can lead to stalling on the main thread when work packages for little cores are too big. We observed that page-level parallelism does not necessarily load balance work on big.LITTLE for a young generation garbage collection due to the limited number of pages. The Scavenger naturally solves this issue by providing medium-grained synchronization using explicit work lists and work stealing.

Figure 5: Total young generation garbage collection time (in ms) across various websites

V8 now ships with the parallel Scavenger which reduces the main thread young generation garbage collection total time by about 20%–50% across a large set of benchmarks (details on our perf waterfalls). Figure 5 shows a comparison of the implementations across various real-world websites, showing improvements around 55% (2×). Similar improvements can be observed on maximum and average pause time while maintaining minimum pause time. The parallel Mark-Evacuate collector scheme has still potential for optimization. Stay tuned if you want to find out what happens next.

Posted by friends of TSAN: Ulan Degenbaev, Michael Lippautz, and Hannes Payer

by Mathias Bynens (noreply@blogger.com) at November 29, 2017 07:06 AM

November 28, 2017

V8 JavaScript Engine

Upcoming RegExp features

Regular expressions, or RegExps, are an important part of the JavaScript language. When used properly, they can greatly simplify string processing.

ES2015 introduced many new features to the JavaScript language, including significant improvements to the regular expression syntax with the Unicode (/u) and sticky (/y) flags. But development has not stopped since then — in tight collaboration with other members at TC39 (the ECMAScript standards body), the V8 team has proposed and co-designed several new features to make RegExps even more powerful.

These features are currently being proposed for inclusion in the JavaScript specification. Even though the proposals have not been fully accepted, they are already at Stage 3 in the TC39 process. We have implemented these features behind flags (see below) in order to be able to provide timely design and implementation feedback before the specification is finalized.

In this blog post we want to give you a preview of this exciting future. If you'd like to follow along with the upcoming examples, enable experimental JavaScript features at chrome://flags/#enable-javascript-harmony.

Named Captures


Regular expressions can contain so-called captures (or groups), which can capture a portion of the matched text. So far, developers could only refer to these captures by their numeric index, which is determined by the position of the capture within the pattern.
const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-03');
// result[0] === '2017-07-03'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '03'

But regular expressions are already notoriously difficult to read, write, and maintain, and numeric references can add further complications. For instance, in longer patterns it can be tricky to determine the index of a particular capture:
/(?:(.)(.(?<=[^(])(.)))/  // Index of the last capture?

And even worse, changes to a pattern can potentially shift the indices of all existing captures:
/(a)(b)(c)\3\2\1/     // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/ // All need to be updated.

Named captures are an upcoming feature that helps mitigate these issues by allowing developers to assign names to captures. The syntax is similar to Perl, Java, .Net, and Ruby:
const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-03');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '03'

Named captures can also be referenced by named backreferences and through String.prototype.replace:
// Named backreferences.
/(?<lowercasex>x)y\k<lowercasex>/.test('xyx'); // true

// String replacement.
const pattern = /(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern, '$<snd>$<fst>'); // 'ba'
'ab'.replace(pattern, (m, p1, p2, o, s, {fst, snd}) => fst + snd); // 'ba'

Full details of this new feature are available in the specification proposal.

dotAll Flag


By default, the . atom in regular expressions matches any character except for line terminators:
/foo.bar/u.test('foo\nbar');  // false

A proposal introduces dotAll mode, enabled through the /s flag. In dotAll mode, . matches line terminators as well.
/foo.bar/su.test('foo\nbar');  // true

Full details of this new feature are available in the specification proposal.

Unicode Property Escapes


Regular expression syntax has always included shorthands for certain character classes. \d represents digits and is really just [0-9]; \w is short for word characters, or [A-Za-z0-9_].

With Unicode awareness introduced in ES2015, there are suddenly many more characters that could be considered numbers, for example the circled digit one: ①; or considered word characters, for example the Chinese character for snow: 雪.

Neither of these can be matched with \d or \w. Changing the meaning of these shorthands would break existing regular expression patterns.

Instead, new character classes are being introduced. Note that they are only available for Unicode-aware RegExps denoted by the /u flag.
/\p{Number}/u.test('①');     // true
/\p{Alphabetic}/u.test('雪'); // true

The inverse can be matched by with \P.
/\P{Number}/u.test('①');     // false
/\P{Alphabetic}/u.test('雪'); // false

The Unicode consortium defines many more ways to classify code points, for example math symbols or Japanese Hiragana characters:
/^\p{Math}+$/u.test('∛∞∉');                            // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな'); // true

The full list of supported Unicode property classes can be found in the current specification proposal. For more examples, take a look at this informative article.

Lookbehind Assertions


Lookahead assertions have been part of JavaScript’s regular expression syntax from the start. Their counterpart, lookbehind assertions, are finally being introduced. Some of you may remember that this has been part of V8 for quite some time already. We even use lookbehind asserts under the hood to implement the Unicode flag specified in ES2015.

The name already describes its meaning pretty well. It offers a way to restrict a pattern to only match if preceded by the pattern in the lookbehind group. It comes in both matching and non-matching flavors:
/(?<=\$)\d+/.exec('$1 is worth about ¥123');  // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123'); // ['123']

For more details, check out our previous blog post dedicated to lookbehind assertions, and examples in related V8 test cases.

Acknowledgements


This blog post wouldn’t be complete without mentioning some of the people that have worked hard to make this happen: especially language champions Mathias Bynens, Dan Ehrenberg, Claude Pache, Brian Terlson, Thomas Wood, Gorkem Yakin, and Irregexp guru Erik Corry; but also everyone else who has contributed to the language specification and V8’s implementation of these features.

We hope you’re as excited about these new RegExp features as we are!

Posted by Yang Guo and Jakob Gruber, V8 RegExperts

by Unknown (noreply@blogger.com) at November 28, 2017 08:32 PM

An internship on laziness: lazy unlinking of deoptimized functions

Roughly three months ago, I joined the V8 team (Google Munich) as an intern and since then I’ve been working on the VM’s Deoptimizer — something completely new to me which proved to be an interesting and challenging project. The first part of my internship focused on improving the VM security-wise. The second part focused on performance improvements. Namely, on the removal of a data-structure used for the unlinking of previously deoptimized functions, which was a performance bottleneck during garbage collection. This blog post describes this second part of my internship. I’ll explain how V8 used to unlink deoptimized functions, how we changed this, and what performance improvements were obtained.

Let’s (very) briefly recap the V8 pipeline for a JavaScript function: V8’s interpreter, Ignition, collects profiling information about that function while interpreting it. Once the function becomes hot, this information is passed to V8’s compiler, TurboFan, which generates optimized machine code. When the profiling information is no longer valid — for example because one of the profiled objects gets a different type during runtime — the optimized machine code might become invalid. In that case, V8 needs to deoptimize it.

Source: JavaScript Start-up Performance

Upon optimization, TurboFan generates a code object, i.e. the optimized machine code, for the function under optimization. When this function is invoked the next time, V8 follows the link to optimized code for that function and executes it. Upon deoptimization of this function, we need to unlink the code object in order to make sure that it won’t be executed again. How does that happen?

For example, in the following code, the function f1 will be invoked many times (always passing an integer as argument). TurboFan then generates machine code for that specific case.

function g() {
return (i) => i;
}

// Create a closure.
const f1 = g();
// Optimize f1.
for (var i = 0; i < 1000; i++) f1(0);

Each function also has a trampoline to the interpreter — more details in these slides— and will keep a pointer to this trampoline in its SharedFunctionInfo (SFI). This trampoline will be used whenever V8 needs to go back to unoptimized code. Thus, upon deoptimization, triggered by passing an argument of a different type, for example, the Deoptimizer can simply set the code field of the JavaScript function to this trampoline.

Although this seems simple, it forces V8 to keep weak lists of optimized JavaScript functions. This is because it is possible to have different functions pointing to the same optimized code object. We can extend our example as follows, and the functions f1 and f2 both point to the same optimized code.

const f2 = g();
f2(0);

If the function f1 is deoptimized (for example by invoking it with an object of different type {x: 0}) we need to make sure that the invalidated code will not be executed again by invoking f2.

Thus, upon deoptimization, V8 used to iterate over all the optimized JavaScript functions, and would unlink those that pointed to the code object being deoptimized. This iteration in applications with many optimized JavaScript functions became a performance bottleneck. Moreover, other than slowing down deoptimization, V8 used to iterate over these lists upon stop-the-world cycles of garbage collection, making it even worse.

In order to have an idea of the impact of such data-structure in the performance of V8, we wrote a micro-benchmarkthat stresses its usage, by triggering many scavenge cycles after creating many JavaScript functions.

function g() {
return (i) => i + 1;
}

// Create an initial closure and optimize.
var f = g();

f(0);
f(0);
%OptimizeFunctionOnNextCall(f);
f(0);

// Create 2M closures, those will get the previously optimized code.
var a = [];
for (var i = 0; i < 2000000; i++) {
var h = g();
h();
a.push(h);
}

// Now cause scavenges, all of them are slow.
for (var i = 0; i < 1000; i++) {
new Array(50000);
}

When running this benchmark, we could observe that V8 spent around 98% of its execution time on garbage collection. We then removed this data structure, and instead used an approach for lazy unlinking, and this was what we observed on x64:

Although this is just a micro-benchmark that creates many JavaScript functions and triggers many garbage collection cycles, it gives us an idea of the overhead introduced by this data structure. Other more realistic applications where we saw some overhead, and which motivated this work, were the router benchmarkimplemented in Node.js and ARES-6 benchmark suite.

Lazy unlinking

Rather than unlinking optimized code from JavaScript functions upon deoptimization, V8 postpones it for the next invocation of such functions. When such functions are invoked, V8 checks whether they have been deoptimized, unlinks them and then continues with their lazy compilation. If these functions are never invoked again, then they will never be unlinked and the deoptimized code objects will not be collected. However, given that during deoptimization, we invalidate all the embedded fields of the code object, we only keep that code object alive.

The committhat removed this list of optimized JavaScript functions required changes in several parts of the VM, but the basic idea is as follows. When assembling the optimized code object, we check if this is the code of a JavaScript function. If so, in its prologue, we assemble machine code to bail out if the code object has been deoptimized. Upon deoptimization we don’t modify the deoptimized code — code patching is gone. Thus, its bit marked_for_deoptimization is still set when invoking the function again. TurboFan generates code to check it, and if it is set, then V8 jumps to a new builtin, CompileLazyDeoptimizedCode, that unlinks the deoptimized code from the JavaScript function and then continues with lazy compilation.

In more detail, the first step is to generate instructions that load the address of the code being currently assembled. We can do that in x64, with the following code:

Label current;
// Load effective address of current instruction into rcx.
__ leaq(rcx, Operand(&current));
__ bind(&current);

After that we need to obtain where in the code object the marked_for_deoptimization bit lives.

int pc = __ pc_offset();
int offset = Code::kKindSpecificFlags1Offset - (Code::kHeaderSize + pc);

We can then test the bit and if it is set, we jump to the CompileLazyDeoptimizedCode built in.

// Test if the bit is set, that is, if the code is marked for deoptimization.
__ testl(Operand(rcx, offset),
Immediate(1 << Code::kMarkedForDeoptimizationBit));
// Jump to builtin if it is.
__ j(not_zero, /* handle to builtin code here */, RelocInfo::CODE_TARGET);

On the side of this CompileLazyDeoptimizedCode builtin, all that’s left to do is to unlink the code field from the JavaScript function and set it to the trampoline to the Interpreter entry. So, considering that the address of the JavaScript function is in the register rdi, we can obtain the pointer to the SharedFunctionInfo with:

// Field read to obtain the SharedFunctionInfo.
__ movq(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));

…and similarly the trampoline with:

// Field read to obtain the code object.
__ movq(rcx, FieldOperand(rcx, SharedFunctionInfo::kCodeOffset));

Then we can use it to update the function slot for the code pointer:

// Update the code field of the function with the trampoline.
__ movq(FieldOperand(rdi, JSFunction::kCodeOffset), rcx);
// Write barrier to protect the field.
__ RecordWriteField(rdi, JSFunction::kCodeOffset, rcx, r15,
kDontSaveFPRegs, OMIT_REMEMBERED_SET, OMIT_SMI_CHECK);

This produces the same result as before. However, rather than taking care of the unlinking in the Deoptimizer, we need to worry about it during code generation. Hence the handwritten assembly.

The above is how it works in the x64 architecture. We have implemented it for ia32, arm, arm64, mips, and mips64as well.

This new technique is already integrated in V8 and, as we’ll discuss later, allows for performance improvements. However, it comes with a minor disadvantage: Before, V8 would consider unlinking only upon deoptimization. Now, it has to do so in the activation of all optimized functions. Moreover, the approach to check the marked_for_deoptimization bit is not as efficient as it could be, given that we need to do some work to obtain the address of the code object. Note that this happens when entering every optimized function. A possible solution for this issue is to keep in a code object a pointer to itself. Rather than doing work to find the address of the code object whenever the function is invoked, V8 would do it only once, after its construction.

Results

We now look at the performance gains and regressions obtained with this project.

General Improvements on x64

The following plot shows us some improvements and regressions, relative to the previous commit. Note that the higher, the better.

The promises benchmarks are the ones where we see greater improvements, observing almost 33% gain for the bluebird-parallelbenchmark, and 22.40% for wikipedia. We also observed a few regressions in some benchmarks. This is related to the issue explained above, on checking whether the code is marked for deoptimization.

We also see improvements in the ARES-6 benchmark suite. Note that in this chart too, the higher the better. These programs used to spend considerable amount of time in GC-related activities. With lazy unlinking we improve performance by 1.9% overall. The most notable case is the Air steadyState where we get an improvement of around 5.36%.


AreWeFastYet results

The performance results for the Octane and ARES-6 benchmark suites also showed up on the AreWeFastYet tracker. We looked at these performance results on September 5th, 2017, using the provided default machine (macOS 10.10 64-bit, Mac Pro, shell).


Impact on Node.js

We can also see performance improvements in the router-benchmark. The following two plots show the number of operations per second of each tested router. Thus the higher the better. We have performed two kinds of experiments with this benchmark suite. Firstly, we ran each test in isolation, so that we could see the performance improvement, independently from the remaining tests. Secondly, we ran all tests at once, without switching of the VM, thus simulating an environment where each test is integrated with other functionalities.

For the first experiment, we saw that the router and express tests perform about twice as many operations than before, in the same amount of time. For the second experiment, we saw even greater improvement. In some of the cases, such as routr, server-router and router, the benchmark performs approximately 3.80×, 3× and 2× more operations, respectively. This happens because V8 accumulates more optimized JavaScript functions, test after test. Thus, whenever executing a given test, if a garbage collection cycle is triggered, V8 has to visit the optimized functions from the current test and from the previous ones.


Further Optimization

Now that V8 does not keep the linked-list of JavaScript functions in the context, we can remove the field next from the JSFunction class. Although this is a simple modification, it allows us to save the size of a pointer per function, which represent significant savings in several web pages:

Benchmark Kind Memory savings (absolute) Memory savings (relative)
facebook.com Average effective size 170KB 3.7%
twitter.com Average size of allocated objects 284KB 1.2%
cnn.com Average size of allocated objects 788KB 1.53%
youtube.com Average size of allocated objects 129KB 0.79%

Acknowledgments

Throughout my internship, I had lots of help from several people, who were always available to answer my many questions. Thus I would like to thank the following people: Benedikt Meurer, Jaroslav Sevcik, and Michael Starzinger for discussions on how the Compiler and the Deoptimizer work, Ulan Degenbaev for helping with the Garbage Collector whenever I broke it, and Mathias Bynens, Peter Marshall, Camillo Bruni, and Maya Lekova for proofreading this article.

Finally, this article is my last contribution as a Google intern and I would like to take the opportunity to thank everyone in the V8 team, and especially my host, Benedikt Meurer, for hosting me and for giving me the opportunity to work on such an interesting project — I definitely learned a lot and enjoyed my time at Google!

Juliana Franco, @jupvfranco, Laziness Expert

by Mathias Bynens (noreply@blogger.com) at November 28, 2017 08:32 PM

Google Chrome Releases

Dev Channel Update for Desktop

The dev channel has been updated to 64.0.3278.0 for Windows, Mac and Linux.


A partial list of changes is available in the log. Interested in switching release channels? Find out how. If you find a new issue, please let us know by filing a bug. The community help forum is also a great place to reach out for help or learn about common issues.

Krishna Govind
Google Chrome

by Krishna Govind (noreply@blogger.com) at November 28, 2017 01:06 PM