On Sep 4, 2013, at 12:17 PM, Niko Matsakis <[email protected]> wrote:
> I think Filip is right that given sufficient cleverness extensible
> properties for typed objects can be implemented efficiently. The real
> question is what the behavior SHOULD be. As others have pointed out,
> we are not forced to support extensible properties for web compat
> reasons.
>
> I also think it is very important and useful to have typed objects be
> a generalization of typed arrays. I suspect nobody wants an "almost
> but not quite the same" set of array types. It'd be my preference that
> (eventually) the "specification" for typed arrays can just be "var
> Uint16Array = new ArrayType(uint16)", which I believe is currently
> plausible.
>
> In light of this consideration, that means that adding exensible
> properties to typed arrays means adding extensible properties to all
> "typed objects that are arrays" (that is, instances of some type
> defined by `new ArrayType()`).
>
> As Dmitry pointed out, extensible properties is only possible for
> "top-level" objects. I think this results in a surprising and
> non-composable spec.
>
> The surprising behavior isn't limited to the copying example that
> Dmitry gave. Another problem is that instances of array types that are
> found embedded in other structures don't have the full capabilities of
> "top-level" instances. Without extensible properties, it is true that
> if I have a function that is given a typed object (of any kind, array
> or struct) and uses it, I can also provide it with an instance of that
> same type that is a part of a bigger structure.
>
> For example:
>
> function doSomething(anArray) {
> anArray[0] = anArray[1];
> }
>
> // Invoke doSomething with top-level array
> var TwoUint8s = new ArrayType(uint8, 2);
> doSomething(new TwoUint8s());
>
> // Invoke doSomething with array that is
> // embedded within a struct:
> var MyStruct = StructType({a: TwoUint8s});
> var instance = new MyStruct();
> doSomething(instance.a);
>
> But this no longer works if `doSomething` makes use of extensible
> properties:
>
> function doSomething(anArray) {
> anArray[0] = anArray[1];
> anArray.foo = anArray.bar;
> }
>
> Now the second use case doesn't work.
>
> To me, it seems a shame to trade a simple story ("typed objects let
> you define the layout and fields of an object, full stop") for a more
> complex, non-composable one ("...except for extra fields on arrays,
> which only work some of the time").
Hi Niko,
The reason why I'm OK with the more complex story is that we already have that
story for '=='. To me, named object properties are analogous to being able to
identify whether you have the same object or a different object: both are
mechanisms that reveal aliasing to the user. Having typed objects that are
embedded in other ones already breaks ==.
-Filip
>
>
>
> Niko
>
>
> On Wed, Sep 04, 2013 at 08:11:14AM -0700, Filip Pizlo wrote:
>>
>> On Sep 4, 2013, at 7:55 AM, Andreas Rossberg <[email protected]> wrote:
>>
>>> On 4 September 2013 16:44, Filip Pizlo <[email protected]> wrote:
>>>>> On Sep 4, 2013, at 3:05 AM, Andreas Rossberg <[email protected]> wrote:
>>>>> As part of binary data, typed arrays are implicitly constructed "on
>>>>> the fly" as views on a backing store. Any notion of identity -- which
>>>>> is the prerequisite for state -- is not particularly meaningful in
>>>>> this setting.
>>>>
>>>> Are you proposing changing how == and === work for typed arrays? If not
>>>> then this whole argument is moot.
>>>
>>> No, they are just rather useless operations on data views. That
>>> doesn't make the argument moot.
>>
>> The point is that as soon as you're using the copy '=' on binary data
>> fields, you're already losing an observable notion of object identity. The
>> '=' here is already unlike the '=' operator for languages that have true
>> value types - in those languages you wouldn't be able to observe if you got
>> the *same* typed array or a different one but with the same underlying data.
>> In JS you will be able to observe this with '==' and '==='. Hence, being
>> able to also observe that you got a different one because you lost some
>> meta-data (i.e. custom named properties) doesn't change the fact that the
>> quirky semantics were already observable to the user.
>>
>>>
>>>>> Also, it is preferable to make them as lightweight as
>>>>> possible.
>>>>
>>>> See my previous mail. You gain zero space and zero performance from making
>>>> typed arrays non extensible.
>>>
>>> I think you are jumping to conclusions. You can very well optimize the
>>> representation of typed arrays if they don't have user-defined
>>> properties. Whether that's worth it I can't tell without experiments.
>>
>> I don't think this is a matter of opinion. There is state that typed arrays
>> are required to store but that is not accessed on the most critical of hot
>> paths, which naturally allows us to play displaced pointer tricks.
>>
>> It would also be useful, if you want to argue this point, if you replied to
>> my previous discussion of why there is no performance difference between
>> expandable and non-expandable typed arrays. I'll copy that here in case you
>> missed it:
>>
>> A typed array *must* know about the following bits of information:
>>
>> T: Its own type.
>> B: A base pointer (not the buffer but the thing you index off of).
>> L: Its length.
>>
>> But that only works if it owns its buffer - that is it was allocated using
>> for example "new Int8Array(100)" and you never used the .buffer property.
>> So in practice you also need:
>>
>> R: Reserved space for a pointer to a buffer.
>>
>> Now observe that 'R' can be reused for either a buffer pointer or a pointer
>> to overflow storage for named properties. If you have both a buffer and
>> overflow storage, you can save room in the overflow storage for the buffer
>> pointer (i.e. displace the buffer pointer into the property storage). We
>> play a slightly less ambitious trick, where R either points to overflow
>> storage or NULL. Most typed arrays don't have a .buffer, but once they get
>> one, we allocate overflow storage and reserve a slot in there for the buffer
>> pointer. So you pay *one more* word of overhead for typed arrays with
>> buffers even if they don't have named properties. I think that's probably
>> good enough - I mean, in that case, you have a freaking buffer object as
>> well so you're not exactly conserving memory.
>>
>> But, using R as a direct pointer to the buffer would be a simple hack if we
>> really felt like saving one word when you also already have a separate
>> buffer object.
>>
>> I could sort of imagine going further and using T as a displaced pointer and
>> saving an extra word, but that might make type checks more expensive,
>> sometimes.
>>
>> So lets do the math, on both 32-bit and 64-bit (where 64-bit implies 64-bit
>> pointers), to see how big this would be.
>>
>> 32-bit:
>>
>> T = 4 bytes, B = 4 bytes, L = 4 bytes, R = 4 bytes. So, you get 16 bytes of
>> overhead for most typed arrays, and 20 if you need to use R as an overflow
>> storage pointer and displace the buffer pointer into the overflow storage.
>>
>> 64-bit:
>>
>> T = 8 bytes, B = 8 bytes, L = 4 bytes, R = 8 bytes. This implies you have 4
>> bytes to spare if you want objects 8-byte aligned (we do); we use this for
>> some extra bookkeeping. So you get 32 bytes of overhead for most typed
>> arrays, and 40 if you need to use R as an overflow storage pointer and
>> displace the buffer pointer into the overflow storage.
>>
>> As far as I can tell, this object model compresses typed arrays about as
>> much as they could be compressed while also allowing them to be extensible.
>> The downside is that you pay a small penalty for typed arrays that have an
>> "active" buffer, in the case that you either accessed the .buffer property
>> or you constructed the typed array using a constructor that takes a buffer
>> as an argument.
>>
>> So, how big are your non-expanddable typed arrays, and what do they look
>> like? If they're not smaller than 16 bytes in the common case with 32-bit
>> pointers, or 32 bytes in the common case with 64-bit pointers, then there is
>> no performance argument in favor of getting rid of expandable properties.
>>
>> -Filip
>>
>>
>>> Admittedly, it's a minor point.
>>>
>>> /Andreas
>>
>
>> _______________________________________________
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss