Tuesday, March 15, 2016

Experimental support for WebAssembly in V8

For a comprehensive overview of WebAssembly and a roadmap for future community collaboration, see A WebAssembly Milestone on the Mozilla Hacks blog.

Since June 2015, collaborators from Google, Mozilla, Microsoft, Apple and the W3C WebAssembly Community Group have been hard at work designing, specifying, and implementing [1][2][3][4] WebAssembly, a new runtime and compilation target for the web. WebAssembly is a low-level, portable bytecode that is designed to be encoded in a compact binary format and executed at near-native speed in a memory-safe sandbox. As an evolution of existing technologies, WebAssembly is tightly integrated with the web platform, as well as faster to download over the network and faster to instantiate than asm.js, a low-level subset of JavaScript.

Starting today, experimental support for WebAssembly is available in V8 and Chromium behind a flag. To try it out in V8, run d8 version 5.1.117 or greater from the command line with the --expose_wasm flag or turn on the Experimental WebAssembly feature under chrome://flags#enable-webassembly in Chrome Canary 51.0.2677.0 or greater. After restarting the browser, a new Wasm object will be available from the JavaScript context which exposes an API that can instantiate and run WebAssembly modules. Thanks to the efforts of collaborators at Mozilla and Microsoft, two compatible implementations of WebAssembly are also running behind a flag in Firefox Nightly and in an internal build of Microsoft Edge (demonstrated in a video screencapture).

The WebAssembly project website has a demo showcasing the runtime’s usage in a 3D game. In browsers that support WebAssembly, the demo page will load and instantiate a wasm module that uses WebGL and other web platform APIs to render an interactive game. In other browsers, the demo page falls back to an asm.js version of the same game.

https://webassembly.github.io/demo/

Under the hood, the WebAssembly implementation in V8 is designed to reuse much of the existing JavaScript virtual machine infrastructure, specifically the TurboFan compiler. A specialized WebAssembly decoder validates modules by checking types, local variable indices, function references, return values, and control flow structure in a single pass. The decoder produces a TurboFan graph which is processed by various optimization passes and finally turned into machine code by the same backend which generates machine code for optimized JavaScript and asm.js. In the next few months, the team will concentrate on improving the startup time of the V8 implementation through compiler tuning, parallelism, and compilation policy improvements.

Two upcoming changes will also significantly improve the developer experience. A standard textual representation of WebAssembly will enable developers to view the source of a WebAssembly binary like any other web script or resource. In addition, the current placeholder Wasm object will be redesigned to provide a more powerful, idiomatic set of methods and properties to instantiate and introspect WebAssembly modules from JavaScript.

The V8 / WebAssembly team looks forward to continued collaboration with other browser vendors and the greater community as we work towards a stable release of the runtime. We’re also planning future WebAssembly features (including multi-threading, dynamic linking, and GC / first-class DOM integration) and continuing the development of toolchains for compiling C, C++, and other languages via the WebAssembly LLVM backend and Emscripten. Check back for more updates as the design and implementation process continues.

Posted by Seth Thompson, WebAssembly Wrangler

V8 Release 5.0

The first step in the V8 release process is a new branch from the git master immediately before Chromium branches for a Chrome Beta milestone (roughly every six weeks). Our newest release branch is V8 5.0, which will remain in beta until we release a stable build in conjunction with Chrome 50 Stable. Here’s a highlight of the new developer-facing features in this version of V8.

Note: The version number 5.0 does not carry semantic significance or mark a major release (as opposed to a minor release).


Improved ECMAScript 2015 (ES6) support

V8 5.0 contains a number of ES2015 features related to regular expression (regex) matching.

RegExp Unicode flag

The RegExp Unicode flag, u, switches on a new Unicode mode for regular expression matching. The Unicode flag treats patterns and regex strings as a series of Unicode codepoints. It also exposes new syntax for Unicode codepoint escapes.
/😊{2}/.test('😊😊');
// false

/😊{2}/u.test('😊😊');
// true

/\u{76}\u{38}/u.test('v8');
// true

/\u{1F60A}/u.test('😊');
// true

