Bug 122667 - llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock
Summary: llint_slow_path_put_by_id can deadlock on a ConcurrentJITLock
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Mark Hahnenberg
URL:
Keywords:
Depends on: 122779
Blocks:
  Show dependency treegraph
 
Reported: 2013-10-11 11:45 PDT by Mark Hahnenberg
Modified: 2013-10-16 16:46 PDT (History)
8 users (show)

See Also:


Attachments
Patch (25.97 KB, patch)
2013-10-11 15:35 PDT, Mark Hahnenberg
no flags Details | Formatted Diff | Diff
build fix (26.02 KB, patch)
2013-10-11 15:44 PDT, Mark Hahnenberg
no flags Details | Formatted Diff | Diff
omgjustbuild (26.33 KB, patch)
2013-10-11 16:36 PDT, Mark Hahnenberg
no flags Details | Formatted Diff | Diff
Patch (33.34 KB, patch)
2013-10-16 15:55 PDT, Mark Hahnenberg
ggaren: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Hahnenberg 2013-10-11 11:45:45 PDT
llint_slow_path_put_by_id has the following line of code:

   599 	                ConcurrentJITLocker locker(codeBlock->m_lock);

and later in the same scope:

   618 	                        StructureChain* chain = structure->prototypeChain(exec);

