Unreviewed, rolling out r203703.
authorbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Jul 2016 01:05:43 +0000 (01:05 +0000)
committerbenjamin@webkit.org <benjamin@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 26 Jul 2016 01:05:43 +0000 (01:05 +0000)
It breaks some internal tests

Reverted changeset:

"[JSC] DFG::Node should not have its own allocator"
https://bugs.webkit.org/show_bug.cgi?id=160098
http://trac.webkit.org/changeset/203703

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

27 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/b3/B3SparseCollection.h
Source/JavaScriptCore/dfg/DFGAllocator.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
Source/JavaScriptCore/dfg/DFGCleanUpPhase.cpp
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGConstantHoistingPhase.cpp
Source/JavaScriptCore/dfg/DFGDCEPhase.cpp
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGLICMPhase.cpp
Source/JavaScriptCore/dfg/DFGLongLivedState.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGLongLivedState.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGNode.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeAllocator.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGPlan.h
Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp
Source/JavaScriptCore/dfg/DFGWorklist.cpp
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h

index e267f74..f8f2309 100644 (file)
@@ -312,6 +312,7 @@ set(JavaScriptCore_SOURCES
     dfg/DFGLazyJSValue.cpp
     dfg/DFGLazyNode.cpp
     dfg/DFGLivenessAnalysisPhase.cpp
+    dfg/DFGLongLivedState.cpp
     dfg/DFGLoopPreHeaderCreationPhase.cpp
     dfg/DFGMaximalFlushInsertionPhase.cpp
     dfg/DFGMayExit.cpp
index 9d93ad2..c0caa4a 100644 (file)
@@ -1,3 +1,15 @@
+2016-07-25  Benjamin Poulain  <benjamin@webkit.org>
+
+        Unreviewed, rolling out r203703.
+
+        It breaks some internal tests
+
+        Reverted changeset:
+
+        "[JSC] DFG::Node should not have its own allocator"
+        https://bugs.webkit.org/show_bug.cgi?id=160098
+        http://trac.webkit.org/changeset/203703
+
 2016-07-25  Benjamin Poulain  <bpoulain@apple.com>
 
         [JSC] DFG::Node should not have its own allocator
index 958dea7..c31b397 100644 (file)
                0FEFC9AB1681A3B600567F53 /* DFGOSRExitJumpPlaceholder.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FEFC9A81681A3B000567F53 /* DFGOSRExitJumpPlaceholder.h */; };
                0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FF054F71AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp */; };
                0FF054FA1AC35B4400E5BE57 /* ExecutableAllocationFuzz.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF054F81AC35B4400E5BE57 /* ExecutableAllocationFuzz.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0FF0F19916B729F6005DF95B /* DFGLongLivedState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB4B51C16B62772003F696B /* DFGLongLivedState.cpp */; };
+               0FF0F19B16B729FA005DF95B /* DFGLongLivedState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51D16B62772003F696B /* DFGLongLivedState.h */; };
                0FF0F19C16B72A03005DF95B /* DFGNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB4B51E16B62772003F696B /* DFGNode.cpp */; };
                0FF0F19D16B72A08005DF95B /* DFGCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB4B51A16B62772003F696B /* DFGCommon.cpp */; };
                0FF0F19E16B72A0B005DF95B /* DFGEdge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB4B51B16B62772003F696B /* DFGEdge.cpp */; };
                0FFA549816B8835300B3A982 /* A64DOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 652A3A231651C69700A80AFE /* A64DOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FFB6C381AF48DDC00DB1BF7 /* TypeofType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */; };
                0FFB6C391AF48DDC00DB1BF7 /* TypeofType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0FFB921816D02EB20055A5DB /* DFGAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51916B62772003F696B /* DFGAllocator.h */; };
                0FFB921A16D02EC50055A5DB /* DFGBasicBlockInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD5652216AB780A00197653 /* DFGBasicBlockInlines.h */; };
+               0FFB921B16D02F010055A5DB /* DFGNodeAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51F16B62772003F696B /* DFGNodeAllocator.h */; };
                0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; };
                0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; };
                0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FB387911BFD31A100E3AB1E /* FTLCompile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLCompile.cpp; path = ftl/FTLCompile.cpp; sourceTree = "<group>"; };
                0FB438A219270B1D00E1FBC9 /* StructureSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureSet.cpp; sourceTree = "<group>"; };
                0FB4B51016B3A964003F696B /* DFGMinifiedID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGMinifiedID.h; path = dfg/DFGMinifiedID.h; sourceTree = "<group>"; };
+               0FB4B51916B62772003F696B /* DFGAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAllocator.h; path = dfg/DFGAllocator.h; sourceTree = "<group>"; };
                0FB4B51A16B62772003F696B /* DFGCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCommon.cpp; path = dfg/DFGCommon.cpp; sourceTree = "<group>"; };
                0FB4B51B16B62772003F696B /* DFGEdge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGEdge.cpp; path = dfg/DFGEdge.cpp; sourceTree = "<group>"; };
+               0FB4B51C16B62772003F696B /* DFGLongLivedState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLongLivedState.cpp; path = dfg/DFGLongLivedState.cpp; sourceTree = "<group>"; };
+               0FB4B51D16B62772003F696B /* DFGLongLivedState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLongLivedState.h; path = dfg/DFGLongLivedState.h; sourceTree = "<group>"; };
                0FB4B51E16B62772003F696B /* DFGNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNode.cpp; path = dfg/DFGNode.cpp; sourceTree = "<group>"; };
+               0FB4B51F16B62772003F696B /* DFGNodeAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeAllocator.h; path = dfg/DFGNodeAllocator.h; sourceTree = "<group>"; };
                0FB4B52116B6278D003F696B /* FunctionExecutableDump.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionExecutableDump.cpp; sourceTree = "<group>"; };
                0FB4B52216B6278D003F696B /* FunctionExecutableDump.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionExecutableDump.h; sourceTree = "<group>"; };
                0FB4FB701BC843140025CA5A /* FTLLazySlowPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLLazySlowPath.cpp; path = ftl/FTLLazySlowPath.cpp; sourceTree = "<group>"; };
                                0F18D3CD1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.cpp */,
                                0F18D3CE1B55A6E0002C5C9F /* DFGAdaptiveStructureWatchpoint.h */,
                                0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */,
+                               0FB4B51916B62772003F696B /* DFGAllocator.h */,
                                0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */,
                                0F2DD80C1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.cpp */,
                                0F2DD80D1AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h */,
                                79C4B15C1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h */,
                                A7D89CEC17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.cpp */,
                                A7D89CED17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.h */,
+                               0FB4B51C16B62772003F696B /* DFGLongLivedState.cpp */,
+                               0FB4B51D16B62772003F696B /* DFGLongLivedState.h */,
                                A767B5B317A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp */,
                                A767B5B417A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h */,
                                79F8FC1C1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp */,
                                A737810B1799EA2E00817533 /* DFGNaturalLoops.h */,
                                0FB4B51E16B62772003F696B /* DFGNode.cpp */,
                                86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */,
+                               0FB4B51F16B62772003F696B /* DFGNodeAllocator.h */,
                                0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */,
                                0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */,
                                0F5D085C1B8CF99D001143B4 /* DFGNodeOrigin.cpp */,
                                998ED6751BED768C00DD8017 /* RemoteControllableTarget.h in Headers */,
                                0F33FCF81C136E2500323F67 /* B3StackmapGenerationParams.h in Headers */,
                                0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */,
+                               0FFB921816D02EB20055A5DB /* DFGAllocator.h in Headers */,
                                0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */,
                                0F2DD8121AB3D8BE00BBB8E8 /* DFGArgumentsEliminationPhase.h in Headers */,
                                0F2DD8141AB3D8BE00BBB8E8 /* DFGArgumentsUtilities.h in Headers */,
                                99D6A1161BEAD34D00E25C37 /* RemoteAutomationTarget.h in Headers */,
                                79C4B15E1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.h in Headers */,
                                A7D89CFC17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.h in Headers */,
+                               0FF0F19B16B729FA005DF95B /* DFGLongLivedState.h in Headers */,
                                0F338DF21BE93AD10013C88F /* B3StackmapValue.h in Headers */,
                                A767B5B617A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h in Headers */,
                                79F8FC1F1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.h in Headers */,
                                0FF2CD5C1B61A4F8004955A8 /* DFGMultiGetByOffsetData.h in Headers */,
                                A737810E1799EA2E00817533 /* DFGNaturalLoops.h in Headers */,
                                86ECA3EA132DEF1C002B2AD7 /* DFGNode.h in Headers */,
+                               0FFB921B16D02F010055A5DB /* DFGNodeAllocator.h in Headers */,
                                70B791931C024A28002481E2 /* GeneratorFrame.h in Headers */,
                                0FA581BB150E953000B9A2D9 /* DFGNodeFlags.h in Headers */,
                                0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */,
                                A7D9A29717A0BC7400EE2618 /* DFGLICMPhase.cpp in Sources */,
                                79C4B15D1BA2158F00FD592E /* DFGLiveCatchVariablePreservationPhase.cpp in Sources */,
                                A7D89CFB17A0B8CC00773AD8 /* DFGLivenessAnalysisPhase.cpp in Sources */,
+                               0FF0F19916B729F6005DF95B /* DFGLongLivedState.cpp in Sources */,
                                A767B5B517A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp in Sources */,
                                79F8FC1E1B9FED0F00CA66AB /* DFGMaximalFlushInsertionPhase.cpp in Sources */,
                                0F5874ED194FEB1200AAB2C1 /* DFGMayExit.cpp in Sources */,