The u flag also makes the . operator (also known as the single character matcher) match any Unicode symbol rather than just the characters in the Basic Multilingual Plane (BMP).
var string = 'the 🅛 train';

/the\s.\strain/.test(string);
// false

/the\s.\strain/u.test(string);
// true 

RegExp customization hooks

ES2015 includes hooks for RegExp subclasses to change the semantics of matching. Subclasses can override methods named Symbol.match, Symbol.replace, Symbol.search and Symbol.split in order to change how RegExp subclasses behave with respect to String.prototype.match and similar methods.

Performance improvements in ES2015 and ES5 features

Release 5.0 also brings a few notable performance improvements to already implemented ES2015 and ES5 features.

The implementation of rest parameters is 8-10x faster than that of the previous release, making it more efficient to gather large numbers of arguments into a single array after a function call. Object.keys(), useful for iterating over an object’s enumerable properties in the same order returned by for..in, is now approximately 2x faster.

V8 API

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

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

Posted by the V8 team

Friday, February 26, 2016

RegExp lookbehind assertions

Introduced with the third edition of the ECMA-262 specification, regular expressions have been part of Javascript since 1999. In functionality and expressiveness, JavaScript’s implementation of regular expressions roughly mirrors that of other programming languages.

One feature in JavaScript’s RegExp that is often overlooked, but can be quite useful at times, is lookahead assertions. For example, to match a sequence of digits that is followed by a percent sign, we can use /\d+(?=%)/. The percent sign itself is not part of the match result. The negation thereof, /\d+(?!%)/, would match a sequence of digits not followed by a percent sign:
/\d+(?=%)/.exec("100% of US presidents have been male")  // ["100"]
/\d+(?!%)/.exec("that’s all 44 of them")                 // ["44"]

The opposite of lookahead, lookbehind assertions, have been missing in JavaScript, but are available in other regular expression implementations, such as that of the .NET framework. Instead of reading ahead, the regular expression engine reads backwards for the match inside the assertion. A sequence of digits following a dollar sign can be matched by /(?<=\$)\d+/, where the dollar sign would not be part of the match result. The negation thereof, /(?<!\$)\d+/, matches a sequence of digits following anything but a dollar sign.
/(?<=\$)\d+/.exec("Benjamin Franklin is on the $100 bill")  // ["100"]
/(?<!\$)\d+/.exec("it’s is worth about €90")                // ["90"]

Generally, there are two ways to implement lookbehind assertions. Perl, for example, requires lookbehind patterns to have a fixed length. That means that quantifiers such as * or + are not allowed. This way, the regular expression engine can step back by that fixed length, and match the lookbehind the exact same way as it would match a lookahead, from the stepped back position.

The regular expression engine in the .NET framework takes a different approach. Instead of needing to know how many characters the lookbehind pattern will match, it simply matches the lookbehind pattern backwards, while reading characters against the normal read direction. This means that the lookbehind pattern can take advantage of the full regular expression syntax and match patterns of arbitrary length.

Clearly, the second option is more powerful than the first. That is why the V8 team, and the TC39 champions for this feature, have agreed that JavaScript should adopt the more expressive version, even though its implementation is slightly more complex.

Because lookbehind assertions match backwards, there are some subtle behaviors that would otherwise be considered surprising. For example, a capturing group with a quantifier captures the last match. Usually, that is the right-most match. But inside a lookbehind assertion, we match from right to left, therefore the left-most match is captured:
/h(?=(\w)+)/.exec("hodor") // ["h", "r"]
/(?<=(\w)+)r/.exec("hodor") // ["r", "h"]

A capturing group can be referenced via back reference after it has been captured. Usually, the back reference has to be to the right of the capture group. Otherwise, it would match the empty string, as nothing has been captured yet. However, inside a lookbehind assertion, the match direction is reversed:
/(?<=(o)d\1)r/.exec("hodor")  // null
/(?<=\1d(o))r/.exec("hodor")  // ["r", "o"]

