2 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
25 #include <wtf/ThreadSpecific.h>
26 #include <wtf/WTFThreadData.h>
27 #include <wtf/text/CString.h>
28 #include <wtf/text/WTFString.h>
35 friend class Structure
;
38 enum EmptyIdentifierFlag
{ EmptyIdentifier
};
39 Identifier(EmptyIdentifierFlag
) : m_string(StringImpl::empty()) { }
41 // Only to be used with string literals.
42 template<unsigned charactersCount
>
43 Identifier(ExecState
* exec
, const char (&characters
)[charactersCount
]) : m_string(add(exec
, characters
)) { }
44 template<unsigned charactersCount
>
45 Identifier(VM
* vm
, const char (&characters
)[charactersCount
]) : m_string(add(vm
, characters
)) { }
47 Identifier(ExecState
* exec
, StringImpl
* rep
) : m_string(add(exec
, rep
)) { }
48 Identifier(ExecState
* exec
, const String
& s
) : m_string(add(exec
, s
.impl())) { }
50 Identifier(VM
* vm
, const LChar
* s
, int length
) : m_string(add(vm
, s
, length
)) { }
51 Identifier(VM
* vm
, const UChar
* s
, int length
) : m_string(add(vm
, s
, length
)) { }
52 Identifier(VM
* vm
, StringImpl
* rep
) : m_string(add(vm
, rep
)) { }
53 Identifier(VM
* vm
, const String
& s
) : m_string(add(vm
, s
.impl())) { }
55 const String
& string() const { return m_string
; }
56 StringImpl
* impl() const { return m_string
.impl(); }
58 const UChar
* characters() const { return m_string
.characters(); }
59 int length() const { return m_string
.length(); }
61 CString
ascii() const { return m_string
.ascii(); }
63 static Identifier
createLCharFromUChar(VM
* vm
, const UChar
* s
, int length
) { return Identifier(vm
, add8(vm
, s
, length
)); }
65 JS_EXPORT_PRIVATE
static Identifier
from(ExecState
* exec
, unsigned y
);
66 JS_EXPORT_PRIVATE
static Identifier
from(ExecState
* exec
, int y
);
67 static Identifier
from(ExecState
* exec
, double y
);
68 static Identifier
from(VM
*, unsigned y
);
69 static Identifier
from(VM
*, int y
);
70 static Identifier
from(VM
*, double y
);
72 bool isNull() const { return m_string
.isNull(); }
73 bool isEmpty() const { return m_string
.isEmpty(); }
75 friend bool operator==(const Identifier
&, const Identifier
&);
76 friend bool operator!=(const Identifier
&, const Identifier
&);
78 friend bool operator==(const Identifier
&, const LChar
*);
79 friend bool operator==(const Identifier
&, const char*);
80 friend bool operator!=(const Identifier
&, const LChar
*);
81 friend bool operator!=(const Identifier
&, const char*);
83 static bool equal(const StringImpl
*, const LChar
*);
84 static inline bool equal(const StringImpl
*a
, const char*b
) { return Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
)); };
85 static bool equal(const StringImpl
*, const LChar
*, unsigned length
);
86 static bool equal(const StringImpl
*, const UChar
*, unsigned length
);
87 static bool equal(const StringImpl
* a
, const StringImpl
* b
) { return ::equal(a
, b
); }
89 // Only to be used with string literals.
90 static PassRefPtr
<StringImpl
> add(VM
*, const char*);
91 JS_EXPORT_PRIVATE
static PassRefPtr
<StringImpl
> add(ExecState
*, const char*);
96 template <typename CharType
>
97 ALWAYS_INLINE
static uint32_t toUInt32FromCharacters(const CharType
* characters
, unsigned length
, bool& ok
);
99 static bool equal(const Identifier
& a
, const Identifier
& b
) { return a
.m_string
.impl() == b
.m_string
.impl(); }
100 static bool equal(const Identifier
& a
, const LChar
* b
) { return equal(a
.m_string
.impl(), b
); }
102 template <typename T
> static PassRefPtr
<StringImpl
> add(VM
*, const T
*, int length
);
103 static PassRefPtr
<StringImpl
> add8(VM
*, const UChar
*, int length
);
104 template <typename T
> ALWAYS_INLINE
static bool canUseSingleCharacterString(T
);
106 static PassRefPtr
<StringImpl
> add(ExecState
* exec
, StringImpl
* r
)
109 checkCurrentIdentifierTable(exec
);
111 if (r
->isIdentifier())
113 return addSlowCase(exec
, r
);
115 static PassRefPtr
<StringImpl
> add(VM
* vm
, StringImpl
* r
)
118 checkCurrentIdentifierTable(vm
);
120 if (r
->isIdentifier())
122 return addSlowCase(vm
, r
);
125 JS_EXPORT_PRIVATE
static PassRefPtr
<StringImpl
> addSlowCase(ExecState
*, StringImpl
* r
);
126 JS_EXPORT_PRIVATE
static PassRefPtr
<StringImpl
> addSlowCase(VM
*, StringImpl
* r
);
128 JS_EXPORT_PRIVATE
static void checkCurrentIdentifierTable(ExecState
*);
129 JS_EXPORT_PRIVATE
static void checkCurrentIdentifierTable(VM
*);
132 template <> ALWAYS_INLINE
bool Identifier::canUseSingleCharacterString(LChar
)
134 ASSERT(maxSingleCharacterString
== 0xff);
138 template <> ALWAYS_INLINE
bool Identifier::canUseSingleCharacterString(UChar c
)
140 return (c
<= maxSingleCharacterString
);
143 template <typename T
>
149 template <typename T
>
150 struct IdentifierCharBufferTranslator
{
151 static unsigned hash(const CharBuffer
<T
>& buf
)
153 return StringHasher::computeHashAndMaskTop8Bits(buf
.s
, buf
.length
);
156 static bool equal(StringImpl
* str
, const CharBuffer
<T
>& buf
)
158 return Identifier::equal(str
, buf
.s
, buf
.length
);
161 static void translate(StringImpl
*& location
, const CharBuffer
<T
>& buf
, unsigned hash
)
164 StringImpl
* r
= StringImpl::createUninitialized(buf
.length
, d
).leakRef();
165 for (unsigned i
= 0; i
!= buf
.length
; i
++)
172 template <typename T
>
173 PassRefPtr
<StringImpl
> Identifier::add(VM
* vm
, const T
* s
, int length
)
177 if (canUseSingleCharacterString(c
))
178 return add(vm
, vm
->smallStrings
.singleCharacterStringRep(c
));
182 return StringImpl::empty();
183 CharBuffer
<T
> buf
= { s
, static_cast<unsigned>(length
) };
184 HashSet
<StringImpl
*>::AddResult addResult
= vm
->identifierTable
->add
<CharBuffer
<T
>, IdentifierCharBufferTranslator
<T
> >(buf
);
186 // If the string is newly-translated, then we need to adopt it.
187 // The boolean in the pair tells us if that is so.
188 return addResult
.isNewEntry
? adoptRef(*addResult
.iterator
) : *addResult
.iterator
;
191 inline bool operator==(const Identifier
& a
, const Identifier
& b
)
193 return Identifier::equal(a
, b
);
196 inline bool operator!=(const Identifier
& a
, const Identifier
& b
)
198 return !Identifier::equal(a
, b
);
201 inline bool operator==(const Identifier
& a
, const LChar
* b
)
203 return Identifier::equal(a
, b
);
206 inline bool operator==(const Identifier
& a
, const char* b
)
208 return Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
));
211 inline bool operator!=(const Identifier
& a
, const LChar
* b
)
213 return !Identifier::equal(a
, b
);
216 inline bool operator!=(const Identifier
& a
, const char* b
)
218 return !Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
));
221 inline bool Identifier::equal(const StringImpl
* r
, const LChar
* s
)
223 return WTF::equal(r
, s
);
226 inline bool Identifier::equal(const StringImpl
* r
, const LChar
* s
, unsigned length
)
228 return WTF::equal(r
, s
, length
);
231 inline bool Identifier::equal(const StringImpl
* r
, const UChar
* s
, unsigned length
)
233 return WTF::equal(r
, s
, length
);
236 IdentifierTable
* createIdentifierTable();
237 void deleteIdentifierTable(IdentifierTable
*);
239 struct IdentifierRepHash
: PtrHash
<RefPtr
<StringImpl
> > {
240 static unsigned hash(const RefPtr
<StringImpl
>& key
) { return key
->existingHash(); }
241 static unsigned hash(StringImpl
* key
) { return key
->existingHash(); }
244 struct IdentifierMapIndexHashTraits
: HashTraits
<int> {
245 static int emptyValue() { return std::numeric_limits
<int>::max(); }
246 static const bool emptyValueIsZero
= false;
249 typedef HashMap
<RefPtr
<StringImpl
>, int, IdentifierRepHash
, HashTraits
<RefPtr
<StringImpl
> >, IdentifierMapIndexHashTraits
> IdentifierMap
;
251 template<typename U
, typename V
>
252 HashSet
<StringImpl
*>::AddResult
IdentifierTable::add(U value
)
254 HashSet
<StringImpl
*>::AddResult result
= m_table
.add
<U
, V
>(value
);
255 (*result
.iterator
)->setIsIdentifier(true);
263 template <> struct VectorTraits
<JSC::Identifier
> : SimpleClassVectorTraits
{ };
267 #endif // Identifier_h