Lazy evaluation

Andrea Giammarchi andrea.giammarchi at
Wed Sep 13 07:30:55 UTC 2017

> The properties already existed, so defineProperty shouldn't modify the
order IIUC

well, nope. the property existed in the prototype, not in the object.

anyway, I guess private properties, that are a possible solution, will be
transpiled through a WeakMap so that most likely anything discussed in here
won't make sense and the future code would look like the following

class A {
  get random() {
    return this.#random ||
          (this.#random = Math.random());

// transpiled
var A = function (wm) {
  function A() {
    wm.set(this, {random: void 0});
      random: {
        configurable: true,
        get: function () {
          return wm.get(this).random ||
                (wm.get(this).random = Math.random());
  return A;
}(new WeakMap);

On Tue, Sep 12, 2017 at 10:39 PM, Steve Fink <sphink at> wrote:

> My intent was only to respond to the performance analysis, specifically
> the implication that the only performance cost is in building the new
> hidden class. That is not the case; everything that touches those objects
> is affected as well.
> Whether or not it's still the right way to accomplish what you're after, I
> wasn't venturing an opinion. I could probably come up with a benchmark
> showing that your WeakMap approach can be faster -- eg by only accessing
> the property once, but feeding the old and new versions of the object into
> code that executes many many many times (doing something that never looks
> at that property, but is now slightly slower because it isn't monomorphic).
> But I suspect that for practical usage, redefining the property *is* faster
> than a WeakMap.
> If I were to look beyond for other solutions for your problem, then I'm
> just speculating. Can decorators populate multiple properties once the
> expensive work is done?
> I really want to tell the VM what's going on. I guess if it knew that
> accessing a getter property would convert it into a value property, and
> that it was doing something that would access the getter, then it could
> know to use the outgoing shape instead of the incoming shape. If only it
> knew that the getter was pure... but that way lies madness.
> Given that most code that would slow down would also trigger the lazy
> defineProperty(), it's really not going to be that much of an issue. Any
> access after the first will see a single shape.
> meh. Just take the perf hit, with awareness that you may be triggering
> slight slowdowns in all users of that object. Or you might not. I doubt
> it'll be that big, since you'll probably just end up with an inline cache
> for both shapes and there won't be all that much to optimize based on
> knowing a single shape.
> Oh, and I think I was wrong about property enumeration order. The
> properties already existed, so defineProperty shouldn't modify the order
> IIUC. (I am awful with language semantics.)
> On 9/11/17 2:48 PM, Andrea Giammarchi wrote:
> Steve it's not solved in any other way. Even if you use a WeakMap with an
> object, you gonna lazy attach properties to that object.
> I honestly would like to see alternatives, if any, 'cause so far there is
> a benchmark and it proves already lazy property assignment is around 4x
> faster.
> So, it's easy to say "it's not the best approach" but apparently hard to
> prove that's the case?
> Looking forward to see better alternatives.
> On Mon, Sep 11, 2017 at 8:15 PM, Steve Fink <sphink at> wrote:
>> On 9/11/17 5:36 AM, Matthew Robb wrote:
>> > I think it's irrelevant if internally VMs are not too happy. VMs are
>> there to solve our problems, not vice-versa ;-)
>>>> This ^​ is very important for everyone to get on board with. Regardless
>> the cost should be negligible as the shape is only changing at the point of
>> delayed init. This will cause, for example V8, to deop the object and have
>> to build a new hidden class but only the one time. I guess it would
>> potentially be interesting to support an own property that when undefined
>> would delegate up the proto chain.
>> (I don't know, but) I would expect it to be worse than this. The shape is
>> changing at the point of delayed init, which means that if an engine is
>> associating the possible set of shapes with the constructor (or some other
>> form of allocation site + mandatory initialization), then that site will
>> produce multiple shapes. All code using such objects, if they ever see both
>> shapes, will have to handle them both. Even worse, if you have several of
>> these delayed init properties and you end up lazily initializing them in
>> different orders (which seems relatively easy to do), then the internal
>> slot offsets will vary.
>> You don't need to bend over backwards to make things easy for the VMs,
>> but you don't want to be mean to them either. :-)
>> Not to mention that the observable property iteration order will vary.
>> On Mon, Sep 11, 2017 at 7:09 AM, Andrea Giammarchi <
>> andrea.giammarchi at> wrote:
>> Hi Peter.
>>> Unless you have a faster way to do lazy property assignment, I think
>>> it's irrelevant if internally VMs are not too happy. VMs are there to solve
>>> our problems, not vice-versa ;-)
>>> Regards
>>> On Mon, Sep 11, 2017 at 11:54 AM, peter miller <fuchsia.groan at
>>> > wrote:
>>>> Hi Andrea,
>>>> ```
>>>>> class CaseLazy {
>>>>>   get bar() {
>>>>>     var value = Math.random();
>>>>>     Object.defineProperty(this, 'bar', {value});
>>>>>     return value;
>>>>>   }
>>>>> }
>>>>> ```
>>>> Doesn't this count as redefining the shape of the object? Or are the
>>>> compilers fine with it?
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list