2011-05-19 Oliver Hunt <oliver@apple.com>
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 May 2011 20:18:39 +0000 (20:18 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 19 May 2011 20:18:39 +0000 (20:18 +0000)
        Reviewed by Geoffrey Garen.

        Make Executables release their JIT code as soon as they become dead
        https://bugs.webkit.org/show_bug.cgi?id=61134

        Add an ability to clear an Executable's jit code without requiring
        it to be destroyed, and then call that from a finalizer.

        * heap/Weak.h:
        (JSC::Weak::Weak):
        (JSC::Weak::leak):
        * jit/JITCode.h:
        (JSC::JITCode::clear):
        * runtime/Executable.cpp:
        (JSC::ExecutableFinalizer::finalize):
        (JSC::ExecutableBase::executableFinalizer):
        * runtime/Executable.h:
        (JSC::ExecutableBase::ExecutableBase):
        (JSC::ExecutableBase::clearExecutableCode):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@86883 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/heap/Handle.h
Source/JavaScriptCore/heap/HandleHeap.h
Source/JavaScriptCore/heap/Weak.h
Source/JavaScriptCore/jit/JITCode.h
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h

index 228043d..e02bf2f 100644 (file)
@@ -1,3 +1,25 @@
+2011-05-19  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Geoffrey Garen.
+
+        Make Executables release their JIT code as soon as they become dead
+        https://bugs.webkit.org/show_bug.cgi?id=61134
+
+        Add an ability to clear an Executable's jit code without requiring
+        it to be destroyed, and then call that from a finalizer.
+
+        * heap/Weak.h:
+        (JSC::Weak::Weak):
+        (JSC::Weak::leak):
+        * jit/JITCode.h:
+        (JSC::JITCode::clear):
+        * runtime/Executable.cpp:
+        (JSC::ExecutableFinalizer::finalize):
+        (JSC::ExecutableBase::executableFinalizer):
+        * runtime/Executable.h:
+        (JSC::ExecutableBase::ExecutableBase):
+        (JSC::ExecutableBase::clearExecutableCode):
+
 2011-05-19  Adam Roben  <aroben@apple.com>
 
         Remove a redundant and broken data export
index 5fc5f2a..8ed2623 100644 (file)
@@ -47,6 +47,7 @@ template <> class Handle<JSValue>;
 template<typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> class WeakGCMap;
 
 class HandleBase {
+    template <typename T> friend class Weak;
     friend class HandleHeap;
     friend struct JSCallbackObjectData;
     template <typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> friend class WeakGCMap;
index 5c151c3..41b7fb2 100644 (file)
@@ -70,6 +70,7 @@ public:
 
 #if !ASSERT_DISABLED
     bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
+    bool hasFinalizer(HandleSlot);
 #endif
 
     unsigned protectedGlobalObjectCount();
@@ -197,6 +198,11 @@ inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwn
 {
     return toNode(handle)->weakOwner() == weakOwner;
 }
+
+inline bool HandleHeap::hasFinalizer(HandleSlot handle)
+{
+    return toNode(handle)->weakOwner();
+}
 #endif
 
 inline HandleHeap::Node::Node(HandleHeap* handleHeap)
index 62e2596..a235a57 100644 (file)
@@ -53,6 +53,13 @@ public:
         set(value);
     }
 
+    enum AdoptTag { Adopt };
+    template<typename U> Weak(AdoptTag, Handle<U> handle)
+        : Handle<T>(handle.slot())
+    {
+        validateCell(get());
+    }
+    
     Weak(const Weak& other)
         : Handle<T>()
     {
@@ -121,6 +128,14 @@ public:
             setSlot(HandleHeap::heapFor(other.slot())->copyWeak(other.slot()));
         return *this;
     }
+    
+    HandleSlot leakHandle()
+    {
+        ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot()));
+        HandleSlot result = slot();
+        setSlot(0);
+        return result;
+    }
 
 private:
     static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); }
index 7346fd5..082d2a7 100644 (file)
@@ -101,6 +101,12 @@ namespace JSC {
             return JITCode(code.dataLocation(), 0, 0);
         }
 
+        void clear()
+        {
+            m_ref.~CodeRef();
+            new (&m_ref) CodeRef();
+        }
+
     private:
         JITCode(void* code, PassRefPtr<ExecutablePool> executablePool, size_t size)
             : m_ref(code, executablePool, size)
index 1138759..8ab422b 100644 (file)
@@ -42,6 +42,22 @@ namespace JSC {
 
 const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, 0 };
 
+#if ENABLE(JIT)
+class ExecutableFinalizer : public WeakHandleOwner {
+    virtual void finalize(Handle<Unknown> handle, void*)
+    {
+        Weak<ExecutableBase> executable(Weak<ExecutableBase>::Adopt, handle);
+        executable->clearExecutableCode();
+    }
+};
+
+WeakHandleOwner* ExecutableBase::executableFinalizer()
+{
+    DEFINE_STATIC_LOCAL(ExecutableFinalizer, finalizer, ());
+    return &finalizer;
+}
+#endif
+    
 const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, 0 };
 
 NativeExecutable::~NativeExecutable()
index 692e347..70e5e61 100644 (file)
@@ -57,6 +57,10 @@ namespace JSC {
             , m_numParametersForCall(numParameters)
             , m_numParametersForConstruct(numParameters)
         {
+#if ENABLE(JIT)
+            Weak<ExecutableBase> finalizer(globalData, this, executableFinalizer());
+            finalizer.leakHandle();
+#endif
         }
 
         bool isHostFunction() const
@@ -88,11 +92,20 @@ namespace JSC {
             return m_jitCodeForConstruct;
         }
 
+        void clearExecutableCode()
+        {
+            m_jitCodeForCall.clear();
+            m_jitCodeForConstruct.clear();
+        }
+
     protected:
         JITCode m_jitCodeForCall;
         JITCode m_jitCodeForConstruct;
         MacroAssemblerCodePtr m_jitCodeForCallWithArityCheck;
         MacroAssemblerCodePtr m_jitCodeForConstructWithArityCheck;
+        
+    private:
+        static WeakHandleOwner* executableFinalizer();
 #endif
     };