Lookbehind assertions are currently in a very early stage in the TC39 specification process. However, because they are such an obvious extension to the RegExp syntax, we decided to prioritize their implementation. You can already experiment with lookbehind assertions by running V8 version 4.9 or later with --harmony, or by enabling experimental JavaScript features (use about:flags) in Chrome from version 49 onwards.

Yang Guo, Regular Expression Engineer

Thursday, February 4, 2016

V8 Extras

V8 implements a large subset of the JavaScript language’s built-in objects and functions in JavaScript itself. For example, you can see our promises implementation is written in JavaScript. Such built-ins are called self-hosted. These implementations are included in our startup snapshot so that new contexts can be quickly created without needing to setup and initialize the self-hosted built-ins at runtime.

Embedders of V8, such as Chromium, sometimes desire to write APIs in JavaScript too. This works especially well for platform features that are self-contained, like streams, or for features that are part of a “layered platform” of higher-level capabilities built on top of pre-existing lower-level ones. Although it’s always possible to run extra code at startup time to bootstrap embedder APIs (as is done in Node.js, for example), ideally embedders should be able to get the same speed benefits for their self-hosted APIs that V8 does.

V8 extras are a new feature of V8, as of our 4.8 release, designed with the goal of allowing embedders to write high-performance, self-hosted APIs via a simple interface. Extras are embedder-provided JavaScript files which are compiled directly into the V8 snapshot. They also have access to a few helper utilities that make it easier to write secure APIs in JavaScript.

An Example

A V8 extra file is simply a JavaScript file with a certain structure:

(function(global, binding, v8) {
  'use strict';
  const Object = global.Object;
  const x = v8.createPrivateSymbol('x');
  const y = v8.createPrivateSymbol('y');
 
  class Vec2 {
    constructor(theX, theY) {
      this[x] = theX;
      this[y] = theY;
    }

    norm() {
      return binding.computeNorm(this[x], this[y]);
    }
  }

  Object.defineProperty(global, 'Vec2', {
    value: Vec2,
    enumerable: false,
    configurable: true,
    writable: true
  });

  binding.Vec2 = Vec2;
});


There are a few things to notice here:
  • The global object is not present in the scope chain, so any access to it (such as that for Object) has to be done explicitly through the provided global argument.
  • The binding object is a place to store values for or retrieve values from the embedder. A C++ API v8::Context::GetExtrasBindingObject() provides access to the binding object from the embedder’s side. In our toy example, we let the embedder perform norm computation; in a real example you might delegate to the embedder for something trickier like URL resolution. We also add the Vec2 constructor to the binding object, so that embedder code can create Vec2 instances without going through the potentially-mutable global object.
  • The v8 object provides a small number of APIs to allow you to write secure code. Here we create private symbols to store our internal state in a way that cannot be manipulated from the outside. (Private symbols are a V8-internal concept and do not make sense in standard JavaScript code.) V8’s built-ins often use “%-function calls” for these sort of things, but V8 extras cannot use %-functions since they are an internal implementation detail of V8 and not suitable for embedders to depend on.
You might be curious about where these objects come from. All three of them are initialized in V8’s bootstrapper, which installs some basic properties but mostly leaves the initialization to V8’s self-hosted JavaScript. For example, almost every .js file in V8 installs something on global; see e.g. promise.js or uri.js. And we install APIs onto the v8 object in a number of places. (The binding object is empty until manipulated by an extra or embedder, so the only relevant code in V8 itself is when the bootstrapper creates it.)

Finally, to tell V8 that we’ll be compiling in an extra, we add a line to our project’s gypfile:

'v8_extra_library_files': ['./Vec2.js']

(You can see a real-world example of this in V8’s gypfile.)

V8 Extras in Practice

V8 extras provide a new and lightweight way for embedders to implement features. JavaScript code can more easily manipulate JavaScript built-ins like arrays, maps, or promises; it can call other JavaScript functions without ceremony; and it can deal with exceptions in an idiomatic way. Unlike C++ implementations, features implemented in JavaScript via V8 extras can benefit from inlining, and calling them does not incur any boundary-crossing costs. These benefits are especially pronounced when compared to a traditional bindings system like Chromium’s Web IDL bindings.

V8 extras were introduced and refined over the last year, and Chromium is currently using them to implement streams. Chromium is also considering V8 extras for implementing scroll customization and efficient geometry APIs.

V8 extras are still a work in progress, and the interface has some rough edges and disadvantages we hope to address over time. The primary area with room for improvement is the debugging story: errors are not easy to track down, and runtime debugging is most often done with print statements. In the future, we hope to integrate V8 extras into Chromium’s developer tools and tracing framework, both for Chromium itself and for any embedders that speak the same protocol.

Another cause for caution when using V8 extras is the extra developer effort required to write secure and robust code. V8 extras code operates directly on the snapshot, just like the code for V8’s self-hosted built-ins. It accesses the same objects as userland JavaScript, with no binding layer or separate context to prevent such access. For example, something as seemingly-simple as global.Object.prototype.hasOwnProperty.call(obj, 5) has six potential ways in which it could fail due to user code modifying the built-ins (count them!). Embedders like Chromium need to be robust against any user code, no matter its behavior, and so in such environments more care is necessary when writing extras than when writing traditional C++-implemented features.

If you’d like to learn more about V8 extras, check out our design document which goes into much more detail. We look forward to improving V8 extras, and adding more features that allow developers and embedders to write expressive, high-performance additions to the V8 runtime.

Posted by Domenic Denicola, Streams Sorcerer

Tuesday, January 26, 2016

V8 Release 4.9

Roughly 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 Chrome branches for a Chrome Beta milestone. Today we’re pleased to announce our newest branch, V8 version 4.9, which will be in beta until it is released in coordination with Chrome 49 Stable. V8 4.9 is filled will all sorts of developer-facing goodies, so we’d like to give you a preview of some of the highlights in anticipation of the release in several weeks.

91% ECMAScript 2015 (ES6) support

In V8 release 4.9 we shipped more JavaScript ES2015 features than in any other previous release, bringing us to 91% completion as measured by the Kangax compatibility table (as of January 26). V8 now supports destructuring, default parameters, Proxy objects, and the Reflect API. Release 4.9 also makes block level constructs such as class and let available outside of strict mode and adds support for the sticky flag on regular expressions and customizable Object.prototype.toString output.

Destructuring

Variable declarations, parameters, and assignments now support destructuring of objects and arrays via patterns. For example:
let o = {a: [1, 2, 3], b: {p: 4}, c: {q: 5}};
let {a: [x, y], b: {p}, c, d} = o;            // x=1, y=2, p=4, c={q: 5}
[x, y] = [y, x];                              // x=2, y=1
function f({a, b}) { return [a, b] }
f({a: 4})                                     // [4, undefined]
Array patterns can contain rest patterns that are assigned the remainder of the array:
let [x, y, ...r] = [1, 2, 3, 4];              // x=1, y=2, r=[3,4]
Furthermore, pattern elements can be given default values, which are used in case the respective property has no match:
let {a: x, b: y = x} = {a: 4};                // x=4, y=4
let [x, y = 0, z = 0] = [1, 2];               // x=1, y=2, z=0
Destructuring can be used to make accessing data from objects and arrays more compact.

Proxies & Reflect

After years of development, V8 now ships with a complete implementation of proxies, up-to-date with the ES2015 spec. Proxies are a powerful mechanism for virtualizing objects and functions through a set of developer-provided hooks to customize property accesses. In addition to object virtualization, proxies can be used to implement interception, add validation for property setting, simplify debugging and profiling, and unlock advanced abstractions like membranes.

To proxy an object, you must create a handler placeholder object that defines various traps and apply it to the target object which the proxy virtualizes:
let target = {};
let handler = {
  get(target, name="world") {
    return `Hello, ${name}!`;
  }
};

let foo = new Proxy(target, handler);
foo.bar  // "Hello, bar!"
The Proxy object is accompanied by the Reflect module, which defines suitable defaults for all proxy traps:
let debugMe = new Proxy({}, {
  get(target, name, receiver) {
    console.log(`Debug: get called for field: ${name}`);
    return Reflect.get(target, name, receiver);
  },
  set(target, name, value, receiver) {
    console.log(`Debug: set called for field: ${name}, and value: ${value}`);
    return Reflect.set(target, name, value, receiver);
  }
});

