1/* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef ParserArena_h 27#define ParserArena_h 28 29#include "Identifier.h" 30#include <array> 31#include <wtf/SegmentedVector.h> 32 33namespace JSC { 34 35 class ParserArenaDeletable; 36 class ParserArenaRefCounted; 37 38 class IdentifierArena { 39 WTF_MAKE_FAST_ALLOCATED; 40 public: 41 IdentifierArena() 42 { 43 clear(); 44 } 45 46 template <typename T> 47 ALWAYS_INLINE const Identifier& makeIdentifier(VM*, const T* characters, size_t length); 48 ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(VM*, const UChar* characters, size_t length); 49 50 const Identifier& makeNumericIdentifier(VM*, double number); 51 52 bool isEmpty() const { return m_identifiers.isEmpty(); } 53 54 public: 55 static const int MaximumCachableCharacter = 128; 56 typedef SegmentedVector<Identifier, 64> IdentifierVector; 57 void clear() 58 { 59 m_identifiers.clear(); 60 for (int i = 0; i < MaximumCachableCharacter; i++) 61 m_shortIdentifiers[i] = 0; 62 for (int i = 0; i < MaximumCachableCharacter; i++) 63 m_recentIdentifiers[i] = 0; 64 } 65 66 private: 67 IdentifierVector m_identifiers; 68 std::array<Identifier*, MaximumCachableCharacter> m_shortIdentifiers; 69 std::array<Identifier*, MaximumCachableCharacter> m_recentIdentifiers; 70 }; 71 72 template <typename T> 73 ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(VM* vm, const T* characters, size_t length) 74 { 75 if (characters[0] >= MaximumCachableCharacter) { 76 m_identifiers.append(Identifier(vm, characters, length)); 77 return m_identifiers.last(); 78 } 79 if (length == 1) { 80 if (Identifier* ident = m_shortIdentifiers[characters[0]]) 81 return *ident; 82 m_identifiers.append(Identifier(vm, characters, length)); 83 m_shortIdentifiers[characters[0]] = &m_identifiers.last(); 84 return m_identifiers.last(); 85 } 86 Identifier* ident = m_recentIdentifiers[characters[0]]; 87 if (ident && Identifier::equal(ident->impl(), characters, length)) 88 return *ident; 89 m_identifiers.append(Identifier(vm, characters, length)); 90 m_recentIdentifiers[characters[0]] = &m_identifiers.last(); 91 return m_identifiers.last(); 92 } 93 94 ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(VM* vm, const UChar* characters, size_t length) 95 { 96 if (characters[0] >= MaximumCachableCharacter) { 97 m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length)); 98 return m_identifiers.last(); 99 } 100 if (length == 1) { 101 if (Identifier* ident = m_shortIdentifiers[characters[0]]) 102 return *ident; 103 m_identifiers.append(Identifier(vm, characters, length)); 104 m_shortIdentifiers[characters[0]] = &m_identifiers.last(); 105 return m_identifiers.last(); 106 } 107 Identifier* ident = m_recentIdentifiers[characters[0]]; 108 if (ident && Identifier::equal(ident->impl(), characters, length)) 109 return *ident; 110 m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length)); 111 m_recentIdentifiers[characters[0]] = &m_identifiers.last(); 112 return m_identifiers.last(); 113 } 114 115 inline const Identifier& IdentifierArena::makeNumericIdentifier(VM* vm, double number) 116 { 117 m_identifiers.append(Identifier(vm, String::numberToStringECMAScript(number))); 118 return m_identifiers.last(); 119 } 120 121 class ParserArena { 122 WTF_MAKE_NONCOPYABLE(ParserArena); 123 public: 124 ParserArena(); 125 ~ParserArena(); 126 127 void swap(ParserArena& otherArena) 128 { 129 std::swap(m_freeableMemory, otherArena.m_freeableMemory); 130 std::swap(m_freeablePoolEnd, otherArena.m_freeablePoolEnd); 131 m_identifierArena.swap(otherArena.m_identifierArena); 132 m_freeablePools.swap(otherArena.m_freeablePools); 133 m_deletableObjects.swap(otherArena.m_deletableObjects); 134 m_refCountedObjects.swap(otherArena.m_refCountedObjects); 135 } 136 137 void* allocateFreeable(size_t size) 138 { 139 ASSERT(size); 140 ASSERT(size <= freeablePoolSize); 141 size_t alignedSize = alignSize(size); 142 ASSERT(alignedSize <= freeablePoolSize); 143 if (UNLIKELY(static_cast<size_t>(m_freeablePoolEnd - m_freeableMemory) < alignedSize)) 144 allocateFreeablePool(); 145 void* block = m_freeableMemory; 146 m_freeableMemory += alignedSize; 147 return block; 148 } 149 150 void* allocateDeletable(size_t size) 151 { 152 ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(allocateFreeable(size)); 153 m_deletableObjects.append(deletable); 154 return deletable; 155 } 156 157 void derefWithArena(PassRefPtr<ParserArenaRefCounted>); 158 bool contains(ParserArenaRefCounted*) const; 159 ParserArenaRefCounted* last() const; 160 void removeLast(); 161 162 bool isEmpty() const; 163 JS_EXPORT_PRIVATE void reset(); 164 165 IdentifierArena& identifierArena() 166 { 167 if (UNLIKELY (!m_identifierArena)) 168 m_identifierArena = adoptPtr(new IdentifierArena); 169 return *m_identifierArena; 170 } 171 172 private: 173 static const size_t freeablePoolSize = 8000; 174 175 static size_t alignSize(size_t size) 176 { 177 return (size + sizeof(WTF::AllocAlignmentInteger) - 1) & ~(sizeof(WTF::AllocAlignmentInteger) - 1); 178 } 179 180 void* freeablePool(); 181 void allocateFreeablePool(); 182 void deallocateObjects(); 183 184 char* m_freeableMemory; 185 char* m_freeablePoolEnd; 186 187 OwnPtr<IdentifierArena> m_identifierArena; 188 Vector<void*> m_freeablePools; 189 Vector<ParserArenaDeletable*> m_deletableObjects; 190 Vector<RefPtr<ParserArenaRefCounted>> m_refCountedObjects; 191 }; 192 193} 194 195#endif 196