2  * Copyright (C) 2009 Apple Inc. All rights reserved. 
   4  * Redistribution and use in source and binary forms, with or without 
   5  * modification, are permitted provided that the following conditions 
   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. 
  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.  
  29 #include "CommonIdentifiers.h" 
  30 #include "Identifier.h" 
  32 #include <wtf/SegmentedVector.h> 
  36     class ParserArenaDeletable
; 
  38     class IdentifierArena 
{ 
  39         WTF_MAKE_FAST_ALLOCATED
; 
  47         ALWAYS_INLINE 
const Identifier
& makeIdentifier(VM
*, const T
* characters
, size_t length
); 
  48         ALWAYS_INLINE 
const Identifier
& makeEmptyIdentifier(VM
*); 
  49         ALWAYS_INLINE 
const Identifier
& makeIdentifierLCharFromUChar(VM
*, const UChar
* characters
, size_t length
); 
  51         const Identifier
& makeNumericIdentifier(VM
*, double number
); 
  54         static const int MaximumCachableCharacter 
= 128; 
  55         typedef SegmentedVector
<Identifier
, 64> IdentifierVector
; 
  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; 
  66         IdentifierVector m_identifiers
; 
  67         std::array
<Identifier
*, MaximumCachableCharacter
> m_shortIdentifiers
; 
  68         std::array
<Identifier
*, MaximumCachableCharacter
> m_recentIdentifiers
; 
  72     ALWAYS_INLINE 
const Identifier
& IdentifierArena::makeIdentifier(VM
* vm
, const T
* characters
, size_t length
) 
  75             return vm
->propertyNames
->emptyIdentifier
; 
  76         if (characters
[0] >= MaximumCachableCharacter
) { 
  77             m_identifiers
.append(Identifier::fromString(vm
, characters
, length
)); 
  78             return m_identifiers
.last(); 
  81             if (Identifier
* ident 
= m_shortIdentifiers
[characters
[0]]) 
  83             m_identifiers
.append(Identifier::fromString(vm
, characters
, length
)); 
  84             m_shortIdentifiers
[characters
[0]] = &m_identifiers
.last(); 
  85             return m_identifiers
.last(); 
  87         Identifier
* ident 
= m_recentIdentifiers
[characters
[0]]; 
  88         if (ident 
&& Identifier::equal(ident
->impl(), characters
, length
)) 
  90         m_identifiers
.append(Identifier::fromString(vm
, characters
, length
)); 
  91         m_recentIdentifiers
[characters
[0]] = &m_identifiers
.last(); 
  92         return m_identifiers
.last(); 
  95     ALWAYS_INLINE 
const Identifier
& IdentifierArena::makeEmptyIdentifier(VM
* vm
) 
  97         return vm
->propertyNames
->emptyIdentifier
; 
 100     ALWAYS_INLINE 
const Identifier
& IdentifierArena::makeIdentifierLCharFromUChar(VM
* vm
, const UChar
* characters
, size_t length
) 
 103             return vm
->propertyNames
->emptyIdentifier
; 
 104         if (characters
[0] >= MaximumCachableCharacter
) { 
 105             m_identifiers
.append(Identifier::createLCharFromUChar(vm
, characters
, length
)); 
 106             return m_identifiers
.last(); 
 109             if (Identifier
* ident 
= m_shortIdentifiers
[characters
[0]]) 
 111             m_identifiers
.append(Identifier::fromString(vm
, characters
, length
)); 
 112             m_shortIdentifiers
[characters
[0]] = &m_identifiers
.last(); 
 113             return m_identifiers
.last(); 
 115         Identifier
* ident 
= m_recentIdentifiers
[characters
[0]]; 
 116         if (ident 
&& Identifier::equal(ident
->impl(), characters
, length
)) 
 118         m_identifiers
.append(Identifier::createLCharFromUChar(vm
, characters
, length
)); 
 119         m_recentIdentifiers
[characters
[0]] = &m_identifiers
.last(); 
 120         return m_identifiers
.last(); 
 123     inline const Identifier
& IdentifierArena::makeNumericIdentifier(VM
* vm
, double number
) 
 125         m_identifiers
.append(Identifier::fromString(vm
, String::numberToStringECMAScript(number
))); 
 126         return m_identifiers
.last(); 
 130         WTF_MAKE_NONCOPYABLE(ParserArena
); 
 135         void swap(ParserArena
& otherArena
) 
 137             std::swap(m_freeableMemory
, otherArena
.m_freeableMemory
); 
 138             std::swap(m_freeablePoolEnd
, otherArena
.m_freeablePoolEnd
); 
 139             m_identifierArena
.swap(otherArena
.m_identifierArena
); 
 140             m_freeablePools
.swap(otherArena
.m_freeablePools
); 
 141             m_deletableObjects
.swap(otherArena
.m_deletableObjects
); 
 144         void* allocateFreeable(size_t size
) 
 147             ASSERT(size 
<= freeablePoolSize
); 
 148             size_t alignedSize 
= alignSize(size
); 
 149             ASSERT(alignedSize 
<= freeablePoolSize
); 
 150             if (UNLIKELY(static_cast<size_t>(m_freeablePoolEnd 
- m_freeableMemory
) < alignedSize
)) 
 151                 allocateFreeablePool(); 
 152             void* block 
= m_freeableMemory
; 
 153             m_freeableMemory 
+= alignedSize
; 
 157         void* allocateDeletable(size_t size
) 
 159             ParserArenaDeletable
* deletable 
= static_cast<ParserArenaDeletable
*>(allocateFreeable(size
)); 
 160             m_deletableObjects
.append(deletable
); 
 164         IdentifierArena
& identifierArena() 
 166             if (UNLIKELY (!m_identifierArena
)) 
 167                 m_identifierArena 
= std::make_unique
<IdentifierArena
>(); 
 168             return *m_identifierArena
; 
 172         static const size_t freeablePoolSize 
= 8000; 
 174         static size_t alignSize(size_t size
) 
 176             return (size 
+ sizeof(WTF::AllocAlignmentInteger
) - 1) & ~(sizeof(WTF::AllocAlignmentInteger
) - 1); 
 179         void* freeablePool(); 
 180         void allocateFreeablePool(); 
 181         void deallocateObjects(); 
 183         char* m_freeableMemory
; 
 184         char* m_freeablePoolEnd
; 
 186         std::unique_ptr
<IdentifierArena
> m_identifierArena
; 
 187         Vector
<void*> m_freeablePools
; 
 188         Vector
<ParserArenaDeletable
*> m_deletableObjects
;