Skip to content

Should ECMAScript implementations be allowed to canonicalize NaN when writing into an Array? #635

Open
@littledan

Description

@littledan

V8 has several representations of Arrays based on different kinds of unboxed content, called ElementKind. One ElementKind is FAST_HOLEY_DOUBLE_ELEMENTS. With this kind, the Array may contain holes (missing properties which delegate to the prototype), but all non-hole elements are unboxed doubles (Numbers). The trick is to canonicalize NaNs when written into such an array, and use a particular NaN value for "the hole" to indicate that a lookup on the prototype is needed.

This implementation technique violates the ECMAScript specification because, in SetValueInBuffer, there is the following text:

An implementation must always choose the same encoding for each implementation distinguishable NaN value.

I believe this text was written with the intent of creating the cross-cutting effect that NaNs should always carry around their payload, and only get a new payload when a "new" NaN is created. (We could use some better spec text here to back that intention with more clear mechanics, and I've promised to do that, except I want to get this other issue worked out first.) A big piece of motivation for that is to prevent information leaks, e.g., in writing properties to frozen objects.

I'm wondering, is there a way that we could weaken this requirement? V8's practice of canonicalizing NaNs just in order to write them into certain objects seems to improve our performance, and it seems harmless to me, as I don't know of any information leaks that we're creating.

For a strawman: what if we simply removed that sentence and let SetValueInBuffer write whatever NaN representation it felt like? Is there another way we could convince ourselves that information leaks won't happen?

cc @bakkot @anba @erights @leobalter @verwaest

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions