-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
JSObject::getDirectConcurrently should take the cell lock.
https://bugs.webkit.org/show_bug.cgi?id=257285 rdar://108166258 Reviewed by Yusuke Suzuki. `JSArray::unshiftCountWithArrayStorage` takes the cell lock and then the structure lock to prevent the compiler thread from accessing the butterfly before it is fully initialized. `JSObject::getDirectConcurrently` only takes the structure lock. This means that the compiler can take the structure lock, the cell can transition to a new structure, then unshift can mess up the butterfly, and finally the compiler thread proceeds to see garbage. The attached POC only reproduces if waits are introduced to extend the race window. It seems that the comment above cellLock is outdated, as our current concurrency protocol to prevent deadlocks is to take the cell lock then the structure lock. I could not find anywhere that uses the reverse, but if I missed something, a deadlock will be pretty easy to debug. * Source/JavaScriptCore/runtime/JSArray.cpp: (JSC::JSArray::unshiftCountWithArrayStorage): * Source/JavaScriptCore/runtime/JSCell.h: (JSC::JSCell::cellLock const): (JSC::JSCell::cellLock): Deleted. * Source/JavaScriptCore/runtime/JSObject.h: (JSC::JSObject::getDirectConcurrently const): Originally-landed-as: 259548.798@safari-7615-branch (b7e3ebd). rdar://108166258 Canonical link: https://commits.webkit.org/266435@main
- Loading branch information
1 parent
4a9d1a5
commit 14530da
Showing
7 changed files
with
123 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp | ||
index 07aed18ca1b4..157a836cf50e 100644 | ||
--- a/Source/JavaScriptCore/dfg/DFGGraph.cpp | ||
+++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp | ||
@@ -25,6 +25,7 @@ | ||
#include "config.h" | ||
#include "DFGGraph.h" | ||
+#include "runtime/JSCast.h" | ||
#if ENABLE(DFG_JIT) | ||
@@ -1337,6 +1338,10 @@ JSValue Graph::tryGetConstantProperty( | ||
Structure* structure = object->structure(); | ||
if (!structureSet.toStructureSet().contains(structure)) | ||
return JSValue(); | ||
+ | ||
+ if (jsDynamicCast<JSArray*>(object)) { | ||
+ usleep(1000 * 1000); | ||
+ } | ||
return object->getDirectConcurrently(structure, offset); | ||
} | ||
diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp | ||
index 7b8907517f9e..f18e5b3a9e0c 100644 | ||
--- a/Source/JavaScriptCore/runtime/JSArray.cpp | ||
+++ b/Source/JavaScriptCore/runtime/JSArray.cpp | ||
@@ -1033,6 +1033,9 @@ bool JSArray::unshiftCountWithArrayStorage(JSGlobalObject* globalObject, unsigne | ||
Structure* structure = this->structure(); | ||
ConcurrentJSLocker structureLock(structure->lock()); | ||
Butterfly* newButterfly = storage->butterfly()->unshift(structure, count); | ||
+ | ||
+ usleep(1000 * 2000); | ||
+ | ||
storage = newButterfly->arrayStorage(); | ||
storage->m_indexBias -= count; | ||
storage->setVectorLength(vectorLength + count); | ||
*/ | ||
|
||
async function sleep(ms) { | ||
return new Promise(resolve => { | ||
setTimeout(() => { | ||
resolve(); | ||
}, ms); | ||
}); | ||
} | ||
|
||
const container = {}; | ||
|
||
function opt() { | ||
const object = container.abc; | ||
|
||
return object.x; | ||
} | ||
|
||
async function main() { | ||
const array = []; | ||
array[1000] = 1.1; | ||
array.fill(1.1); | ||
array.unshift(1.1); | ||
|
||
array.__defineGetter__('x', () => 1); | ||
|
||
container.abc = array; | ||
|
||
for (let i = 0; i < 0x10000; i++) { | ||
opt(); | ||
} | ||
|
||
await sleep(250); | ||
|
||
array.y = 0x2222; | ||
array.unshift(1.1, 2.2, 3.3); | ||
|
||
await sleep(2000); | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters