[SCM] WebKit Debian packaging branch, debian/experimental, updated. debian/1.3.8-1-142-g786665c

barraclough at apple.com barraclough at apple.com
Mon Dec 27 16:29:04 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit bd837624dd3e57455e4b2cbf0ba30c2a89ed9ded
Author: barraclough at apple.com <barraclough at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Wed Dec 22 04:18:58 2010 +0000

     Reviewed by Geoff Garen.
    
    <rdar://problem/8765333> CRASH running out of executable memory, loading io9.com
    https://bugs.webkit.org/show_bug.cgi?id=51443
    
    The problem here is that each page uses a reasonable amount of memory, (~4Mb),
    and that when miultiple pages are open we keep all JIT code for all functions
    in all pages alive.
    
    Add a check to detect high memory pressure situations in the executable allocator
    (>50% of available memory allocated), and upon a top level entry into JSC (no code
    running on the stack) in this situation throw away all JIT code.
    
    * JavaScriptCore.exp:
    * debugger/Debugger.cpp:
    (JSC::Debugger::recompileAllJSFunctions): stop passing exec to recompile.
    * jit/ExecutableAllocator.h:
    * jit/ExecutableAllocatorFixedVMPool.cpp:
    (JSC::ExecutablePool::systemAlloc): Count allocations.
    (JSC::ExecutablePool::systemRelease): Count deallocations.
    (JSC::ExecutablePool::underMemoryPressure): Check memory pressure.
    * jit/ExecutableAllocatorPosix.cpp:
    (JSC::ExecutablePool::underMemoryPressure): Stub out; only meaningful with FixedVMPool.
    * jit/ExecutableAllocatorWin.cpp:
    (JSC::ExecutablePool::underMemoryPressure): Stub out; only meaningful with FixedVMPool.
    * runtime/Executable.cpp:
    (JSC::FunctionExecutable::recompile): Remove ExecState argument to recompile.
    * runtime/Executable.h:
    * runtime/JSGlobalData.cpp:
    (JSC::JSGlobalData::recompileAllJSFunctions): throws away all JIT code.
    * runtime/JSGlobalData.h:
    * runtime/JSGlobalObject.h:
    (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): add check / call to throw away.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@74454 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 0bf8863..eb25e7d 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,5 +1,41 @@
 2010-12-21  Gavin Barraclough  <barraclough at apple.com>
 
+         Reviewed by Geoff Garen.
+ 
+        <rdar://problem/8765333> CRASH running out of executable memory, loading io9.com
+        https://bugs.webkit.org/show_bug.cgi?id=51443
+
+        The problem here is that each page uses a reasonable amount of memory, (~4Mb),
+        and that when miultiple pages are open we keep all JIT code for all functions
+        in all pages alive.
+
+        Add a check to detect high memory pressure situations in the executable allocator
+        (>50% of available memory allocated), and upon a top level entry into JSC (no code
+        running on the stack) in this situation throw away all JIT code.
+
+        * JavaScriptCore.exp:
+        * debugger/Debugger.cpp:
+        (JSC::Debugger::recompileAllJSFunctions): stop passing exec to recompile.
+        * jit/ExecutableAllocator.h:
+        * jit/ExecutableAllocatorFixedVMPool.cpp:
+        (JSC::ExecutablePool::systemAlloc): Count allocations.
+        (JSC::ExecutablePool::systemRelease): Count deallocations.
+        (JSC::ExecutablePool::underMemoryPressure): Check memory pressure.
+        * jit/ExecutableAllocatorPosix.cpp:
+        (JSC::ExecutablePool::underMemoryPressure): Stub out; only meaningful with FixedVMPool.
+        * jit/ExecutableAllocatorWin.cpp:
+        (JSC::ExecutablePool::underMemoryPressure): Stub out; only meaningful with FixedVMPool.
+        * runtime/Executable.cpp:
+        (JSC::FunctionExecutable::recompile): Remove ExecState argument to recompile.
+        * runtime/Executable.h:
+        * runtime/JSGlobalData.cpp:
+        (JSC::JSGlobalData::recompileAllJSFunctions): throws away all JIT code.
+        * runtime/JSGlobalData.h:
+        * runtime/JSGlobalObject.h:
+        (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): add check / call to throw away.
+
+2010-12-21  Gavin Barraclough  <barraclough at apple.com>
+
         Reviewed by Geoff Garen.
 
         <rdar://problem/8241425> JIT executable memory excessive usage due to regex caching
diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp
index a8ee65b..2e999ef 100644
--- a/JavaScriptCore/JavaScriptCore.exp
+++ b/JavaScriptCore/JavaScriptCore.exp
@@ -200,6 +200,7 @@ __ZN3JSC22globalMemoryStatisticsEv
 __ZN3JSC23AbstractSamplingCounter4dumpEv
 __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
 __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
+__ZN3JSC24DynamicGlobalObjectScopeC1EPNS_9ExecStateEPNS_14JSGlobalObjectE
 __ZN3JSC24JSObjectWithGlobalObjectC2EPNS_14JSGlobalObjectEN3WTF17NonNullPassRefPtrINS_9StructureEEE
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
 __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
diff --git a/JavaScriptCore/debugger/Debugger.cpp b/JavaScriptCore/debugger/Debugger.cpp
index 472a03a..6b24c5a 100644
--- a/JavaScriptCore/debugger/Debugger.cpp
+++ b/JavaScriptCore/debugger/Debugger.cpp
@@ -85,7 +85,7 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData)
             continue;
 
         ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec();
-        executable->recompile(exec);
+        executable->discardCode();
         if (function->scope().globalObject()->debugger() == this)
             sourceProviders.add(executable->source().provider(), exec);
     }
diff --git a/JavaScriptCore/jit/ExecutableAllocator.cpp b/JavaScriptCore/jit/ExecutableAllocator.cpp
index 4ebc8b3..8d4036a 100644
--- a/JavaScriptCore/jit/ExecutableAllocator.cpp
+++ b/JavaScriptCore/jit/ExecutableAllocator.cpp
@@ -67,6 +67,11 @@ bool ExecutableAllocator::isValid() const
     return true;
 }
     
+bool ExecutableAllocator::underMemoryPressure() const
+{
+    return false;
+}
+    
 size_t ExecutableAllocator::committedByteCount()
 {
     return 0;
diff --git a/JavaScriptCore/jit/ExecutableAllocator.h b/JavaScriptCore/jit/ExecutableAllocator.h
index b6debe4..4580a67 100644
--- a/JavaScriptCore/jit/ExecutableAllocator.h
+++ b/JavaScriptCore/jit/ExecutableAllocator.h
@@ -184,7 +184,9 @@ public:
     }
 
     bool isValid() const;
-    
+
+    static bool underMemoryPressure();
+
     PassRefPtr<ExecutablePool> poolForSize(size_t n)
     {
         // Try to fit in the existing small allocator
diff --git a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
index b79df77..e280b2d 100644
--- a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
+++ b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp
@@ -431,7 +431,8 @@ void ExecutableAllocator::intializePageSize()
 }
 
 static FixedVMPoolAllocator* allocator = 0;
-    
+static size_t allocatedCount = 0;
+
 bool ExecutableAllocator::isValid() const
 {
     SpinLockHolder lock_holder(&spinlock);
@@ -440,10 +441,18 @@ bool ExecutableAllocator::isValid() const
     return allocator->isValid();
 }
 
+bool ExecutableAllocator::underMemoryPressure()
+{
+    // Technically we should take the spin lock here, but we don't care if we get stale data.
+    // This is only really a heuristic anyway.
+    return allocatedCount > (VM_POOL_SIZE / 2);
+}
+
 ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
 {
     SpinLockHolder lock_holder(&spinlock);
     ASSERT(allocator);
+    allocatedCount += size;
     return allocator->alloc(size);
 }
 
@@ -451,6 +460,7 @@ void ExecutablePool::systemRelease(ExecutablePool::Allocation& allocation)
 {
     SpinLockHolder lock_holder(&spinlock);
     ASSERT(allocator);
+    allocatedCount -= allocation.size();
     allocator->free(allocation);
 }
 
diff --git a/JavaScriptCore/runtime/Executable.cpp b/JavaScriptCore/runtime/Executable.cpp
index f229f96..c7262be 100644
--- a/JavaScriptCore/runtime/Executable.cpp
+++ b/JavaScriptCore/runtime/Executable.cpp
@@ -264,7 +264,7 @@ void FunctionExecutable::markAggregate(MarkStack& markStack)
         m_codeBlockForConstruct->markAggregate(markStack);
 }
 