debugMe.name = "John Doe";
// Debug: set called for field: name, and value: John Doe
let title = `Mr. ${debugMe.name}`; // "Mr. John Doe"
// Debug: get called for field: name
For more information on the usage of Proxies and the Reflect API, see the examples section of the MDN Proxy page and look out for our upcoming Proxies article on the Web Fundamentals blog.

Default Parameters

In ES5 and below, optional parameters in function definitions required boilerplate code to check whether parameters were undefined:
function sublist(list, start, end) {
  if (typeof start === "undefined") start = 0;
  if (typeof end === "undefined") end = list.length;
  ...
}
ES2015 now allows function parameters to have default values, providing for clearer and more succinct function definitions:
function sublist(list, start = 0, end = list.length) { ... }
sublist([1, 2, 3], 1)  // sublist([1, 2, 3], 1, 3)
Default parameters and destructuring can be combined, of course:
function vector([x, y, z] = []) { ... }

Classes & lexical declarations in sloppy mode

V8 has supported lexical declarations (let, const, block-local function) and classes since versions 4.1 and 4.2 respectively, but so far strict mode has been required in order to use them. As of V8 release 4.9, all of these features are now enabled outside of strict mode as well, per the ES2015 spec. This makes prototyping in the DevTools Console much easier, although we encourage developers in general to upgrade to strict mode for new code.

Regular expressions

V8 now supports the new sticky flag on regular expressions. The sticky flag toggles whether searches in strings start from the beginning of the string (normal) or from the lastIndex property (sticky). This behavior is useful for efficiently parsing arbitrarily long input strings with many different regular expressions. To enable sticky searching, add the y flag to a regex: (e.g. var regex = /foo/y; ).

Customizable Object.prototype.toString output

Using Symbol.toStringTag, user-defined types can now return customized output when passed to Object.prototype.toString (either directly or as a result of string coercion):
class Custom {
  get [Symbol.toStringTag]() {
    return "Custom"
  }
}
Object.prototype.toString.call(new Custom)  // "[object Custom]"
String(new Custom)                          // "[object Custom]"

Improved Math.random()

V8 4.9 includes an improvement in the implementation of Math.random(). As announced last month, we switched V8’s PRNG algorithm to xorshift128+ in order to provide higher-quality pseudo-randomness.

V8 API

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

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

Posted by the V8 team

Thursday, December 17, 2015

There's Math.random(), and then there's Math.random()


Math.random()
Returns a Number value with positive sign, greater than or equal to 0 but less than 1, chosen randomly or pseudo randomly with approximately uniform distribution over that range, using an implementation-dependent algorithm or strategy. This function takes no arguments.


Math.random() is the most well-known and frequently-used source of randomness in Javascript. In V8 and most other Javascript engines, it is implemented using a pseudo-random number generator (PRNG). As with all PRNGs, the random number is derived from an internal state, which is altered by a fixed algorithm for every new random number. So for a given initial state, the sequence of random numbers is deterministic. Since the bit size n of the internal state is limited, the numbers that a PRNG generates will eventually repeat themselves. The upper bound for the period length of this permutation cycle is of course 2n.

There are many different PRNG algorithms; among the most well-known ones are Mersenne-Twister and LCG. Each has its particular characteristics, advantages, and drawbacks. Ideally, it would use as little memory as possible for the initial state, be quick to perform, have a large period length, and offer a high quality random distribution. While memory usage, performance, and period length can easily be measured or calculated, the quality is harder to determine. There is a lot of math behind statistical tests to check the quality of random numbers. The de-facto standard PRNG test suite, TestU01, implements many of these tests.