index 0c1f9ac..d027a48 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef B3SparseCollection_h
 #define B3SparseCollection_h
 
+#if ENABLE(B3_JIT)
+
 #include <wtf/StdLibExtras.h>
 #include <wtf/Vector.h>
 
@@ -138,5 +140,7 @@ private:
 
 } } // namespace JSC::B3
 
+#endif // ENABLE(B3_JIT)
+
 #endif // B3SparseCollection_h
 
diff --git a/Source/JavaScriptCore/dfg/DFGAllocator.h b/Source/JavaScriptCore/dfg/DFGAllocator.h
new file mode 100644 (file)
index 0000000..f380df0
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGAllocator_h
+#define DFGAllocator_h
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGCommon.h"
+#include <wtf/StdLibExtras.h>
+
+namespace JSC { namespace DFG {
+
+// Custom pool allocator for exactly one type (type T). It has fast (O(1), only a few
+// instructions) allocator, and a similarly fast free(). Recycling works if either of
+// the following is true:
+// - T has a trivial destructor. In that case you don't have to ever call free() on
+//   anything. You can just call freeAll() instead.
+// - You call free() on all T's that you allocated, and never use freeAll().
+
+template<typename T>
+class Allocator {
+public:
+    Allocator();
+    ~Allocator();
+    
+    void* allocate(); // Use placement new to allocate, and avoid using this method.
+    void free(T*); // Call this method to delete; never use 'delete' directly.
+    
+    void freeAll(); // Only call this if you've either freed everything or if T has a trivial destructor.
+    void reset(); // Like freeAll(), but also returns all memory to the OS.
+    
+    unsigned indexOf(const T*);
+    
+    static Allocator* allocatorOf(const T*);
+    
+private:
+    void* bumpAllocate();
+    void* freeListAllocate();
+    void* allocateSlow();
+
+    struct Region {
+        static size_t size() { return 64 * KB; }
+        static size_t headerSize() { return std::max(sizeof(Region), sizeof(T)); }
+        static unsigned numberOfThingsPerRegion() { return (size() - headerSize()) / sizeof(T); }
+        T* data() { return bitwise_cast<T*>(bitwise_cast<char*>(this) + headerSize()); }
+        bool isInThisRegion(const T* pointer) { return static_cast<unsigned>(pointer - data()) < numberOfThingsPerRegion(); }
+        static Region* regionFor(const T* pointer) { return bitwise_cast<Region*>(bitwise_cast<uintptr_t>(pointer) & ~(size() - 1)); }
+        
+        void* m_allocation;
+        Allocator* m_allocator;
+        Region* m_next;
+    };
+    
+    void freeRegionsStartingAt(Region*);
+    void startBumpingIn(Region*);
+    
+    Region* m_regionHead;
+    void** m_freeListHead;
+    T* m_bumpEnd;
+    unsigned m_bumpRemaining;
+};
+
+template<typename T>
+inline Allocator<T>::Allocator()
+    : m_regionHead(0)
+    , m_freeListHead(0)
+    , m_bumpRemaining(0)
+{
+}
+
+template<typename T>
+inline Allocator<T>::~Allocator()
+{
+    reset();
+}
+
+template<typename T>
+ALWAYS_INLINE void* Allocator<T>::allocate()
+{
+    void* result = bumpAllocate();
+    if (LIKELY(!!result))
+        return result;
+    return freeListAllocate();
+}
+
+template<typename T>
+void Allocator<T>::free(T* object)
+{
+    object->~T();
+    
+    void** cell = bitwise_cast<void**>(object);
+    *cell = m_freeListHead;
+    m_freeListHead = cell;
+}
+
+template<typename T>
+void Allocator<T>::freeAll()
+{
+    if (!m_regionHead) {
+        ASSERT(!m_bumpRemaining);
+        ASSERT(!m_freeListHead);
+        return;
+    }
+    
+    // Since the caller is opting out of calling the destructor for any allocated thing,
+    // we have two choices, plus a continuum between: we can either just delete all regions
+    // (i.e. call reset()), or we can make all regions available for reuse. We do something
+    // that optimizes for (a) speed of freeAll(), (b) the assumption that if the user calls
+    // freeAll() then they will probably be calling allocate() in the near future. Namely,
+    // we free all but one region, and make the remaining region a bump allocation region.
+    
+    freeRegionsStartingAt(m_regionHead->m_next);
+    
+    m_regionHead->m_next = 0;
+    m_freeListHead = 0;
+    startBumpingIn(m_regionHead);
+}
+
+template<typename T>
+void Allocator<T>::reset()
+{
+    freeRegionsStartingAt(m_regionHead);
+    
+    m_regionHead = 0;
+    m_freeListHead = 0;
+    m_bumpRemaining = 0;
+}
+
+template<typename T>
+unsigned Allocator<T>::indexOf(const T* object)
+{
+    unsigned numRegions = 0;
+    for (Region* region = m_regionHead; region; region = region->m_next)
+        numRegions++;
+    unsigned regionIndex = 0;
+    for (Region* region = m_regionHead; region; region = region->m_next) {
+        if (region->isInThisRegion(object))
+            return (numRegions - 1 - regionIndex) * Region::numberOfThingsPerRegion() + (object - region->data());
+        regionIndex++;
+    }
+    CRASH();
+    return 0;
+}
+
+template<typename T>
+Allocator<T>* Allocator<T>::allocatorOf(const T* object)
+{
+    return Region::regionFor(object)->m_allocator;
+}
+
+template<typename T>
+ALWAYS_INLINE void* Allocator<T>::bumpAllocate()
+{
+    if (unsigned remaining = m_bumpRemaining) {
+        remaining--;
+        m_bumpRemaining = remaining;
+        return m_bumpEnd - (remaining + 1);
+    }
+    return 0;
+}
+
+template<typename T>
+void* Allocator<T>::freeListAllocate()
+{
+    void** result = m_freeListHead;
+    if (UNLIKELY(!result))
+        return allocateSlow();
+    m_freeListHead = bitwise_cast<void**>(*result);
+    return result;
+}
+
+template<typename T>
+void* Allocator<T>::allocateSlow()
+{
+    ASSERT(!m_freeListHead);
+    ASSERT(!m_bumpRemaining);
+    
+    if (logCompilationChanges())
+        dataLog("Allocating another allocator region.\n");
+
+    void* allocation = fastAlignedMalloc(Region::size(), Region::size());
+    Region* region = static_cast<Region*>(allocation);
+    region->m_allocation = allocation;
+    region->m_allocator = this;
+    startBumpingIn(region);
+    region->m_next = m_regionHead;
+    m_regionHead = region;
+    
+    void* result = bumpAllocate();
+    ASSERT(result);
+    return result;
+}
+
+template<typename T>
+void Allocator<T>::freeRegionsStartingAt(typename Allocator<T>::Region* region)
+{
+    while (region) {
+        Region* nextRegion = region->m_next;
+        fastAlignedFree(region->m_allocation);
+        region = nextRegion;
+    }
+}
+
+template<typename T>
+void Allocator<T>::startBumpingIn(typename Allocator<T>::Region* region)
+{
+    m_bumpEnd = region->data() + Region::numberOfThingsPerRegion();
+    m_bumpRemaining = Region::numberOfThingsPerRegion();
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGAllocator_h
+
index 026d083..36d4759 100644 (file)
@@ -712,46 +712,46 @@ private:
     Node* addToGraph(NodeType op, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
     {
         Node* result = m_graph.addNode(
-            op, currentNodeOrigin(), Edge(child1), Edge(child2),
+            SpecNone, op, currentNodeOrigin(), Edge(child1), Edge(child2),
             Edge(child3));
         return addToGraph(result);
     }
     Node* addToGraph(NodeType op, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
     {
         Node* result = m_graph.addNode(
-            op, currentNodeOrigin(), child1, child2, child3);
+            SpecNone, op, currentNodeOrigin(), child1, child2, child3);
         return addToGraph(result);
     }
     Node* addToGraph(NodeType op, OpInfo info, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
     {
         Node* result = m_graph.addNode(
-            op, currentNodeOrigin(), info, Edge(child1), Edge(child2),
+            SpecNone, op, currentNodeOrigin(), info, Edge(child1), Edge(child2),
             Edge(child3));
         return addToGraph(result);
     }
     Node* addToGraph(NodeType op, OpInfo info, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
     {
-        Node* result = m_graph.addNode(op, currentNodeOrigin(), info, child1, child2, child3);
+        Node* result = m_graph.addNode(SpecNone, op, currentNodeOrigin(), info, child1, child2, child3);
         return addToGraph(result);
     }
     Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Node* child1 = 0, Node* child2 = 0, Node* child3 = 0)
     {
         Node* result = m_graph.addNode(
-            op, currentNodeOrigin(), info1, info2,
+            SpecNone, op, currentNodeOrigin(), info1, info2,
             Edge(child1), Edge(child2), Edge(child3));
         return addToGraph(result);
     }
     Node* addToGraph(NodeType op, OpInfo info1, OpInfo info2, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
     {
         Node* result = m_graph.addNode(
-            op, currentNodeOrigin(), info1, info2, child1, child2, child3);
+            SpecNone, op, currentNodeOrigin(), info1, info2, child1, child2, child3);
         return addToGraph(result);
     }
     
     Node* addToGraph(Node::VarArgTag, NodeType op, OpInfo info1, OpInfo info2)
     {
         Node* result = m_graph.addNode(
-            Node::VarArg, op, currentNodeOrigin(), info1, info2,
+            SpecNone, Node::VarArg, op, currentNodeOrigin(), info1, info2,
             m_graph.m_varArgChildren.size() - m_numPassedVarArgs, m_numPassedVarArgs);
         addToGraph(result);
         
index 67b3574..63101ff 100644 (file)
@@ -90,7 +90,7 @@ private:
                     break;
                 case Phantom:
                     if (!node->child1()) {
-                        m_graph.deleteNode(node);
+                        m_graph.m_allocator.free(node);
                         continue;
                     }
                     switch (node->child1()->op()) {
@@ -112,7 +112,7 @@ private:
             block->resize(toIndex);
             
             for (unsigned phiIndex = block->phis.size(); phiIndex--;)
-                m_graph.deleteNode(block->phis[phiIndex]);
+                m_graph.m_allocator.free(block->phis[phiIndex]);
             block->phis.resize(0);
         }
     }
@@ -132,7 +132,7 @@ private:
     
     ALWAYS_INLINE Node* addPhiSilently(BasicBlock* block, const NodeOrigin& origin, VariableAccessData* variable)
     {
-        Node* result = m_graph.addNode(Phi, origin, OpInfo(variable));
+        Node* result = m_graph.addNode(SpecNone, Phi, origin, OpInfo(variable));
         block->phis.append(result);
         return result;
     }
index b0bb8cc..df2ef52 100644 (file)
@@ -69,7 +69,7 @@ public:
                 }
                 
                 if (kill)
-                    m_graph.deleteNode(node);
+                    m_graph.m_allocator.free(node);
                 else
                     block->at(targetIndex++) = node;
             }
index 495a064..f5face9 100644 (file)
@@ -83,7 +83,7 @@ public:
                     if (!m_state.isValid()) {
                         NodeOrigin origin = block->at(nodeIndex)->origin;
                         for (unsigned killIndex = nodeIndex; killIndex < block->size(); ++killIndex)
-                            m_graph.deleteNode(block->at(killIndex));
+                            m_graph.m_allocator.free(block->at(killIndex));
                         block->resize(nodeIndex);
                         block->appendNode(m_graph, SpecNone, Unreachable, origin);
                         didClipBlock = true;
index 7b491c2..d28c01d 100644 (file)
@@ -129,7 +129,7 @@ public:
         
         // And finally free the constants that we removed.
         for (Node* node : toFree)
-            m_graph.deleteNode(node);
+            m_graph.m_allocator.free(node);
         
         return true;
     }
index a70a869..6a6af75 100644 (file)
@@ -93,7 +93,7 @@ private:
             for (unsigned phiIndex = 0; phiIndex < block->phis.size(); ++phiIndex) {
                 Node* phi = block->phis[phiIndex];
                 if (!phi->shouldGenerate()) {
-                    m_graph.deleteNode(phi);
+                    m_graph.m_allocator.free(phi);
                     block->phis[phiIndex--] = block->phis.last();
                     block->phis.removeLast();
                 }
index e199773..ff3257a 100644 (file)
@@ -108,7 +108,7 @@ static CompilationResult compileImpl(
         return CompilationDeferred;
     }
     
-    plan->compileInThread(nullptr);
+    plan->compileInThread(*vm.dfgState, 0);
     return plan->finalizeWithoutNotifyingCallback();
 }
 #else // ENABLE(DFG_JIT)
index 9b2cc90..a8b2f9c 100644 (file)
@@ -66,11 +66,12 @@ static const char* dfgOpNames[] = {
 #undef STRINGIZE_DFG_OP_ENUM
 };
 
-Graph::Graph(VM& vm, Plan& plan)
+Graph::Graph(VM& vm, Plan& plan, LongLivedState& longLivedState)
     : m_vm(vm)
     , m_plan(plan)
     , m_codeBlock(m_plan.codeBlock)
     , m_profiledBlock(m_codeBlock->alternative())
+    , m_allocator(longLivedState.m_allocator)
     , m_cfg(std::make_unique<CFG>(*this))
     , m_nextMachineLocal(0)
     , m_fixpointState(BeforeFixpoint)
@@ -86,6 +87,17 @@ Graph::Graph(VM& vm, Plan& plan)
 
 Graph::~Graph()
 {
+    for (BlockIndex blockIndex = numBlocks(); blockIndex--;) {
+        BasicBlock* block = this->block(blockIndex);
+        if (!block)
+            continue;
+
+        for (unsigned phiIndex = block->phis.size(); phiIndex--;)
+            m_allocator.free(block->phis[phiIndex]);
+        for (unsigned nodeIndex = block->size(); nodeIndex--;)
+            m_allocator.free(block->at(nodeIndex));
+    }
+    m_allocator.freeAll();
 }
 
 const char *Graph::opName(NodeType op)
@@ -567,11 +579,6 @@ void Graph::dump(PrintStream& out, DumpContext* context)
     }
 }
 
-void Graph::deleteNode(Node* node)
-{
-    m_nodes.remove(node);
-}
-
 void Graph::dethread()
 {
     if (m_form == LoadStore || m_form == SSA)
@@ -738,9 +745,9 @@ void Graph::computeRefCounts()
 void Graph::killBlockAndItsContents(BasicBlock* block)
 {
     for (unsigned phiIndex = block->phis.size(); phiIndex--;)
-        deleteNode(block->phis[phiIndex]);
-    for (Node* node : *block)
-        deleteNode(node);
+        m_allocator.free(block->phis[phiIndex]);
+    for (unsigned nodeIndex = block->size(); nodeIndex--;)
+        m_allocator.free(block->at(nodeIndex));
     
     killBlock(block);
 }
index 2a8a3b6..7b89b7a 100644 (file)
 #if ENABLE(DFG_JIT)
 
 #include "AssemblyHelpers.h"
-#include "B3SparseCollection.h"
 #include "BytecodeLivenessAnalysisInlines.h"
 #include "CodeBlock.h"
 #include "DFGArgumentPosition.h"
 #include "DFGBasicBlock.h"
 #include "DFGFrozenValue.h"
+#include "DFGLongLivedState.h"
 #include "DFGNode.h"
+#include "DFGNodeAllocator.h"
 #include "DFGPlan.h"
 #include "DFGPropertyTypeKey.h"
 #include "DFGScannable.h"
@@ -123,7 +124,7 @@ enum AddSpeculationMode {
 // Nodes that are 'dead' remain in the vector with refCount 0.
 class Graph : public virtual Scannable {
 public:
-    Graph(VM&, Plan&);
+    Graph(VM&, Plan&, LongLivedState&);
     ~Graph();
     
     void changeChild(Edge& edge, Node* newNode)
@@ -181,20 +182,12 @@ public:
     }
     
     template<typename... Params>
-    Node* addNode(Params... params)
-    {
-        Node* node = new Node(params...);
-        m_nodes.add(std::unique_ptr<Node>(node));
-        return node;
-    }
-    template<typename... Params>
     Node* addNode(SpeculatedType type, Params... params)
     {
-        Node* node = addNode(params...);
+        Node* node = new (m_allocator) Node(params...);
         node->predict(type);
         return node;
     }
-    void deleteNode(Node*);
 
     void dethread();
     
@@ -828,6 +821,8 @@ public:
     Plan& m_plan;
     CodeBlock* m_codeBlock;
     CodeBlock* m_profiledBlock;
+    
+    NodeAllocator& m_allocator;
 
     Vector< RefPtr<BasicBlock> , 8> m_blocks;
     Vector<Edge, 16> m_varArgChildren;
@@ -916,7 +911,6 @@ public:
     bool m_hasDebuggerEnabled;
     bool m_hasExceptionHandlers { false };
 private:
-    void adoptNodeOutOfLine(Node&);
 
     bool isStringPrototypeMethodSane(JSGlobalObject*, UniquedStringImpl*);
 
@@ -949,8 +943,6 @@ private:
         
         return bytecodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateInt32AndTruncateConstants : DontSpeculateInt32;
     }
-
-    B3::SparseCollection<Node> m_nodes;
 };
 
 } } // namespace JSC::DFG
