WebKit Bugzilla
New
Browse
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
RESOLVED FIXED
158280
Structure::previousID() races with Structure::allocateRareData()
https://bugs.webkit.org/show_bug.cgi?id=158280
Summary
Structure::previousID() races with Structure::allocateRareData()
Filip Pizlo
Reported
2016-06-01 15:46:20 PDT
It's such an uncommon race, but it's totally devastating: we'll get a RareData pointer but thing it's a Structure. This passes most assertions - for example it passes cell validation - but later causes crashes in AI.
Attachments
possibly the patch
(28.69 KB, patch)
2016-06-01 15:52 PDT
,
Filip Pizlo
no flags
Details
Formatted Diff
Diff
performance
(78.34 KB, text/plain)
2016-06-01 18:55 PDT
,
Filip Pizlo
no flags
Details
the patch
(5.66 KB, patch)
2016-06-01 20:16 PDT
,
Filip Pizlo
mark.lam
: review+
Details
Formatted Diff
Diff
Show Obsolete
(2)
View All
Add attachment
proposed patch, testcase, etc.
Filip Pizlo
Comment 1
2016-06-01 15:52:07 PDT
Created
attachment 280275
[details]
possibly the patch I haven't benchmarked it yet.
WebKit Commit Bot
Comment 2
2016-06-01 15:53:42 PDT
Attachment 280275
[details]
did not pass style-queue: ERROR: Source/JavaScriptCore/bytecode/PutByIdVariant.cpp:77: Place brace on its own line for function definitions. [whitespace/braces] [4] ERROR: Source/WTF/wtf/Locker.h:48: Should be indented on a separate line, with the colon or comma first on that line. [whitespace/indent] [4] Total errors found: 2 in 10 files If any of these errors are false positives, please file a bug against check-webkit-style.
Filip Pizlo
Comment 3
2016-06-01 18:55:22 PDT
Created
attachment 280292
[details]
performance Performance is not so great - there are slow-downs. I'll test some more, but I think that I want to go with a lock-free solution. It should be easy.
Filip Pizlo
Comment 4
2016-06-01 20:14:31 PDT
Ran again, and the regression disappeared. Nonetheless, I have a better approach, patch coming soon.
Filip Pizlo
Comment 5
2016-06-01 20:16:44 PDT
Created
attachment 280299
[details]
the patch
Mark Lam
Comment 6
2016-06-01 20:50:13 PDT
Comment on
attachment 280299
[details]
the patch View in context:
https://bugs.webkit.org/attachment.cgi?id=280299&action=review
r=me. Is there a test case for this race condition?
> Source/JavaScriptCore/runtime/Structure.h:290 > + // This is so written because it's used concurrently. > + JSCell* cell = m_previousOrRareData.get(); > + if (isRareData(cell)) > + return static_cast<StructureRareData*>(cell)->previousID(); > + return static_cast<Structure*>(cell);
Can you make it more explicit as to what makes this safe for concurrency? I believe that it is the part that pre-fetches the cell before operating on it. How about having the comment say something like: // We must pre-fetch the cell from m_previousOrRareData before examining it. The m_previousOrRareData field may change on us due to another thread writing to it, but the local copy won't.
> Source/JavaScriptCore/runtime/Structure.h:703 > + bool isRareData(JSCell* cell) const
I think this should be a static method instead of a const instance method. You're not accessing any members of the instance here.
Filip Pizlo
Comment 7
2016-06-01 21:11:05 PDT
(In reply to
comment #6
)
> Comment on
attachment 280299
[details]
> the patch > > View in context: >
https://bugs.webkit.org/attachment.cgi?id=280299&action=review
> > r=me. Is there a test case for this race condition?
No. It does cause occasional crashes in run-javascriptcore-tests.
> > > Source/JavaScriptCore/runtime/Structure.h:290 > > + // This is so written because it's used concurrently. > > + JSCell* cell = m_previousOrRareData.get(); > > + if (isRareData(cell)) > > + return static_cast<StructureRareData*>(cell)->previousID(); > > + return static_cast<Structure*>(cell); > > Can you make it more explicit as to what makes this safe for concurrency? I > believe that it is the part that pre-fetches the cell before operating on > it.
I don't think that's right. A pre-fetch is an instruction that tells the CPU to initiate loading a cache line because it's actually used. This is nothing special. It's safe for concurrency because there's only one load of a mutable field.
> How about having the comment say something like: > > // We must pre-fetch the cell from m_previousOrRareData before examining it. > The m_previousOrRareData field may change on us due to another thread > writing to it, but the local copy won't.
I'll elaborate that it's because there's only one load of mutable state.
> > > Source/JavaScriptCore/runtime/Structure.h:703 > > + bool isRareData(JSCell* cell) const > > I think this should be a static method instead of a const instance method. > You're not accessing any members of the instance here.
No, it calls this->previousID(), which is an instance method.
Mark Lam
Comment 8
2016-06-01 21:19:30 PDT
Comment on
attachment 280299
[details]
the patch View in context:
https://bugs.webkit.org/attachment.cgi?id=280299&action=review
>>> Source/JavaScriptCore/runtime/Structure.h:290 >>> + return static_cast<Structure*>(cell); >> >> Can you make it more explicit as to what makes this safe for concurrency? I believe that it is the part that pre-fetches the cell before operating on it. How about having the comment say something like: >> >> // We must pre-fetch the cell from m_previousOrRareData before examining it. The m_previousOrRareData field may change on us due to another thread writing to it, but the local copy won't. > > I don't think that's right. A pre-fetch is an instruction that tells the CPU to initiate loading a cache line because it's actually used. > > This is nothing special. It's safe for concurrency because there's only one load of a mutable field.
My use of "pre-fetch" wasn't the best choice of words. I meant the same thing i.e. reading the field only once instead of twice: once for the check, once for the return value.
>>> Source/JavaScriptCore/runtime/Structure.h:703 >>> + bool isRareData(JSCell* cell) const >> >> I think this should be a static method instead of a const instance method. You're not accessing any members of the instance here. > > No, it calls this->previousID(), which is an instance method.
Oh ... I see. Actually, it calls this->structureID() which is the instance method.
Filip Pizlo
Comment 9
2016-06-01 21:25:29 PDT
Landed in
http://trac.webkit.org/changeset/201590
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