-void FunctionExecutable::recompile(ExecState*)
+void FunctionExecutable::discardCode()
 {
     m_codeBlockForCall.clear();
     m_codeBlockForConstruct.clear();
diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h
index 14ed927..544e487 100644
--- a/JavaScriptCore/runtime/Executable.h
+++ b/JavaScriptCore/runtime/Executable.h
@@ -348,7 +348,7 @@ namespace JSC {
         UString paramString() const;
         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
 
-        void recompile(ExecState*);
+        void discardCode();
         void markAggregate(MarkStack&);
         static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
 
diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp
index 6f1de3b..aca995a 100644
--- a/JavaScriptCore/runtime/JSGlobalData.cpp
+++ b/JavaScriptCore/runtime/JSGlobalData.cpp
@@ -31,6 +31,7 @@
 
 #include "ArgList.h"
 #include "Collector.h"
+#include "CollectorHeapIterator.h"
 #include "CommonIdentifiers.h"
 #include "FunctionConstructor.h"
 #include "GetterSetter.h"
@@ -311,6 +312,22 @@ void JSGlobalData::dumpSampleData(ExecState* exec)
     interpreter->dumpSampleData(exec);
 }
 
+void JSGlobalData::recompileAllJSFunctions()
+{
+    // If JavaScript is running, it's not safe to recompile, since we'll end
+    // up throwing away code that is live on the stack.
+    ASSERT(!dynamicGlobalObject);
+
+    LiveObjectIterator it = heap.primaryHeapBegin();
+    LiveObjectIterator heapEnd = heap.primaryHeapEnd();
+    for ( ; it != heapEnd; ++it) {
+        if ((*it)->inherits(&JSFunction::info)) {
+            JSFunction* function = asFunction(*it);
+            if (!function->executable()->isHostFunction())
+                function->jsExecutable()->discardCode();
+        }
+    }
+}
 
 #if ENABLE(REGEXP_TRACING)
 void JSGlobalData::addRegExpToTrace(PassRefPtr<RegExp> regExp)
diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h
index 1dad920..699f975 100644
--- a/JavaScriptCore/runtime/JSGlobalData.h
+++ b/JavaScriptCore/runtime/JSGlobalData.h
@@ -248,6 +248,7 @@ namespace JSC {
         void startSampling();
         void stopSampling();
         void dumpSampleData(ExecState* exec);
+        void recompileAllJSFunctions();
         RegExpCache* regExpCache() { return m_regExpCache; }
 #if ENABLE(REGEXP_TRACING)
         void addRegExpToTrace(PassRefPtr<RegExp> regExp);
diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp
index a8fb7bf..408aea7 100644
--- a/JavaScriptCore/runtime/JSGlobalObject.cpp
+++ b/JavaScriptCore/runtime/JSGlobalObject.cpp
@@ -455,4 +455,22 @@ void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData)
     delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData);
 }
 
+DynamicGlobalObjectScope::DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
+    : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
+    , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
+{
+    if (!m_dynamicGlobalObjectSlot) {
+#if ENABLE(ASSEMBLER)
+        if (ExecutableAllocator::underMemoryPressure())
+            callFrame->globalData().recompileAllJSFunctions();
+#endif
+
+        m_dynamicGlobalObjectSlot = dynamicGlobalObject;
+
+        // Reset the date cache between JS invocations to force the VM
+        // to observe time zone changes.
+        callFrame->globalData().resetDateCache();
+    }
+}
+
 } // namespace JSC
diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h
index 714999f..a22b0aa 100644
--- a/JavaScriptCore/runtime/JSGlobalObject.h
+++ b/JavaScriptCore/runtime/JSGlobalObject.h
@@ -467,18 +467,7 @@ namespace JSC {
 
     class DynamicGlobalObjectScope : public Noncopyable {
     public:
-        DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) 
-            : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
-            , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
-        {
-            if (!m_dynamicGlobalObjectSlot) {
-                m_dynamicGlobalObjectSlot = dynamicGlobalObject;
-
-                // Reset the date cache between JS invocations to force the VM
-                // to observe time zone changes.
-                callFrame->globalData().resetDateCache();
-            }
-        }
+        DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject);
 
         ~DynamicGlobalObjectScope()
         {

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list