- Revision
- 110379
- Author
- [email protected]
- Date
- 2012-03-10 09:38:42 -0800 (Sat, 10 Mar 2012)
Log Message
Web Worker crashes with WX_EXCLUSIVE
https://bugs.webkit.org/show_bug.cgi?id=80532
Let each JS global object own a meta allocator
for WX_EXCLUSIVE to avoid conflicts from Web Worker.
Also fix a mutex leak in MetaAllocator's dtor.
Patch by Yong Li <[email protected]> on 2012-03-10
Reviewed by Filip Pizlo.
* jit/ExecutableAllocator.cpp:
(JSC::DemandExecutableAllocator::DemandExecutableAllocator):
(JSC::DemandExecutableAllocator::~DemandExecutableAllocator):
(JSC::DemandExecutableAllocator::bytesAllocatedByAllAllocators):
(DemandExecutableAllocator):
(JSC::DemandExecutableAllocator::bytesCommittedByAllocactors):
(JSC::DemandExecutableAllocator::dumpProfileFromAllAllocators):
(JSC::DemandExecutableAllocator::allocateNewSpace):
(JSC::DemandExecutableAllocator::allocators):
(JSC::DemandExecutableAllocator::allocatorsMutex):
(JSC):
(JSC::ExecutableAllocator::initializeAllocator):
(JSC::ExecutableAllocator::ExecutableAllocator):
(JSC::ExecutableAllocator::underMemoryPressure):
(JSC::ExecutableAllocator::memoryPressureMultiplier):
(JSC::ExecutableAllocator::allocate):
(JSC::ExecutableAllocator::committedByteCount):
(JSC::ExecutableAllocator::dumpProfile):
* jit/ExecutableAllocator.h:
(JSC):
(ExecutableAllocator):
(JSC::ExecutableAllocator::allocator):
* wtf/MetaAllocator.h:
(WTF::MetaAllocator::~MetaAllocator): Finalize the spin lock.
* wtf/TCSpinLock.h:
(TCMalloc_SpinLock::Finalize): Add empty Finalize() to some implementations.
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (110378 => 110379)
--- trunk/Source/_javascript_Core/ChangeLog 2012-03-10 17:08:02 UTC (rev 110378)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-03-10 17:38:42 UTC (rev 110379)
@@ -1,3 +1,41 @@
+2012-03-10 Yong Li <[email protected]>
+
+ Web Worker crashes with WX_EXCLUSIVE
+ https://bugs.webkit.org/show_bug.cgi?id=80532
+
+ Let each JS global object own a meta allocator
+ for WX_EXCLUSIVE to avoid conflicts from Web Worker.
+ Also fix a mutex leak in MetaAllocator's dtor.
+
+ Reviewed by Filip Pizlo.
+
+ * jit/ExecutableAllocator.cpp:
+ (JSC::DemandExecutableAllocator::DemandExecutableAllocator):
+ (JSC::DemandExecutableAllocator::~DemandExecutableAllocator):
+ (JSC::DemandExecutableAllocator::bytesAllocatedByAllAllocators):
+ (DemandExecutableAllocator):
+ (JSC::DemandExecutableAllocator::bytesCommittedByAllocactors):
+ (JSC::DemandExecutableAllocator::dumpProfileFromAllAllocators):
+ (JSC::DemandExecutableAllocator::allocateNewSpace):
+ (JSC::DemandExecutableAllocator::allocators):
+ (JSC::DemandExecutableAllocator::allocatorsMutex):
+ (JSC):
+ (JSC::ExecutableAllocator::initializeAllocator):
+ (JSC::ExecutableAllocator::ExecutableAllocator):
+ (JSC::ExecutableAllocator::underMemoryPressure):
+ (JSC::ExecutableAllocator::memoryPressureMultiplier):
+ (JSC::ExecutableAllocator::allocate):
+ (JSC::ExecutableAllocator::committedByteCount):
+ (JSC::ExecutableAllocator::dumpProfile):
+ * jit/ExecutableAllocator.h:
+ (JSC):
+ (ExecutableAllocator):
+ (JSC::ExecutableAllocator::allocator):
+ * wtf/MetaAllocator.h:
+ (WTF::MetaAllocator::~MetaAllocator): Finalize the spin lock.
+ * wtf/TCSpinLock.h:
+ (TCMalloc_SpinLock::Finalize): Add empty Finalize() to some implementations.
+
2012-03-09 Gavin Barraclough <[email protected]>
Array.prototype.toLocaleString visits elements in wrong order under certain conditions
Modified: trunk/Source/_javascript_Core/jit/ExecutableAllocator.cpp (110378 => 110379)
--- trunk/Source/_javascript_Core/jit/ExecutableAllocator.cpp 2012-03-10 17:08:02 UTC (rev 110378)
+++ trunk/Source/_javascript_Core/jit/ExecutableAllocator.cpp 2012-03-10 17:38:42 UTC (rev 110379)
@@ -30,8 +30,13 @@
#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
#include "CodeProfiling.h"
#include <wtf/DataLog.h>
+#include <wtf/HashSet.h>
#include <wtf/MetaAllocator.h>
#include <wtf/PageReservation.h>
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+#include <wtf/PassOwnPtr.h>
+#endif
+#include <wtf/ThreadingPrimitives.h>
#include <wtf/VMTags.h>
#endif
@@ -53,15 +58,48 @@
DemandExecutableAllocator()
: MetaAllocator(32) // round up all allocations to 32 bytes
{
+ MutexLocker lock(allocatorsMutex());
+ allocators().add(this);
// Don't preallocate any memory here.
}
virtual ~DemandExecutableAllocator()
{
+ {
+ MutexLocker lock(allocatorsMutex());
+ allocators().remove(this);
+ }
for (unsigned i = 0; i < reservations.size(); ++i)
reservations.at(i).deallocate();
}
+ static size_t bytesAllocatedByAllAllocators()
+ {
+ size_t total = 0;
+ MutexLocker lock(allocatorsMutex());
+ for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
+ total += (*allocator)->bytesAllocated();
+ return total;
+ }
+
+ static size_t bytesCommittedByAllocactors()
+ {
+ size_t total = 0;
+ MutexLocker lock(allocatorsMutex());
+ for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
+ total += (*allocator)->bytesCommitted();
+ return total;
+ }
+
+#if ENABLE(META_ALLOCATOR_PROFILE)
+ static void dumpProfileFromAllAllocators()
+ {
+ MutexLocker lock(allocatorsMutex());
+ for (HashSet<DemandExecutableAllocator*>::const_iterator allocator = allocators().begin(); allocator != allocators().end(); ++allocator)
+ (*allocator)->dumpProfile();
+ }
+#endif
+
protected:
virtual void* allocateNewSpace(size_t& numPages)
{
@@ -72,7 +110,7 @@
numPages = newNumPages;
#ifdef EXECUTABLE_MEMORY_LIMIT
- if (bytesAllocated() >= EXECUTABLE_MEMORY_LIMIT)
+ if (bytesAllocatedByAllAllocators() >= EXECUTABLE_MEMORY_LIMIT)
return 0;
#endif
@@ -97,22 +135,52 @@
private:
Vector<PageReservation, 16> reservations;
+ static HashSet<DemandExecutableAllocator*>& allocators()
+ {
+ DEFINE_STATIC_LOCAL(HashSet<DemandExecutableAllocator*>, sAllocators, ());
+ return sAllocators;
+ }
+ static Mutex& allocatorsMutex()
+ {
+ DEFINE_STATIC_LOCAL(Mutex, mutex, ());
+ return mutex;
+ }
};
-static DemandExecutableAllocator* allocator;
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+void ExecutableAllocator::initializeAllocator()
+{
+}
+#else
+static DemandExecutableAllocator* gAllocator;
+namespace {
+static inline DemandExecutableAllocator* allocator()
+{
+ return gAllocator;
+}
+}
+
void ExecutableAllocator::initializeAllocator()
{
- ASSERT(!allocator);
- allocator = new DemandExecutableAllocator();
- CodeProfiling::notifyAllocator(allocator);
+ ASSERT(!gAllocator);
+ gAllocator = new DemandExecutableAllocator();
+ CodeProfiling::notifyAllocator(gAllocator);
}
+#endif
ExecutableAllocator::ExecutableAllocator(JSGlobalData&)
+#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
+ : m_allocator(adoptPtr(new DemandExecutableAllocator()))
+#endif
{
- ASSERT(allocator);
+ ASSERT(allocator());
}
+ExecutableAllocator::~ExecutableAllocator()
+{
+}
+
bool ExecutableAllocator::isValid() const
{
return true;
@@ -121,7 +189,7 @@
bool ExecutableAllocator::underMemoryPressure()
{
#ifdef EXECUTABLE_MEMORY_LIMIT
- return allocator->bytesAllocated() > EXECUTABLE_MEMORY_LIMIT / 2;
+ return DemandExecutableAllocator::bytesAllocatedByAllAllocators() > EXECUTABLE_MEMORY_LIMIT / 2;
#else
return false;
#endif
@@ -130,7 +198,7 @@
double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage)
{
#ifdef EXECUTABLE_MEMORY_LIMIT
- size_t bytesAllocated = allocator->bytesAllocated() + addedMemoryUsage;
+ size_t bytesAllocated = DemandExecutableAllocator::bytesAllocatedByAllAllocators() + addedMemoryUsage;
if (bytesAllocated >= EXECUTABLE_MEMORY_LIMIT)
bytesAllocated = EXECUTABLE_MEMORY_LIMIT;
return static_cast<double>(EXECUTABLE_MEMORY_LIMIT) /
@@ -143,7 +211,7 @@
PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort)
{
- RefPtr<ExecutableMemoryHandle> result = allocator->allocate(sizeInBytes, ownerUID);
+ RefPtr<ExecutableMemoryHandle> result = allocator()->allocate(sizeInBytes, ownerUID);
if (!result && effort == JITCompilationMustSucceed)
CRASH();
return result.release();
@@ -151,13 +219,13 @@
size_t ExecutableAllocator::committedByteCount()
{
- return allocator->bytesCommitted();
+ return DemandExecutableAllocator::bytesCommittedByAllocactors();
}
#if ENABLE(META_ALLOCATOR_PROFILE)
void ExecutableAllocator::dumpProfile()
{
- allocator->dumpProfile();
+ DemandExecutableAllocator::dumpProfileFromAllAllocators();
}
#endif
Modified: trunk/Source/_javascript_Core/jit/ExecutableAllocator.h (110378 => 110379)
--- trunk/Source/_javascript_Core/jit/ExecutableAllocator.h 2012-03-10 17:08:02 UTC (rev 110378)
+++ trunk/Source/_javascript_Core/jit/ExecutableAllocator.h 2012-03-10 17:38:42 UTC (rev 110379)
@@ -96,11 +96,16 @@
#if ENABLE(JIT) && ENABLE(ASSEMBLER)
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+class DemandExecutableAllocator;
+#endif
+
class ExecutableAllocator {
enum ProtectionSetting { Writable, Executable };
public:
ExecutableAllocator(JSGlobalData&);
+ ~ExecutableAllocator();
static void initializeAllocator();
@@ -235,7 +240,13 @@
#if ENABLE(ASSEMBLER_WX_EXCLUSIVE)
static void reprotectRegion(void*, size_t, ProtectionSetting);
+#if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND)
+ // We create a MetaAllocator for each JS global object.
+ OwnPtr<DemandExecutableAllocator> m_allocator;
+ DemandExecutableAllocator* allocator() { return m_allocator.get(); }
#endif
+#endif
+
};
#endif // ENABLE(JIT) && ENABLE(ASSEMBLER)
Modified: trunk/Source/_javascript_Core/jit/ExecutableAllocatorFixedVMPool.cpp (110378 => 110379)
--- trunk/Source/_javascript_Core/jit/ExecutableAllocatorFixedVMPool.cpp 2012-03-10 17:08:02 UTC (rev 110378)
+++ trunk/Source/_javascript_Core/jit/ExecutableAllocatorFixedVMPool.cpp 2012-03-10 17:38:42 UTC (rev 110379)
@@ -104,6 +104,10 @@
ASSERT(allocator);
}
+ExecutableAllocator::~ExecutableAllocator()
+{
+}
+
bool ExecutableAllocator::isValid() const
{
return !!allocator->bytesReserved();
Modified: trunk/Source/_javascript_Core/wtf/MetaAllocator.h (110378 => 110379)
--- trunk/Source/_javascript_Core/wtf/MetaAllocator.h 2012-03-10 17:08:02 UTC (rev 110378)
+++ trunk/Source/_javascript_Core/wtf/MetaAllocator.h 2012-03-10 17:38:42 UTC (rev 110379)
@@ -204,6 +204,7 @@
freeFreeSpaceNode(node);
node = next;
}
+ m_lock.Finalize();
#ifndef NDEBUG
ASSERT(!m_mallocBalance);
#endif
Modified: trunk/Source/_javascript_Core/wtf/TCSpinLock.h (110378 => 110379)
--- trunk/Source/_javascript_Core/wtf/TCSpinLock.h 2012-03-10 17:08:02 UTC (rev 110378)
+++ trunk/Source/_javascript_Core/wtf/TCSpinLock.h 2012-03-10 17:38:42 UTC (rev 110379)
@@ -128,6 +128,7 @@
}
inline void Init() { lockword_ = 0; }
+ inline void Finalize() { }
volatile unsigned int lockword_;
};
@@ -221,6 +222,7 @@
}
inline void Init() { m_lockword = 0; }
+ inline void Finalize() { }
LONG m_lockword;
};