Title: [110127] trunk/Source/_javascript_Core
Revision
110127
Author
mhahnenb...@apple.com
Date
2012-03-07 18:14:38 -0800 (Wed, 07 Mar 2012)

Log Message

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

Reviewed by Geoffrey Garen.

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.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (110126 => 110127)


--- trunk/Source/_javascript_Core/ChangeLog	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-03-08 02:14:38 UTC (rev 110127)
@@ -1,3 +1,38 @@
+2012-03-07  Mark Hahnenberg  <mhahnenb...@apple.com>
+
+        Refactor recompileAllJSFunctions() to be less expensive
+        https://bugs.webkit.org/show_bug.cgi?id=80330
+
+        Reviewed by Geoffrey Garen.
+
+        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.
+
 2012-03-06  Oliver Hunt  <oli...@apple.com>
 
         Further harden 64-bit JIT

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (110126 => 110127)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2012-03-08 02:14:38 UTC (rev 110127)
@@ -764,12 +764,22 @@
     return m_objectSpace.forEachCell<RecordType>();
 }
 
+void Heap::discardAllCompiledCode()
+{
+    // 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(!m_globalData->dynamicGlobalObject);
+    
+    for (FunctionExecutable* current = m_functions.head(); current; current = current->next())
+        current->discardCode();
+}
+
 void Heap::collectAllGarbage()
 {
     if (!m_isSafeToCollect)
         return;
     if (!m_globalData->dynamicGlobalObject)
-        m_globalData->recompileAllJSFunctions();
+        discardAllCompiledCode();
 
     collect(DoSweep);
 }
@@ -924,4 +934,14 @@
     finalizer(weak.get());
 }
 
+void Heap::addFunctionExecutable(FunctionExecutable* executable)
+{
+    m_functions.append(executable);
+}
+
+void Heap::removeFunctionExecutable(FunctionExecutable* executable)
+{
+    m_functions.remove(executable);
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/Heap.h (110126 => 110127)


--- trunk/Source/_javascript_Core/heap/Heap.h	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/heap/Heap.h	2012-03-08 02:14:38 UTC (rev 110127)
@@ -42,6 +42,7 @@
 
     class CopiedSpace;
     class CodeBlock;
+    class FunctionExecutable;
     class GCActivityCallback;
     class GlobalCodeBlock;
     class Heap;
@@ -105,6 +106,8 @@
 
         typedef void (*Finalizer)(JSCell*);
         JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
+        void addFunctionExecutable(FunctionExecutable*);
+        void removeFunctionExecutable(FunctionExecutable*);
 
         void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
         JS_EXPORT_PRIVATE void collectAllGarbage();
@@ -140,6 +143,8 @@
 
         double lastGCLength() { return m_lastGCLength; }
 
+        void discardAllCompiledCode();
+
     private:
         friend class CodeBlock;
         friend class LLIntOffsetsExtractor;
@@ -239,6 +244,8 @@
 
         JSGlobalData* m_globalData;
         double m_lastGCLength;
+
+        DoublyLinkedList<FunctionExecutable> m_functions;
     };
 
     bool Heap::isBusy()

Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (110126 => 110127)


--- trunk/Source/_javascript_Core/runtime/Executable.cpp	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp	2012-03-08 02:14:38 UTC (rev 110127)
@@ -146,6 +146,8 @@
     , m_name(name)
     , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
     , m_symbolTable(0)
+    , m_next(0)
+    , m_prev(0)
 {
 }
 
@@ -157,6 +159,8 @@
     , m_name(name)
     , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
     , m_symbolTable(0)
+    , m_next(0)
+    , m_prev(0)
 {
 }
 
@@ -654,7 +658,9 @@
 
 void FunctionExecutable::finalize(JSCell* cell)
 {
-    jsCast<FunctionExecutable*>(cell)->clearCode();
+    FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
+    Heap::heap(executable)->removeFunctionExecutable(executable);
+    executable->clearCode();
 }
 
 inline void FunctionExecutable::clearCode()

Modified: trunk/Source/_javascript_Core/runtime/Executable.h (110126 => 110127)


--- trunk/Source/_javascript_Core/runtime/Executable.h	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/runtime/Executable.h	2012-03-08 02:14:38 UTC (rev 110127)
@@ -463,9 +463,10 @@
         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     };
 
-    class FunctionExecutable : public ScriptExecutable {
+    class FunctionExecutable : public ScriptExecutable, public DoublyLinkedListNode<FunctionExecutable> {
         friend class JIT;
         friend class LLIntOffsetsExtractor;
+        friend class DoublyLinkedListNode<FunctionExecutable>;
     public:
         typedef ScriptExecutable Base;
 
@@ -473,6 +474,7 @@
         {
             FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
             executable->finishCreation(exec->globalData(), name, firstLine, lastLine);
+            exec->globalData().heap.addFunctionExecutable(executable);
             exec->globalData().heap.addFinalizer(executable, &finalize);
             return executable;
         }
@@ -481,6 +483,7 @@
         {
             FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext);
             executable->finishCreation(globalData, name, firstLine, lastLine);
+            globalData.heap.addFunctionExecutable(executable);
             globalData.heap.addFinalizer(executable, &finalize);
             return executable;
         }
@@ -688,6 +691,8 @@
         Identifier m_inferredName;
         WriteBarrier<JSString> m_nameValue;
         SharedSymbolTable* m_symbolTable;
+        FunctionExecutable* m_next;
+        FunctionExecutable* m_prev;
     };
 
     inline FunctionExecutable* JSFunction::jsExecutable() const

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp (110126 => 110127)


--- trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp	2012-03-08 02:14:38 UTC (rev 110127)
@@ -68,27 +68,6 @@
 
 using namespace WTF;
 
-namespace {
-
-using namespace JSC;
-
-class Recompiler : public MarkedBlock::VoidFunctor {
-public:
-    void operator()(JSCell*);
-};
-
-inline void Recompiler::operator()(JSCell* cell)
-{
-    if (!cell->inherits(&JSFunction::s_info))
-        return;
-    JSFunction* function = asFunction(cell);
-    if (!function->executable() || function->executable()->isHostFunction())
-        return;
-    function->jsExecutable()->discardCode();
-}
-
-} // namespace
-
 namespace JSC {
 
 extern const HashTable arrayConstructorTable;
@@ -443,15 +422,6 @@
 #endif
 }
 
-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);
-    
-    heap.objectSpace().forEachCell<Recompiler>();
-}
-
 struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor {
     HashSet<FunctionExecutable*> currentlyExecutingFunctions;
     void operator()(JSCell* cell)

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.h (110126 => 110127)


--- trunk/Source/_javascript_Core/runtime/JSGlobalData.h	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.h	2012-03-08 02:14:38 UTC (rev 110127)
@@ -324,7 +324,7 @@
         JS_EXPORT_PRIVATE void startSampling();
         JS_EXPORT_PRIVATE void stopSampling();
         JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec);
-        void recompileAllJSFunctions();
+        void discardAllCompiledCode();
         RegExpCache* regExpCache() { return m_regExpCache; }
 #if ENABLE(REGEXP_TRACING)
         void addRegExpToTrace(PassRefPtr<RegExp> regExp);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (110126 => 110127)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2012-03-08 02:12:26 UTC (rev 110126)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2012-03-08 02:14:38 UTC (rev 110127)
@@ -460,7 +460,7 @@
     if (!m_dynamicGlobalObjectSlot) {
 #if ENABLE(ASSEMBLER)
         if (ExecutableAllocator::underMemoryPressure())
-            globalData.recompileAllJSFunctions();
+            globalData.heap.discardAllCompiledCode();
 #endif
 
         m_dynamicGlobalObjectSlot = dynamicGlobalObject;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to