Title: [119844] trunk/Source/_javascript_Core
Revision
119844
Author
[email protected]
Date
2012-06-08 11:17:16 -0700 (Fri, 08 Jun 2012)

Log Message

Don't rely on weak pointers for eager CodeBlock finalization
https://bugs.webkit.org/show_bug.cgi?id=88465

Reviewed by Gavin Barraclough.

This is incompatible with lazy weak pointer finalization.

I considered just making CodeBlock finalization lazy-friendly, but it
turns out that the heap is already way up in CodeBlock's business when
it comes to finalization, so I decided to finish the job and move full
responsibility for CodeBlock finalization into the heap.

* _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def: Maybe this
will build.

* debugger/Debugger.cpp: Updated for rename.

* heap/Heap.cpp:
(JSC::Heap::deleteAllCompiledCode): Renamed for consistency. Fixed a bug
where we would not delete code for a code block that had been previously
jettisoned. I don't know if this happens in practice -- I mostly did
this to improve consistency with deleteUnmarkedCompiledCode.

(JSC::Heap::deleteUnmarkedCompiledCode): New function, responsible for
eager finalization of unmarked code blocks.

(JSC::Heap::collect): Updated for rename. Updated to call
deleteUnmarkedCompiledCode(), which takes care of jettisoned DFG code
blocks too.

(JSC::Heap::addCompiledCode): Renamed, since this points to all code
now, not just functions.

* heap/Heap.h:
(Heap): Keep track of all user code, not just functions. This is a
negligible additional overhead, since most code is function code.

* runtime/Executable.cpp:
(JSC::*::finalize): Removed these functions, since we don't rely on
weak pointer finalization anymore.

(JSC::FunctionExecutable::FunctionExecutable): Moved linked-list stuff
into base class so all executables can be in the list.

(JSC::EvalExecutable::clearCode):
(JSC::ProgramExecutable::clearCode):
(JSC::FunctionExecutable::clearCode): All we need to do is delete our
CodeBlock -- that will delete all of its internal data structures.

(JSC::FunctionExecutable::clearCodeIfNotCompiling): Factored out a helper
function to improve clarity.

* runtime/Executable.h:
(JSC::ExecutableBase): Moved linked-list stuff
into base class so all executables can be in the list.

(JSC::NativeExecutable::create):
(NativeExecutable):
(ScriptExecutable):
(JSC::ScriptExecutable::finishCreation):
(JSC::EvalExecutable::create):
(EvalExecutable):
(JSC::ProgramExecutable::create):
(ProgramExecutable):
(FunctionExecutable):
(JSC::FunctionExecutable::create): Don't use a finalizer -- the heap
will call us back to destroy our code block.

(JSC::FunctionExecutable::discardCode): Renamed to clearCodeIfNotCompiling()
for clarity.

(JSC::FunctionExecutable::isCompiling): New helper function, for clarity.

(JSC::ScriptExecutable::clearCodeVirtual): New helper function, since
the heap needs to make polymorphic calls to clear code.

