Title: [183212] trunk/Source/_javascript_Core
- Revision
- 183212
- Author
- [email protected]
- Date
- 2015-04-23 14:56:23 -0700 (Thu, 23 Apr 2015)
Log Message
Make FunctionRareData allocation thread-safe
https://bugs.webkit.org/show_bug.cgi?id=144001
Patch by Basile Clement <[email protected]> on 2015-04-23
Reviewed by Mark Lam.
The two things we want to prevent are:
1. A thread seeing a pointer to a not-yet-fully-created rare data from
a JSFunction
2. A thread seeing a pointer to a not-yet-fully-created Structure from
an ObjectAllocationProfile
For 1., only the JS thread can be creating the rare data (in
runtime/CommonSlowPaths.cpp or in dfg/DFGOperations.cpp), so we don't need to
worry about concurrent writes, and we don't need any fences when *reading* the
rare data from the JS thread. Thus we only need a storeStoreFence between the
rare data creation and assignment to m_rareData in
JSFunction::createAndInitializeRareData() to ensure that when the store to
m_rareData is issued, the rare data has been properly created.
For the DFG compilation threads, the only place they can access the
rare data is through JSFunction::rareData(), and so we only need a
loadLoadFence there to ensure that when we see a non-null pointer in
m_rareData, the pointed object will be seen as a fully created
FunctionRareData.
For 2., the structure is created in
ObjectAllocationProfile::initialize() (which appears to be called only by the
JS thread as well, in bytecode/CodeBlock.cpp and on rare data initialization,
which always happen in the JS thread), and read through
ObjectAllocationProfile::structure() and
ObjectAllocationProfile::inlineCapacity(), so following the same reasoning we
put a storeStoreFence in ObjectAllocationProfile::initialize() and a
loadLoadFence in ObjectAllocationProfile::structure() (and change
ObjectAllocationProfile::inlineCapacity() to go through
ObjectAllocationProfile::structure()).
We don't need a fence in ObjectAllocationProfile::clear() because
clearing the structure is already as atomic as it gets.
Finally, notice that we don't care about the ObjectAllocationProfile's
m_allocator as that is only used by ObjectAllocationProfile::initialize() and
ObjectAllocationProfile::clear() that are always run in the JS thread.
ObjectAllocationProfile::isNull() could cause some trouble, but it is
currently only used in the ObjectAllocationProfile::clear()'s ASSERT in the JS
thread. Doing isNull()-style pre-checks would be wrong in any other concurrent
thread anyway.
* bytecode/ObjectAllocationProfile.h:
(JSC::ObjectAllocationProfile::initialize):
(JSC::ObjectAllocationProfile::structure):
(JSC::ObjectAllocationProfile::inlineCapacity):
* runtime/JSFunction.cpp:
(JSC::JSFunction::allocateAndInitializeRareData):
* runtime/JSFunction.h:
(JSC::JSFunction::rareData):
(JSC::JSFunction::allocationStructure): Deleted.
This is no longer used, as all the accesses to the ObjectAllocationProfile go through the rare data.
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (183211 => 183212)
--- trunk/Source/_javascript_Core/ChangeLog 2015-04-23 21:33:23 UTC (rev 183211)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-04-23 21:56:23 UTC (rev 183212)
@@ -1,3 +1,65 @@
+2015-04-23 Basile Clement <[email protected]>
+
+ Make FunctionRareData allocation thread-safe
+ https://bugs.webkit.org/show_bug.cgi?id=144001
+
+ Reviewed by Mark Lam.
+
+ The two things we want to prevent are:
+
+ 1. A thread seeing a pointer to a not-yet-fully-created rare data from
+ a JSFunction
+ 2. A thread seeing a pointer to a not-yet-fully-created Structure from
+ an ObjectAllocationProfile
+
+ For 1., only the JS thread can be creating the rare data (in
+ runtime/CommonSlowPaths.cpp or in dfg/DFGOperations.cpp), so we don't need to
+ worry about concurrent writes, and we don't need any fences when *reading* the
+ rare data from the JS thread. Thus we only need a storeStoreFence between the
+ rare data creation and assignment to m_rareData in
+ JSFunction::createAndInitializeRareData() to ensure that when the store to
+ m_rareData is issued, the rare data has been properly created.
+
+ For the DFG compilation threads, the only place they can access the
+ rare data is through JSFunction::rareData(), and so we only need a
+ loadLoadFence there to ensure that when we see a non-null pointer in
+ m_rareData, the pointed object will be seen as a fully created
+ FunctionRareData.
+
+
+ For 2., the structure is created in
+ ObjectAllocationProfile::initialize() (which appears to be called only by the
+ JS thread as well, in bytecode/CodeBlock.cpp and on rare data initialization,
+ which always happen in the JS thread), and read through
+ ObjectAllocationProfile::structure() and
+ ObjectAllocationProfile::inlineCapacity(), so following the same reasoning we
+ put a storeStoreFence in ObjectAllocationProfile::initialize() and a
+ loadLoadFence in ObjectAllocationProfile::structure() (and change
+ ObjectAllocationProfile::inlineCapacity() to go through
+ ObjectAllocationProfile::structure()).
+
+ We don't need a fence in ObjectAllocationProfile::clear() because
+ clearing the structure is already as atomic as it gets.
+
+ Finally, notice that we don't care about the ObjectAllocationProfile's
+ m_allocator as that is only used by ObjectAllocationProfile::initialize() and
+ ObjectAllocationProfile::clear() that are always run in the JS thread.
+ ObjectAllocationProfile::isNull() could cause some trouble, but it is
+ currently only used in the ObjectAllocationProfile::clear()'s ASSERT in the JS
+ thread. Doing isNull()-style pre-checks would be wrong in any other concurrent
+ thread anyway.
+
+ * bytecode/ObjectAllocationProfile.h:
+ (JSC::ObjectAllocationProfile::initialize):
+ (JSC::ObjectAllocationProfile::structure):
+ (JSC::ObjectAllocationProfile::inlineCapacity):
+ * runtime/JSFunction.cpp:
+ (JSC::JSFunction::allocateAndInitializeRareData):
+ * runtime/JSFunction.h:
+ (JSC::JSFunction::rareData):
+ (JSC::JSFunction::allocationStructure): Deleted.
+ This is no longer used, as all the accesses to the ObjectAllocationProfile go through the rare data.
+
2015-04-22 Filip Pizlo <[email protected]>
DFG should insert Phantoms late using BytecodeKills and block-local OSR availability
Modified: trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfile.h (183211 => 183212)
--- trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfile.h 2015-04-23 21:33:23 UTC (rev 183211)
+++ trunk/Source/_javascript_Core/bytecode/ObjectAllocationProfile.h 2015-04-23 21:56:23 UTC (rev 183212)
@@ -89,13 +89,23 @@
if (inlineCapacity > JSFinalObject::maxInlineCapacity())
inlineCapacity = JSFinalObject::maxInlineCapacity();
+ Structure* structure = vm.prototypeMap.emptyObjectStructureForPrototype(prototype, inlineCapacity);
+
+ // Ensure that if another thread sees the structure, it will see it properly created
+ WTF::storeStoreFence();
+
m_allocator = allocator;
- m_structure.set(vm, owner,
- vm.prototypeMap.emptyObjectStructureForPrototype(prototype, inlineCapacity));
+ m_structure.set(vm, owner, structure);
}
- Structure* structure() { return m_structure.get(); }
- unsigned inlineCapacity() { return m_structure->inlineCapacity(); }
+ Structure* structure()
+ {
+ Structure* structure = m_structure.get();
+ // Ensure that if we see the structure, it has been properly created
+ WTF::loadLoadFence();
+ return structure;
+ }
+ unsigned inlineCapacity() { return structure()->inlineCapacity(); }
void clear()
{
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.cpp (183211 => 183212)
--- trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2015-04-23 21:33:23 UTC (rev 183211)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.cpp 2015-04-23 21:56:23 UTC (rev 183212)
@@ -116,6 +116,11 @@
if (!prototype)
prototype = globalObject()->objectPrototype();
FunctionRareData* rareData = FunctionRareData::create(vm, prototype, inlineCapacity);
+
+ // A DFG compilation thread may be trying to read the rare data
+ // We want to ensure that it sees it properly allocated
+ WTF::storeStoreFence();
+
m_rareData.set(vm, this, rareData);
return m_rareData.get();
}
Modified: trunk/Source/_javascript_Core/runtime/JSFunction.h (183211 => 183212)
--- trunk/Source/_javascript_Core/runtime/JSFunction.h 2015-04-23 21:33:23 UTC (rev 183211)
+++ trunk/Source/_javascript_Core/runtime/JSFunction.h 2015-04-23 21:56:23 UTC (rev 183212)
@@ -118,14 +118,15 @@
return m_rareData.get();
}
- FunctionRareData* rareData() { return m_rareData.get(); }
-
- Structure* allocationStructure()
+ FunctionRareData* rareData()
{
- if (!m_rareData)
- return nullptr;
+ FunctionRareData* rareData = m_rareData.get();
- return m_rareData.get()->allocationStructure();
+ // The JS thread may be concurrently creating the rare data
+ // If we see it, we want to ensure it has been properly created
+ WTF::loadLoadFence();
+
+ return rareData;
}
bool isHostOrBuiltinFunction() const;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes