WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
214765
[WebGL2] expando-loss and expando-loss-2 conformance tests are failing
https://bugs.webkit.org/show_bug.cgi?id=214765
Summary
[WebGL2] expando-loss and expando-loss-2 conformance tests are failing
Kenneth Russell
Reported
2020-07-24 15:34:54 PDT
Per
Bug 189641
and
Bug 189672
the following two WebGL conformance tests are failing: webgl/2.0.0/conformance/misc/expando-loss.html webgl/2.0.0/conformance2/misc/expando-loss-2.html the reason is that the WebGL rendering context maintains RefPtrs to objects which are latched into the OpenGL context state, but those implicitly retain weak pointers to their JavaScript wrappers.
https://trac.webkit.org/browser/webkit/trunk/Source/JavaScriptCore/heap/Strong.h
appears to be designed to hold a strong reference to its target JavaScript object, and it is used in a select few places in WebCore - for example,
https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/bindings/js/WorkerScriptController.h
. In order to fix the expando-loss failures, it seems likely that WebGLRenderingContextBase and WebGL2RenderingContext will have to retain strong references to the objects which are latched in to the context state, and which can be queried back from the context - like WebGLTextures, via bindTexture and getParameter(TEXTURE_BINDING_2D). In this case it seems the TextureUnitState will need to maintain Strong<JSWebGLTexture> instead of RefPtr<WebGLTexture>. This will have to be carefully designed. Currently WebGLRenderingContextBase::m_contextObjects and WebGLContextGroup::m_groupObjects maintain weak downward references to all of the objects they allocated, and WebGLContextObject::m_context and WebGLSharedObject::m_contextGroup maintain weak upward references to the context which allocated them. Reference cycles must not be introduced. A similar restructuring was done in Chromium in
http://crbug.com/485634
. There was a significant bug tail associated with this change; a couple of the performance regressions were
http://crbug.com/569668
and
http://crbug.com/608576
. Care must be taken to not run into similar issues in WebCore.
Attachments
Patch
(19.36 KB, patch)
2020-08-10 16:11 PDT
,
Kenneth Russell
no flags
Details
Formatted Diff
Diff
Patch
(62.63 KB, patch)
2020-08-10 21:27 PDT
,
Kenneth Russell
no flags
Details
Formatted Diff
Diff
Patch
(62.58 KB, patch)
2020-08-11 09:43 PDT
,
Kenneth Russell
no flags
Details
Formatted Diff
Diff
Patch
(83.25 KB, patch)
2020-08-12 10:05 PDT
,
Kenneth Russell
no flags
Details
Formatted Diff
Diff
Patch
(84.07 KB, patch)
2020-08-12 16:48 PDT
,
Kenneth Russell
no flags
Details
Formatted Diff
Diff
Patch
(144.24 KB, patch)
2020-08-13 16:28 PDT
,
Kenneth Russell
no flags
Details
Formatted Diff
Diff
Show Obsolete
(5)
View All
Add attachment
proposed patch, testcase, etc.
Radar WebKit Bug Importer
Comment 1
2020-07-31 15:35:15 PDT
<
rdar://problem/66401953
>
Dean Jackson
Comment 2
2020-08-07 16:48:13 PDT
Adding Sam and Chris who might have advice here.
Dean Jackson
Comment 3
2020-08-07 17:46:00 PDT
I see expando-loss passing. expando-loss-2 is failing though. Direct link:
https://www.khronos.org/registry/webgl/conformance-suites/2.0.0/conformance2/misc/expando-loss-2.html
Sam Weinig
Comment 4
2020-08-07 18:02:39 PDT
Using Strong is usually not the right solution for GC problems. Rather, the bindings layer likely needs custom marking to inform the GC about the relationships. In most cases, this is done by using the JSCustomMarkFunction extended attribute in the IDL file, and then implementing a custom visitAdditionalChildren for the wrapper.
Sam Weinig
Comment 5
2020-08-07 18:09:35 PDT
(In reply to Sam Weinig from
comment #4
)
> Using Strong is usually not the right solution for GC problems. Rather, the > bindings layer likely needs custom marking to inform the GC about the > relationships. > > In most cases, this is done by using the JSCustomMarkFunction extended > attribute in the IDL file, and then implementing a custom > visitAdditionalChildren for the wrapper.
Alternatively, if the objects that are getting collected have references to their parents, you could fix this on their side, by marking them reachable from the WebGLRenderingContextBase. It work was done towards this for WebGL1 maybe, see uses of GenerateIsReachable=ImplWebGLRenderingContext.
Sam Weinig
Comment 6
2020-08-07 18:20:55 PDT
(In reply to Sam Weinig from
comment #5
)
> (In reply to Sam Weinig from
comment #4
) > > Using Strong is usually not the right solution for GC problems. Rather, the > > bindings layer likely needs custom marking to inform the GC about the > > relationships. > > > > In most cases, this is done by using the JSCustomMarkFunction extended > > attribute in the IDL file, and then implementing a custom > > visitAdditionalChildren for the wrapper. > > Alternatively, if the objects that are getting collected have references to > their parents, you could fix this on their side, by marking them reachable > from the WebGLRenderingContextBase. It work was done towards this for WebGL1 > maybe, see uses of GenerateIsReachable=ImplWebGLRenderingContext.
Hm, no, it looks like GenerateIsReachable won't work for at least WebGLTexture, as it inherits from WebGLSharedObject, and therefore can belong to multiple contexts it seems. So the contexts will each have to mark the textures they currently own.
Kenneth Russell
Comment 7
2020-08-10 12:42:46 PDT
Thanks very much for the tips Sam. I was going down the wrong track trying to use Strong for this purpose. It looks like extending JSWebGLRenderingContext's and JSWebGL2RenderingContext's existing visitAdditionalChildren callbacks will be both simpler and more correct.
Kenneth Russell
Comment 8
2020-08-10 16:11:48 PDT
Created
attachment 406340
[details]
Patch
Kenneth Russell
Comment 9
2020-08-10 16:13:49 PDT
This patch implements what I understood as being the needed tracing, but it doesn't work - the results produced by: ./Tools/Scripts/run-webkit-tests --debug webgl/2.0.0/conformance/misc/expando-loss.html ./Tools/Scripts/run-webkit-tests --debug webgl/2.0.0/conformance2/misc/expando-loss-2.html are identical to what they are currently - which are failing results. Would appreciate any advice. Thanks.
Kenneth Russell
Comment 10
2020-08-10 16:22:54 PDT
Note also - would appreciate help with the unresolved symbol JSC::SlotVisitor::addOpaqueRoot(void*) on the tv, tv-sim, watch-sim platforms. Maybe I hooked this up incorrectly, but ideally the tracing code will live inside the WebGL classes rather than the bindings.
Kenneth Russell
Comment 11
2020-08-10 16:28:24 PDT
Looks like this patch only works in Mac Debug builds - which is the flavor I was testing.
Kenneth Russell
Comment 12
2020-08-10 18:31:50 PDT
ysuzuki@ helped me figure out what was wrong with the earlier patch - have a version that's working now. Obsoleting the old one.
Kenneth Russell
Comment 13
2020-08-10 21:27:15 PDT
Created
attachment 406359
[details]
Patch
Darin Adler
Comment 14
2020-08-11 08:45:35 PDT
Comment on
attachment 406359
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=406359&action=review
> Source/WebCore/html/canvas/WebGLFramebuffer.h:38 > +} // namespace JSC
Normally we reserve this kind of comment for larger namespace blocks.
Kenneth Russell
Comment 15
2020-08-11 09:43:13 PDT
Thanks Darin for your review and Yusuke for your help on this patch. Removing the extraneous namespace comments and CQ'ing.
Kenneth Russell
Comment 16
2020-08-11 09:43:42 PDT
Created
attachment 406387
[details]
Patch
EWS
Comment 17
2020-08-11 10:30:00 PDT
Committed
r265502
: <
https://trac.webkit.org/changeset/265502
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 406387
[details]
.
Yusuke Suzuki
Comment 18
2020-08-11 14:23:36 PDT
Comment on
attachment 406387
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=406387&action=review
Commented about locking & FIXME :)
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:3041 > + WebGLRenderingContextBase::visitReferencedJSWrappers(visitor); > + > + visitor.addOpaqueRoot(m_readFramebufferBinding.get()); > + if (m_readFramebufferBinding) > + m_readFramebufferBinding->visitReferencedJSWrappers(visitor); > + > + visitor.addOpaqueRoot(m_boundTransformFeedback.get()); > + if (m_boundTransformFeedback) > + m_boundTransformFeedback->visitReferencedJSWrappers(visitor); > + > + visitor.addOpaqueRoot(m_boundCopyReadBuffer.get()); > + visitor.addOpaqueRoot(m_boundCopyWriteBuffer.get()); > + visitor.addOpaqueRoot(m_boundPixelPackBuffer.get()); > + visitor.addOpaqueRoot(m_boundPixelUnpackBuffer.get()); > + visitor.addOpaqueRoot(m_boundTransformFeedbackBuffer.get()); > + visitor.addOpaqueRoot(m_boundUniformBuffer.get()); > + > + for (auto& buffer : m_boundIndexedUniformBuffers) > + visitor.addOpaqueRoot(buffer.get()); > + > + for (auto& entry : m_activeQueries) > + visitor.addOpaqueRoot(entry.value.get()); > + > + for (auto& entry : m_boundSamplers) > + visitor.addOpaqueRoot(entry.get());
GC marking can run concurrently to the main thread. So we should have a lock when touching these fields. Can you add that?
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:3042 > +}
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLBuffer.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:145 > + visitor.addOpaqueRoot(m_renderbuffer.get());
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:267 > + visitor.addOpaqueRoot(m_texture.get());
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:708 > + for (auto& entry : m_attachments)
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLFramebuffer.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLProgram.cpp:204 > + visitor.addOpaqueRoot(m_fragmentShader.get());
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLProgram.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLQuery.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLRenderbuffer.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7798 > + visitor.addOpaqueRoot(m_boundArrayBuffer.get()); > + > + visitor.addOpaqueRoot(m_boundVertexArrayObject.get()); > + if (m_boundVertexArrayObject) > + m_boundVertexArrayObject->visitReferencedJSWrappers(visitor); > + > + visitor.addOpaqueRoot(m_currentProgram.get()); > + if (m_currentProgram) > + m_currentProgram->visitReferencedJSWrappers(visitor); > + > + visitor.addOpaqueRoot(m_framebufferBinding.get()); > + if (m_framebufferBinding) > + m_framebufferBinding->visitReferencedJSWrappers(visitor); > + > + visitor.addOpaqueRoot(m_renderbufferBinding.get()); > + > + for (auto& unit : m_textureUnits) { > + visitor.addOpaqueRoot(unit.texture2DBinding.get()); > + visitor.addOpaqueRoot(unit.textureCubeMapBinding.get()); > + visitor.addOpaqueRoot(unit.texture3DBinding.get()); > + visitor.addOpaqueRoot(unit.texture2DArrayBinding.get()); > + } > + > + // Extensions' IDL files use GenerateIsReachable=ImplWebGLRenderingContext, > + // which checks to see whether the context is in the opaque root set (it is; > + // it's added in JSWebGLRenderingContext / JSWebGL2RenderingContext's custom > + // bindings code). For this reason it's unnecessary to explicitly add opaque > + // roots for extensions.
We should have a lock for each access to these fields due to the reason described above.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7799 > +}
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLSampler.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLShader.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLTexture.idl:28 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:96 > + for (auto& buffer : m_boundIndexedTransformFeedbackBuffers) > + visitor.addOpaqueRoot(buffer.get()); > + > + visitor.addOpaqueRoot(m_program.get());
We should have a lock for each access of these fields due to the above reason.
> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:98 > +
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLTransformFeedback.idl:29 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLVertexArrayObject.idl:29 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:114 > + visitor.addOpaqueRoot(m_boundElementArrayBuffer.get()); > + for (auto& state : m_vertexAttribState) > + visitor.addOpaqueRoot(state.bufferBinding.get());
Ditto. Need locking.
> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:115 > +}
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
> Source/WebCore/html/canvas/WebGLVertexArrayObjectOES.idl:29 > + GenerateIsReachable=Impl
Can you also add FIXME to change this model to querying connected WebGLContext instead? i.e. we should not register a lot of opaque roots here, and instead, each object should have a reference to WebGLContext and say "This is live if WebGLContext is live". This model is not good in terms of performance, and we should fix it.
Darin Adler
Comment 19
2020-08-11 14:25:33 PDT
Oops, guess I should not have done review+. Concerned about the threading issue!
Kenneth Russell
Comment 20
2020-08-11 14:29:51 PDT
ysuzuki@ thanks for your review. I'll file a follow-on bug about addressing your feedback, specifically the locking issue. However - I disagree with the idea of adding a FIXME to change "GenerateIsReachable=Impl" to querying the WebGL context. It would be *very* expensive to answer the question for any WebGLTexture, WebGLBuffer, etc. "am I latched into the WebGL context state"? That would basically mean searching through all of the latched objects that this patch currently enumerates, looking to see if it's referenced - and that would be done for *every* reachable WebGL object during GC.
Kenneth Russell
Comment 21
2020-08-11 14:47:06 PDT
Filed
Bug 215394
about addressing ysuzuki@'s review feedback.
WebKit Commit Bot
Comment 22
2020-08-11 15:00:25 PDT
Re-opened since this is blocked by
bug 215396
Kenneth Russell
Comment 23
2020-08-11 15:01:55 PDT
After discussion with ysuzuki@ on Slack, reverting the above patch in
Bug 215396
because designing the locking mechanism is going to take some time.
Kenneth Russell
Comment 24
2020-08-11 15:17:42 PDT
Revert landed in
r265523
. Will re-attempt.
Kenneth Russell
Comment 25
2020-08-12 10:05:38 PDT
Created
attachment 406462
[details]
Patch
Kenneth Russell
Comment 26
2020-08-12 10:08:46 PDT
ysuzuki@ could you please review this new patch? The new locking covers all of the data structures like HashMaps and Vectors which are traversed by visitAdditionalChildren and their callees, as well as mutations of RefPtrs whose contents are tested via if-tests before descending into them. Thanks for explaining the concurrent marking to me!
Yusuke Suzuki
Comment 27
2020-08-12 14:58:51 PDT
Comment on
attachment 406462
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=406462&action=review
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:698 > + LockHolder locker(m_objectGraphLock);
Use auto locker = holdLock(m_objectGraphLock) instead.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1847 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1878 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1903 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1976 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:2002 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:2191 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:2261 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:3032 > +void WebGL2RenderingContext::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
I think we should rename this to, something like `addMembersToOpaqueRoots` because this function is not actually visiting as GC does.
> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:3033 > +{
This function is not grabbing a lock.
> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:144 > + void WebGLRenderbufferAttachment::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
Ditto.
> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:266 > + void WebGLTextureAttachment::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
Ditto.
> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:713 > +void WebGLFramebuffer::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
Ditto.
> Source/WebCore/html/canvas/WebGLProgram.cpp:202 > +void WebGLProgram::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1324 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1429 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1442 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1457 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1473 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2017 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2026 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2042 > + LockHolder locker(objectGraphLock());
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2143 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:5922 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:5989 > + LockHolder locker(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7795 > +void WebGLRenderingContextBase::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7797 > + LockHolder lock(m_objectGraphLock);
Ditto.
> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7832 > +Lock* WebGLRenderingContextBase::objectGraphLock() > +{ > + return &m_objectGraphLock; > +}
Let's just return Lock&.
> Source/WebCore/html/canvas/WebGLSharedObject.cpp:65 > + return m_contextGroup ? m_contextGroup->objectGraphLockForAContext() : nullptr;
When it is returning nullptr, shouldn't we need to take a lock?
> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:93 > +void WebGLTransformFeedback::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
Ditto.
> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:112 > +void WebGLVertexArrayObjectBase::visitReferencedJSWrappers(JSC::SlotVisitor& visitor)
Ditto.
Kenneth Russell
Comment 28
2020-08-12 16:43:28 PDT
Comment on
attachment 406462
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=406462&action=review
New patch incoming which addresses this review feedback and also fixes the timing-out layout tests.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:698 >> + LockHolder locker(m_objectGraphLock); > > Use > > auto locker = holdLock(m_objectGraphLock) instead.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1847 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1878 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1903 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:1976 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:2002 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:2191 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:2261 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Done.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:3032 >> +void WebGL2RenderingContext::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > I think we should rename this to, something like `addMembersToOpaqueRoots` because this function is not actually visiting as GC does.
Renamed this and the related methods.
>> Source/WebCore/html/canvas/WebGL2RenderingContext.cpp:3033 >> +{ > > This function is not grabbing a lock.
Thanks for catching that, I'll fix. WebGLRenderingContextBase::visitReferencedJSWrappers does. It wasn't clear to me whether Lock supports recursive locking or not.
>> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:144 >> + void WebGLRenderbufferAttachment::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > Ditto.
Renamed.
>> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:266 >> + void WebGLTextureAttachment::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > Ditto.
Renamed.
>> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:713 >> +void WebGLFramebuffer::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > Ditto.
Renamed.
>> Source/WebCore/html/canvas/WebGLProgram.cpp:202 >> +void WebGLProgram::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > Ditto.
Renamed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1324 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1429 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1442 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1457 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:1473 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2017 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2026 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2042 >> + LockHolder locker(objectGraphLock()); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:2143 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:5922 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:5989 >> + LockHolder locker(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7795 >> +void WebGLRenderingContextBase::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > Ditto.
Renamed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7797 >> + LockHolder lock(m_objectGraphLock); > > Ditto.
Changed.
>> Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp:7832 >> +} > > Let's just return Lock&.
I thought this was going to be a problem, but after making everything compile using holdLock and Lock& elsewhere, there were only a few places that needed to check whether the context had been destroyed and return early rather than trying to grab the lock. Changed to Lock&.
>> Source/WebCore/html/canvas/WebGLSharedObject.cpp:65 >> + return m_contextGroup ? m_contextGroup->objectGraphLockForAContext() : nullptr; > > When it is returning nullptr, shouldn't we need to take a lock?
The few callers of this can check explicitly whether the context has been destroyed, so changed this to Lock&.
>> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:93 >> +void WebGLTransformFeedback::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > Ditto.
Renamed.
>> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:112 >> +void WebGLVertexArrayObjectBase::visitReferencedJSWrappers(JSC::SlotVisitor& visitor) > > Ditto.
Renamed.
Kenneth Russell
Comment 29
2020-08-12 16:48:09 PDT
Created
attachment 406483
[details]
Patch
Kenneth Russell
Comment 30
2020-08-12 16:49:04 PDT
New patch addresses all review feedback and fixes the layout test timeouts from the previous patch, which were caused by an illegal attempt to recursively lock the object graph lock during framebuffer deletion.
Yusuke Suzuki
Comment 31
2020-08-12 17:03:05 PDT
Comment on
attachment 406483
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=406483&action=review
> Source/WebCore/html/canvas/WebGLContextGroup.cpp:50 > return *(*m_contexts.begin())->graphicsContextGL();
Let's use `first()` here :)
> Source/WebCore/html/canvas/WebGLContextGroup.cpp:61 > + return (*m_contexts.begin())->objectGraphLock();
Use `m_contexts.first().objectGraphLock();`
> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:563 > void WebGLFramebuffer::deleteObjectImpl(GraphicsContextGLOpenGL* context3d, PlatformGLObject object)
Let's take `const AbstractLocker&` parameter instead.
> Source/WebCore/html/canvas/WebGLProgram.cpp:161 > bool WebGLProgram::attachShader(WebGLShader* shader)
Let's take `const AbstractLocker&` parameter to make it explicit that this function needs locker.
> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:61 > {
Let's take `const AbstractLocker&` parameter.
> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:69 > + // Covered under the objectGraphLock in WebGL2RenderingContext::setIndexedBufferBinding.
Let's take `const AbstractLocker&` parameter.
> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:94 > +{
Let's take `const AbstractLocker&` parameter.
> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:54 > void WebGLVertexArrayObjectBase::setVertexAttribState(GCGLuint index, GCGLsizei bytesPerElement, GCGLint size, GCGLenum type, GCGLboolean normalized, GCGLsizei stride, GCGLintptr offset, WebGLBuffer* buffer)
Let's take `const AbstractLocker&` from WebGLRenderingContextBase::vertexAttribPointer (passing `locker`). Like, ...->setVertexAttribState(locker, ...); And ...::setVertexAttribState(const AbstractLocker&, ...) { .... }
> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:76 > void WebGLVertexArrayObjectBase::unbindBuffer(WebGLBuffer& buffer)
Let's take `const AbstractLocker&` from WebGLRenderingContextBase::uncacheDeletedBuffer (passing `locker`).
> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:112 > +void WebGLVertexArrayObjectBase::addMembersToOpaqueRoots(JSC::SlotVisitor& visitor)
Let's take `const AbstractLocker&` parameter.
Kenneth Russell
Comment 32
2020-08-13 16:27:56 PDT
Comment on
attachment 406483
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=406483&action=review
>> Source/WebCore/html/canvas/WebGLContextGroup.cpp:50 >> return *(*m_contexts.begin())->graphicsContextGL(); > > Let's use `first()` here :)
Neither HashSet nor HashMap in WTF has a first() method.
>> Source/WebCore/html/canvas/WebGLContextGroup.cpp:61 >> + return (*m_contexts.begin())->objectGraphLock(); > > Use `m_contexts.first().objectGraphLock();`
Same answer - neither HashSet nor HashMap in WTF has a first() method.
>> Source/WebCore/html/canvas/WebGLFramebuffer.cpp:563 >> void WebGLFramebuffer::deleteObjectImpl(GraphicsContextGLOpenGL* context3d, PlatformGLObject object) > > Let's take `const AbstractLocker&` parameter instead.
Done.
>> Source/WebCore/html/canvas/WebGLProgram.cpp:161 >> bool WebGLProgram::attachShader(WebGLShader* shader) > > Let's take `const AbstractLocker&` parameter to make it explicit that this function needs locker.
Done.
>> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:61 >> { > > Let's take `const AbstractLocker&` parameter.
Done.
>> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:69 >> + // Covered under the objectGraphLock in WebGL2RenderingContext::setIndexedBufferBinding. > > Let's take `const AbstractLocker&` parameter.
Done.
>> Source/WebCore/html/canvas/WebGLTransformFeedback.cpp:94 >> +{ > > Let's take `const AbstractLocker&` parameter.
Done.
>> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:54 >> void WebGLVertexArrayObjectBase::setVertexAttribState(GCGLuint index, GCGLsizei bytesPerElement, GCGLint size, GCGLenum type, GCGLboolean normalized, GCGLsizei stride, GCGLintptr offset, WebGLBuffer* buffer) > > Let's take `const AbstractLocker&` from WebGLRenderingContextBase::vertexAttribPointer (passing `locker`). > Like, > > ...->setVertexAttribState(locker, ...); > > And > > ...::setVertexAttribState(const AbstractLocker&, ...) > { > .... > }
Done.
>> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:76 >> void WebGLVertexArrayObjectBase::unbindBuffer(WebGLBuffer& buffer) > > Let's take `const AbstractLocker&` from WebGLRenderingContextBase::uncacheDeletedBuffer (passing `locker`).
Done.
>> Source/WebCore/html/canvas/WebGLVertexArrayObjectBase.cpp:112 >> +void WebGLVertexArrayObjectBase::addMembersToOpaqueRoots(JSC::SlotVisitor& visitor) > > Let's take `const AbstractLocker&` parameter.
Done.
Kenneth Russell
Comment 33
2020-08-13 16:28:08 PDT
Created
attachment 406554
[details]
Patch
Kenneth Russell
Comment 34
2020-08-13 16:33:24 PDT
The current patch passes "const AbstractLocker&" throughout WebGL's call hierarchy to prove that the lock's held where needed. This was a substantial change involving many more methods than just those highlighted via comments in the previous code review. This passes all tests locally. During development, bugs caused hangs or assertion failures in the WebGL tests, so it seems that correctness is ensured by those tests. Please re-review. Thanks.
Kenneth Russell
Comment 35
2020-08-13 18:43:45 PDT
Comment on
attachment 406554
[details]
Patch If this looks OK then please go ahead and CQ it - thanks.
Yusuke Suzuki
Comment 36
2020-08-14 14:57:09 PDT
Comment on
attachment 406554
[details]
Patch r=me
EWS
Comment 37
2020-08-14 15:06:46 PDT
Committed
r265708
: <
https://trac.webkit.org/changeset/265708
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 406554
[details]
.
Note
You need to
log in
before you can comment on or make changes to this bug.
Top of Page
Format For Printing
XML
Clone This Bug