Filip Pizlo <mailto:[email protected]>
September 4, 2013 12:34 PM
My point is that having custom properties, or not, doesn't change the
overhead for the existing typed array spec and hence has no effect on
small arrays. The reasons for this include:
- Typed arrays already have to be objects, and hence have a
well-defined behavior on '=='.
- Typed arrays already have to be able to tell you that they are in
fact typed arrays, since JS doesn't have static typing.
- Typed arrays already have prototypes, and those are observable
regardless of expandability. A typed array from one global object
will have a different prototype than a typed array from a different
global object. Or am I misunderstanding the spec?
- Typed arrays already have to know about their buffer.
- Typed arrays already have to know about their offset into the
buffer. Or, more likely, they have to have a second pointer that
points directly at the base from which they are indexed.
- Typed arrays already have to know their length.
You're not proposing changing these aspects of typed arrays, right?
Of course not, but for very small fixed length arrays whose .buffer is
never accessed, an implementation might optimize harder. It's hard for
me to say "no, Filip's analysis shows that's never worthwhile, for all
time."
The super short message is this: so long as an object obeys object
identity on '==' then you can have "free if unused, suboptimal if you
use them" custom properties by using a weak map on the side. This is
true of typed arrays and it would be true of any other object that
does object-style ==. If you allocate such an object and never add a
custom property then the weak map will never have an entry for it; but
if you put custom properties in the object then the map will have
things in it. But with typed arrays you can do even better as my
previous message suggests: so long as an object has a seldom-touched
field and you're willing to eat an extra indirection or an extra
branch on that field, you can have "free if unused, still pretty good
if you use them" custom properties by displacing that field. Typed
arrays have both of these properties right now and so expandability is
a free lunch.
The last sentence makes a "for-all" assertion I don't think
implementations must be constrained by. Small fixed-length arrays whose
.buffer is never accessed (which an implementation might be able to
prove by type inference) could be optimized harder.
The lack of static types in JS does not mean exactly one implementation
representation must serve for all instances of a given JS-level
abstraction. We already have strings optimized variously in the top VMs,
including Chords or Ropes, dependent strings, different character sets, etc.
Still find this discussion amusing? Here's the long story is: It is
these things that I list above that lead to a 16 byte overhead on
32-bit, and a 32-byte overhead on 64-bit in the best "sane" case.
Giving typed array objects expandability doesn't add to this
overhead, because two of the fields necessary to implement the above
(the type, and the buffer) can be displaced for pointing to property
storage. Any imaginable attempt to reduce the overhead incurred by
the information - using BBOP (big bag of pages) for the type, using an
out-of-line weak map for the buffer or the type, encoding some of the
bits inside the pointer to the typed array, etc. - can be also used to
eradicate any space overhead you'd need for custom properties, so long
as you're on board with the "free if unused, sub-optimal if you use
them" philosophy.
For something like decimal, it matters whether there's an empty side
table and large-N decimal instances of total size N*S, vs. N*(S+K) for
some constant K we could eliminate by specializing harder. Even better
if we agree that decimal instances should be non-extensible (and have
value not reference semantics -- more below).
- If the VM wants to go further and create immediate representations
of some or all Int64's, similarly to what VMs do for JS small integers
today, then the main problem you run into is object identity: does
Int64(1).add(Int64(1)) == Int64(1).add(Int64(1))? A naive JS
implementation of an Int64 class would say that this is false, since
it's likely to allocate a new Int64 each time. But an immediate
representation would have no choice but to say true. You can work
around this if you say that the VM's implementation of Int64
operations behaves /as if/ the add()/sub()/whatever() methods used a
singleton cache. You can still then have custom properties; i.e. you
could do Int64(2).foo = 42 and then Int64(1).add(Int64(1)).foo will
return 42, since the VM can keep an
immediate-int64-to-customproperties map on the side. That's kind of
analogous to how you could put a setter on field '2' of
Array.prototype and do some really hilarious things.
The value objects proposal for ES7 is live, I'm championing it. It does
not use (double-dispatch for dyadic) operators as methods. It does not
use extensible objects.
http://wiki.ecmascript.org/doku.php?id=strawman:value_objects
http://www.slideshare.net/BrendanEich/value-objects
Warning: both are slightly out of date, I'll be updating the strawman
over the next week.
With value objects, TC39 has definitely favored something that I think
you oppose, namely extending JS to have (more) objects with value not
reference semantics, which requires non-extensibility.
If I have followed your messages correctly, this is because you think
non-extensibility is a rare case that should not proliferate. But with
ES5 Object.preventExtensions, etc., the horse is out of the barn.
At a deeper level, the primitives wired into the language, boolean
number string -- in particular number when considering int64, bignum,
etc. -- can be rationalized as value objects provided we make typeof
work as people want (and work so as to uphold a == b && typeof a ==
typeof b <=> a === b).
This seems more winning in how it unifies concepts and empowers users to
make more value objects, than the alternative of saying "the primitives
are legacy, everything else has reference semantics" and turning a blind
eye, or directing harsh and probably ineffective deprecating words, to
Object.preventExtensions.
/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss