]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - parser/ParserArena.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / parser / ParserArena.h
index 66c8529abe174362182a93f6041d4cf0a7289fb6..d8bc2cffa427314564fd1b0415c82475ce52b235 100644 (file)
 #ifndef ParserArena_h
 #define ParserArena_h
 
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/Vector.h>
+#include "CommonIdentifiers.h"
+#include "Identifier.h"
+#include <array>
+#include <wtf/SegmentedVector.h>
 
 namespace JSC {
 
     class ParserArenaDeletable;
     class ParserArenaRefCounted;
 
+    class IdentifierArena {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        IdentifierArena()
+        {
+            clear();
+        }
+
+        template <typename T>
+        ALWAYS_INLINE const Identifier& makeIdentifier(VM*, const T* characters, size_t length);
+        ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(VM*, const UChar* characters, size_t length);
+
+        const Identifier& makeNumericIdentifier(VM*, double number);
+
+        bool isEmpty() const { return m_identifiers.isEmpty(); }
+
+    public:
+        static const int MaximumCachableCharacter = 128;
+        typedef SegmentedVector<Identifier, 64> IdentifierVector;
+        void clear()
+        {
+            m_identifiers.clear();
+            for (int i = 0; i < MaximumCachableCharacter; i++)
+                m_shortIdentifiers[i] = 0;
+            for (int i = 0; i < MaximumCachableCharacter; i++)
+                m_recentIdentifiers[i] = 0;
+        }
+
+    private:
+        IdentifierVector m_identifiers;
+        std::array<Identifier*, MaximumCachableCharacter> m_shortIdentifiers;
+        std::array<Identifier*, MaximumCachableCharacter> m_recentIdentifiers;
+    };
+
+    template <typename T>
+    ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(VM* vm, const T* characters, size_t length)
+    {
+        if (!length)
+            return vm->propertyNames->emptyIdentifier;
+        if (characters[0] >= MaximumCachableCharacter) {
+            m_identifiers.append(Identifier(vm, characters, length));
+            return m_identifiers.last();
+        }
+        if (length == 1) {
+            if (Identifier* ident = m_shortIdentifiers[characters[0]])
+                return *ident;
+            m_identifiers.append(Identifier(vm, characters, length));
+            m_shortIdentifiers[characters[0]] = &m_identifiers.last();
+            return m_identifiers.last();
+        }
+        Identifier* ident = m_recentIdentifiers[characters[0]];
+        if (ident && Identifier::equal(ident->impl(), characters, length))
+            return *ident;
+        m_identifiers.append(Identifier(vm, characters, length));
+        m_recentIdentifiers[characters[0]] = &m_identifiers.last();
+        return m_identifiers.last();
+    }
+
+    ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(VM* vm, const UChar* characters, size_t length)
+    {
+        if (!length)
+            return vm->propertyNames->emptyIdentifier;
+        if (characters[0] >= MaximumCachableCharacter) {
+            m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length));
+            return m_identifiers.last();
+        }
+        if (length == 1) {
+            if (Identifier* ident = m_shortIdentifiers[characters[0]])
+                return *ident;
+            m_identifiers.append(Identifier(vm, characters, length));
+            m_shortIdentifiers[characters[0]] = &m_identifiers.last();
+            return m_identifiers.last();
+        }
+        Identifier* ident = m_recentIdentifiers[characters[0]];
+        if (ident && Identifier::equal(ident->impl(), characters, length))
+            return *ident;
+        m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length));
+        m_recentIdentifiers[characters[0]] = &m_identifiers.last();
+        return m_identifiers.last();
+    }
+    
+    inline const Identifier& IdentifierArena::makeNumericIdentifier(VM* vm, double number)
+    {
+        m_identifiers.append(Identifier(vm, String::numberToStringECMAScript(number)));
+        return m_identifiers.last();
+    }
+
     class ParserArena {
+        WTF_MAKE_NONCOPYABLE(ParserArena);
     public:
+        ParserArena();
+        ~ParserArena();
+
         void swap(ParserArena& otherArena)
         {
+            std::swap(m_freeableMemory, otherArena.m_freeableMemory);
+            std::swap(m_freeablePoolEnd, otherArena.m_freeablePoolEnd);
+            m_identifierArena.swap(otherArena.m_identifierArena);
+            m_freeablePools.swap(otherArena.m_freeablePools);
             m_deletableObjects.swap(otherArena.m_deletableObjects);
             m_refCountedObjects.swap(otherArena.m_refCountedObjects);
         }
-        ~ParserArena();
 
-        void deleteWithArena(ParserArenaDeletable* object) { m_deletableObjects.append(object); }
-        void derefWithArena(PassRefPtr<ParserArenaRefCounted> object) { m_refCountedObjects.append(object); }
+        void* allocateFreeable(size_t size)
+        {
+            ASSERT(size);
+            ASSERT(size <= freeablePoolSize);
+            size_t alignedSize = alignSize(size);
+            ASSERT(alignedSize <= freeablePoolSize);
+            if (UNLIKELY(static_cast<size_t>(m_freeablePoolEnd - m_freeableMemory) < alignedSize))
+                allocateFreeablePool();
+            void* block = m_freeableMemory;
+            m_freeableMemory += alignedSize;
+            return block;
+        }
+
+        void* allocateDeletable(size_t size)
+        {
+            ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(allocateFreeable(size));
+            m_deletableObjects.append(deletable);
+            return deletable;
+        }
 
+        void derefWithArena(PassRefPtr<ParserArenaRefCounted>);
         bool contains(ParserArenaRefCounted*) const;
         ParserArenaRefCounted* last() const;
         void removeLast();
 
-        bool isEmpty() const { return m_deletableObjects.isEmpty() && m_refCountedObjects.isEmpty(); }
-        void reset();
+        bool isEmpty() const;
+        JS_EXPORT_PRIVATE void reset();
+
+        IdentifierArena& identifierArena()
+        {
+            if (UNLIKELY (!m_identifierArena))
+                m_identifierArena = adoptPtr(new IdentifierArena);
+            return *m_identifierArena;
+        }
 
     private:
+        static const size_t freeablePoolSize = 8000;
+
+        static size_t alignSize(size_t size)
+        {
+            return (size + sizeof(WTF::AllocAlignmentInteger) - 1) & ~(sizeof(WTF::AllocAlignmentInteger) - 1);
+        }
+
+        void* freeablePool();
+        void allocateFreeablePool();
+        void deallocateObjects();
+
+        char* m_freeableMemory;
+        char* m_freeablePoolEnd;
+
+        OwnPtr<IdentifierArena> m_identifierArena;
+        Vector<void*> m_freeablePools;
         Vector<ParserArenaDeletable*> m_deletableObjects;
-        Vector<RefPtr<ParserArenaRefCounted> > m_refCountedObjects;
+        Vector<RefPtr<ParserArenaRefCounted>> m_refCountedObjects;
     };
 
 }