Title: [110379] trunk/Source/_javascript_Core
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;
 };
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to