* runtime/JSGlobalData.cpp:
(JSC::StackPreservingRecompiler::operator()):
* runtime/JSGlobalObject.cpp:
(JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Updated for
renames.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (119843 => 119844)


--- trunk/Source/_javascript_Core/ChangeLog	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-06-08 18:17:16 UTC (rev 119844)
@@ -1,3 +1,85 @@
+        Don't rely on weak pointers for eager CodeBlock finalization
+        https://bugs.webkit.org/show_bug.cgi?id=88465
+
+        Reviewed by Gavin Barraclough.
+
+        This is incompatible with lazy weak pointer finalization.
+
+        I considered just making CodeBlock finalization lazy-friendly, but it
+        turns out that the heap is already way up in CodeBlock's business when
+        it comes to finalization, so I decided to finish the job and move full
+        responsibility for CodeBlock finalization into the heap.
+
+        * _javascript_Core.vcproj/_javascript_Core/_javascript_Core.def: Maybe this
+        will build.
+
+        * debugger/Debugger.cpp: Updated for rename.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::deleteAllCompiledCode): Renamed for consistency. Fixed a bug
+        where we would not delete code for a code block that had been previously
+        jettisoned. I don't know if this happens in practice -- I mostly did
+        this to improve consistency with deleteUnmarkedCompiledCode.
+
+        (JSC::Heap::deleteUnmarkedCompiledCode): New function, responsible for
+        eager finalization of unmarked code blocks.
+
+        (JSC::Heap::collect): Updated for rename. Updated to call
+        deleteUnmarkedCompiledCode(), which takes care of jettisoned DFG code
+        blocks too.
+
+        (JSC::Heap::addCompiledCode): Renamed, since this points to all code
+        now, not just functions.
+
+        * heap/Heap.h:
+        (Heap): Keep track of all user code, not just functions. This is a
+        negligible additional overhead, since most code is function code.
+
+        * runtime/Executable.cpp:
+        (JSC::*::finalize): Removed these functions, since we don't rely on
+        weak pointer finalization anymore.
+
+        (JSC::FunctionExecutable::FunctionExecutable): Moved linked-list stuff
+        into base class so all executables can be in the list.
+
+        (JSC::EvalExecutable::clearCode):
+        (JSC::ProgramExecutable::clearCode):
+        (JSC::FunctionExecutable::clearCode): All we need to do is delete our
+        CodeBlock -- that will delete all of its internal data structures.
+
+        (JSC::FunctionExecutable::clearCodeIfNotCompiling): Factored out a helper
+        function to improve clarity.
+
+        * runtime/Executable.h:
+        (JSC::ExecutableBase): Moved linked-list stuff
+        into base class so all executables can be in the list.
+
+        (JSC::NativeExecutable::create):
+        (NativeExecutable):
+        (ScriptExecutable):
+        (JSC::ScriptExecutable::finishCreation):
+        (JSC::EvalExecutable::create):
+        (EvalExecutable):
+        (JSC::ProgramExecutable::create):
+        (ProgramExecutable):
+        (FunctionExecutable):
+        (JSC::FunctionExecutable::create): Don't use a finalizer -- the heap
+        will call us back to destroy our code block.
+
+        (JSC::FunctionExecutable::discardCode): Renamed to clearCodeIfNotCompiling()
+        for clarity.
+
+        (JSC::FunctionExecutable::isCompiling): New helper function, for clarity.
+
+        (JSC::ScriptExecutable::clearCodeVirtual): New helper function, since
+        the heap needs to make polymorphic calls to clear code.
+
+        * runtime/JSGlobalData.cpp:
+        (JSC::StackPreservingRecompiler::operator()):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Updated for
+        renames.
+
 2012-06-07  Filip Pizlo  <[email protected]>
 
         DFG should inline prototype chain accesses, and do the right things if the

Modified: trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def (119843 => 119844)


--- trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcproj/_javascript_Core/_javascript_Core.def	2012-06-08 18:17:16 UTC (rev 119844)
@@ -151,7 +151,7 @@
     ?detach@Debugger@JSC@@UAEXPAVJSGlobalObject@2@@Z
     ?detachThread@WTF@@YAXI@Z
     ?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z
-    ?discardAllCompiledCode@Heap@JSC@@QAEXXZ
+    ?deleteAllCompiledCode@Heap@JSC@@QAEXXZ
     ?displayName@JSFunction@JSC@@QAE?BVUString@2@PAVExecState@2@@Z
     ?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z
     ?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z

Modified: trunk/Source/_javascript_Core/debugger/Debugger.cpp (119843 => 119844)


--- trunk/Source/_javascript_Core/debugger/Debugger.cpp	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/debugger/Debugger.cpp	2012-06-08 18:17:16 UTC (rev 119844)
@@ -79,7 +79,7 @@
         return;
 
     ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec();
-    executable->discardCode();
+    executable->clearCodeIfNotCompiling();
     if (m_debugger == function->scope()->globalObject->debugger())
         m_sourceProviders.add(executable->source().provider(), exec);
 }

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (119843 => 119844)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2012-06-08 18:17:16 UTC (rev 119844)
@@ -643,17 +643,40 @@
     return m_objectSpace.forEachCell<RecordType>();
 }
 
-void Heap::discardAllCompiledCode()
+void Heap::deleteAllCompiledCode()
 {
-    // If _javascript_ is running, it's not safe to recompile, since we'll end
-    // up throwing away code that is live on the stack.
+    // If _javascript_ is running, it's not safe to delete code, since we'll end
+    // up deleting code that is live on the stack.
     if (m_globalData->dynamicGlobalObject)
         return;
 
-    for (FunctionExecutable* current = m_functions.head(); current; current = current->next())
-        current->discardCode();
+    for (ExecutableBase* current = m_compiledCode.head(); current; current = current->next()) {
+        if (!current->isFunctionExecutable())
+            continue;
+        static_cast<FunctionExecutable*>(current)->clearCodeIfNotCompiling();
+    }
+
+    m_dfgCodeBlocks.clearMarks();
+    m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
 }
 
+void Heap::deleteUnmarkedCompiledCode()
+{
+    ExecutableBase* next;
+    for (ExecutableBase* current = m_compiledCode.head(); current; current = next) {
+        next = current->next();
+        if (isMarked(current))
+            continue;
+
+        // We do this because executable memory is limited on some platforms and because
+        // CodeBlock requires eager finalization.
+        ExecutableBase::clearCodeVirtual(current);
+        m_compiledCode.remove(current);
+    }
+
+    m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+}
+
 void Heap::collectAllGarbage()
 {
     if (!m_isSafeToCollect)
@@ -680,7 +703,7 @@
 
     double lastGCStartTime = WTF::currentTime();
     if (lastGCStartTime - m_lastCodeDiscardTime > minute) {
-        discardAllCompiledCode();
+        deleteAllCompiledCode();
         m_lastCodeDiscardTime = WTF::currentTime();
     }
 
@@ -703,6 +726,8 @@
         m_objectSpace.reapWeakSets();
     }
 
+    _javascript_CORE_GC_MARKED();
+
     {
         GCPHASE(FinalizeUnconditionalFinalizers);
         finalizeUnconditionalFinalizers();
@@ -713,12 +738,10 @@
         m_objectSpace.sweepWeakSets();
         m_globalData->smallStrings.finalizeSmallStrings();
     }
-    
-    _javascript_CORE_GC_MARKED();
 
     {
         GCPHASE(DeleteCodeBlocks);
-        m_dfgCodeBlocks.deleteUnmarkedJettisonedCodeBlocks();
+        deleteUnmarkedCompiledCode();
     }
 
     if (sweepToggle == DoSweep) {
@@ -808,14 +831,9 @@
     WeakSet::deallocate(WeakImpl::asWeakImpl(slot));
 }
 
-void Heap::addFunctionExecutable(FunctionExecutable* executable)
+void Heap::addCompiledCode(ExecutableBase* executable)
 {
-    m_functions.append(executable);
+    m_compiledCode.append(executable);
 }
 
-void Heap::removeFunctionExecutable(FunctionExecutable* executable)
-{
-    m_functions.remove(executable);
-}
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/Heap.h (119843 => 119844)


--- trunk/Source/_javascript_Core/heap/Heap.h	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/heap/Heap.h	2012-06-08 18:17:16 UTC (rev 119844)
@@ -42,7 +42,7 @@
 
     class CopiedSpace;
     class CodeBlock;
-    class FunctionExecutable;
+    class ExecutableBase;
     class GCActivityCallback;
     class GlobalCodeBlock;
     class Heap;
@@ -116,8 +116,7 @@
 
         typedef void (*Finalizer)(JSCell*);
         JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer);
-        void addFunctionExecutable(FunctionExecutable*);
-        void removeFunctionExecutable(FunctionExecutable*);
+        void addCompiledCode(ExecutableBase*);
 
         void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
 
@@ -159,7 +158,7 @@
         double lastGCLength() { return m_lastGCLength; }
         void increaseLastGCLength(double amount) { m_lastGCLength += amount; }
 
-        JS_EXPORT_PRIVATE void discardAllCompiledCode();
+        JS_EXPORT_PRIVATE void deleteAllCompiledCode();
 
         void didAllocate(size_t);
         void didAbandon(size_t);
@@ -194,6 +193,7 @@
         void markTempSortVectors(HeapRootVisitor&);
         void harvestWeakReferences();
         void finalizeUnconditionalFinalizers();
+        void deleteUnmarkedCompiledCode();
         
         RegisterFile& registerFile();
         BlockAllocator& blockAllocator();
@@ -239,7 +239,7 @@
         double m_lastGCLength;
         double m_lastCodeDiscardTime;
 
-        DoublyLinkedList<FunctionExecutable> m_functions;
+        DoublyLinkedList<ExecutableBase> m_compiledCode;
     };
 
     inline bool Heap::shouldCollect()

Modified: trunk/Source/_javascript_Core/runtime/Executable.cpp (119843 => 119844)


--- trunk/Source/_javascript_Core/runtime/Executable.cpp	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/runtime/Executable.cpp	2012-06-08 18:17:16 UTC (rev 119844)
@@ -47,7 +47,7 @@
 }
 #endif
 
-inline void ExecutableBase::clearCode()
+void ExecutableBase::clearCode()
 {
 #if ENABLE(JIT)
     m_jitCodeForCall.clear();
@@ -98,11 +98,6 @@
 }
 #endif
 
-void NativeExecutable::finalize(JSCell* cell)
-{
-    jsCast<NativeExecutable*>(cell)->clearCode();
-}
-
 const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
 
 #if ENABLE(JIT)
@@ -146,8 +141,6 @@
     , m_name(name)
     , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName)
     , m_symbolTable(0)
-    , m_next(0)
-    , m_prev(0)
 {
 }
 
@@ -159,8 +152,6 @@
     , m_name(name)
     , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName)
     , m_symbolTable(0)
-    , m_next(0)
-    , m_prev(0)
 {
 }
 
@@ -292,17 +283,9 @@
 #endif
 }
 
-void EvalExecutable::finalize(JSCell* cell)
+void EvalExecutable::clearCode()
 {
-    jsCast<EvalExecutable*>(cell)->clearCode();
-}
-
-inline void EvalExecutable::clearCode()
-{
-    if (m_evalCodeBlock) {
-        m_evalCodeBlock->clearEvalCache();
-        m_evalCodeBlock.clear();
-    }
+    m_evalCodeBlock.clear();
     Base::clearCode();
 }
 
@@ -424,17 +407,9 @@
         thisObject->m_programCodeBlock->visitAggregate(visitor);
 }
 
-void ProgramExecutable::finalize(JSCell* cell)
+void ProgramExecutable::clearCode()
 {
-    jsCast<ProgramExecutable*>(cell)->clearCode();
-}
-
-inline void ProgramExecutable::clearCode()
-{
-    if (m_programCodeBlock) {
-        m_programCodeBlock->clearEvalCache();
-        m_programCodeBlock.clear();
-    }
+    m_programCodeBlock.clear();
     Base::clearCode();
 }
 
@@ -642,37 +617,17 @@
         thisObject->m_codeBlockForConstruct->visitAggregate(visitor);
 }
 
-void FunctionExecutable::discardCode()
+void FunctionExecutable::clearCodeIfNotCompiling()
 {
-#if ENABLE(JIT)
-    // These first two checks are to handle the rare case where
-    // we are trying to evict code for a function during its
-    // codegen.
-    if (!m_jitCodeForCall && m_codeBlockForCall)
+    if (isCompiling())
         return;
-    if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
-        return;
-#endif
     clearCode();
 }
 
-void FunctionExecutable::finalize(JSCell* cell)
+void FunctionExecutable::clearCode()
 {
-    FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
-    Heap::heap(executable)->removeFunctionExecutable(executable);
-    executable->clearCode();
-}
-
-inline void FunctionExecutable::clearCode()
-{
-    if (m_codeBlockForCall) {
-        m_codeBlockForCall->clearEvalCache();
-        m_codeBlockForCall.clear();
-    }
-    if (m_codeBlockForConstruct) {
-        m_codeBlockForConstruct->clearEvalCache();
-        m_codeBlockForConstruct.clear();
-    }
+    m_codeBlockForCall.clear();
+    m_codeBlockForConstruct.clear();
     Base::clearCode();
 }
 

Modified: trunk/Source/_javascript_Core/runtime/Executable.h (119843 => 119844)


