• Benedikt Meurer's avatar
    [runtime] Better instance pre-sizing with transpiled classes. · 4b9eb7f7
    Benedikt Meurer authored
    For instances created via constructors and `new` we try to pre-size
    the instances such that ideally all the data properties can be
    allocated as in-object properties (and we don't need to allocate the
    out-of-object PropertyArray backing store). This is accomplished with
    the helper of the Parser, which counts the property assignments to
    `this` in the constructor, and we use that as the starting point for
    pre-sizing logic (a mechanism called *slack tracking* is used to
    dynamically shrink the objects based on the real memory usage, and
    eventually compute the final starting size for instances of the
    individual constructors).
    
    This works well even with class hierarchies, since for a derived class
    constructor we just include the current constructor plus all the base
    constructors. I.e. with
    
    ```js
    class A {
      constructor() {
        this.x00 = null;
        this.x01 = null;
        this.x02 = null;
        this.x03 = null;
        this.x04 = null;
        this.x05 = null;
        this.x06 = null;
        this.x07 = null;
        this.x08 = null;
        this.x09 = null;
        this.x10 = null;
        this.x11 = null;
        this.x12 = null;
        this.x13 = null;
        this.x14 = null;
        this.x15 = null;
        this.x16 = null;
        this.x17 = null;
        this.x18 = null;
        this.x19 = null;
      }
    }
    
    class B extends A {
      constructor() {
        super();
      }
    }
    ```
    
    we will eventually learn that instances of `B` need 20 in-object
    properties. However this breaks with transpiled code (i.e. as
    generated via TypeScript or Babel), even when the constructors are
    properly chained.
    
    ```js
    function A() {
      this.x00 = null;
      this.x01 = null;
      this.x02 = null;
      this.x03 = null;
      this.x04 = null;
      this.x05 = null;
      this.x06 = null;
      this.x07 = null;
      this.x08 = null;
      this.x09 = null;
      this.x10 = null;
      this.x11 = null;
      this.x12 = null;
      this.x13 = null;
      this.x14 = null;
      this.x15 = null;
      this.x16 = null;
      this.x17 = null;
      this.x18 = null;
      this.x19 = null;
    }
    
    function B() {
      A.call(this);
    }
    Object.setPrototypeOf(B, A);
    ```
    
    Here we will always have 10 in-object properties for instances of
    `B` (due to the generic over-allocation logic), and the other 10
    properties have to be allocated in the out-of-object PropertyArray.
    
    This is unfortunate and actually not necessary. Instead we could just
    do the same [[Prototype]] walk on the constructor for regular function
    constructors that we perform for derived (native) class constructors.
    This CL changes that, such that we give the same treatment to transpiled
    class that we have for native classes.
    
    R=verwaest@chromium.org
    
    Bug: v8:8764, v8:8765
    Doc: https://bit.ly/v8-instance-presizing-with-transpiled-classes
    Change-Id: Iac54391e41c9a39101751a678b3a647269fb009d
    Reviewed-on: https://chromium-review.googlesource.com/c/1442643
    Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
    Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#59214}
    4b9eb7f7
js-objects.h 59.5 KB