@@initialize, or describing subclassing with mixins

Jussi Kalliokoski jussi.kalliokoski at gmail.com
Mon Jun 30 12:00:40 PDT 2014


On Mon, Jun 30, 2014 at 4:41 PM, Boris Zbarsky <bzbarsky at mit.edu> wrote:

> On 6/30/14, 5:37 AM, Jussi Kalliokoski wrote:
>
>> However, the key thing is that it could be applied to any given object,
>> not just
>> instances of the host object.
>>
>
> The problem with this is that it requires either allocating the hidden
> state outside the object itself somewhere or requiring all objects to have
> space for this hidden space or both (e.g. allocating some amount of space
> for hidden state in all objects but spilling out into out-of-line slots
> when you want more hidden state than that).
>
> So this fails one of the primary design criteria for @@create: being able
> to explain the existing builtins (both ES and DOM), which allocate hidden
> state inline for efficiency's sake.
>
> I realize you consider this an irrelevant implementation detail, but it
> _is_ important.


No, I don't consider potential to optimize an irrelevant implementation
detail, especially when it comes to DOM. However, my knowledge in
engine-level DOM optimization is relatively poor, so I'm glad to have any
flaws in the idea pointed out.


>  As an example, here's how you could self-host Map in these terms:
>> https://gist.github.com/jussi-kalliokoski/5ef02ef90c6cbb8c1a70 . In the
>> example, the uninitialized state is never revealed.
>>
>
> Right, at the cost of requiring the symbol thing, which costs both
> performance and memory.
>

The host environment needs not use actual symbols, but I see your point.


>               DocumentFragment.prototype.appendChild.call(this, value);
>>
>
> This is an interesting example.  How do you expect the appendChild code to
> perform the check that its this value is a Node (not necessarily
> DocumentFragment, note, appendChild needs to work on any node) in this
> case?  Your time budget for this is 20 machine instructions as an absolute
> limit, 10 preferred and your space budget is "as small as possible".
>

There are various approaches to that, all cost something, but the current
approach is not free either. One heavy-handed optimization for the poor
performance common case is to have Object's struct contain a pointer to a
Node's host object, then if that's null, the object doesn't represent a
Node. Depending on what you count in, that's around 4 instructions per
check (I'm surprised if the current implementations do better than that).
Memory footprint is 32bits on ARM and x86, and 64 bits on 64bit
environments, per every Object, so pretty damn high. Performance often lies
in tradeoffs, however, so an implementation might spend some extra cycles
on having its own memory map of DOM nodes instead and enforce 32bit, or if
they're sadistic towards developers of massive table sites, 24 bits. This
can also be implemented as a binary flag where the layout is expanded if
the flag is active to take the non-Node object memory footprint addition to
1 bit.

Another, more general, approach that's less memory-greedy for DOM-light
applications is to store that pointer (or the whole state) in the layout of
objects that are "naturally" instances of Node, then even possibly use the
symbol space (or something less expensive) for the state if it's not. That
doesn't change the current situation's best-case performance (i.e. only
instances of Node are attempted to be appended to the DOM, where you have
to do the instance checks in the current situation as well), adds one check
to the case of erroring out for appending a non-Node, and leaves the
performance cost on the doorstep of the thing that wasn't even possible
before.

Aside, out of curiosity, which is more problematic in DOM currently:
creation or appending of nodes? My guess is appending, but when it comes to
performance I'd take data over instinct any day.


> (This is not even worrying about the fact that in practice we want
> different in-memory layouts for different DOM objects,


These different in-memory layouts can be applied to the state behind the
pointer.


> that Object.prototype.toString needs to return different values for
> different sorts of DOM objects


Depending on how the internal layout problem is solved, that can be looked
up from the internal state just as now, or the prototype chain (latter
being a slight compatibility hazard). After all, no code is currently using
@@initialize today so we can't break the behavior of plain object - DOM
node mixins.


> , or that some DOM objects need different internal hooks (akin to proxies)
> from normal objects.)
>

The internals can again be in the internal state. However, this internal
state is now explainable in terms of the spec language. For all the
implementation cares, the spec may describe that the implementation uses
private symbols to store the internal state, and then the implementation
stores the state inline anyway, because there's no test can prove that it
doesn't internally use private symbols for it.

Cheers,
Jussi


> -Boris
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140630/40144f24/attachment.html>


More information about the es-discuss mailing list