Changeset 112624 in webkit


Ignore:
Timestamp:
Mar 29, 2012 5:36:37 PM (12 years ago)
Author:
mhahnenberg@apple.com
Message:

Refactor recompileAllJSFunctions() to be less expensive
https://bugs.webkit.org/show_bug.cgi?id=80330

Reviewed by Filip Pizlo.

This change is performance neutral on the JS benchmarks we track. It's mostly to improve page
load performance, which currently does at least a couple full GCs per navigation.

  • heap/Heap.cpp:

(JSC::Heap::discardAllCompiledCode): Rename recompileAllJSFunctions to discardAllCompiledCode
because the function doesn't actually recompile anything (and never did); it simply throws code
away for it to be recompiled later if we determine we should do so.
(JSC):
(JSC::Heap::collectAllGarbage):
(JSC::Heap::addFunctionExecutable): Adds a newly created FunctionExecutable to the Heap's list.
(JSC::Heap::removeFunctionExecutable): Removes the specified FunctionExecutable from the Heap's list.

  • heap/Heap.h:

(JSC):
(Heap):

  • runtime/Executable.cpp: Added next and prev fields to FunctionExecutables so that they can

be used in DoublyLinkedLists.
(JSC::FunctionExecutable::FunctionExecutable):
(JSC::FunctionExecutable::finalize): Removes the FunctionExecutable from the Heap's list.

  • runtime/Executable.h:

(FunctionExecutable):
(JSC::FunctionExecutable::create): Adds the FunctionExecutable to the Heap's list.

  • runtime/JSGlobalData.cpp: Remove recompileAllJSFunctions, as it's the Heap's job to own and manage

the list of FunctionExecutables.

  • runtime/JSGlobalData.h:

(JSGlobalData):

  • runtime/JSGlobalObject.cpp:

(JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Use the new discardAllCompiledCode.

Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r112595 r112624  
     12012-03-29  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        Refactor recompileAllJSFunctions() to be less expensive
     4        https://bugs.webkit.org/show_bug.cgi?id=80330
     5
     6        Reviewed by Filip Pizlo.
     7
     8        This change is performance neutral on the JS benchmarks we track. It's mostly to improve page
     9        load performance, which currently does at least a couple full GCs per navigation.
     10
     11        * heap/Heap.cpp:
     12        (JSC::Heap::discardAllCompiledCode): Rename recompileAllJSFunctions to discardAllCompiledCode
     13        because the function doesn't actually recompile anything (and never did); it simply throws code
     14        away for it to be recompiled later if we determine we should do so.
     15        (JSC):
     16        (JSC::Heap::collectAllGarbage):
     17        (JSC::Heap::addFunctionExecutable): Adds a newly created FunctionExecutable to the Heap's list.
     18        (JSC::Heap::removeFunctionExecutable): Removes the specified FunctionExecutable from the Heap's list.
     19        * heap/Heap.h:
     20        (JSC):
     21        (Heap):
     22        * runtime/Executable.cpp: Added next and prev fields to FunctionExecutables so that they can
     23        be used in DoublyLinkedLists.
     24        (JSC::FunctionExecutable::FunctionExecutable):
     25        (JSC::FunctionExecutable::finalize): Removes the FunctionExecutable from the Heap's list.
     26        * runtime/Executable.h:
     27        (FunctionExecutable):
     28        (JSC::FunctionExecutable::create): Adds the FunctionExecutable to the Heap's list.
     29        * runtime/JSGlobalData.cpp: Remove recompileAllJSFunctions, as it's the Heap's job to own and manage
     30        the list of FunctionExecutables.
     31        * runtime/JSGlobalData.h:
     32        (JSGlobalData):
     33        * runtime/JSGlobalObject.cpp:
     34        (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Use the new discardAllCompiledCode.
     35
    1362012-03-29  Filip Pizlo  <fpizlo@apple.com>
    237
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r111877 r112624  
    766766}
    767767
     768void Heap::discardAllCompiledCode()
     769{
     770    // If JavaScript is running, it's not safe to recompile, since we'll end
     771    // up throwing away code that is live on the stack.
     772    ASSERT(!m_globalData->dynamicGlobalObject);
     773   
     774    for (FunctionExecutable* current = m_functions.head(); current; current = current->next())
     775        current->discardCode();
     776}
     777
    768778void Heap::collectAllGarbage()
    769779{
     
    771781        return;
    772782    if (!m_globalData->dynamicGlobalObject)
    773         m_globalData->recompileAllJSFunctions();
     783        discardAllCompiledCode();
    774784
    775785    collect(DoSweep);
     
    926936}
    927937
     938void Heap::addFunctionExecutable(FunctionExecutable* executable)
     939{
     940    m_functions.append(executable);
     941}
     942
     943void Heap::removeFunctionExecutable(FunctionExecutable* executable)
     944{
     945    m_functions.remove(executable);
     946}
     947
    928948} // namespace JSC
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r111877 r112624  
    4343    class CopiedSpace;
    4444    class CodeBlock;
     45    class FunctionExecutable;
    4546    class GCActivityCallback;
    4647    class GlobalCodeBlock;
     
    106107        typedef void (*Finalizer)(JSCell*);
    107108        JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
     109        void addFunctionExecutable(FunctionExecutable*);
     110        void removeFunctionExecutable(FunctionExecutable*);
    108111
    109112        void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
     
    140143
    141144        double lastGCLength() { return m_lastGCLength; }
     145
     146        void discardAllCompiledCode();
    142147
    143148    private:
     
    241246        JSGlobalData* m_globalData;
    242247        double m_lastGCLength;
     248
     249        DoublyLinkedList<FunctionExecutable> m_functions;
    243250    };
    244251
  • trunk/Source/JavaScriptCore/runtime/Executable.cpp

    r110287 r112624  
    147147    , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
    148148    , m_symbolTable(0)
     149    , m_next(0)
     150    , m_prev(0)
    149151{
    150152}
     
    158160    , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
    159161    , m_symbolTable(0)
     162    , m_next(0)
     163    , m_prev(0)
    160164{
    161165}
     
    655659void FunctionExecutable::finalize(JSCell* cell)
    656660{
    657     jsCast<FunctionExecutable*>(cell)->clearCode();
     661    FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
     662    Heap::heap(executable)->removeFunctionExecutable(executable);
     663    executable->clearCode();
    658664}
    659665
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r111739 r112624  
    464464    };
    465465
    466     class FunctionExecutable : public ScriptExecutable {
     466    class FunctionExecutable : public ScriptExecutable, public DoublyLinkedListNode<FunctionExecutable> {
    467467        friend class JIT;
    468468        friend class LLIntOffsetsExtractor;
     469        friend class WTF::DoublyLinkedListNode<FunctionExecutable>;
    469470    public:
    470471        typedef ScriptExecutable Base;
     
    474475            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
    475476            executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
     477            exec->globalData().heap.addFunctionExecutable(executable);
    476478            exec->globalData().heap.addFinalizer(executable, &finalize);
    477479            return executable;
     
    482484            FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
    483485            executable->finishCreation(globalData, name, firstLine, lastLine);
     486            globalData.heap.addFunctionExecutable(executable);
    484487            globalData.heap.addFinalizer(executable, &finalize);
    485488            return executable;
     
    689692        WriteBarrier<JSString> m_nameValue;
    690693        SharedSymbolTable* m_symbolTable;
     694        FunctionExecutable* m_next;
     695        FunctionExecutable* m_prev;
    691696    };
    692697
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.cpp

    r111739 r112624  
    6969using namespace WTF;
    7070
    71 namespace {
    72 
    73 using namespace JSC;
    74 
    75 class Recompiler : public MarkedBlock::VoidFunctor {
    76 public:
    77     void operator()(JSCell*);
    78 };
    79 
    80 inline void Recompiler::operator()(JSCell* cell)
    81 {
    82     if (!cell->inherits(&JSFunction::s_info))
    83         return;
    84     JSFunction* function = jsCast<JSFunction*>(cell);
    85     if (!function->executable() || function->executable()->isHostFunction())
    86         return;
    87     function->jsExecutable()->discardCode();
    88 }
    89 
    90 } // namespace
    91 
    9271namespace JSC {
    9372
     
    444423}
    445424
    446 void JSGlobalData::recompileAllJSFunctions()
    447 {
    448     // If JavaScript is running, it's not safe to recompile, since we'll end
    449     // up throwing away code that is live on the stack.
    450     ASSERT(!dynamicGlobalObject);
    451    
    452     heap.objectSpace().forEachCell<Recompiler>();
    453 }
    454 
    455425struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
    456426    HashSet<FunctionExecutable*> currentlyExecutingFunctions;
  • trunk/Source/JavaScriptCore/runtime/JSGlobalData.h

    r111013 r112624  
    325325        JS_EXPORT_PRIVATE void stopSampling();
    326326        JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec);
    327         void recompileAllJSFunctions();
     327        void discardAllCompiledCode();
    328328        RegExpCache* regExpCache() { return m_regExpCache; }
    329329#if ENABLE(REGEXP_TRACING)
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r110138 r112624  
    461461#if ENABLE(ASSEMBLER)
    462462        if (ExecutableAllocator::underMemoryPressure())
    463             globalData.recompileAllJSFunctions();
     463            globalData.heap.discardAllCompiledCode();
    464464#endif
    465465
Note: See TracChangeset for help on using the changeset viewer.