index e609764..deed20b 100644 (file)
@@ -341,7 +341,7 @@ private:
         // code. But for now we just assert that's the case.
         DFG_ASSERT(m_graph, node, !(node->flags() & NodeHasVarArgs));
         
-        nodeRef = m_graph.addNode(Check, originalOrigin, node->children);
+        nodeRef = m_graph.addNode(SpecNone, Check, originalOrigin, node->children);
         
         return true;
     }
diff --git a/Source/JavaScriptCore/dfg/DFGLongLivedState.cpp b/Source/JavaScriptCore/dfg/DFGLongLivedState.cpp
new file mode 100644 (file)
index 0000000..7a2f2f1
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DFGLongLivedState.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "JSCInlines.h"
+
+namespace JSC { namespace DFG {
+
+LongLivedState::LongLivedState()
+{
+}
+
+LongLivedState::~LongLivedState()
+{
+}
+
+void LongLivedState::shrinkToFit()
+{
+    m_allocator.reset();
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/Source/JavaScriptCore/dfg/DFGLongLivedState.h b/Source/JavaScriptCore/dfg/DFGLongLivedState.h
new file mode 100644 (file)
index 0000000..77fab04
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGLongLivedState_h
+#define DFGLongLivedState_h
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGNodeAllocator.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC { namespace DFG {
+
+class LongLivedState {
+    WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(LongLivedState);
+public:
+    LongLivedState();
+    ~LongLivedState();
+    
+    void shrinkToFit();
+    
+    NodeAllocator m_allocator;
+};
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGLongLivedState_h
+
index 44b2845..48f1d55 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(DFG_JIT)
 
 #include "DFGGraph.h"
+#include "DFGNodeAllocator.h"
 #include "DFGPromotedHeapLocation.h"
 #include "JSCInlines.h"
 
@@ -63,6 +64,11 @@ void BranchTarget::dump(PrintStream& out) const
         out.print("/w:", count);
 }
 
+unsigned Node::index() const
+{
+    return NodeAllocator::allocatorOf(this)->indexOf(this);
+}
+
 bool Node::hasVariableAccessData(Graph& graph)
 {
     switch (op()) {
index 5c48cf1..560da4b 100644 (file)
@@ -28,7 +28,6 @@
 
 #if ENABLE(DFG_JIT)
 
-#include "B3SparseCollection.h"
 #include "BasicBlockLocation.h"
 #include "CodeBlock.h"
 #include "DFGAbstractValue.h"
@@ -231,8 +230,6 @@ struct StackAccessData {
 //
 // Node represents a single operation in the data flow graph.
 struct Node {
-    WTF_MAKE_FAST_ALLOCATED;
-public:
     enum VarArgTag { VarArg };
     
     Node() { }
@@ -349,8 +346,9 @@ public:
     
     NodeType op() const { return static_cast<NodeType>(m_op); }
     NodeFlags flags() const { return m_flags; }
-
-    unsigned index() const { return m_index; }
+    
+    // This is not a fast method.
+    unsigned index() const;
     
     void setOp(NodeType op)
     {
@@ -2346,9 +2344,6 @@ public:
     AdjacencyList children;
 
 private:
-    friend class B3::SparseCollection<Node>;
-
-    unsigned m_index { std::numeric_limits<unsigned>::max() };
     unsigned m_op : 10; // real type is NodeType
     unsigned m_flags : 20;
     // The virtual register number (spill location) associated with this .
@@ -2356,7 +2351,7 @@ private:
     // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects).
     unsigned m_refCount;
     // The prediction ascribed to this node after propagation.
-    SpeculatedType m_prediction { SpecNone };
+    SpeculatedType m_prediction;
     // Immediate values, accesses type-checked via accessors above. The first one is
     // big enough to store a pointer.
     uintptr_t m_opInfo;
diff --git a/Source/JavaScriptCore/dfg/DFGNodeAllocator.h b/Source/JavaScriptCore/dfg/DFGNodeAllocator.h
new file mode 100644 (file)
index 0000000..e9024cc
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGNodeAllocator_h
+#define DFGNodeAllocator_h
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAllocator.h"
+#include "DFGNode.h"
+
+namespace JSC { namespace DFG {
+
+typedef Allocator<Node> NodeAllocator;
+
+} } // namespace JSC::DFG
+
+inline void* operator new (size_t size, JSC::DFG::NodeAllocator& allocator)
+{
+    ASSERT_UNUSED(size, size == sizeof(JSC::DFG::Node));
+    return allocator.allocate();
+}
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGNodeAllocator_h
+
index 4d34730..98cc5bf 100644 (file)
@@ -2102,6 +2102,7 @@ private:
                 data->identifierNumber = identifierNumber;
 
                 return m_graph.addNode(
+                    SpecNone,
                     PutByOffset,
                     origin.takeValidExit(canExit),
                     OpInfo(data),
@@ -2136,6 +2137,7 @@ private:
             }
 
             return m_graph.addNode(
+                SpecNone,
                 MultiPutByOffset,
                 origin.takeValidExit(canExit),
                 OpInfo(data),
@@ -2146,6 +2148,7 @@ private:
 
         case ClosureVarPLoc: {
             return m_graph.addNode(
+                SpecNone,
                 PutClosureVar,
                 origin.takeValidExit(canExit),
                 OpInfo(location.info()),
index 251554b..88d1f15 100644 (file)
@@ -170,7 +170,7 @@ bool Plan::reportCompileTimes() const
         || (Options::reportFTLCompileTimes() && isFTL(mode));
 }
 
-void Plan::compileInThread(ThreadData* threadData)
+void Plan::compileInThread(LongLivedState& longLivedState, ThreadData* threadData)
 {
     this->threadData = threadData;
     
@@ -186,7 +186,7 @@ void Plan::compileInThread(ThreadData* threadData)
     if (logCompilationChanges(mode))
         dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
 
-    CompilationPath path = compileInThreadImpl();
+    CompilationPath path = compileInThreadImpl(longLivedState);
 
     RELEASE_ASSERT(path == CancelPath || finalizer);
     RELEASE_ASSERT((path == CancelPath) == (stage == Cancelled));
@@ -236,7 +236,7 @@ void Plan::compileInThread(ThreadData* threadData)
     }
 }
 
-Plan::CompilationPath Plan::compileInThreadImpl()
+Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
 {
     cleanMustHandleValuesIfNecessary();
     
@@ -246,7 +246,7 @@ Plan::CompilationPath Plan::compileInThreadImpl()
         dataLog("\n");
     }
     
-    Graph dfg(*vm, *this);
+    Graph dfg(*vm, *this, longLivedState);
     
     if (!parse(dfg)) {
         finalizer = std::make_unique<FailedFinalizer>(*this);
index 6e35268..9594dff 100644 (file)
@@ -48,6 +48,7 @@ class SlotVisitor;
 
 namespace DFG {
 
+class LongLivedState;
 class ThreadData;
 
 #if ENABLE(DFG_JIT)
@@ -59,7 +60,7 @@ struct Plan : public ThreadSafeRefCounted<Plan> {
         const Operands<JSValue>& mustHandleValues);
     ~Plan();
 
-    void compileInThread(ThreadData*);
+    void compileInThread(LongLivedState&, ThreadData*);
     
     CompilationResult finalizeWithoutNotifyingCallback();
     void finalizeAndNotifyCallback();
@@ -120,7 +121,7 @@ private:
     bool reportCompileTimes() const;
     
     enum CompilationPath { FailPath, DFGPath, FTLPath, CancelPath };
-    CompilationPath compileInThreadImpl();
+    CompilationPath compileInThreadImpl(LongLivedState&);
     
     bool isStillValid();
     void reallyAdd(CommonData*);
index cde0740..fe99ba0 100644 (file)
@@ -373,7 +373,7 @@ public:
             if (!block)
                 continue;
             for (unsigned phiIndex = block->phis.size(); phiIndex--;)
-                m_graph.deleteNode(block->phis[phiIndex]);
+                m_graph.m_allocator.free(block->phis[phiIndex]);
             block->phis.clear();
             block->variablesAtHead.clear();
             block->variablesAtTail.clear();
index 9b6d2c3..d528e14 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "CodeBlock.h"
 #include "DeferGC.h"
+#include "DFGLongLivedState.h"
 #include "DFGSafepoint.h"
 #include "JSCInlines.h"
 #include <mutex>
@@ -361,6 +362,8 @@ void Worklist::runThread(ThreadData* data)
     if (Options::verboseCompilationQueue())
         dataLog(*this, ": Thread started\n");
     
+    LongLivedState longLivedState;
+    
     for (;;) {
         RefPtr<Plan> plan;
         {
@@ -396,7 +399,7 @@ void Worklist::runThread(ThreadData* data)
                 dataLog(*this, ": Compiling ", plan->key(), " asynchronously\n");
         
             RELEASE_ASSERT(!plan->vm->heap.isCollecting());
-            plan->compileInThread(data);
+            plan->compileInThread(longLivedState, data);
             RELEASE_ASSERT(plan->stage == Plan::Cancelled || !plan->vm->heap.isCollecting());
             
             {
index 9416ea9..b1ff424 100644 (file)
@@ -38,6 +38,7 @@
 #include "CommonIdentifiers.h"
 #include "CommonSlowPaths.h"
 #include "CustomGetterSetter.h"
+#include "DFGLongLivedState.h"
 #include "DFGWorklist.h"
 #include "Disassembler.h"
 #include "ErrorInstance.h"
@@ -289,6 +290,11 @@ VM::VM(VMType vmType, HeapType heapType)
     }
 
     callFrameForCatch = nullptr;
+
+#if ENABLE(DFG_JIT)
+    if (canUseJIT())
+        dfgState = std::make_unique<DFG::LongLivedState>();
+#endif
     
     // Initialize this last, as a free way of asserting that VM initialization itself
     // won't use this.
index 4e9f21c..f0de151 100644 (file)
@@ -119,6 +119,11 @@ class Watchdog;
 class Watchpoint;
 class WatchpointSet;
 
+#if ENABLE(DFG_JIT)
+namespace DFG {
+class LongLivedState;
+}
+#endif // ENABLE(DFG_JIT)
 #if ENABLE(FTL_JIT)
 namespace FTL {
 class Thunks;
@@ -266,6 +271,10 @@ public:
     // destructed after all the objects that reference it.
     Heap heap;
 
+#if ENABLE(DFG_JIT)
+    std::unique_ptr<DFG::LongLivedState> dfgState;
+#endif // ENABLE(DFG_JIT)
+
     VMType vmType;
     ClientData* clientData;
     VMEntryFrame* topVMEntryFrame;