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

Reply via email to