+ 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();
+ }
+