Closed
Bug 720580
Opened 13 years ago
Closed 13 years ago
InitClassesWithNewWrappedGlobal should only create one global (with JS_NewCompartmentAndGlobal)
Categories
(Core :: XPConnect, defect)
Core
XPConnect
Tracking
()
RESOLVED
FIXED
mozilla13
People
(Reporter: luke, Assigned: bholley)
References
Details
Attachments
(2 files)
55 bytes,
text/plain
|
mrbkap
:
review+
|
Details |
93.92 KB,
patch
|
Details | Diff | Splinter Review |
To have compartment-per-global, every use of JS_NewGlobal needs to be replaced with JS_NewCompartmentAndGlobalObject. There are only 3 calls in the browser, two are trivial (xpc_CreateGlobalObject, xpc_CreateMTGlobalObject) and one is non-trivial: xpc_NewSystemInheritingJSObject. This bug is to fix the non-trivial case. IIUC, it is only used for a few non-content globals so I think this could land ahead of bug 650353. Lasty, there is one more JS_NewGlobalObject use in xpcshell.cpp that needs to be replaced.
Assignee | ||
Comment 1•13 years ago
|
||
I'm busy with new DOM binding stuff at the moment, but hopefully I can start on this in two weeks or so.
Assignee | ||
Comment 2•13 years ago
|
||
(In reply to Luke Wagner [:luke] from comment #0) > To have compartment-per-global, every use of JS_NewGlobal needs to be > replaced with JS_NewCompartmentAndGlobalObject. There are only 3 calls in > the browser, two are trivial (xpc_CreateGlobalObject, > xpc_CreateMTGlobalObject) and one is non-trivial: > xpc_NewSystemInheritingJSObject. This bug is to fix the non-trivial case. > IIUC, it is only used for a few non-content globals Digging into it, I don't think this is true. The first few dozen times that code path is hit, it is indeed for the BackstagePass, but that's just because a lot of component loading goes on (via mozJSComponentLoader) long before we do anything with content. A cursory reading of nsXPConnect::InitClassesWithNewWrappedGlobal would indicate that we're using xpc_CreateGlobalObject for the common path. But the following comment explains that this is contrary to reality: > // XXX This is not pretty. We make a temporary global object and > // init it with all the Components object junk just so we have a > // parent with an xpc scope to use when wrapping the object that will > // become the 'real' global. Indeed, looking more closely, the only uses of xpc_Create{,MT}GlobalObject are sandboxes, this temp global stuff, and mSafeJSContext. Everything else goes through the newSystemInheritingJSObject path. :-(
![]() |
Reporter | |
Comment 3•13 years ago
|
||
(First of all, good news: xpc_NewMTGlobal is going away: bug 722594.) Hm, you seem to be right; and the clasps are not just BackstagePass, but ChromeWindow, Window, and ContentFrameMessageManager so, like, all global windows. I wonder if this changed in the last 5 months, because I was fairly certain I had looked at this. Another interesting thing is that the calls to xpc_NewGlobal and xpc_NewSystemInheritingJSObject almost seemed paired. Also: loading a browser with a single google.com tab shows 102 system compartments and 7 user compartments (with the c-p-g patch, of course). Thus, it seems that compartments are being created. Perhaps xpc_NewSystemInheritingJSObject always (or almost always) creates a global in the compartment created by xpc_NewGlobal and the fix is to undo the hack by creating the (non-temporary) global up-front?
![]() |
Reporter | |
Comment 4•13 years ago
|
||
After a bit more inspection, it seems that what the bug really wants is for InitClassesWithNewWrappedGlobal to create its global object directly without calling xpc_NewSystemInheritingJSObject. That way xpc_NewSystemInheritingJSObject could assert that the given clasp was not a global class.
Summary: s/JS_NewGlobalObject/JS_NewCompartmentAndGlobalObject/ in xpc_NewSystemInheritingJSObject → InitClassesWithNewWrappedGlobal should only create one global (with JS_NewCompartmentAndGlobal)
Assignee | ||
Comment 5•13 years ago
|
||
(In reply to Luke Wagner [:luke] from comment #4) > After a bit more inspection, it seems that what the bug really wants is for > InitClassesWithNewWrappedGlobal to create its global object directly without > calling xpc_NewSystemInheritingJSObject. That way > xpc_NewSystemInheritingJSObject could assert that the given clasp was not a > global class. Yeah, that's my (and Blake's) assessment as well. I got partway through some patches for this, but ran into cross-compartment assertions when trying to set the prototype. Blake and I talked about this today, and I think the solution is to create the global much earlier on, and stop using all the generic XPCScriptable machinery for everything (since we're getting rid of that anyway with the new DOM bindings). I'll be working on this in the coming days, though I'll be a bit distracted with FOSDEM stuff.
![]() |
Reporter | |
Comment 6•13 years ago
|
||
On the subject, if there is any way you can see to avoid calling that JS_SplicePrototype madness, that'd be awesome.. IIUC, this patch could land early? (In particular, with the assert(!(clasp->flags & JSCLASS_IS_GLOBAL)) in xpc_NewSystemInheritingJSObject)?
Assignee | ||
Comment 7•13 years ago
|
||
(In reply to Luke Wagner [:luke] from comment #6) > On the subject, if there is any way you can see to avoid calling that > JS_SplicePrototype madness, that'd be awesome.. Unlikely. We can't create the prototype first, because there's no global > > IIUC, this patch could land early? (In particular, with the > assert(!(clasp->flags & JSCLASS_IS_GLOBAL)) in > xpc_NewSystemInheritingJSObject)?
Assignee | ||
Comment 8•13 years ago
|
||
Ooops, hit enter before I meant to. (In reply to Luke Wagner [:luke] from comment #6) > On the subject, if there is any way you can see to avoid calling that > JS_SplicePrototype madness, that'd be awesome.. Unlikely. We can't create the prototype first, because there's no global to parent it to. As I understand it, it's easy to create a global without a prototype, but not the reverse. > > IIUC, this patch could land early? (In particular, with the > assert(!(clasp->flags & JSCLASS_IS_GLOBAL)) in > xpc_NewSystemInheritingJSObject)? Depends. I don't have a good sense of what the assumptions are before and after c-p-g and whether we need any of those new assumptions in the fix here.
![]() |
Reporter | |
Comment 9•13 years ago
|
||
(In reply to Bobby Holley (:bholley) from comment #8) > > On the subject, if there is any way you can see to avoid calling that > > JS_SplicePrototype madness, that'd be awesome.. > > Unlikely. We can't create the prototype first, because there's no global to > parent it to. As I understand it, it's easy to create a global without a > prototype, but not the reverse. True (and, as I say this, I know this is "for some later bug"), but perhaps this is a very reasonable thing to want to do (create your global's prototype before the global) and we could add a JSAPI giving a sane way to do it. One idea is to allow creating a compartment before the global. We could do this without breaking assumptions everywhere by specifying that the compartment couldn't be used until its global was created and set. > > IIUC, this patch could land early? (In particular, with the > > assert(!(clasp->flags & JSCLASS_IS_GLOBAL)) in > > xpc_NewSystemInheritingJSObject)? > > Depends. I don't have a good sense of what the assumptions are before and > after c-p-g and whether we need any of those new assumptions in the fix here. I don't think this patch would depend on c-p-g invariants: the task is just to remove the temp-global hack. As long the new strategy looks roughly like xpc_NewGlobalObject (that is, there is a hash table lookup that conditionally creates a new compartment), then the c-p-g patch can just remove the branch and always create a new compartment.
Comment 10•13 years ago
|
||
(In reply to Luke Wagner [:luke] from comment #9) > True (and, as I say this, I know this is "for some later bug"), but perhaps > this is a very reasonable thing to want to do (create your global's > prototype before the global) and we could add a JSAPI giving a sane way to I don't really like this idea. Especially in the case of windows where we're going to change the prototype at least one or two more times, it doesn't really gain us anything for the most common case. How bad is splicing the prototype once on object creation? > do it. One idea is to allow creating a compartment before the global. We > could do this without breaking assumptions everywhere by specifying that the > compartment couldn't be used until its global was created and set. This complicates the lifetime of compartments quite a bit, though. What happens for the first GC? The second? What if we enter another compartment and hit an exception?
![]() |
Reporter | |
Comment 11•13 years ago
|
||
(In reply to Blake Kaplan (:mrbkap) from comment #10) > How bad is splicing the prototype once on object creation? It used to be analogous to setting __proto__ from script, but that now is heavily deoptimized (which is bad for global objects), so we had to introduce a special set-__proto__-but-don't-be-slow-because-we-know...stuff path. Blech. > > do it. One idea is to allow creating a compartment before the global. We > > could do this without breaking assumptions everywhere by specifying that the > > compartment couldn't be used until its global was created and set. > > This complicates the lifetime of compartments quite a bit, though. What > happens for the first GC? The second? What if we enter another compartment > and hit an exception? With enough asserts (to enforce that a compartment never gets used before it gets initialized with a global) I think there would be no global increase in complexity over just making sure GC doesn't kill un-initialized compartments. If the reseting-prototypes-during-init problem is systemic and baked into our design, then I agree it doesn't make sense to fix in just one place. Judging by the six calls to JS_SplicePrototype in mxr, I suspect this is the case.
Assignee | ||
Comment 12•13 years ago
|
||
This is going well. My github branch is here: https://github.com/bholley/mozilla-central/commits/cpg2 I've finally got the browser starting up, running, and shutting down with this stuff applied. For the most part everything goes normally, though there are few small anomalies in the console that I need to look into. There are also a few other changes I want to make, and a hack commit that I need to write a real fix for. But I'm closing in on it. ;-)
Assignee | ||
Comment 13•13 years ago
|
||
So one of the anomalies I ran into was that |window.Window| wasn't being defined properly. As it turned out, we were bailing early in nsDOMClassInfo::PostCreatePrototype, because we tried to get the native associated with the global and QI it to nsPIDOMWindow all at once. The native was null (because we hadn't yet created a wrapper for it), so we were just returning early from all that stuff, assuming that we weren't dealing with a window for a global. I've fixed that, but now there's a whole host of other issues cropping up with the code in nsDOMClassInfo that assumes we're farther along in creating a window than we really are. They're all tractable problems so far, but it's back to compile-run-crash-fix for now. ;-)
Assignee | ||
Comment 14•13 years ago
|
||
I ended up abandoning my efforts to try to make PostCreatePrototype deal with bootstrapping windows, and worked up a solution akin to RefreshPrototype instead. That stuff now works, and the browser builds and passes XPConnect tests. I've just got a few other things to look into and then it should be ready to push to try.
Assignee | ||
Comment 15•13 years ago
|
||
This is now in good shape. The latest patches are on my gitub branch (see comment 12), and I've pushed it to try here: https://tbpl.mozilla.org/?tree=Try&rev=8eb4db4f5eec In the event that it goes green, I'll flag mrbkap for review.
Assignee | ||
Comment 16•13 years ago
|
||
Looks green! Flagging mrbkap for review.
Attachment #596232 -
Flags: review?(mrbkap)
Comment 17•13 years ago
|
||
- In "Stop passing isGlobal everywhere and use the nsIXPCScriptable flags instead. v1" @@ -1093,7 +1090,7 @@ XPCWrappedNative::Init(XPCCallContext& ccx, JSClass* jsclazz = si ? si->GetJSClass() : Jsvalify(&XPC_WN_NoHelper_JSClass); - if (isGlobal) { + if (si && si->GetFlags().IsGlobalObject()) { // Resolving a global object's class can cause us to create a global's // JS class without the proper global flags. Notice that here and fix // the problem. With these changes, this should no longer be possible. So we should be able to assert that IsGlobalObject implies XPCONNECT_GLOBAL_FLAGS.
Assignee | ||
Comment 18•13 years ago
|
||
Attaching a combined patch, rebased to tip for luke.
Assignee | ||
Comment 19•13 years ago
|
||
Patch updated to pass false rather than true for wantXray during global creation. It appears that this is more what we want.
Comment 20•13 years ago
|
||
*out = foo.forget().get() should be replaced with foo.forget(out); throughout
Updated•13 years ago
|
Attachment #596232 -
Flags: review?(mrbkap) → review+
Assignee | ||
Comment 21•13 years ago
|
||
Pushed this all to try one more time: https://tbpl.mozilla.org/?tree=Try&rev=6bd6af6ccd66
Assignee | ||
Comment 22•13 years ago
|
||
Looks green. Pushed 19 changesets to m-i: http://hg.mozilla.org/integration/mozilla-inbound/rev/a8115574617b (and ancestors)
Target Milestone: --- → mozilla13
Comment 23•13 years ago
|
||
Was this expected? Regression :( Dromaeo (jslib) decrease 2.43% on Win7 Mozilla-Inbound-Non-PGO ---------------------------------------------------------------------------- Previous: avg 145.708 stddev 1.351 of 30 runs up to revision 0601f686e1b8 New : avg 142.165 stddev 0.597 of 5 runs since revision a8115574617b Change : -3.543 (2.43% / z=2.622) Graph : http://mzl.la/AoGbEm Changeset range: http://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=0601f686e1b8&tochange=a8115574617b https://groups.google.com/d/msg/mozilla.dev.tree-management/oPLq7LW9iQw/dDiGYhxLGu8J
Assignee | ||
Comment 24•13 years ago
|
||
I'm spinning up a profiling build to investigate this now. I'll check if any of the dromaeo tests are disproportionately affected, and if anything jumps out at me from the profiler. If I don't find anything though, I think we should probably ignore this: * It's only on Win7 Non-PGO * It's not clear from the graph that this is actually the culprit changeset * It's a small drop on one-platform, making it very difficult to say anything definitive about * It's a huge change that blocks compartment-per-global (a Q1 DOM goal). FWIW, khuey agrees with the above analysis.
Comment 25•13 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/a8115574617b https://hg.mozilla.org/mozilla-central/rev/56c192395dd3 https://hg.mozilla.org/mozilla-central/rev/119787ed1514 https://hg.mozilla.org/mozilla-central/rev/8277b919772d https://hg.mozilla.org/mozilla-central/rev/592a35a4e03d https://hg.mozilla.org/mozilla-central/rev/b5abccf004e2 https://hg.mozilla.org/mozilla-central/rev/d6e1981c7d3e https://hg.mozilla.org/mozilla-central/rev/62b27d043ec8 https://hg.mozilla.org/mozilla-central/rev/a17c3b23a664 https://hg.mozilla.org/mozilla-central/rev/3ebefca0bf40 https://hg.mozilla.org/mozilla-central/rev/32ae32597625 https://hg.mozilla.org/mozilla-central/rev/951150c4758a https://hg.mozilla.org/mozilla-central/rev/36df6e53c4a1 https://hg.mozilla.org/mozilla-central/rev/0fd1e730ebd3 https://hg.mozilla.org/mozilla-central/rev/e7228f6767ae https://hg.mozilla.org/mozilla-central/rev/2880b8cc9551 https://hg.mozilla.org/mozilla-central/rev/cf7d53530360 https://hg.mozilla.org/mozilla-central/rev/9592334d4aff https://hg.mozilla.org/mozilla-central/rev/79c6b50a95c5
Status: ASSIGNED → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Assignee | ||
Comment 26•13 years ago
|
||
InitClassesWithNewWrappedGlobal, which is where the meat of the changes are, seems to be barely called on the dromaeo stuff (which would make sense, since dromaeo doesn't do too much with iframes AFAIK). So I say we ignore the comment 23.
Comment 27•13 years ago
|
||
wfm :-)
Comment 28•13 years ago
|
||
we (Thunderbird) are hitting this assertion, !(clasp->flags & (1<<((8 + 8)+2)))", in NewSystemInheritingJSObject - we're loading a js module from a modal dialog, and calling a method that takes an nsIRequestObserver, which in turn passes a callback to an other js component - that callback calls onStopRequest on the nsIRequestObserver after running an xhr request, and that call to onStopRequest triggers this assertion. Any hints on what we could be doing wrong?
Assignee | ||
Comment 29•13 years ago
|
||
(In reply to David :Bienvenu from comment #28) > we (Thunderbird) are hitting this assertion, !(clasp->flags & (1<<((8 + > 8)+2)))", in NewSystemInheritingJSObject - we're loading a js module from a > modal dialog, and calling a method that takes an nsIRequestObserver, which > in turn passes a callback to an other js component - that callback calls > onStopRequest on the nsIRequestObserver after running an xhr request, and > that call to onStopRequest triggers this assertion. Whoa, that's quite a mouthful! ;-) Can you file a separate bug and attach a stack?
Comment 30•13 years ago
|
||
(In reply to Bobby Holley (:bholley) from comment #29) > Whoa, that's quite a mouthful! ;-) > > Can you file a separate bug and attach a stack? turned out we had a callback function with a bad "this" pointer by the time it got called back, so the error was most likely correct. Sorry for the false alarm!
Updated•11 years ago
|
You need to log in
before you can comment on or make changes to this bug.
Description
•