4f1352d3f37d35b7d288a323d016206c1deeae94
[WebKit-https.git] / Source / JavaScriptCore / parser / ParserArena.h
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 <wtf/SegmentedVector.h>
31
32 namespace JSC {
33
34     class ParserArenaDeletable;
35     class ParserArenaRefCounted;
36
37     class IdentifierArena {
38         WTF_MAKE_FAST_ALLOCATED;
39     public:
40         IdentifierArena()
41         {
42             clear();
43         }
44
45         template <typename T>
46         ALWAYS_INLINE const Identifier& makeIdentifier(VM*, const T* characters, size_t length);
47         ALWAYS_INLINE const Identifier& makeIdentifierLCharFromUChar(VM*, const UChar* characters, size_t length);
48
49         const Identifier& makeNumericIdentifier(VM*, double number);
50
51         bool isEmpty() const { return m_identifiers.isEmpty(); }
52
53     public:
54         static const int MaximumCachableCharacter = 128;
55         typedef SegmentedVector<Identifier, 64> IdentifierVector;
56         void clear()
57         {
58             m_identifiers.clear();
59             for (int i = 0; i < MaximumCachableCharacter; i++)
60                 m_shortIdentifiers[i] = 0;
61             for (int i = 0; i < MaximumCachableCharacter; i++)
62                 m_recentIdentifiers[i] = 0;
63         }
64
65     private:
66         IdentifierVector m_identifiers;
67         FixedArray<Identifier*, MaximumCachableCharacter> m_shortIdentifiers;
68         FixedArray<Identifier*, MaximumCachableCharacter> m_recentIdentifiers;
69     };
70
71     template <typename T>
72     ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifier(VM* vm, const T* characters, size_t length)
73     {
74         if (characters[0] >= MaximumCachableCharacter) {
75             m_identifiers.append(Identifier(vm, characters, length));
76             return m_identifiers.last();
77         }
78         if (length == 1) {
79             if (Identifier* ident = m_shortIdentifiers[characters[0]])
80                 return *ident;
81             m_identifiers.append(Identifier(vm, characters, length));
82             m_shortIdentifiers[characters[0]] = &m_identifiers.last();
83             return m_identifiers.last();
84         }
85         Identifier* ident = m_recentIdentifiers[characters[0]];
86         if (ident && Identifier::equal(ident->impl(), characters, length))
87             return *ident;
88         m_identifiers.append(Identifier(vm, characters, length));
89         m_recentIdentifiers[characters[0]] = &m_identifiers.last();
90         return m_identifiers.last();
91     }
92
93     ALWAYS_INLINE const Identifier& IdentifierArena::makeIdentifierLCharFromUChar(VM* vm, const UChar* characters, size_t length)
94     {
95         if (characters[0] >= MaximumCachableCharacter) {
96             m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length));
97             return m_identifiers.last();
98         }
99         if (length == 1) {
100             if (Identifier* ident = m_shortIdentifiers[characters[0]])
101                 return *ident;
102             m_identifiers.append(Identifier(vm, characters, length));
103             m_shortIdentifiers[characters[0]] = &m_identifiers.last();
104             return m_identifiers.last();
105         }
106         Identifier* ident = m_recentIdentifiers[characters[0]];
107         if (ident && Identifier::equal(ident->impl(), characters, length))
108             return *ident;
109         m_identifiers.append(Identifier::createLCharFromUChar(vm, characters, length));
110         m_recentIdentifiers[characters[0]] = &m_identifiers.last();
111         return m_identifiers.last();
112     }
113     
114     inline const Identifier& IdentifierArena::makeNumericIdentifier(VM* vm, double number)
115     {
116         m_identifiers.append(Identifier(vm, String::numberToStringECMAScript(number)));
117         return m_identifiers.last();
118     }
119
120     class ParserArena {
121         WTF_MAKE_NONCOPYABLE(ParserArena);
122     public:
123         ParserArena();
124         ~ParserArena();
125
126         void swap(ParserArena& otherArena)
127         {
128             std::swap(m_freeableMemory, otherArena.m_freeableMemory);
129             std::swap(m_freeablePoolEnd, otherArena.m_freeablePoolEnd);
130             m_identifierArena.swap(otherArena.m_identifierArena);
131             m_freeablePools.swap(otherArena.m_freeablePools);
132             m_deletableObjects.swap(otherArena.m_deletableObjects);
133             m_refCountedObjects.swap(otherArena.m_refCountedObjects);
134         }
135
136         void* allocateFreeable(size_t size)
137         {
138             ASSERT(size);
139             ASSERT(size <= freeablePoolSize);
140             size_t alignedSize = alignSize(size);
141             ASSERT(alignedSize <= freeablePoolSize);
142             if (UNLIKELY(static_cast<size_t>(m_freeablePoolEnd - m_freeableMemory) < alignedSize))
143                 allocateFreeablePool();
144             void* block = m_freeableMemory;
145             m_freeableMemory += alignedSize;
146             return block;
147         }
148
149         void* allocateDeletable(size_t size)
150         {
151             ParserArenaDeletable* deletable = static_cast<ParserArenaDeletable*>(allocateFreeable(size));
152             m_deletableObjects.append(deletable);
153             return deletable;
154         }
155
156         void derefWithArena(PassRefPtr<ParserArenaRefCounted>);
157         bool contains(ParserArenaRefCounted*) const;
158         ParserArenaRefCounted* last() const;
159         void removeLast();
160
161         bool isEmpty() const;
162         JS_EXPORT_PRIVATE void reset();
163
164         IdentifierArena& identifierArena()
165         {
166             if (UNLIKELY (!m_identifierArena))
167                 m_identifierArena = adoptPtr(new IdentifierArena);
168             return *m_identifierArena;
169         }
170
171     private:
172         static const size_t freeablePoolSize = 8000;
173
174         static size_t alignSize(size_t size)
175         {
176             return (size + sizeof(WTF::AllocAlignmentInteger) - 1) & ~(sizeof(WTF::AllocAlignmentInteger) - 1);
177         }
178
179         void* freeablePool();
180         void allocateFreeablePool();
181         void deallocateObjects();
182
183         char* m_freeableMemory;
184         char* m_freeablePoolEnd;
185
186         OwnPtr<IdentifierArena> m_identifierArena;
187         Vector<void*> m_freeablePools;
188         Vector<ParserArenaDeletable*> m_deletableObjects;
189         Vector<RefPtr<ParserArenaRefCounted>> m_refCountedObjects;
190     };
191
192 }
193
194 #endif