2 * Copyright (C) 2003, 2006, 2007, 2008, 2009 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.
24 #include "JSGlobalData.h"
25 #include <wtf/ThreadSpecific.h>
27 #include <wtf/WTFThreadData.h>
28 #include <wtf/text/CString.h>
35 friend class Structure
;
39 Identifier(ExecState
* exec
, const char* s
) : m_string(add(exec
, s
)) { } // Only to be used with string literals.
40 Identifier(ExecState
* exec
, StringImpl
* rep
) : m_string(add(exec
, rep
)) { }
41 Identifier(ExecState
* exec
, const UString
& s
) : m_string(add(exec
, s
.impl())) { }
43 Identifier(JSGlobalData
* globalData
, const char* s
) : m_string(add(globalData
, s
)) { } // Only to be used with string literals.
44 Identifier(JSGlobalData
* globalData
, const LChar
* s
, int length
) : m_string(add(globalData
, s
, length
)) { }
45 Identifier(JSGlobalData
* globalData
, const UChar
* s
, int length
) : m_string(add(globalData
, s
, length
)) { }
46 Identifier(JSGlobalData
* globalData
, StringImpl
* rep
) : m_string(add(globalData
, rep
)) { }
47 Identifier(JSGlobalData
* globalData
, const UString
& s
) : m_string(add(globalData
, s
.impl())) { }
49 const UString
& ustring() const { return m_string
; }
50 StringImpl
* impl() const { return m_string
.impl(); }
52 const UChar
* characters() const { return m_string
.characters(); }
53 int length() const { return m_string
.length(); }
55 CString
ascii() const { return m_string
.ascii(); }
57 static Identifier
createLCharFromUChar(JSGlobalData
* globalData
, const UChar
* s
, int length
) { return Identifier(globalData
, add8(globalData
, s
, length
)); }
59 JS_EXPORT_PRIVATE
static Identifier
from(ExecState
* exec
, unsigned y
);
60 JS_EXPORT_PRIVATE
static Identifier
from(ExecState
* exec
, int y
);
61 static Identifier
from(ExecState
* exec
, double y
);
62 static Identifier
from(JSGlobalData
*, unsigned y
);
63 static Identifier
from(JSGlobalData
*, int y
);
64 static Identifier
from(JSGlobalData
*, double y
);
66 JS_EXPORT_PRIVATE
static uint32_t toUInt32(const UString
&, bool& ok
);
67 uint32_t toUInt32(bool& ok
) const { return toUInt32(m_string
, ok
); }
68 unsigned toArrayIndex(bool& ok
) const;
70 bool isNull() const { return m_string
.isNull(); }
71 bool isEmpty() const { return m_string
.isEmpty(); }
73 friend bool operator==(const Identifier
&, const Identifier
&);
74 friend bool operator!=(const Identifier
&, const Identifier
&);
76 friend bool operator==(const Identifier
&, const LChar
*);
77 friend bool operator==(const Identifier
&, const char*);
78 friend bool operator!=(const Identifier
&, const LChar
*);
79 friend bool operator!=(const Identifier
&, const char*);
81 static bool equal(const StringImpl
*, const LChar
*);
82 static inline bool equal(const StringImpl
*a
, const char*b
) { return Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
)); };
83 static bool equal(const StringImpl
*, const LChar
*, unsigned length
);
84 static bool equal(const StringImpl
*, const UChar
*, unsigned length
);
85 static bool equal(const StringImpl
* a
, const StringImpl
* b
) { return ::equal(a
, b
); }
87 JS_EXPORT_PRIVATE
static PassRefPtr
<StringImpl
> add(ExecState
*, const char*); // Only to be used with string literals.
88 static PassRefPtr
<StringImpl
> add(JSGlobalData
*, const char*); // Only to be used with string literals.
93 template <typename CharType
>
94 ALWAYS_INLINE
static uint32_t toUInt32FromCharacters(const CharType
* characters
, unsigned length
, bool& ok
);
96 static bool equal(const Identifier
& a
, const Identifier
& b
) { return a
.m_string
.impl() == b
.m_string
.impl(); }
97 static bool equal(const Identifier
& a
, const LChar
* b
) { return equal(a
.m_string
.impl(), b
); }
99 template <typename T
> static PassRefPtr
<StringImpl
> add(JSGlobalData
*, const T
*, int length
);
100 static PassRefPtr
<StringImpl
> add8(JSGlobalData
*, const UChar
*, int length
);
101 template <typename T
> ALWAYS_INLINE
static bool canUseSingleCharacterString(T
);
103 static PassRefPtr
<StringImpl
> add(ExecState
* exec
, StringImpl
* r
)
106 checkCurrentIdentifierTable(exec
);
108 if (r
->isIdentifier())
110 return addSlowCase(exec
, r
);
112 static PassRefPtr
<StringImpl
> add(JSGlobalData
* globalData
, StringImpl
* r
)
115 checkCurrentIdentifierTable(globalData
);
117 if (r
->isIdentifier())
119 return addSlowCase(globalData
, r
);
122 JS_EXPORT_PRIVATE
static PassRefPtr
<StringImpl
> addSlowCase(ExecState
*, StringImpl
* r
);
123 JS_EXPORT_PRIVATE
static PassRefPtr
<StringImpl
> addSlowCase(JSGlobalData
*, StringImpl
* r
);
125 JS_EXPORT_PRIVATE
static void checkCurrentIdentifierTable(ExecState
*);
126 JS_EXPORT_PRIVATE
static void checkCurrentIdentifierTable(JSGlobalData
*);
129 template <> ALWAYS_INLINE
bool Identifier::canUseSingleCharacterString(LChar
)
131 ASSERT(maxSingleCharacterString
== 0xff);
135 template <> ALWAYS_INLINE
bool Identifier::canUseSingleCharacterString(UChar c
)
137 return (c
<= maxSingleCharacterString
);
140 template <typename T
>
146 template <typename T
>
147 struct IdentifierCharBufferTranslator
{
148 static unsigned hash(const CharBuffer
<T
>& buf
)
150 return StringHasher::computeHash
<T
>(buf
.s
, buf
.length
);
153 static bool equal(StringImpl
* str
, const CharBuffer
<T
>& buf
)
155 return Identifier::equal(str
, buf
.s
, buf
.length
);
158 static void translate(StringImpl
*& location
, const CharBuffer
<T
>& buf
, unsigned hash
)
161 StringImpl
* r
= StringImpl::createUninitialized(buf
.length
, d
).leakRef();
162 for (unsigned i
= 0; i
!= buf
.length
; i
++)
169 template <typename T
>
170 PassRefPtr
<StringImpl
> Identifier::add(JSGlobalData
* globalData
, const T
* s
, int length
)
174 if (canUseSingleCharacterString(c
))
175 return add(globalData
, globalData
->smallStrings
.singleCharacterStringRep(c
));
179 return StringImpl::empty();
180 CharBuffer
<T
> buf
= {s
, length
};
181 HashSet
<StringImpl
*>::AddResult addResult
= globalData
->identifierTable
->add
<CharBuffer
<T
>, IdentifierCharBufferTranslator
<T
> >(buf
);
183 // If the string is newly-translated, then we need to adopt it.
184 // The boolean in the pair tells us if that is so.
185 return addResult
.isNewEntry
? adoptRef(*addResult
.iterator
) : *addResult
.iterator
;
188 inline bool operator==(const Identifier
& a
, const Identifier
& b
)
190 return Identifier::equal(a
, b
);
193 inline bool operator!=(const Identifier
& a
, const Identifier
& b
)
195 return !Identifier::equal(a
, b
);
198 inline bool operator==(const Identifier
& a
, const LChar
* b
)
200 return Identifier::equal(a
, b
);
203 inline bool operator==(const Identifier
& a
, const char* b
)
205 return Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
));
208 inline bool operator!=(const Identifier
& a
, const LChar
* b
)
210 return !Identifier::equal(a
, b
);
213 inline bool operator!=(const Identifier
& a
, const char* b
)
215 return !Identifier::equal(a
, reinterpret_cast<const LChar
*>(b
));
218 inline bool Identifier::equal(const StringImpl
* r
, const LChar
* s
)
220 return WTF::equal(r
, s
);
223 inline bool Identifier::equal(const StringImpl
* r
, const LChar
* s
, unsigned length
)
225 return WTF::equal(r
, s
, length
);
228 inline bool Identifier::equal(const StringImpl
* r
, const UChar
* s
, unsigned length
)
230 return WTF::equal(r
, s
, length
);
233 IdentifierTable
* createIdentifierTable();
234 void deleteIdentifierTable(IdentifierTable
*);
236 struct IdentifierRepHash
: PtrHash
<RefPtr
<StringImpl
> > {
237 static unsigned hash(const RefPtr
<StringImpl
>& key
) { return key
->existingHash(); }
238 static unsigned hash(StringImpl
* key
) { return key
->existingHash(); }
241 struct IdentifierMapIndexHashTraits
: HashTraits
<int> {
242 static int emptyValue() { return std::numeric_limits
<int>::max(); }
243 static const bool emptyValueIsZero
= false;
246 typedef HashMap
<RefPtr
<StringImpl
>, int, IdentifierRepHash
, HashTraits
<RefPtr
<StringImpl
> >, IdentifierMapIndexHashTraits
> IdentifierMap
;
248 template<typename U
, typename V
>
249 HashSet
<StringImpl
*>::AddResult
IdentifierTable::add(U value
)
251 HashSet
<StringImpl
*>::AddResult result
= m_table
.add
<U
, V
>(value
);
252 (*result
.iterator
)->setIsIdentifier(true);
258 #endif // Identifier_h