|
|
DescriptionRefactor Script(Loader|Runner): don't access Resources all over the place...
... but use proper layering instead.
PendingScript holds a Resource, and many places in the code are using both the
PendingScript and the underlying Resource. For example, ScriptRunner holds a
collection of PendingScripts, and ScriptLoaders then listen to the underlying
Resources. This is confusing and error prone.
The Resource - ScriptLoader - PendingScript - Element love quadrangle is messy
in general. Both ScriptLoader and PendingScript refer to the Resource. The way
to get ScriptLoader from PendingScript is via Element which PendingScript also
holds. But there's no way to get PendingScript from ScriptLoader.
This CL makes ScriptRunner access the ScriptLoaders directly and moves the
PendingScript to ScriptLoader. In addition, it makes ScriptRunner not access the
Resource of the ScriptLoader directly.
This CL also cancels the hack from https://bugs.webkit.org/show_bug.cgi?id=92211
(r139942) where it was speculated that a crash can be caused by ScriptLoader
getting the notifyFinished notification twice because it doesn't unsubscribe yet
when it gets the first one. The speculative fix was to made it nullify
ScriptLoader::m_resource and check for the nullity later. This is pretty
surprising, since the obvious solution would've been to just unsubscribe early
enough (which is done by this CL).
Note a behavioral change: It's OK to call Resource::addClient even if the
Resource is finished, and in that case, the client will be notified
immediately. But PendingScript used to ASSERT that the Resource is not
finished. This CL removes that restriction (the underlying Resource already
handles adding clients to finished resources + made ScriptStreamer handle it
too).
Committed: https://src.chromium.org/viewvc/blink?view=rev&revision=183873
Patch Set 1 #Patch Set 2 : . #Patch Set 3 : . #Patch Set 4 : . #
Total comments: 16
Patch Set 5 : code review (haraken) #
Total comments: 2
Messages
Total messages: 28 (5 generated)
marja@chromium.org changed reviewers: + jochen@chromium.org
jochen, ptal haraken, fyi, and you're ofc welcome to have a look too.
lgtm
haraken@chromium.org changed reviewers: + haraken@chromium.org
This is nice refactoring. https://codereview.chromium.org/656113002/diff/60001/Source/bindings/core/v8/... File Source/bindings/core/v8/ScriptStreamer.h (left): https://codereview.chromium.org/656113002/diff/60001/Source/bindings/core/v8/... Source/bindings/core/v8/ScriptStreamer.h:69: ASSERT(!isFinished()); Can we keep this ASSERT? We want to avoid a situation where addClient is reentered. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/PendingS... File Source/core/dom/PendingScript.cpp (left): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/PendingS... Source/core/dom/PendingScript.cpp:43: ASSERT(!isReady()); Can we keep this ASSERT? The comment implies that we don't want to enter this fucntion when isReady. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... File Source/core/dom/ScriptLoader.cpp (right): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... Source/core/dom/ScriptLoader.cpp:78: m_pendingScript.stopWatchingForLoad(this); We might want to avoid calling stopWatchingForLoad twice. It's possible that notifyFinished called stopWatchingForLoad before. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... Source/core/dom/ScriptLoader.cpp:376: m_resource = 0; Just help me understand: Don't we need to call m_pendingScript.stopWatchingForLoad(this) here? https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... Source/core/dom/ScriptLoader.cpp:389: Shall we add ASSERT(m_resource)? https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... File Source/core/dom/ScriptRunner.cpp (left): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... Source/core/dom/ScriptRunner.cpp:62: ASSERT(element->inDocument()); Why did you remove these ASSERTs? https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... File Source/core/dom/ScriptRunner.h (right): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... Source/core/dom/ScriptRunner.h:72: // FIXME: Oilpan: what to do with these? You can remove this comment now. This comment was about PendingScript. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... Source/core/dom/ScriptRunner.h:75: HashSet<ScriptLoader*> m_pendingAsyncScripts; Just help me understand: You're using raw pointers to ScriptLoader but who owns the ScriptLoader? (i.e., who guarantees that these raw ScriptLoaders don't become stale pointers?)
Thanks for having a look. haraken@, I didn't end up actually doing any of the non-trivial comments... https://codereview.chromium.org/656113002/diff/60001/Source/bindings/core/v8/... File Source/bindings/core/v8/ScriptStreamer.h (left): https://codereview.chromium.org/656113002/diff/60001/Source/bindings/core/v8/... Source/bindings/core/v8/ScriptStreamer.h:69: ASSERT(!isFinished()); On 2014/10/15 15:09:41, haraken wrote: > > Can we keep this ASSERT? > > We want to avoid a situation where addClient is reentered. No, since ScriptLoader::prepareScript calls this for scripts which are already finished and wants to get the notification immediately. This is also consistent with Resource::addClient. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/PendingS... File Source/core/dom/PendingScript.cpp (left): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/PendingS... Source/core/dom/PendingScript.cpp:43: ASSERT(!isReady()); On 2014/10/15 15:09:41, haraken wrote: > > Can we keep this ASSERT? The comment implies that we don't want to enter this > fucntion when isReady. Ditto https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... File Source/core/dom/ScriptLoader.cpp (right): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... Source/core/dom/ScriptLoader.cpp:78: m_pendingScript.stopWatchingForLoad(this); On 2014/10/15 15:09:41, haraken wrote: > > We might want to avoid calling stopWatchingForLoad twice. It's possible that > notifyFinished called stopWatchingForLoad before. No, stopWatchingForLoad handles it gracefully - which is really handy here because it's tedious to track it otherwise. The hack which used to be in ScriptLoader::stopLoadRequest() ("we're watching if the Resource is non-null and if !m_willBeParserExecuted) is horrible. We'd basically end up tracking the exact same thing ("are we watching or not") which PendingScript already does internally. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... Source/core/dom/ScriptLoader.cpp:376: m_resource = 0; On 2014/10/15 15:09:41, haraken wrote: > > Just help me understand: Don't we need to call > m_pendingScript.stopWatchingForLoad(this) here? No, because it's already called in execute(). https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... Source/core/dom/ScriptLoader.cpp:389: On 2014/10/15 15:09:41, haraken wrote: > > Shall we add ASSERT(m_resource)? It's a bit unnecessary since we already ASSERT resource == m_resource and this is not called with NULL... https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... File Source/core/dom/ScriptRunner.cpp (left): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... Source/core/dom/ScriptRunner.cpp:62: ASSERT(element->inDocument()); On 2014/10/15 15:09:41, haraken wrote: > > Why did you remove these ASSERTs? Because we no longer need to access the Element here. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... File Source/core/dom/ScriptRunner.h (right): https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... Source/core/dom/ScriptRunner.h:72: // FIXME: Oilpan: what to do with these? On 2014/10/15 15:09:41, haraken wrote: > > You can remove this comment now. This comment was about PendingScript. Done. https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... Source/core/dom/ScriptRunner.h:75: HashSet<ScriptLoader*> m_pendingAsyncScripts; On 2014/10/15 15:09:41, haraken wrote: > > Just help me understand: You're using raw pointers to ScriptLoader but who owns > the ScriptLoader? (i.e., who guarantees that these raw ScriptLoaders don't > become stale pointers?) That didn't change with this CL; ScriptLoader is owned by... hmm... Element, I think. ScriptRunner only accesses the ScriptLoaders if the ScriptLoaders tell them they're finished, so it can theoretically happen that during ramp-down, these pointers are stale but never accessed. But that was the same situation before too (it's possible that the ScriptLoaders never notify about the PendingScripts being finished).
marja@chromium.org changed reviewers: + morrita@chromium.org
morrita@, re: our chat discussion. Here I'm moving the "stop watching" call (~ Resource::removeClient) from ScriptLoader::execute to ScriptLoader::notifyFinished. Are you saying this would cause problems?
On 2014/10/16 15:19:50, marja wrote: > morrita@, re: our chat discussion. > > Here I'm moving the "stop watching" call (~ Resource::removeClient) from > ScriptLoader::execute to ScriptLoader::notifyFinished. > > Are you saying this would cause problems? I have no clear idea what was wrong when there was a crash. Here are a couple of reverts I made due to the crash. Yours is much smaller (thus safer) so I think it's worth giving a shot. - https://codereview.chromium.org/288033006 - https://codereview.chromium.org/283333002 Byte the way, ScriptLoader is a mess and the refactoring is appreciated. Thanks for working on this.
On 2014/10/16 17:04:05, morrita wrote: > On 2014/10/16 15:19:50, marja wrote: > > morrita@, re: our chat discussion. > > > > Here I'm moving the "stop watching" call (~ Resource::removeClient) from > > ScriptLoader::execute to ScriptLoader::notifyFinished. > > > > Are you saying this would cause problems? > > I have no clear idea what was wrong when there was a crash. > Here are a couple of reverts I made due to the crash. > Yours is much smaller (thus safer) so I think it's worth giving a shot. > > - https://codereview.chromium.org/288033006 > - https://codereview.chromium.org/283333002 > > Byte the way, ScriptLoader is a mess and the refactoring is appreciated. s/Byte/By/
On 2014/10/16 15:19:04, marja wrote: > Thanks for having a look. > > haraken@, I didn't end up actually doing any of the non-trivial comments... > > https://codereview.chromium.org/656113002/diff/60001/Source/bindings/core/v8/... > File Source/bindings/core/v8/ScriptStreamer.h (left): > > https://codereview.chromium.org/656113002/diff/60001/Source/bindings/core/v8/... > Source/bindings/core/v8/ScriptStreamer.h:69: ASSERT(!isFinished()); > On 2014/10/15 15:09:41, haraken wrote: > > > > Can we keep this ASSERT? > > > > We want to avoid a situation where addClient is reentered. > > No, since ScriptLoader::prepareScript calls this for scripts which are already > finished and wants to get the notification immediately. > > This is also consistent with Resource::addClient. > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/PendingS... > File Source/core/dom/PendingScript.cpp (left): > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/PendingS... > Source/core/dom/PendingScript.cpp:43: ASSERT(!isReady()); > On 2014/10/15 15:09:41, haraken wrote: > > > > Can we keep this ASSERT? The comment implies that we don't want to enter this > > fucntion when isReady. > > Ditto > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... > File Source/core/dom/ScriptLoader.cpp (right): > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... > Source/core/dom/ScriptLoader.cpp:78: m_pendingScript.stopWatchingForLoad(this); > On 2014/10/15 15:09:41, haraken wrote: > > > > We might want to avoid calling stopWatchingForLoad twice. It's possible that > > notifyFinished called stopWatchingForLoad before. > > No, stopWatchingForLoad handles it gracefully - which is really handy here > because it's tedious to track it otherwise. The hack which used to be in > ScriptLoader::stopLoadRequest() ("we're watching if the Resource is non-null and > if !m_willBeParserExecuted) is horrible. > > We'd basically end up tracking the exact same thing ("are we watching or not") > which PendingScript already does internally. > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... > Source/core/dom/ScriptLoader.cpp:376: m_resource = 0; > On 2014/10/15 15:09:41, haraken wrote: > > > > Just help me understand: Don't we need to call > > m_pendingScript.stopWatchingForLoad(this) here? > > No, because it's already called in execute(). > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptLo... > Source/core/dom/ScriptLoader.cpp:389: > On 2014/10/15 15:09:41, haraken wrote: > > > > Shall we add ASSERT(m_resource)? > > It's a bit unnecessary since we already ASSERT resource == m_resource and this > is not called with NULL... > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... > File Source/core/dom/ScriptRunner.cpp (left): > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... > Source/core/dom/ScriptRunner.cpp:62: ASSERT(element->inDocument()); > On 2014/10/15 15:09:41, haraken wrote: > > > > Why did you remove these ASSERTs? > > Because we no longer need to access the Element here. > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... > File Source/core/dom/ScriptRunner.h (right): > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... > Source/core/dom/ScriptRunner.h:72: // FIXME: Oilpan: what to do with these? > On 2014/10/15 15:09:41, haraken wrote: > > > > You can remove this comment now. This comment was about PendingScript. > > Done. > > https://codereview.chromium.org/656113002/diff/60001/Source/core/dom/ScriptRu... > Source/core/dom/ScriptRunner.h:75: HashSet<ScriptLoader*> m_pendingAsyncScripts; > On 2014/10/15 15:09:41, haraken wrote: > > > > Just help me understand: You're using raw pointers to ScriptLoader but who > owns > > the ScriptLoader? (i.e., who guarantees that these raw ScriptLoaders don't > > become stale pointers?) > > That didn't change with this CL; ScriptLoader is owned by... hmm... Element, I > think. > > ScriptRunner only accesses the ScriptLoaders if the ScriptLoaders tell them > they're finished, so it can theoretically happen that during ramp-down, these > pointers are stale but never accessed. But that was the same situation before > too (it's possible that the ScriptLoaders never notify about the PendingScripts > being finished). Thanks for the clarification. LGTM, this is a nice cleanup!
On 2014/10/16 17:04:05, morrita wrote: > On 2014/10/16 15:19:50, marja wrote: > > morrita@, re: our chat discussion. > > > > Here I'm moving the "stop watching" call (~ Resource::removeClient) from > > ScriptLoader::execute to ScriptLoader::notifyFinished. > > > > Are you saying this would cause problems? > > I have no clear idea what was wrong when there was a crash. > Here are a couple of reverts I made due to the crash. > Yours is much smaller (thus safer) so I think it's worth giving a shot. > > - https://codereview.chromium.org/288033006 > - https://codereview.chromium.org/283333002 > > Byte the way, ScriptLoader is a mess and the refactoring is appreciated. > Thanks for working on this. Alright, based on these CLs, it doesn't look like moving the un-listen call from execute() to notifyFinished would be a problem. Let's see. Thanks for reviews, everyone.
The CQ bit was checked by marja@chromium.org
CQ is trying da patch. Follow status at https://chromium-cq-status.appspot.com/patch-status/656113002/80001
Message was sent while issue was closed.
Committed patchset #5 (id:80001) as 183873
Message was sent while issue was closed.
sigbjornf@opera.com changed reviewers: + sigbjornf@opera.com
Message was sent while issue was closed.
https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... File Source/core/dom/ScriptLoader.h (right): https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... Source/core/dom/ScriptLoader.h:107: PendingScript m_pendingScript; This is a problem; PendingScript has traceable Member.
Message was sent while issue was closed.
On 2014/10/17 10:23:17, sof wrote: > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > File Source/core/dom/ScriptLoader.h (right): > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > Source/core/dom/ScriptLoader.h:107: PendingScript m_pendingScript; > This is a problem; PendingScript has traceable Member. https://codereview.chromium.org/576853003/ is somewhat related; ScriptLoader needs to similarly wrap, I suspect.
Message was sent while issue was closed.
On 2014/10/17 10:30:04, sof wrote: > On 2014/10/17 10:23:17, sof wrote: > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > > File Source/core/dom/ScriptLoader.h (right): > > > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > > Source/core/dom/ScriptLoader.h:107: PendingScript m_pendingScript; > > This is a problem; PendingScript has traceable Member. > > https://codereview.chromium.org/576853003/ is somewhat related; ScriptLoader > needs to similarly wrap, I suspect. Hmm, I know we discussed this once already, but I'm confused again. Why is not adding a trace function to ScriptLoader enough? The wrapper is really clumsy!
Message was sent while issue was closed.
On 2014/10/17 10:39:59, marja wrote: > On 2014/10/17 10:30:04, sof wrote: > > On 2014/10/17 10:23:17, sof wrote: > > > > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > > > File Source/core/dom/ScriptLoader.h (right): > > > > > > > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > > > Source/core/dom/ScriptLoader.h:107: PendingScript m_pendingScript; > > > This is a problem; PendingScript has traceable Member. > > > > https://codereview.chromium.org/576853003/ is somewhat related; ScriptLoader > > needs to similarly wrap, I suspect. > > Hmm, I know we discussed this once already, but I'm confused again. Why is not > adding a trace function to ScriptLoader enough? The wrapper is really clumsy! (HTMLScriptRunner also has a PendingScript member and it just trace()s it...)
Message was sent while issue was closed.
On 2014/10/17 10:41:11, marja wrote: > On 2014/10/17 10:39:59, marja wrote: > > On 2014/10/17 10:30:04, sof wrote: > > > On 2014/10/17 10:23:17, sof wrote: > > > > > > > > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > > > > File Source/core/dom/ScriptLoader.h (right): > > > > > > > > > > > > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptLo... > > > > Source/core/dom/ScriptLoader.h:107: PendingScript m_pendingScript; > > > > This is a problem; PendingScript has traceable Member. > > > > > > https://codereview.chromium.org/576853003/ is somewhat related; ScriptLoader > > > needs to similarly wrap, I suspect. > > > > Hmm, I know we discussed this once already, but I'm confused again. Why is not > > adding a trace function to ScriptLoader enough? The wrapper is really clumsy! > > (HTMLScriptRunner also has a PendingScript member and it just trace()s it...) ResourceClients aren't on the Oilpan heap / GCed objects.
Message was sent while issue was closed.
https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptRu... File Source/core/dom/ScriptRunner.cpp (right): https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptRu... Source/core/dom/ScriptRunner.cpp:146: visitor->trace(m_scriptsToExecuteInOrder); Vector<ScriptLoader*> isn't traceable. Hmm, I wonder if we really need to force ScriptLoader onto the heap somehow.
Message was sent while issue was closed.
On 2014/10/17 10:55:50, sof wrote: > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptRu... > File Source/core/dom/ScriptRunner.cpp (right): > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptRu... > Source/core/dom/ScriptRunner.cpp:146: visitor->trace(m_scriptsToExecuteInOrder); > Vector<ScriptLoader*> isn't traceable. > > Hmm, I wonder if we really need to force ScriptLoader onto the heap somehow. https://codereview.chromium.org/660233002/ does that; it looks unproblematic (but checking with the bots.)
Message was sent while issue was closed.
On 2014/10/17 11:26:27, sof wrote: > On 2014/10/17 10:55:50, sof wrote: > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptRu... > > File Source/core/dom/ScriptRunner.cpp (right): > > > > > https://codereview.chromium.org/656113002/diff/80001/Source/core/dom/ScriptRu... > > Source/core/dom/ScriptRunner.cpp:146: > visitor->trace(m_scriptsToExecuteInOrder); > > Vector<ScriptLoader*> isn't traceable. > > > > Hmm, I wonder if we really need to force ScriptLoader onto the heap somehow. > > https://codereview.chromium.org/660233002/ does that; it looks unproblematic > (but checking with the bots.) Thx for working on this!
Message was sent while issue was closed.
A revert of this CL (patchset #5 id:80001) has been created in https://codereview.chromium.org/662863002/ by aboxhall@chromium.org. The reason for reverting is: Seems to have caused a leak: http://test-results.appspot.com/dashboards/flakiness_dashboard.html#master=Ch....
Message was sent while issue was closed.
On 2014/10/17 20:10:31, aboxhall wrote: > A revert of this CL (patchset #5 id:80001) has been created in > https://codereview.chromium.org/662863002/ by mailto:aboxhall@chromium.org. > > The reason for reverting is: Seems to have caused a leak: > http://test-results.appspot.com/dashboards/flakiness_dashboard.html#master=Ch.... Oh, this didn't apply, probably because of https://chromium.googlesource.com/chromium/blink/+/b46dd2f5a79b7574e94deb168c... which may have fixed the issue...
Message was sent while issue was closed.
On 2014/10/17 20:19:43, aboxhall wrote: > On 2014/10/17 20:10:31, aboxhall wrote: > > A revert of this CL (patchset #5 id:80001) has been created in > > https://codereview.chromium.org/662863002/ by mailto:aboxhall@chromium.org. > > > > The reason for reverting is: Seems to have caused a leak: > > > http://test-results.appspot.com/dashboards/flakiness_dashboard.html#master=Ch.... > > Oh, this didn't apply, probably because of > https://chromium.googlesource.com/chromium/blink/+/b46dd2f5a79b7574e94deb168c... > which may have fixed the issue... Yes, they go together & it needs to be reverted first. I'd be quite surprised if it changes non-Oilpan leak behavior.
Message was sent while issue was closed.
A revert of this CL (patchset #5 id:80001) has been created in https://codereview.chromium.org/669503003/ by dstockwell@chromium.org. The reason for reverting is: Introduced leaks in the following tests: fast/dom/HTMLScriptElement/append-child-adopt-node-error-crash.html fast/dom/HTMLScriptElement/script-async-attr.html fast/dom/HTMLScriptElement/script-load-events.html fast/dom/URL-attribute-reflection.html fast/events/onerror-bubbling.html http/tests/cache/loaded-from-cache-after-reload.html http/tests/cache/subresource-expiration-2.html http/tests/cache/subresource-multiple-instances.html http/tests/htmlimports/import-script-block-crossorigin-dynamic.html http/tests/loading/script-priorities.html. |