Implement the Record and Tuple primitives based on objects
Categories
(Core :: JavaScript Engine, enhancement, P3)
Tracking
()
Tracking | Status | |
---|---|---|
firefox97 | --- | fixed |
People
(Reporter: nicolo.ribaudo, Assigned: nicolo.ribaudo)
References
(Blocks 3 open bugs, )
Details
Attachments
(21 files, 7 obsolete files)
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review | |
48 bytes,
text/x-phabricator-request
|
Details | Review |
+++ This bug was initially created as a clone of Bug #1658309 +++
https://github.com/tc39/proposal-record-tuple
I am opening this bug to track an alternative implementation for Bug #1658309 - "Implement the Record and Tuple proposal". Rather than implementing them as three custom new primitive types, they can be implemented as if they were objects but still be exposed to the JS code as if they were primitives.
Assignee | ||
Comment 1•3 years ago
|
||
This is an alternative implementation to D87232. I didn't implement
object wrappers for these new primitive-like-objects yet, so
typeof Object(rec)
is currently "record"
and not "object"
.
Assignee | ||
Comment 2•3 years ago
|
||
They are internally implemented using as dense elements. After that the tuple is fully initialized it's frozen to prevent modifications.
Depends on D125644
Assignee | ||
Comment 3•3 years ago
|
||
This patch adds #{} and #[] support to the parser and to Reflect.parse.
The AST has the same shapre of object and array literals, but the node
names are "RecordExpression" and "TupleExpression".
Since this patch only implements parser support and not bytecode emitter
support, any attempt of evaluating those literals will crash. This is why
I have only used Reflect.parse in the tests.
The ParseNode class sets the hasNonConstInitializerBit
flag for records
and tuples, since this will allow us to use a single record/tuple instance
if it's constant but evaluated multiple times.
This patch is effectively the same as D87586
Depends on D125645
Assignee | ||
Comment 4•3 years ago
|
||
This patch introduces three new op codes:
InitTuple length
preallocates a tuple of the given length: this is the final length if the
tuple doesn't contain spreads, otherwise it's the most pessimisitc choice possible
(i.e. spreads are assumed to introduce no new elements). The preallocated tuple size
can still grow if needed.AddTupleElement
pushes the last value in the stack to the tuple (the second-last stack element)FinishTuple
marks the tuple as initialized. An unfinished tuple should never leak to JavaScript
code, and any attempt to get its element will fail.
The bytecode relative to tuple spread is similar to the bytecode used for array spread, emitting
op codes to call the different steps of the iterator protocol.
Depends on D125646
Assignee | ||
Comment 5•3 years ago
|
||
This patch implements the SameValueZero
(===
) and SameValue
(Object.is
) algorithms for tuples, and adds the equivalent functions for records (they will crash when called).
Depends on D125647
Assignee | ||
Comment 6•3 years ago
|
||
This patch adds support for properties in records, when created using the Record({})
function.
Record properties are stored as normal object properties, but there is
an additional sortedKeys
internal slot containing an array of all the record
keys sorted alphabetically. This will be necessary when comparing two records
for equality, or when enumerating their properties.
Depends on D125649
Assignee | ||
Comment 7•3 years ago
|
||
This patch defines the bytecode for record literals, similarly to how it has been implemented for tuple literals:
InitRecord [length]
pushes a new record to the stack, allocating
memory forlength
propertiesAddRecordProperty
reads the key and the value from the stack,
and defines it on the record which is being initializedFinishRecord
freezes a record and sorts its keys
This patch doesn't implement support for spread in record literals yet.
Depends on D125650
Assignee | ||
Comment 8•3 years ago
|
||
This is done introducing a new opcode, AddRecordSpread
, that
takes a value and defines its enumerable properties on the record
which is currently being initialized.
Depends on D125651
Assignee | ||
Comment 9•3 years ago
|
||
This reuses the same implementation strategy used for tuples
Depends on D125652
Assignee | ||
Comment 10•3 years ago
|
||
This patch implements the third new type introduced by the Records and Tuples proposal: Box
.
It implements:
- the
"box"
primitive type, implemented as an object - the
Box
function and its instance methods - boxes equality
Still missing:
- support for boxes as
Map
andSet
keys Box.containBoxes
(this function will likely change in the proposal)
Depends on D125654
Assignee | ||
Comment 11•3 years ago
|
||
This patch fixes Object.keys
in records to return sorted keys, and adds
tests for the other Object.*
methods.
Assignee | ||
Comment 12•3 years ago
|
||
This patch fixes the missing pieces to make enumeration and object
operations work with tuples (they need to be handled
specially in some places because of the contextual prototype).
Depends on D125656
Assignee | ||
Comment 13•3 years ago
|
||
This patch implements JSON.stringify
as specified in the Record and Tuple proposal.
Due to the Box unwrapping logic, balancing between "don't duplicate code" and "keep the R&T code isolated behind the ENABLE_RECORD_TUPLE
flag" was tricky: I ended up extracting the code to call toJSON
to a separate funcition even
if without the R&T proposal it's used only once.
Depends on D125657
Assignee | ||
Comment 14•3 years ago
|
||
Depends on D125658
Assignee | ||
Comment 15•3 years ago
|
||
When preparing records, tuples and boxes to be used as a Map/Set key, we
recursively atomize the strings that they contain. This makes it
possible to compute a hash for the whole structure, and to compare them
with an infallible function.
ToDo: Figure out where to store the isAtomized flag for tuples
Depends on D125659
Updated•3 years ago
|
Assignee | ||
Comment 16•3 years ago
|
||
This is in preparation of the next patch which will introduce object wrappers
Depends on D125660
Assignee | ||
Comment 17•3 years ago
|
||
Depends on D126690
Assignee | ||
Comment 18•3 years ago
|
||
Even if they are still implemented as subclasses of JSObject
, representing
them differently in the Value
wrapper has a few advantages:
- Checking the equality semantics of an object (deep vs pointer) is faster,
since we only need to check theValue
's bits. - It's easier to differentiate between R/T/B and R/T/B object wrappers,
since.isObject()
returnsfalse
for the "primitives". For example,
this patch fixes thetypeof Object(#{})
tests.
This approach's advantages are the same as what we would get implementing them
as primitives from scratch (https://phabricator.services.mozilla.com/D87232),
but it also allows us to re-use the existing objects optimizations.
Depends on D126691
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Assignee | ||
Comment 19•3 years ago
|
||
Even if R&T are internally implemented as objects, they are still
primitives and they should be have object wrappers:
typeof Tuple() === "tuple"
typeof Object(Tuple()) === "object"
Depends on D125644
Assignee | ||
Comment 20•3 years ago
|
||
This patch fixes and tests handling of property descriptors for record properties
Depends on D125650
Assignee | ||
Comment 21•3 years ago
|
||
This patch fixes the missing pieces to make object operations work with tuples.
Depends on D129675
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Updated•3 years ago
|
Assignee | ||
Comment 22•3 years ago
|
||
The proposal currently specifies R/T/B wrappers as frozen.
This patch makes them look as if they were frozen, while still internally
keeping them marked as extensible. This allows lazily resolving the
wrapper properties (so that we can avoid a full copy every time we
create the wrapper object), but they are exposed as non-extensible to JS
code.
It's still possible that the proposal will switch to make them mutable;
you can follow the discussion (and participate!) at
https://github.com/tc39/proposal-record-tuple/issues/137.
Depends on D125660
Comment 23•3 years ago
|
||
Hi Anba,
In this patch, Nicolò has encountered some oddity with make_intl_data.py
and the resulting headers. Would you mind taking a peek to give a hint on what's going on; I don't really understand what's going on here.
Comment 24•3 years ago
|
||
Sorry about those bugs. I've filed bug 1741220 and bug 1741222 to fix this.
Assignee | ||
Comment 25•2 years ago
|
||
This is done by not using the NativeGetProperty
and NativeDeleteProperty
functions for R/T/B, but by creating two new "parallel" functions that handle them specifically.
This is because R/T/B don't behave like classic objects, but they get their prototype lexically (like other primitives).
It's not necessary to reimplement NativeSetProperty
, because it always throw since R/T/B are frozen.
Depends on D131124
Assignee | ||
Comment 26•2 years ago
|
||
Since tuples use inline elements, they cannot have internal slots and thus we cannot store the IS_ATOMIZED
flag as we do for records and tuples. However, we can store it in a bit of the ObjectElements
flags.
Depends on D132367
Assignee | ||
Comment 27•2 years ago
|
||
Depends on D132393
Assignee | ||
Comment 28•2 years ago
|
||
The code for converting records and objects to strings would be almost identical:
to avoid dynamic branches I converted them to if constexpr
statements.
I also found that we didn't have a test for boxed R&T (only for boxes Box).
Ref https://phabricator.services.mozilla.com/D132367#inline-730448
Depends on D132367
Assignee | ||
Comment 29•2 years ago
|
||
This patch fixes a regression introduced by the --enable-record-tuple
build flag, which made
https://searchfox.org/mozilla-central/source/js/src/tests/non262/template-strings/bug1559123.js
crash because the IsExtendedPrimitive
doesn't work with forwarded objects.
This patch introduces a new gc::MaybeForwardedIsExtendedPrimitive
function, similar to
the existing gc::MaybeForwardedObjectIs
one.
Depends on D132393
Updated•2 years ago
|
Comment 30•2 years ago
|
||
Comment on attachment 9253022 [details]
Bug 1730843 - Part 20 - Run Records&Tuples tests on ci
Revision D132467 was moved to bug 1744967. Setting attachment 9253022 [details] to obsolete.
Assignee | ||
Updated•2 years ago
|
Assignee | ||
Comment 31•2 years ago
|
||
After the feedback received at the Dec 2021 TC39 meeting, it's very unlikely
that the proposal will include Box
. This patch removes it so that the
rest of the R&T implementation can be merged.
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Updated•2 years ago
|
Comment 32•2 years ago
|
||
Pushed by arai_a@mac.com: https://hg.mozilla.org/integration/autoland/rev/ffe0bb1cf293 Part 1 - Add support for empty R&T based on objects r=jandem https://hg.mozilla.org/integration/autoland/rev/a8299b7a31fb Part 1-bis - Implement object wrappers for records and tuples r=jandem https://hg.mozilla.org/integration/autoland/rev/392c8d7d8ca0 Part 2 - Add support for elements in tuples r=mgaudet,jandem https://hg.mozilla.org/integration/autoland/rev/f9064fa3d5a9 Part 3 - Add parser support for records and tuples r=mgaudet https://hg.mozilla.org/integration/autoland/rev/8357f3e24b2b Part 4 - Add bytecode emitter and interpreter support for tuple literals r=jandem https://hg.mozilla.org/integration/autoland/rev/2a468171b056 Part 5 - Implement === and Object.is support for tuples r=mgaudet https://hg.mozilla.org/integration/autoland/rev/c0a945467649 Part 6 - Add support for properties in records r=mgaudet https://hg.mozilla.org/integration/autoland/rev/dd527f2cda3e Part 6-bis - Implement correct handling of record properties r=mgaudet https://hg.mozilla.org/integration/autoland/rev/db55cc5e622f Part 7 - Implement bytecode/interpreter for record literals r=mgaudet https://hg.mozilla.org/integration/autoland/rev/084f3f116de4 Part 8 - Add support for spread in records r=jandem https://hg.mozilla.org/integration/autoland/rev/364f21c8f9d9 Part 9 - Implement === and Object.is support for records r=mgaudet https://hg.mozilla.org/integration/autoland/rev/85bcb1310053 Part 11 - Add support for iterating records r=mgaudet https://hg.mozilla.org/integration/autoland/rev/117538978e60 Part 12 - Add support for iterating tuples r=mgaudet https://hg.mozilla.org/integration/autoland/rev/2a2a3a3e7f89 Part 13 - Add `JSON.stringify` support for R&T r=mgaudet https://hg.mozilla.org/integration/autoland/rev/2e0010e8acde Part 14 - Implement `JSON.parseImmutable` r=mgaudet https://hg.mozilla.org/integration/autoland/rev/5820e13028f9 Part 15 - Implement support for R&T as Map/Set keys r=jandem https://hg.mozilla.org/integration/autoland/rev/2ad3c818ecd8 Part 16 - Mark R&T object wrappers as frozen r=mgaudet https://hg.mozilla.org/integration/autoland/rev/2e211a594b05 Part 17 - Don't use ObjectOps for `ExtendedPrimitive` properties r=jandem https://hg.mozilla.org/integration/autoland/rev/b15d9ea6fcd4 Part 17-bis - Avoid branching between objects/records in `JO` r=jandem https://hg.mozilla.org/integration/autoland/rev/9999c06e4fbe Part 18 - Mark atomized tuples using the elements header r=jandem https://hg.mozilla.org/integration/autoland/rev/3f37e6c2e61f Part 19 - Fix IsExtendedPrimitive check for forwarded objects r=jandem
Comment 33•2 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/ffe0bb1cf293
https://hg.mozilla.org/mozilla-central/rev/a8299b7a31fb
https://hg.mozilla.org/mozilla-central/rev/392c8d7d8ca0
https://hg.mozilla.org/mozilla-central/rev/f9064fa3d5a9
https://hg.mozilla.org/mozilla-central/rev/8357f3e24b2b
https://hg.mozilla.org/mozilla-central/rev/2a468171b056
https://hg.mozilla.org/mozilla-central/rev/c0a945467649
https://hg.mozilla.org/mozilla-central/rev/dd527f2cda3e
https://hg.mozilla.org/mozilla-central/rev/db55cc5e622f
https://hg.mozilla.org/mozilla-central/rev/084f3f116de4
https://hg.mozilla.org/mozilla-central/rev/364f21c8f9d9
https://hg.mozilla.org/mozilla-central/rev/85bcb1310053
https://hg.mozilla.org/mozilla-central/rev/117538978e60
https://hg.mozilla.org/mozilla-central/rev/2a2a3a3e7f89
https://hg.mozilla.org/mozilla-central/rev/2e0010e8acde
https://hg.mozilla.org/mozilla-central/rev/5820e13028f9
https://hg.mozilla.org/mozilla-central/rev/2ad3c818ecd8
https://hg.mozilla.org/mozilla-central/rev/2e211a594b05
https://hg.mozilla.org/mozilla-central/rev/b15d9ea6fcd4
https://hg.mozilla.org/mozilla-central/rev/9999c06e4fbe
https://hg.mozilla.org/mozilla-central/rev/3f37e6c2e61f
Description
•