--- trunk/Source/_javascript_Core/runtime/Executable.h	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/runtime/Executable.h	2012-06-08 18:17:16 UTC (rev 119844)
@@ -54,7 +54,8 @@
         return false;
     }
 
-    class ExecutableBase : public JSCell {
+    class ExecutableBase : public JSCell, public DoublyLinkedListNode<ExecutableBase> {
+        friend class WTF::DoublyLinkedListNode<ExecutableBase>;
         friend class JIT;
 
     protected:
@@ -80,6 +81,11 @@
         static void destroy(JSCell*);
 #endif
 
+        bool isFunctionExecutable()
+        {
+            return structure()->typeInfo().type() == FunctionExecutableType;
+        }
+
         bool isHostFunction() const
         {
             ASSERT((m_numParametersForCall == NUM_PARAMETERS_IS_HOST) == (m_numParametersForConstruct == NUM_PARAMETERS_IS_HOST));
@@ -88,6 +94,8 @@
 
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(globalData, globalObject, proto, TypeInfo(CompoundType, StructureFlags), &s_info); }
         
+        void clearCode();
+
         static JS_EXPORTDATA const ClassInfo s_info;
 
     protected:
@@ -97,6 +105,8 @@
 
 #if ENABLE(JIT)
     public:
+        static void clearCodeVirtual(ExecutableBase*);
+
         JITCode& generatedJITCodeForCall()
         {
             ASSERT(m_jitCodeForCall);
@@ -168,12 +178,14 @@
         }
 
     protected:
+        ExecutableBase* m_prev;
+        ExecutableBase* m_next;
+
         JITCode m_jitCodeForCall;
         JITCode m_jitCodeForConstruct;
         MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
         MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
 #endif
-        void clearCode();
     };
 
     class NativeExecutable : public ExecutableBase {
@@ -194,7 +206,6 @@
                 executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
                 executable->finishCreation(globalData, JITCode::HostFunction(callThunk), JITCode::HostFunction(constructThunk), intrinsic);
             }
-            globalData.heap.addFinalizer(executable, &finalize);
             return executable;
         }
 #endif
@@ -205,7 +216,6 @@
             ASSERT(!globalData.canUseJIT());
             NativeExecutable* executable = new (NotNull, allocateCell<NativeExecutable>(globalData.heap)) NativeExecutable(globalData, function, constructor);
             executable->finishCreation(globalData);
-            globalData.heap.addFinalizer(executable, &finalize);
             return executable;
         }
 #endif
@@ -246,8 +256,6 @@
         }
 #endif
 
-        static void finalize(JSCell*);
- 
     private:
         NativeExecutable(JSGlobalData& globalData, NativeFunction function, NativeFunction constructor)
             : ExecutableBase(globalData, globalData.nativeExecutableStructure.get(), NUM_PARAMETERS_IS_HOST)
@@ -303,6 +311,8 @@
         void finishCreation(JSGlobalData& globalData)
         {
             Base::finishCreation(globalData);
+            globalData.heap.addCompiledCode(this); // Balanced by Heap::deleteUnmarkedCompiledCode().
+
 #if ENABLE(CODEBLOCK_SAMPLING)
             if (SamplingTool* sampler = globalData.interpreter->sampler())
                 sampler->notifyOfScope(globalData, this);
@@ -358,7 +368,6 @@
         {
             EvalExecutable* executable = new (NotNull, allocateCell<EvalExecutable>(*exec->heap())) EvalExecutable(exec, source, isInStrictContext);
             executable->finishCreation(exec->globalData());
-            exec->globalData().heap.addFinalizer(executable, &finalize);
             return executable;
         }
 
@@ -377,9 +386,7 @@
 
         void unlinkCalls();
 
-    protected:
         void clearCode();
-        static void finalize(JSCell*);
 
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
@@ -400,7 +407,6 @@
         {
             ProgramExecutable* executable = new (NotNull, allocateCell<ProgramExecutable>(*exec->heap())) ProgramExecutable(exec, source);
             executable->finishCreation(exec->globalData());
-            exec->globalData().heap.addFinalizer(executable, &finalize);
             return executable;
         }
 
@@ -447,9 +453,7 @@
         
         void unlinkCalls();
 
-    protected:
         void clearCode();
-        static void finalize(JSCell*);
 
     private:
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
@@ -461,10 +465,9 @@
         OwnPtr<ProgramCodeBlock> m_programCodeBlock;
     };
 