Until recently (up to version 4.9.40), V8’s choice of PRNG was MWC1616 (multiply with carry, combining two 16-bit parts). It uses 64 bits of internal state and looks roughly like this:
uint32_t state0 = 1;
uint32_t state1 = 2;
uint32_t mwc1616() {
  state0 = 18030 * (state0 & 0xffff) + (state0 >> 16);
  state1 = 30903 * (state1 & 0xffff) + (state1 >> 16);
  return state0 << 16 + (state1 & 0xffff);
The 32-bit value is then turned into a floating point number between 0 and 1 in agreement with the specification.

MWC1616 uses little memory and is pretty fast to compute, but unfortunately offers sub-par quality:

  • The number of random values it can generate is limited to 232 as opposed to the 252 numbers between 0 and 1 that double precision floating point can represent.
  • The more significant upper half of the result is almost entirely dependent on the value of state0. The period length would be at most 232, but instead of few large permutation cycles, there are many short ones. With a badly chosen initial state, the cycle length could be less than 40 million.
  • It fails many statistical tests in the TestU01 suite.

This has been pointed out to us, and having understood the problem and after some research, we decided to reimplement Math.random based on an algorithm called xorshift128+. It uses 128 bits of internal state, has a period length of 2128 - 1, and passes all tests from the TestU01 suite.
uint64_t state0 = 1;
uint64_t state1 = 2;
uint64_t xorshift128plus() {
  uint64_t s1 = state0;
  uint64_t s0 = state1;
  state0 = s0;
  s1 ^= s1 << 23;
  s1 ^= s1 >> 17;
  s1 ^= s0;
  s1 ^= s0 >> 26;
  state1 = s1;
  return state0 + state1;
}
The new implementation landed in V8 4.9.41.0 within a few days of us becoming aware of the issue. It will become available with Chrome 49. Both Firefox and Safari switched to xorshift128+ as well.

Make no mistake however: even though xorshift128+ is a huge improvement over MWC1616, it still is not cryptographically secure. For use cases such as hashing, signature generation, and encryption/decryption, ordinary PRNGs are unsuitable. The Web Cryptography API introduces window.crypto.getRandomValues, a method that returns cryptographically secure random values, at a performance cost.

Please keep in mind, if you find areas of improvement in V8 and Chrome, even ones that—like this one—do not directly affect spec compliance, stability, or security, please file an issue on our bug tracker.

Posted by Yang Guo, Software Engineer and dice designer

Wednesday, November 25, 2015

V8 Release 4.8

Roughly 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 Chrome branches for a Chrome Beta milestone. Today we’re pleased to announce our newest branch, V8 version 4.8, which will be in beta until it is released in coordination with Chrome 48 Stable. V8 4.8 contains a handful of developer-facing features, so we’d like to give you a preview of some of the highlights in anticipation of the release in several weeks.

Improved ECMAScript 2015 (ES6) support

This release of V8 provides support for two well-known symbols, built-in symbols from the ES2015 spec that allow developers to leverage several low-level language constructs which were previously hidden.

@@isConcatSpreadable

The name for a Boolean valued property that if true indicates an object should be flattened to its array elements by Array.prototype.concat.

(function(){
"use strict";
class AutomaticallySpreadingArray extends Array {
   get [Symbol.isConcatSpreadable]() {
      return true;
   }
}
let first = [1];
let second = new AutomaticallySpreadingArray();
second[0] = 2;
second[1] = 3;
let all = first.concat(second);
// Outputs [1, 2, 3]
console.log(all);
}());

@@toPrimitive

The name for a method to invoke on an object for implicit conversions to primitive values.

(function(){
"use strict";
class V8 {
   [Symbol.toPrimitive](hint) {
      if (hint === 'string') {
         console.log('string');
         return 'V8';
      } else if (hint === 'number') {
         console.log('number');
         return 8;
      } else {
         console.log('default:' + hint);
         return 8;
      }
   }
}

let engine = new V8();
console.log(Number(engine));
console.log(String(engine));
}());

ToLength

The ES2015 spec adjusts the abstract operation for type conversion to convert an argument to an integer suitable for use as the length of an array-like object.  (While not directly observable, this change might be indirectly visible when dealing with array-like objects with negative length.)

V8 API

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

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

Posted by the V8 team