X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/ba379fdc102753d6be2c4d937058fe40257329fe..2d39b0e377c0896910ee49ae70082ba665faf986:/parser/ParserArena.h diff --git a/parser/ParserArena.h b/parser/ParserArena.h index 66c8529..d8bc2cf 100644 --- a/parser/ParserArena.h +++ b/parser/ParserArena.h @@ -26,37 +26,173 @@ #ifndef ParserArena_h #define ParserArena_h -#include -#include -#include +#include "CommonIdentifiers.h" +#include "Identifier.h" +#include +#include namespace JSC { class ParserArenaDeletable; class ParserArenaRefCounted; + class IdentifierArena { + WTF_MAKE_FAST_ALLOCATED; + public: + IdentifierArena() + { + clear(); + } + + template + 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 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 m_shortIdentifiers; + std::array m_recentIdentifiers; + }; + + template + 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 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(m_freeablePoolEnd - m_freeableMemory) < alignedSize)) + allocateFreeablePool(); + void* block = m_freeableMemory; + m_freeableMemory += alignedSize; + return block; + } + + void* allocateDeletable(size_t size) + { + ParserArenaDeletable* deletable = static_cast(allocateFreeable(size)); + m_deletableObjects.append(deletable); + return deletable; + } + void derefWithArena(PassRefPtr); 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 m_identifierArena; + Vector m_freeablePools; Vector m_deletableObjects; - Vector > m_refCountedObjects; + Vector> m_refCountedObjects; }; }