-    class FunctionExecutable : public ScriptExecutable, public DoublyLinkedListNode<FunctionExecutable> {
+    class FunctionExecutable : public ScriptExecutable {
         friend class JIT;
         friend class LLIntOffsetsExtractor;
-        friend class WTF::DoublyLinkedListNode<FunctionExecutable>;
     public:
         typedef ScriptExecutable Base;
 
@@ -472,8 +475,6 @@
         {
             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,8 +482,6 @@
         {
             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;
         }
 
@@ -639,7 +638,7 @@
         UString paramString() const;
         SharedSymbolTable* symbolTable() const { return m_symbolTable; }
 
-        void discardCode();
+        void clearCodeIfNotCompiling();
         static void visitChildren(JSCell*, SlotVisitor&);
         static FunctionExecutable* fromGlobalCode(const Identifier&, ExecState*, Debugger*, const SourceCode&, JSObject** exception);
         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto)
@@ -651,10 +650,9 @@
         
         void unlinkCalls();
 
-    protected:
         void clearCode();
-        static void finalize(JSCell*);
 
+    protected:
         void finishCreation(JSGlobalData& globalData, const Identifier& name, int firstLine, int lastLine)
         {
             Base::finishCreation(globalData);
@@ -677,7 +675,18 @@
             ASSERT(kind == CodeForConstruct);
             return m_codeBlockForConstruct;
         }
-        
+ 
+        bool isCompiling()
+        {
+#if ENABLE(JIT)
+            if (!m_jitCodeForCall && m_codeBlockForCall)
+                return true;
+            if (!m_jitCodeForConstruct && m_codeBlockForConstruct)
+                return true;
+#endif
+            return false;
+        }
+
         static const unsigned StructureFlags = OverridesVisitChildren | ScriptExecutable::StructureFlags;
         unsigned m_numCapturedVariables : 31;
         bool m_forceUsesArguments : 1;
@@ -689,8 +698,6 @@
         Identifier m_inferredName;
         WriteBarrier<JSString> m_nameValue;
         SharedSymbolTable* m_symbolTable;
-        FunctionExecutable* m_next;
-        FunctionExecutable* m_prev;
     };
 
     inline FunctionExecutable* JSFunction::jsExecutable() const
@@ -725,6 +732,20 @@
         return function->nativeFunction() == nativeFunction;
     }
 
+    inline void ExecutableBase::clearCodeVirtual(ExecutableBase* executable)
+    {
+        switch (executable->structure()->typeInfo().type()) {
+        case EvalExecutableType:
+            return jsCast<EvalExecutable*>(executable)->clearCode();
+        case ProgramExecutableType:
+            return jsCast<ProgramExecutable*>(executable)->clearCode();
+        case FunctionExecutableType:
+            return jsCast<FunctionExecutable*>(executable)->clearCode();
+        default:
+            return jsCast<NativeExecutable*>(executable)->clearCode();
+        }
+    }
+
     inline void ScriptExecutable::unlinkCalls()
     {
         switch (structure()->typeInfo().type()) {

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp (119843 => 119844)


--- trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalData.cpp	2012-06-08 18:17:16 UTC (rev 119844)
@@ -419,7 +419,7 @@
         FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell);
         if (currentlyExecutingFunctions.contains(executable))
             return;
-        executable->discardCode();
+        executable->clearCodeIfNotCompiling();
     }
 };
 

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (119843 => 119844)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2012-06-08 18:14:55 UTC (rev 119843)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2012-06-08 18:17:16 UTC (rev 119844)
@@ -443,7 +443,7 @@
     if (!m_dynamicGlobalObjectSlot) {
 #if ENABLE(ASSEMBLER)
         if (ExecutableAllocator::underMemoryPressure())
-            globalData.heap.discardAllCompiledCode();
+            globalData.heap.deleteAllCompiledCode();
 #endif
 
         m_dynamicGlobalObjectSlot = dynamicGlobalObject;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to