Changeset 74454 in webkit


Ignore:
Timestamp:
Dec 21, 2010 8:18:58 PM (13 years ago)
Author:
barraclough@apple.com
Message:

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.

(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.

Location:
trunk/JavaScriptCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r74441 r74454  
     12010-12-21  Gavin Barraclough  <barraclough@apple.com>
     2
     3         Reviewed by Geoff Garen.
     4 
     5        <rdar://problem/8765333> CRASH running out of executable memory, loading io9.com
     6        https://bugs.webkit.org/show_bug.cgi?id=51443
     7
     8        The problem here is that each page uses a reasonable amount of memory, (~4Mb),
     9        and that when miultiple pages are open we keep all JIT code for all functions
     10        in all pages alive.
     11
     12        Add a check to detect high memory pressure situations in the executable allocator
     13        (>50% of available memory allocated), and upon a top level entry into JSC (no code
     14        running on the stack) in this situation throw away all JIT code.
     15
     16        * JavaScriptCore.exp:
     17        * debugger/Debugger.cpp:
     18        (JSC::Debugger::recompileAllJSFunctions): stop passing exec to recompile.
     19        * jit/ExecutableAllocator.h:
     20        * jit/ExecutableAllocatorFixedVMPool.cpp:
     21        (JSC::ExecutablePool::systemAlloc): Count allocations.
     22        (JSC::ExecutablePool::systemRelease): Count deallocations.
     23        (JSC::ExecutablePool::underMemoryPressure): Check memory pressure.
     24        * jit/ExecutableAllocatorPosix.cpp:
     25        (JSC::ExecutablePool::underMemoryPressure): Stub out; only meaningful with FixedVMPool.
     26        * jit/ExecutableAllocatorWin.cpp:
     27        (JSC::ExecutablePool::underMemoryPressure): Stub out; only meaningful with FixedVMPool.
     28        * runtime/Executable.cpp:
     29        (JSC::FunctionExecutable::recompile): Remove ExecState argument to recompile.
     30        * runtime/Executable.h:
     31        * runtime/JSGlobalData.cpp:
     32        (JSC::JSGlobalData::recompileAllJSFunctions): throws away all JIT code.
     33        * runtime/JSGlobalData.h:
     34        * runtime/JSGlobalObject.h:
     35        (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): add check / call to throw away.
     36
    1372010-12-21  Gavin Barraclough  <barraclough@apple.com>
    238
  • trunk/JavaScriptCore/JavaScriptCore.exp

    r74431 r74454  
    201201__ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE
    202202__ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE
     203__ZN3JSC24DynamicGlobalObjectScopeC1EPNS_9ExecStateEPNS_14JSGlobalObjectE
    203204__ZN3JSC24JSObjectWithGlobalObjectC2EPNS_14JSGlobalObjectEN3WTF17NonNullPassRefPtrINS_9StructureEEE
    204205__ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE
  • trunk/JavaScriptCore/debugger/Debugger.cpp

    r70703 r74454  
    8686
    8787        ExecState* exec = function->scope().globalObject()->JSGlobalObject::globalExec();
    88         executable->recompile(exec);
     88        executable->discardCode();
    8989        if (function->scope().globalObject()->debugger() == this)
    9090            sourceProviders.add(executable->source().provider(), exec);
  • trunk/JavaScriptCore/jit/ExecutableAllocator.cpp

    r74357 r74454  
    6868}
    6969   
     70bool ExecutableAllocator::underMemoryPressure() const
     71{
     72    return false;
     73}
     74   
    7075size_t ExecutableAllocator::committedByteCount()
    7176{
  • trunk/JavaScriptCore/jit/ExecutableAllocator.h

    r74210 r74454  
    185185
    186186    bool isValid() const;
    187    
     187
     188    static bool underMemoryPressure();
     189
    188190    PassRefPtr<ExecutablePool> poolForSize(size_t n)
    189191    {
  • trunk/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp

    r73570 r74454  
    432432
    433433static FixedVMPoolAllocator* allocator = 0;
    434    
     434static size_t allocatedCount = 0;
     435
    435436bool ExecutableAllocator::isValid() const
    436437{
     
    441442}
    442443
     444bool ExecutableAllocator::underMemoryPressure()
     445{
     446    // Technically we should take the spin lock here, but we don't care if we get stale data.
     447    // This is only really a heuristic anyway.
     448    return allocatedCount > (VM_POOL_SIZE / 2);
     449}
     450
    443451ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t size)
    444452{
    445453    SpinLockHolder lock_holder(&spinlock);
    446454    ASSERT(allocator);
     455    allocatedCount += size;
    447456    return allocator->alloc(size);
    448457}
     
    452461    SpinLockHolder lock_holder(&spinlock);
    453462    ASSERT(allocator);
     463    allocatedCount -= allocation.size();
    454464    allocator->free(allocation);
    455465}
  • trunk/JavaScriptCore/runtime/Executable.cpp

    r72360 r74454  
    265265}
    266266
    267 void FunctionExecutable::recompile(ExecState*)
     267void FunctionExecutable::discardCode()
    268268{
    269269    m_codeBlockForCall.clear();
  • trunk/JavaScriptCore/runtime/Executable.h

    r72360 r74454  
    349349        SharedSymbolTable* symbolTable() const { return m_symbolTable; }
    350350
    351         void recompile(ExecState*);
     351        void discardCode();
    352352        void markAggregate(MarkStack&);
    353353        static PassRefPtr<FunctionExecutable> fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
  • trunk/JavaScriptCore/runtime/JSGlobalData.cpp

    r74360 r74454  
    3232#include "ArgList.h"
    3333#include "Collector.h"
     34#include "CollectorHeapIterator.h"
    3435#include "CommonIdentifiers.h"
    3536#include "FunctionConstructor.h"
     
    312313}
    313314
     315void JSGlobalData::recompileAllJSFunctions()
     316{
     317    // If JavaScript is running, it's not safe to recompile, since we'll end
     318    // up throwing away code that is live on the stack.
     319    ASSERT(!dynamicGlobalObject);
     320
     321    LiveObjectIterator it = heap.primaryHeapBegin();
     322    LiveObjectIterator heapEnd = heap.primaryHeapEnd();
     323    for ( ; it != heapEnd; ++it) {
     324        if ((*it)->inherits(&JSFunction::info)) {
     325            JSFunction* function = asFunction(*it);
     326            if (!function->executable()->isHostFunction())
     327                function->jsExecutable()->discardCode();
     328        }
     329    }
     330}
    314331
    315332#if ENABLE(REGEXP_TRACING)
  • trunk/JavaScriptCore/runtime/JSGlobalData.h

    r74441 r74454  
    249249        void stopSampling();
    250250        void dumpSampleData(ExecState* exec);
     251        void recompileAllJSFunctions();
    251252        RegExpCache* regExpCache() { return m_regExpCache; }
    252253#if ENABLE(REGEXP_TRACING)
  • trunk/JavaScriptCore/runtime/JSGlobalObject.cpp

    r70496 r74454  
    456456}
    457457
     458DynamicGlobalObjectScope::DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
     459    : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
     460    , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
     461{
     462    if (!m_dynamicGlobalObjectSlot) {
     463#if ENABLE(ASSEMBLER)
     464        if (ExecutableAllocator::underMemoryPressure())
     465            callFrame->globalData().recompileAllJSFunctions();
     466#endif
     467
     468        m_dynamicGlobalObjectSlot = dynamicGlobalObject;
     469
     470        // Reset the date cache between JS invocations to force the VM
     471        // to observe time zone changes.
     472        callFrame->globalData().resetDateCache();
     473    }
     474}
     475
    458476} // namespace JSC
  • trunk/JavaScriptCore/runtime/JSGlobalObject.h

    r72360 r74454  
    468468    class DynamicGlobalObjectScope : public Noncopyable {
    469469    public:
    470         DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
    471             : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
    472             , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
    473         {
    474             if (!m_dynamicGlobalObjectSlot) {
    475                 m_dynamicGlobalObjectSlot = dynamicGlobalObject;
    476 
    477                 // Reset the date cache between JS invocations to force the VM
    478                 // to observe time zone changes.
    479                 callFrame->globalData().resetDateCache();
    480             }
    481         }
     470        DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject);
    482471
    483472        ~DynamicGlobalObjectScope()
Note: See TracChangeset for help on using the changeset viewer.