Closed
Bug 1370608
Opened 8 years ago
Closed 8 years ago
Add a newEnumerate-friendly version of JS_EnumerateStandardClasses
Categories
(Core :: JavaScript Engine, enhancement)
Tracking
()
RESOLVED
FIXED
mozilla56
Tracking | Status | |
---|---|---|
firefox56 | --- | fixed |
People
(Reporter: bzbarsky, Assigned: jandem)
References
(Depends on 1 open bug, Blocks 1 open bug)
Details
Attachments
(3 files)
93.23 KB,
patch
|
evilpies
:
review+
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
9.75 KB,
patch
|
evilpies
:
review+
|
Details | Diff | Splinter Review |
8.34 KB,
patch
|
bzbarsky
:
review+
|
Details | Diff | Splinter Review |
Right now things that do lazy standard classes have to enumerate them all whenever someone asks them for their list of properties. This is noticeably slow (order of ~1ms on modern-ish laptop hardware) on the first call.
If we had this API, we could use it on top of bug 1364816 to improve things for window in particular.
Assignee | ||
Updated•8 years ago
|
Flags: needinfo?(jdemooij)
Assignee | ||
Comment 1•8 years ago
|
||
I was looking at this earlier today and it doesn't seem too hard, but I don't understand why it's okay for the newEnumerate hook on Window to ignore its enumerableOnly argument.
Things do seem to work correctly: Object.keys(window) does not return everything that Object.getOwnPropertyNames(window) returns.
Flags: needinfo?(bzbarsky)
Assignee | ||
Comment 2•8 years ago
|
||
For window it's probably because of this if-else, where Object.keys ends up in the else-branch:
http://searchfox.org/mozilla-central/rev/d840ebd5858a61dbc1622487c1fab74ecf235e03/js/src/jsiter.cpp#385-416
(And Object.keys(window) is still slow)
Assignee | ||
Comment 4•8 years ago
|
||
Maybe nsOuterWindowProxy::getOwnEnumerablePropertyKeys should forward to Wrapper::getOwnEnumerablePropertyKeys instead of BaseProxyHandler::getOwnEnumerablePropertyKeys.
That would match what we do for ownPropertyKeys and should give us the fast behavior, but we do need to fix the enumerableOnly bit first. I'll file a bug for this tomorrow.
Reporter | ||
Comment 5•8 years ago
|
||
> but I don't understand why it's okay for the newEnumerate hook on Window to ignore its enumerableOnly argument.
Hrm. I thought it was because all those properties were enumerable anyway, but I now see that they are NOT supposed to be enumerable. So this is kinda working by accident.
I believe comment 2 is correct in terms of what's going on here at the moment.
Comment 4 is also correct. I filed bug 1372371 on this enumerability stuff.
Assignee | ||
Comment 6•8 years ago
|
||
This moves the JSNewEnumerate hook to ClassOps, to make it easier to port code from the old hook to the new one.
Very mechanical for the most part, because most classes don't have a JSNewEnumerate hook.
Assignee: nobody → jdemooij
Status: NEW → ASSIGNED
Flags: needinfo?(jdemooij)
Attachment #8877054 -
Flags: review?(evilpies)
Attachment #8877054 -
Flags: review?(bzbarsky)
Assignee | ||
Comment 7•8 years ago
|
||
This adds JS_NewEnumerateStandardClasses and uses it instead of JS_EnumerateStandardClasses in js/src.
I confirmed Object.getOwnPropertyNames(this).sort() is the same as before.
I also changed PreventExtensions to force resolving lazy properties when there's a newEnumerate hook and a resolve hook, to handle Object.freeze(this) etc correctly.
Attachment #8877057 -
Flags: review?(evilpies)
Assignee | ||
Comment 8•8 years ago
|
||
I didn't convert SystemGlobalEnumerate as there are some XPConnect callers that are not trivial to convert to newEnumerate.
Maybe I'll take a stab at it later (it would be nice if we could remove the enumerate hook completely), but it's better done as a followup.
Attachment #8877062 -
Flags: review?(bzbarsky)
Reporter | ||
Comment 9•8 years ago
|
||
Comment on attachment 8877054 [details] [diff] [review]
Part 1 - Move newEnumerate from ObjectOps to ClassOps
r=me on the bits outside js/src
I did no read the js/src parts.
Attachment #8877054 -
Flags: review?(bzbarsky) → review+
Reporter | ||
Comment 10•8 years ago
|
||
Comment on attachment 8877062 [details] [diff] [review]
Part 3 - Use JS_NewEnumerateStandardClasses outside js/src
>+ if (!EnumerateGlobal(cx, obj, properties, enumerableOnly)) {
Does the JS engine deduplicate the list we return here? Or is that our responsibility?
The reason I ask is that the old behavior just resolved the standard classes on the global, then returned a list of names for the DOM bits, and the JS engine would pick up the standard class names itself as own props of the global and presumably ensure that we didn't end up repeating names.
But in the new setup we're just adding ids to the list from EnumerateGlobal and then from the Window bits. We really _shouldn't_ end up with duplicate IDs, because people better not be defining WebIDL interface names that are the same as JS standard classes. And Window is really the only consumer of this code... But conceptually, where should the deduplication happen? If in this code, it could use a comment explaining why we're not bothering.
r=me with that.
Attachment #8877062 -
Flags: review?(bzbarsky) → review+
Comment 11•8 years ago
|
||
Comment on attachment 8877054 [details] [diff] [review]
Part 1 - Move newEnumerate from ObjectOps to ClassOps
Review of attachment 8877054 [details] [diff] [review]:
-----------------------------------------------------------------
Ignore the renaming if you are going to change the name later anyway.
::: dom/plugins/base/nsJSNPRuntime.cpp
@@ +224,5 @@
> NPObjWrapper_DelProperty,
> NPObjWrapper_GetProperty,
> NPObjWrapper_SetProperty,
> + nullptr, /* enumerate */
> + NPObjWrapper_Enumerate,
_NewEnumerate
::: js/src/builtin/TypedObject.cpp
@@ +2233,5 @@
> nullptr, /* delProperty */ \
> nullptr, /* getProperty */ \
> nullptr, /* setProperty */ \
> nullptr, /* enumerate */ \
> + TypedObject::obj_enumerate, \
newEnumerate.
We should really rename the old hook like you suggested.
::: js/src/vm/EnvironmentObject.cpp
@@ +416,5 @@
> + nullptr, /* delProperty */
> + nullptr, /* getProperty */
> + nullptr, /* setProperty */
> + nullptr, /* enumerate */
> + ModuleEnvironmentObject::enumerate
newEnumerate
::: js/src/vm/UnboxedObject.cpp
@@ +950,5 @@
> nullptr, /* delProperty */
> nullptr, /* getProperty */
> nullptr, /* setProperty */
> nullptr, /* enumerate */
> + UnboxedPlainObject::enumerate,
^
Attachment #8877054 -
Flags: review?(evilpies) → review+
Comment 12•8 years ago
|
||
Comment on attachment 8877057 [details] [diff] [review]
Part 2 - Add JS_NewEnumerateStandardClasses
Review of attachment 8877057 [details] [diff] [review]:
-----------------------------------------------------------------
Looks good. I am a bit surprised that we only had to make a single change to make lazy resolving of the properties work.
::: js/src/jsapi.cpp
@@ +1126,5 @@
> + continue;
> +
> + JSProtoKey key = table[i].key;
> + if (key == JSProto_Null ||
> + global->isStandardClassResolved(key) ||
Can we make this a single if statement, maybe with a short comment?
Attachment #8877057 -
Flags: review?(evilpies) → review+
Assignee | ||
Comment 13•8 years ago
|
||
(In reply to Boris Zbarsky [:bz] (if a patch has no decent message, automatic r-) from comment #10)
> Does the JS engine deduplicate the list we return here? Or is that our
> responsibility?
The JS engine does this. For each property, we call Enumerate and there we use a HashSet to check for duplicates:
http://searchfox.org/mozilla-central/rev/61054508641ee76f9c49bcf7303ef3cfb6b410d2/js/src/jsiter.cpp#97-100
Sometimes we optimize this when we know the HashSet is not necessary, but we always use the HashSet when we have a newEnumerate hook (see the outer if-statement), so we should be good.
Assignee | ||
Comment 14•8 years ago
|
||
(In reply to Tom Schuster [:evilpie] from comment #11)
> Ignore the renaming if you are going to change the name later anyway.
I'll rename the ones you suggested. I'm a bit on the fence about it because in the end we do want to remove the enumerate hook and rename newEnumerate -> enumerate but I'm not sure when that will be and it should be easy to rename them back.
Comment 15•8 years ago
|
||
Pushed by jandemooij@gmail.com:
https://hg.mozilla.org/integration/mozilla-inbound/rev/f30ec8ac7239
part 1 - Move newEnumerate hook from ObjectOps to ClassOps. r=evilpie,bz
https://hg.mozilla.org/integration/mozilla-inbound/rev/51f0acbee7c9
part 2 - Add JS_NewEnumerateStandardClasses and use it in js/src. r=evilpie
https://hg.mozilla.org/integration/mozilla-inbound/rev/d4a0301fac3a
part 3 - Use JS_NewEnumerateStandardClasses outside js/src. r=bz
Comment 16•8 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/f30ec8ac7239
https://hg.mozilla.org/mozilla-central/rev/51f0acbee7c9
https://hg.mozilla.org/mozilla-central/rev/d4a0301fac3a
Status: ASSIGNED → RESOLVED
Closed: 8 years ago
status-firefox56:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla56
You need to log in
before you can comment on or make changes to this bug.
Description
•