Search code examples
javascriptjavascript-objectsv8

V8 Hidden classes for two objects of the same type are not the same if property types are different


I have read about the hidden classes in V8 and make some tests in d8 debugger shell.

function Vector(a, b) {
  this.a = a;
  this.b = b;
}

var x = new Vector(1, 2);
var y = new Vector(1, 3);
var z = new Vector(1, 'a');

print( %HaveSameMap( x, y ) ); //true
print( %HaveSameMap( x, z ) ); //false
x.b;
print( %HaveSameMap( x, z ) ); //true
print( %HaveSameMap( y, z ) ); //false
y.b;
print( %HaveSameMap( y, z ) ); //true

as we can see if the object property types are different they don't share their hidden class until we try to access the property in elder object which type is different. Can anyone give a clear explanation what is happening "behind the scenes", maybe it has something to do with inline caches.


Solution

  • V8 developer here. In short, what's happening is that "hidden classes" store information not just about the existence of properties, but also (relatively coarse-grained) type information about their values. To avoid having too many different hidden classes, they are consolidated when objects are touched.

    In your example:

    var x = new Vector(1, 2);
    var y = new Vector(1, 3);
    

    Both x and y now have a hidden class HC1 that knows "I have a property .b, and its value is always a small integer (a.k.a. Smi)". But then this happens:

    var z = new Vector(1, 'a');
    

    So z needs an updated version of that hidden class, because the value of its .b is a string. V8 doesn't currently go as far as remembering "the value could be an integer or string"; instead it just discards the type information. So z gets a new hidden class HC2 that knows "I have a property .b (but I know nothing about its value, it could be anything)". When this hidden class HC2 is created, HC1 is marked as "outdated"; but to save time, no effort is made to find and update objects using HC1. When you run

    x.b;
    

    then V8 has to look at x and its hidden class HC1 anyway, and it notices that HC1 has been marked "outdated", so it finds the updated version HC2 and updates x to use that.

    Optimizing dynamic languages like JavaScript is pretty complicated ;-)