WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
235529
ASSERTION FAILED: m_processCallback in WebCore::AudioWorkletProcessor::process
https://bugs.webkit.org/show_bug.cgi?id=235529
Summary
ASSERTION FAILED: m_processCallback in WebCore::AudioWorkletProcessor::process
Sam Sneddon [:gsnedders]
Reported
2022-01-24 11:13:30 PST
Loading the mdn-bcd-collector sometimes (but not always) asserts here in debug. This implies that feature detection can sometimes assert, which doesn’t seem great. <
rdar://87980379
>
Attachments
Patch
(22.69 KB, patch)
2022-01-26 11:30 PST
,
Chris Dumez
ews-feeder
: commit-queue-
Details
Formatted Diff
Diff
Patch
(24.82 KB, patch)
2022-01-26 12:07 PST
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(24.82 KB, patch)
2022-01-26 13:19 PST
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(25.71 KB, patch)
2022-01-27 08:25 PST
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(25.63 KB, patch)
2022-01-27 10:35 PST
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(25.60 KB, patch)
2022-01-27 11:37 PST
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Patch
(25.41 KB, patch)
2022-01-28 10:46 PST
,
Chris Dumez
no flags
Details
Formatted Diff
Diff
Show Obsolete
(6)
View All
Add attachment
proposed patch, testcase, etc.
Chris Dumez
Comment 1
2022-01-25 14:37:05 PST
Are you sure the link is correct? Not only I am unable to reproduce but also, logging shows AudioWorkletProcessor::process() is not even called.
Chris Dumez
Comment 2
2022-01-25 14:40:39 PST
Ok, now I can reproduce. You provided an http:// link but this can only reproduce with an https:// link it seems.
Chris Dumez
Comment 3
2022-01-26 11:30:36 PST
Created
attachment 450045
[details]
Patch
Chris Dumez
Comment 4
2022-01-26 12:07:39 PST
Created
attachment 450053
[details]
Patch
Eric Carlson
Comment 5
2022-01-26 13:08:09 PST
Comment on
attachment 450053
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450053&action=review
> Source/WebCore/ChangeLog:14 > + To address the issue, I added a visitor to for the AudioWorkletGlobalScope wrapper
s/to for the/to the/
Chris Dumez
Comment 6
2022-01-26 13:19:00 PST
Created
attachment 450060
[details]
Patch
Geoffrey Garen
Comment 7
2022-01-26 21:05:45 PST
Comment on
attachment 450060
[details]
Patch r=me
Geoffrey Garen
Comment 8
2022-01-26 21:12:37 PST
Maybe AudioWorkletProcessor should inherit from ScriptWrappable. That's a slightly more idiomatic way to point to your own wrapper. (The semantics are ultimately the same.)
Chris Dumez
Comment 9
2022-01-27 07:41:34 PST
(In reply to Geoffrey Garen from
comment #8
)
> Maybe AudioWorkletProcessor should inherit from ScriptWrappable. That's a > slightly more idiomatic way to point to your own wrapper. (The semantics are > ultimately the same.)
If I use ScriptWrappable, how does the AudioWorkletGlobalScope "visit" the AudioWorkletProcessor then? I don't see a visit function on ScriptWrappable. I *think* I should be able to call SlotVisitor::append() with the Weak<> data member as parameter. However, ScriptWrappable doesn't have a getter for that Weak<> (only one that returns the raw pointer).
Chris Dumez
Comment 10
2022-01-27 08:25:23 PST
Created
attachment 450139
[details]
Patch
Chris Dumez
Comment 11
2022-01-27 08:28:17 PST
Comment on
attachment 450139
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450139&action=review
Ok, I think I got it but Geoff, could you please double check?
> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 > + visitor.addOpaqueRoot(&processor);
I now call addOpaqueRoot() here.
> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.cpp:255 > + auto result = JSCallbackData::invokeCallback(vm, wrapper(), jsUndefined(), args, JSCallbackData::CallbackType::Object, Identifier::fromString(vm, "process"), returnedException);
I now use ScriptWrappable::wrapper() here instead of m_processCallback.
> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:56 > +class AudioWorkletProcessor : public ScriptWrappable, public ThreadSafeRefCounted<AudioWorkletProcessor>, public CanMakeWeakPtr<AudioWorkletProcessor> {
AudioWorkletProcessor how subclasses ScriptWrappable.
> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:-76 > - JSValueInWrappedObject m_processCallback;
I dropped the m_processCallback data member that is no longer needed now that I can get the JS wrapper from ScriptWrappable::wrapper().
> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.idl:32 > + GenerateIsReachable=Impl,
I added GenerateIsReachable=Impl on AudioWorkletProcessor since AudioWorkletGlobalScope adds the processors as opaque roots when visiting.
Darin Adler
Comment 12
2022-01-27 10:03:10 PST
Comment on
attachment 450139
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450139&action=review
I’ll let Geoff do the actual r+
>> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 >> + visitor.addOpaqueRoot(&processor); > > I now call addOpaqueRoot() here.
I guess this is specifically a SlotVisitor, not a generic Visitor, which would be more of a arbitrary function, not an object to call addOpaqueRoot on. In the past, there have been some lock-free wants to do marking/visiting, and that was sort of an overall goal for our GC system. Not saying I know how to achieve that here, or that it’s really important.
> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.h:61 > + template<typename Visitor> void visitProcessors(Visitor&);
I think it’s worth using the name SlotVisitor here to be a little more explicit.
> Source/WebCore/bindings/js/JSAudioWorkletGlobalScopeCustom.cpp:35 > +using namespace JSC;
I think it’s nicer to just do JSC:: as needed rather than this, especially on a new source file.
Chris Dumez
Comment 13
2022-01-27 10:10:50 PST
(In reply to Darin Adler from
comment #12
)
> Comment on
attachment 450139
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=450139&action=review
> > I’ll let Geoff do the actual r+ > > >> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 > >> + visitor.addOpaqueRoot(&processor); > > > > I now call addOpaqueRoot() here. > > I guess this is specifically a SlotVisitor, not a generic Visitor, which > would be more of a arbitrary function, not an object to call addOpaqueRoot > on.
I am not sure I understand this comment. #define DEFINE_VISIT_ADDITIONAL_CHILDREN(className) \ template void className::visitAdditionalChildren(JSC::AbstractSlotVisitor&); \ template void className::visitAdditionalChildren(JSC::SlotVisitor&) So I need to be able to deal with AbstractSlotVisitor too, no?
> > In the past, there have been some lock-free wants to do marking/visiting, > and that was sort of an overall goal for our GC system. Not saying I know > how to achieve that here, or that it’s really important. > > > Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.h:61 > > + template<typename Visitor> void visitProcessors(Visitor&); > > I think it’s worth using the name SlotVisitor here to be a little more > explicit. > > > Source/WebCore/bindings/js/JSAudioWorkletGlobalScopeCustom.cpp:35 > > +using namespace JSC; > > I think it’s nicer to just do JSC:: as needed rather than this, especially > on a new source file.
Ok.
Darin Adler
Comment 14
2022-01-27 10:18:52 PST
Comment on
attachment 450139
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450139&action=review
>>>> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 >>>> + visitor.addOpaqueRoot(&processor); >>> >>> I now call addOpaqueRoot() here. >> >> I guess this is specifically a SlotVisitor, not a generic Visitor, which would be more of a arbitrary function, not an object to call addOpaqueRoot on. >> >> In the past, there have been some lock-free wants to do marking/visiting, and that was sort of an overall goal for our GC system. Not saying I know how to achieve that here, or that it’s really important. > > I am not sure I understand this comment. > #define DEFINE_VISIT_ADDITIONAL_CHILDREN(className) \ > template void className::visitAdditionalChildren(JSC::AbstractSlotVisitor&); \ > template void className::visitAdditionalChildren(JSC::SlotVisitor&) > > So I need to be able to deal with AbstractSlotVisitor too, no?
Yes, AbstractSlotVisitor, but I was simply pointing out that the Visitor pattern generally means a function object, not an object of class AbstractSlotVisitor.
Chris Dumez
Comment 15
2022-01-27 10:29:31 PST
Comment on
attachment 450139
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450139&action=review
>>>>> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 >>>>> + visitor.addOpaqueRoot(&processor); >>>> >>>> I now call addOpaqueRoot() here. >>> >>> I guess this is specifically a SlotVisitor, not a generic Visitor, which would be more of a arbitrary function, not an object to call addOpaqueRoot on. >>> >>> In the past, there have been some lock-free wants to do marking/visiting, and that was sort of an overall goal for our GC system. Not saying I know how to achieve that here, or that it’s really important. >> >> I am not sure I understand this comment. >> #define DEFINE_VISIT_ADDITIONAL_CHILDREN(className) \ >> template void className::visitAdditionalChildren(JSC::AbstractSlotVisitor&); \ >> template void className::visitAdditionalChildren(JSC::SlotVisitor&) >> >> So I need to be able to deal with AbstractSlotVisitor too, no? > > Yes, AbstractSlotVisitor, but I was simply pointing out that the Visitor pattern generally means a function object, not an object of class AbstractSlotVisitor.
Sorry, I am still not following. Should I update AudioWorkletGlobalScope::visitProcessors() to take in a JSC::AbstractSlotVisitor& and drop the templating? It seems SlotVisitor inherits from AbstractSlotVisitor and addOpaqueRoot() is defined on AbstractSlotVisitor anyway.
Darin Adler
Comment 16
2022-01-27 10:33:32 PST
(In reply to Chris Dumez from
comment #15
)
> Sorry, I am still not following.
My comment was intended to only be about naming.
> Should I update AudioWorkletGlobalScope::visitProcessors() to take in a > JSC::AbstractSlotVisitor& and drop the templating? It seems SlotVisitor > inherits from AbstractSlotVisitor and addOpaqueRoot() is defined on > AbstractSlotVisitor anyway.
Yes, you probably should! I was not suggesting it, but I think you have hit on something. Unless there is a significant performance benefit to using the template function.
Chris Dumez
Comment 17
2022-01-27 10:35:21 PST
Created
attachment 450154
[details]
Patch
Chris Dumez
Comment 18
2022-01-27 10:35:56 PST
Ok. I fixed the naming though some existing code likely needs updating too. E.g.: ``` void Range::visitNodesConcurrently(JSC::AbstractSlotVisitor& visitor) const { visitor.addOpaqueRoot(root(&m_start.container())); visitor.addOpaqueRoot(root(&m_end.container())); } ```
Darin Adler
Comment 19
2022-01-27 10:36:47 PST
I was referring to the name of the template argument.
Darin Adler
Comment 20
2022-01-27 10:36:57 PST
Not the name of the function.
Chris Dumez
Comment 21
2022-01-27 10:39:58 PST
(In reply to Darin Adler from
comment #20
)
> Not the name of the function.
Ahhh you wanted me to rename the template parameter from "Visitor" to "SlotVisitor", I get it now. I got confused because I didn't realize you were talking about the template parameter and JSC::SlotVisitor is an actual type. Well, in my latest iteration the template parameter is gone anyway. I did rename the function as well from visitProcessors() to addProcessorsToOpaqueRoots(). I am not sure which one is better. I found both patterns in our code base.
Chris Dumez
Comment 22
2022-01-27 11:37:36 PST
Created
attachment 450161
[details]
Patch
Darin Adler
Comment 23
2022-01-28 10:21:28 PST
Comment on
attachment 450161
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450161&action=review
> Source/WTF/wtf/WeakHashSet.h:101 > + return m_set.add(*static_cast<const T&>(value).weakPtrFactory().template createWeakPtr<T>(const_cast<U&>(value), enableWeakPtrThreadingAssertions).m_impl);
This seems like such a long argument name. Is there any shorter name that would be sufficiently unambiguous? I might just call the local "assertions" and not worry that was too confusing. After all we still have the strong typing of EnableWeakPtrThreadingAssertions that will follow us around.
> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 > + Locker locker { m_processorsLock }; > + m_processors.forEach([&](auto& processor) { > + visitor.addOpaqueRoot(&processor); > + });
If I understand correctly, it’s generally bad for performance to have to take locks during GC marking. Would be nice to have some lock-free safe way to do this.
> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.h:61 > + void processorIsNoLongerNeeded(AudioWorkletProcessor&); > + > + void visitProcessors(JSC::AbstractSlotVisitor&);
Not sure these need to be in separate paragraphs.
> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:37 > +#include <wtf/Lock.h>
Any way to avoid needing this new include in the header? I don’t see any new use of Lock below.
Darin Adler
Comment 24
2022-01-28 10:21:46 PST
Comment on
attachment 450161
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450161&action=review
>> Source/WTF/wtf/WeakHashSet.h:101 >> + return m_set.add(*static_cast<const T&>(value).weakPtrFactory().template createWeakPtr<T>(const_cast<U&>(value), enableWeakPtrThreadingAssertions).m_impl); > > This seems like such a long argument name. Is there any shorter name that would be sufficiently unambiguous? I might just call the local "assertions" and not worry that was too confusing. After all we still have the strong typing of EnableWeakPtrThreadingAssertions that will follow us around.
Or "assertionsPolicy" or "policy".
Chris Dumez
Comment 25
2022-01-28 10:38:22 PST
Comment on
attachment 450161
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450161&action=review
>>> Source/WTF/wtf/WeakHashSet.h:101 >>> + return m_set.add(*static_cast<const T&>(value).weakPtrFactory().template createWeakPtr<T>(const_cast<U&>(value), enableWeakPtrThreadingAssertions).m_impl); >> >> This seems like such a long argument name. Is there any shorter name that would be sufficiently unambiguous? I might just call the local "assertions" and not worry that was too confusing. After all we still have the strong typing of EnableWeakPtrThreadingAssertions that will follow us around. > > Or "assertionsPolicy" or "policy".
Ok, will go with assertionsPolicy.
>> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 >> + }); > > If I understand correctly, it’s generally bad for performance to have to take locks during GC marking. Would be nice to have some lock-free safe way to do this.
Not sure how to avoid the locking at this point since this iterates a WeakHashSet on a GC thread and the WeakHashSet gets modified on the audio worklet thread. I asked on the JSC channel to see if there are suggestions.
>> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.h:61 >> + void visitProcessors(JSC::AbstractSlotVisitor&); > > Not sure these need to be in separate paragraphs.
OK
>> Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:37 >> +#include <wtf/Lock.h> > > Any way to avoid needing this new include in the header? I don’t see any new use of Lock below.
Indeed, this is a reminiscence of an earlier patch iteration. Will drop.
Darin Adler
Comment 26
2022-01-28 10:40:08 PST
Comment on
attachment 450161
[details]
Patch View in context:
https://bugs.webkit.org/attachment.cgi?id=450161&action=review
>>> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 >>> + }); >> >> If I understand correctly, it’s generally bad for performance to have to take locks during GC marking. Would be nice to have some lock-free safe way to do this. > > Not sure how to avoid the locking at this point since this iterates a WeakHashSet on a GC thread and the WeakHashSet gets modified on the audio worklet thread. I asked on the JSC channel to see if there are suggestions.
I hope to learn about this, too; what are the best techniques for a case like this. Seems likely we will land it like this, but want to do the best long term.
Filip Pizlo
Comment 27
2022-01-28 10:42:10 PST
(In reply to Darin Adler from
comment #23
)
> Comment on
attachment 450161
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=450161&action=review
> > > Source/WTF/wtf/WeakHashSet.h:101 > > + return m_set.add(*static_cast<const T&>(value).weakPtrFactory().template createWeakPtr<T>(const_cast<U&>(value), enableWeakPtrThreadingAssertions).m_impl); > > This seems like such a long argument name. Is there any shorter name that > would be sufficiently unambiguous? I might just call the local "assertions" > and not worry that was too confusing. After all we still have the strong > typing of EnableWeakPtrThreadingAssertions that will follow us around. > > > Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 > > + Locker locker { m_processorsLock }; > > + m_processors.forEach([&](auto& processor) { > > + visitor.addOpaqueRoot(&processor); > > + }); > > If I understand correctly, it’s generally bad for performance to have to > take locks during GC marking. Would be nice to have some lock-free safe way > to do this.
It's only bad for perf if we do it a lot. How many of these objects will be live at any time? During a full GC that walks the whole heap, how many AudioWorkletGlobalScopes are we going to see? If it's between 0 and 100 then grabbing a lock is fine. If it's more than 100 then maybe grabbing a lock is bad.
> > > Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.h:61 > > + void processorIsNoLongerNeeded(AudioWorkletProcessor&); > > + > > + void visitProcessors(JSC::AbstractSlotVisitor&); > > Not sure these need to be in separate paragraphs. > > > Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:37 > > +#include <wtf/Lock.h> > > Any way to avoid needing this new include in the header? I don’t see any new > use of Lock below.
Filip Pizlo
Comment 28
2022-01-28 10:43:56 PST
(In reply to Darin Adler from
comment #26
)
> Comment on
attachment 450161
[details]
> Patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=450161&action=review
> > >>> Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 > >>> + }); > >> > >> If I understand correctly, it’s generally bad for performance to have to take locks during GC marking. Would be nice to have some lock-free safe way to do this. > > > > Not sure how to avoid the locking at this point since this iterates a WeakHashSet on a GC thread and the WeakHashSet gets modified on the audio worklet thread. I asked on the JSC channel to see if there are suggestions. > > I hope to learn about this, too; what are the best techniques for a case > like this. Seems likely we will land it like this, but want to do the best > long term.
JSC's own object model falls back on locks for interactions with GC when the alternatives are too crazy. JSC uses lock-free tricks for scanning the most frequently allocated objects - like plain JS objects and plain JS arrays. But even for those, when they get into some highly dynamic state (like they are dictionary objects), we use locks. In fact, each JSObject has a two-bit lock in its header for those cases. So, I would go ahead and use locks in cases like this, unless you think that there will really be a lot of instances of the object, and you have a good idea for how to avoid locking.
Chris Dumez
Comment 29
2022-01-28 10:44:39 PST
(In reply to Filip Pizlo from
comment #27
)
> (In reply to Darin Adler from
comment #23
) > > Comment on
attachment 450161
[details]
> > Patch > > > > View in context: > >
https://bugs.webkit.org/attachment.cgi?id=450161&action=review
> > > > > Source/WTF/wtf/WeakHashSet.h:101 > > > + return m_set.add(*static_cast<const T&>(value).weakPtrFactory().template createWeakPtr<T>(const_cast<U&>(value), enableWeakPtrThreadingAssertions).m_impl); > > > > This seems like such a long argument name. Is there any shorter name that > > would be sufficiently unambiguous? I might just call the local "assertions" > > and not worry that was too confusing. After all we still have the strong > > typing of EnableWeakPtrThreadingAssertions that will follow us around. > > > > > Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.cpp:216 > > > + Locker locker { m_processorsLock }; > > > + m_processors.forEach([&](auto& processor) { > > > + visitor.addOpaqueRoot(&processor); > > > + }); > > > > If I understand correctly, it’s generally bad for performance to have to > > take locks during GC marking. Would be nice to have some lock-free safe way > > to do this. > > It's only bad for perf if we do it a lot. > > How many of these objects will be live at any time? During a full GC that > walks the whole heap, how many AudioWorkletGlobalScopes are we going to see? > > If it's between 0 and 100 then grabbing a lock is fine. > > If it's more than 100 then maybe grabbing a lock is bad.
AudioWorkletGlobalScope's wrapper is the global object so there is a single AudioWorkletGlobalScope for this VM which lives on the AudioWorklet thread. Also, I don't expect contention here as registering / unregistering AudioWorkletProcessors is a rare operation.
> > > > > > Source/WebCore/Modules/webaudio/AudioWorkletGlobalScope.h:61 > > > + void processorIsNoLongerNeeded(AudioWorkletProcessor&); > > > + > > > + void visitProcessors(JSC::AbstractSlotVisitor&); > > > > Not sure these need to be in separate paragraphs. > > > > > Source/WebCore/Modules/webaudio/AudioWorkletProcessor.h:37 > > > +#include <wtf/Lock.h> > > > > Any way to avoid needing this new include in the header? I don’t see any new > > use of Lock below.
Chris Dumez
Comment 30
2022-01-28 10:46:33 PST
Created
attachment 450257
[details]
Patch
EWS
Comment 31
2022-01-28 12:57:38 PST
Committed
r288759
(
246547@main
): <
https://commits.webkit.org/246547@main
> All reviewed patches have been landed. Closing bug and clearing flags on
attachment 450257
[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