which can cause a garbage collection. Garbage collection acquires the ConcurrentJITLock as it processes CodeBlocks, causing a deadlock.
Comment 1 Filip Pizlo 2013-10-11 11:49:53 PDT
(In reply to comment #0)
> llint_slow_path_put_by_id has the following line of code:
> 
>    599                     ConcurrentJITLocker locker(codeBlock->m_lock);
> 
> and later in the same scope:
> 
>    618                             StructureChain* chain = structure->prototypeChain(exec);
> 
> which can cause a garbage collection. Garbage collection acquires the ConcurrentJITLock as it processes CodeBlocks, causing a deadlock.

L
Comment 2 Filip Pizlo 2013-10-11 11:50:15 PDT
(In reply to comment #1)
> (In reply to comment #0)
> > llint_slow_path_put_by_id has the following line of code:
> > 
> >    599                     ConcurrentJITLocker locker(codeBlock->m_lock);
> > 
> > and later in the same scope:
> > 
> >    618                             StructureChain* chain = structure->prototypeChain(exec);
> > 
> > which can cause a garbage collection. Garbage collection acquires the ConcurrentJITLock as it processes CodeBlocks, causing a deadlock.
> 
> L

Dunno what happened there.  I meant to say "Lol."
Comment 3 Filip Pizlo 2013-10-11 11:51:49 PDT
(In reply to comment #2)
> (In reply to comment #1)
> > (In reply to comment #0)
> > > llint_slow_path_put_by_id has the following line of code:
> > > 
> > >    599                     ConcurrentJITLocker locker(codeBlock->m_lock);
> > > 
> > > and later in the same scope:
> > > 
> > >    618                             StructureChain* chain = structure->prototypeChain(exec);
> > > 
> > > which can cause a garbage collection. Garbage collection acquires the ConcurrentJITLock as it processes CodeBlocks, causing a deadlock.
> > 
> > L
> 
> Dunno what happened there.  I meant to say "Lol."

We could either move the call to prototypeChain(exec) up above the ConcurrentJITLocker, or we could do my favorite thing: DeferGC.

I like DeferGC more since it's more comprehensive.
Comment 4 Mark Hahnenberg 2013-10-11 11:52:20 PDT
(In reply to comment #3)
> (In reply to comment #2)
> > (In reply to comment #1)
> > > (In reply to comment #0)
> > > > llint_slow_path_put_by_id has the following line of code:
> > > > 
> > > >    599                     ConcurrentJITLocker locker(codeBlock->m_lock);
> > > > 
> > > > and later in the same scope:
> > > > 
> > > >    618                             StructureChain* chain = structure->prototypeChain(exec);
> > > > 
> > > > which can cause a garbage collection. Garbage collection acquires the ConcurrentJITLock as it processes CodeBlocks, causing a deadlock.
> > > 
> > > L
> > 
> > Dunno what happened there.  I meant to say "Lol."
> 
> We could either move the call to prototypeChain(exec) up above the ConcurrentJITLocker, or we could do my favorite thing: DeferGC.
> 
> I like DeferGC more since it's more comprehensive.

Yeah I like that too.
Comment 5 Mark Hahnenberg 2013-10-11 11:53:29 PDT
(In reply to comment #4)
> (In reply to comment #3)
> > (In reply to comment #2)
> > > (In reply to comment #1)
> > > > (In reply to comment #0)
> > > > > llint_slow_path_put_by_id has the following line of code:
> > > > > 
> > > > >    599                     ConcurrentJITLocker locker(codeBlock->m_lock);
> > > > > 
> > > > > and later in the same scope:
> > > > > 
> > > > >    618                             StructureChain* chain = structure->prototypeChain(exec);
> > > > > 
> > > > > which can cause a garbage collection. Garbage collection acquires the ConcurrentJITLock as it processes CodeBlocks, causing a deadlock.
> > > > 
> > > > L
> > > 
> > > Dunno what happened there.  I meant to say "Lol."
> > 
> > We could either move the call to prototypeChain(exec) up above the ConcurrentJITLocker, or we could do my favorite thing: DeferGC.
> > 
> > I like DeferGC more since it's more comprehensive.
> 
> Yeah I like that too.

We could even make ConcurrentJITLocker do an implicit DeferGC. Thoughts?
Comment 6 Filip Pizlo 2013-10-11 11:55:29 PDT
(In reply to comment #5)
> (In reply to comment #4)
> > (In reply to comment #3)
> > > (In reply to comment #2)
> > > > (In reply to comment #1)
> > > > > (In reply to comment #0)
> > > > > > llint_slow_path_put_by_id has the following line of code:
> > > > > > 
> > > > > >    599                     ConcurrentJITLocker locker(codeBlock->m_lock);
> > > > > > 
> > > > > > and later in the same scope:
> > > > > > 
> > > > > >    618                             StructureChain* chain = structure->prototypeChain(exec);
> > > > > > 
> > > > > > which can cause a garbage collection. Garbage collection acquires the ConcurrentJITLock as it processes CodeBlocks, causing a deadlock.
> > > > > 
> > > > > L
> > > > 
> > > > Dunno what happened there.  I meant to say "Lol."
> > > 
> > > We could either move the call to prototypeChain(exec) up above the ConcurrentJITLocker, or we could do my favorite thing: DeferGC.
> > > 
> > > I like DeferGC more since it's more comprehensive.
> > 
> > Yeah I like that too.
> 
> We could even make ConcurrentJITLocker do an implicit DeferGC. Thoughts?

Or even better: have two versions of ConcurrentJITLocker.

One version sets a thread-local variable that in causes all GC allocations and other GC calls to fail in debug mode.  We could use that in as many places as possible.  The cool thing about this is that it also guarantees that the method is safe to call from a concurrent thread, from the GC's standpoint.

Another version does what you say.

We can then try to use the asserting version in as many places as possible.  Probably by doing this we will learn some fun surprises.
Comment 7 Mark Hahnenberg 2013-10-11 15:35:46 PDT
Created attachment 214030 [details]
Patch
Comment 8 Filip Pizlo 2013-10-11 15:40:23 PDT
Comment on attachment 214030 [details]
Patch

love it.
Comment 9 EFL EWS Bot 2013-10-11 15:42:18 PDT
Comment on attachment 214030 [details]
Patch

Attachment 214030 [details] did not pass efl-wk2-ews (efl-wk2):
Output: http://webkit-queues.appspot.com/results/3950221
Comment 10 Mark Hahnenberg 2013-10-11 15:44:40 PDT
Created attachment 214031 [details]
build fix
Comment 11 EFL EWS Bot 2013-10-11 15:49:20 PDT
Comment on attachment 214031 [details]
build fix

Attachment 214031 [details] did not pass efl-ews (efl):
Output: http://webkit-queues.appspot.com/results/3776306
Comment 12 EFL EWS Bot 2013-10-11 15:50:26 PDT
Comment on attachment 214031 [details]
build fix

Attachment 214031 [details] did not pass efl-wk2-ews (efl-wk2):
Output: http://webkit-queues.appspot.com/results/3946253
Comment 13 Mark Hahnenberg 2013-10-11 16:36:17 PDT
Created attachment 214035 [details]
omgjustbuild
Comment 14 WebKit Commit Bot 2013-10-14 11:58:26 PDT
Comment on attachment 214035 [details]
omgjustbuild

Rejecting attachment 214035 [details] from commit-queue.

Failed to run "['/Volumes/Data/EWS/WebKit/Tools/Scripts/webkit-patch', '--status-host=webkit-queues.appspot.com', '--bot-id=webkit-cq-01', 'apply-attachment', '--no-update', '--non-interactive', 214035, '--port=mac']" exit_code: 2 cwd: /Volumes/Data/EWS/WebKit

Last 500 characters of output:
avaScriptCore/llint/LLIntSlowPaths.cpp
patching file Source/JavaScriptCore/runtime/ConcurrentJITLock.h
patching file Source/JavaScriptCore/runtime/InitializeThreading.cpp
patching file Source/JavaScriptCore/runtime/JSCellInlines.h
patching file Source/JavaScriptCore/runtime/Structure.cpp
patching file Source/JavaScriptCore/runtime/Structure.h

Failed to run "[u'/Volumes/Data/EWS/WebKit/Tools/Scripts/svn-apply', '--force', '--reviewer', u'Filip Pizlo']" exit_code: 1 cwd: /Volumes/Data/EWS/WebKit

Full output: http://webkit-queues.appspot.com/results/3766906
Comment 15 Mark Hahnenberg 2013-10-14 12:33:12 PDT
Committed r157413: <http://trac.webkit.org/changeset/157413>
Comment 16 WebKit Commit Bot 2013-10-14 14:56:22 PDT
Re-opened since this is blocked by bug 122779
Comment 17 Alexey Proskuryakov 2013-10-14 15:00:36 PDT
This looks like the most likely culprit for WebGL and other crashes and timeouts:

http://build.webkit.org/results/Apple%20MountainLion%20Debug%20WK1%20(Tests)/r157416%20(10770)/results.html

http://build.webkit.org/results/Apple%20MountainLion%20Release%20WK1%20(Tests)/r157419%20(13809)/results.html

Rolled out in <https://trac.webkit.org/r157424>. We'll see if this helps.
Comment 19 Mark Hahnenberg 2013-10-15 10:28:30 PDT
(In reply to comment #18)
> This may have improved Dromaeo/jslib-event-jquery's score by ~28%:
> https://perf.webkit.org/#mode=charts&chartList=%5B%5B%22mac-lion%22%2C%22Dromaeo%2Fjslib-event-jquery%3ARuns%22%5D%2C%5B%22mac-mountainlion%22%2C%22Dromaeo%2Fjslib-event-jquery%3ARuns%22%5D%2C%5B%22mac-mountainlion%22%2C%22Dromaeo%2Fjslib-event-prototype%3ARuns%22%5D%2C%5B%22mac-lion%22%2C%22Dromaeo%2Fjslib-event-prototype%3ARuns%22%5D%5D&days=52&zoom=%5B1381585431357.5227%2C1381827392596%5D

Uhh, I don't think so. The patch was rolled out, but we still have the perf win. Also, this patch just fixes a deadlock, no reason it would improve performance.
Comment 20 Ryosuke Niwa 2013-10-15 11:09:33 PDT
So it's probably either http://trac.webkit.org/changeset/157412 or http://trac.webkit.org/changeset/157411
Comment 21 Mark Hahnenberg 2013-10-15 11:32:16 PDT
(In reply to comment #20)
> So it's probably either http://trac.webkit.org/changeset/157412 or http://trac.webkit.org/changeset/157411

Yeah, my money is on http://trac.webkit.org/changeset/157411.
Comment 22 Mark Hahnenberg 2013-10-16 15:55:03 PDT
Created attachment 214399 [details]
Patch
Comment 23 Geoffrey Garen 2013-10-16 16:10:48 PDT
Comment on attachment 214399 [details]
Patch

r=me based on previous reviews, assuming tests pass.
Comment 24 Mark Hahnenberg 2013-10-16 16:46:12 PDT
Committed r157539: <http://trac.webkit.org/changeset/157539>