Function hidden classes

JavaScript performance comparison

Test case created by Kevin Gadd

Info

Functions in v8 have hidden classes like objects, and functions only get fully optimized if using the default hidden class

Preparation code

<script type="text/javascript">
var f1 = function (n) {
  return n;
};
var f2 = function (n) {
  return n;
};

f2.toString = function () { return "f2"; };
Object.defineProperty(f2, "displayName", { value: "f2" });
Object.defineProperty(f2, "debugName", { value: "f2" });

Function.prototype.invoke1 = function () {
  return this.apply(null, arguments);
};

Function.prototype.invoke2 = function () {
  return this.apply(null, arguments);
};

Function.prototype.invoke3 = function () {
  return this.apply(null, arguments);
};

var count = 5000;

// Feed information into the ICs for each function
for (var i = 0; i < count; i++) {
  f1.invoke1(1);
  f2.invoke2(1);

  // The IC for invoke3 will get two different hidden class entries, which deoptimizes it
  if (i % 2 == 0)
    f1.invoke3(1);
  else
    f2.invoke3(1);
}
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in unknown unknown
Test Ops/sec
Direct (unmodified)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f1(i);
}
if (sum != 12497500)
  throw new Error();
pending…
Direct (modified)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f2(i);
}
if (sum != 12497500)
  throw new Error();
pending…
.call (unmodified)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f1.call(this, i);
}
if (sum != 12497500)
  throw new Error();
pending…
.call (modified)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f2.call(this, i);
}
if (sum != 12497500)
  throw new Error();
pending…
Consistent IC information (unmodified fn)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f1.invoke1(i);
}
if (sum != 12497500)
  throw new Error();
pending…
Consistent IC information (modified fn)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f2.invoke2(i);
}
if (sum != 12497500)
  throw new Error();
pending…
Conflicting IC information (unmodified fn)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f1.invoke3(i);
}
if (sum != 12497500)
  throw new Error();
pending…
Conflicting IC information (modified fn)
var sum = 0;
for (var i = 0; i < count; i++) {
  sum += f2.invoke3(i);
}
if (sum != 12497500)
  throw new Error();
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL. Here’s a list of current revisions for this page:

1 comment

Oleksandr Nikitin commented :

you should also try this on different CPUs (at least, Intel Core iX, Athlon and Intel Atom - they all have very different architectures. Probably ARM too, but you're already testing on Android/iPhone)

Add a comment