]>
Commit | Line | Data |
---|---|---|
9dae56ea | 1 | /* |
93a37866 | 2 | * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights reserved. |
9dae56ea A |
3 | * |
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. | |
8 | * | |
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. | |
13 | * | |
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. | |
18 | * | |
19 | */ | |
20 | ||
21 | #include "config.h" | |
22 | #include "Identifier.h" | |
23 | ||
24 | #include "CallFrame.h" | |
14957cd0 | 25 | #include "JSObject.h" |
93a37866 | 26 | #include "JSScope.h" |
4e4e5a6f | 27 | #include "NumericStrings.h" |
93a37866 A |
28 | #include "Operations.h" |
29 | #include <new> | |
30 | #include <string.h> | |
9dae56ea A |
31 | #include <wtf/Assertions.h> |
32 | #include <wtf/FastMalloc.h> | |
33 | #include <wtf/HashSet.h> | |
93a37866 | 34 | #include <wtf/text/ASCIIFastPath.h> |
4e4e5a6f | 35 | #include <wtf/text/StringHash.h> |
9dae56ea | 36 | |
f9bf01c6 A |
37 | using WTF::ThreadSpecific; |
38 | ||
9dae56ea A |
39 | namespace JSC { |
40 | ||
9dae56ea A |
41 | IdentifierTable* createIdentifierTable() |
42 | { | |
43 | return new IdentifierTable; | |
44 | } | |
45 | ||
46 | void deleteIdentifierTable(IdentifierTable* table) | |
47 | { | |
48 | delete table; | |
49 | } | |
50 | ||
93a37866 | 51 | struct IdentifierASCIIStringTranslator { |
6fe7ccc8 | 52 | static unsigned hash(const LChar* c) |
9dae56ea | 53 | { |
93a37866 | 54 | return StringHasher::computeHashAndMaskTop8Bits(c); |
9dae56ea A |
55 | } |
56 | ||
6fe7ccc8 | 57 | static bool equal(StringImpl* r, const LChar* s) |
9dae56ea A |
58 | { |
59 | return Identifier::equal(r, s); | |
60 | } | |
61 | ||
6fe7ccc8 | 62 | static void translate(StringImpl*& location, const LChar* c, unsigned hash) |
9dae56ea | 63 | { |
6fe7ccc8 | 64 | size_t length = strlen(reinterpret_cast<const char*>(c)); |
93a37866 A |
65 | location = StringImpl::createFromLiteral(reinterpret_cast<const char*>(c), length).leakRef(); |
66 | location->setHash(hash); | |
9dae56ea A |
67 | } |
68 | }; | |
69 | ||
6fe7ccc8 A |
70 | struct IdentifierLCharFromUCharTranslator { |
71 | static unsigned hash(const CharBuffer<UChar>& buf) | |
72 | { | |
93a37866 | 73 | return StringHasher::computeHashAndMaskTop8Bits(buf.s, buf.length); |
6fe7ccc8 A |
74 | } |
75 | ||
76 | static bool equal(StringImpl* str, const CharBuffer<UChar>& buf) | |
77 | { | |
78 | return Identifier::equal(str, buf.s, buf.length); | |
79 | } | |
80 | ||
81 | static void translate(StringImpl*& location, const CharBuffer<UChar>& buf, unsigned hash) | |
82 | { | |
83 | LChar* d; | |
84 | StringImpl* r = StringImpl::createUninitialized(buf.length, d).leakRef(); | |
93a37866 | 85 | WTF::copyLCharsFromUCharSource(d, buf.s, buf.length); |
6fe7ccc8 A |
86 | r->setHash(hash); |
87 | location = r; | |
88 | } | |
89 | }; | |
90 | ||
93a37866 | 91 | PassRefPtr<StringImpl> Identifier::add(VM* vm, const char* c) |
9dae56ea | 92 | { |
93a37866 A |
93 | ASSERT(c); |
94 | ASSERT(c[0]); | |
9dae56ea | 95 | if (!c[1]) |
93a37866 | 96 | return add(vm, vm->smallStrings.singleCharacterStringRep(c[0])); |
9dae56ea | 97 | |
93a37866 | 98 | IdentifierTable& identifierTable = *vm->identifierTable; |
9dae56ea | 99 | |
93a37866 | 100 | HashSet<StringImpl*>::AddResult addResult = identifierTable.add<const LChar*, IdentifierASCIIStringTranslator>(reinterpret_cast<const LChar*>(c)); |
9dae56ea A |
101 | |
102 | // If the string is newly-translated, then we need to adopt it. | |
103 | // The boolean in the pair tells us if that is so. | |
6fe7ccc8 | 104 | RefPtr<StringImpl> addedString = addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator; |
9dae56ea | 105 | |
9dae56ea A |
106 | return addedString.release(); |
107 | } | |
108 | ||
14957cd0 | 109 | PassRefPtr<StringImpl> Identifier::add(ExecState* exec, const char* c) |
9dae56ea | 110 | { |
93a37866 | 111 | return add(&exec->vm(), c); |
9dae56ea A |
112 | } |
113 | ||
93a37866 | 114 | PassRefPtr<StringImpl> Identifier::add8(VM* vm, const UChar* s, int length) |
14957cd0 | 115 | { |
6fe7ccc8 A |
116 | if (length == 1) { |
117 | UChar c = s[0]; | |
118 | ASSERT(c <= 0xff); | |
119 | if (canUseSingleCharacterString(c)) | |
93a37866 | 120 | return add(vm, vm->smallStrings.singleCharacterStringRep(c)); |
6fe7ccc8 A |
121 | } |
122 | ||
14957cd0 | 123 | if (!length) |
6fe7ccc8 | 124 | return StringImpl::empty(); |
93a37866 A |
125 | CharBuffer<UChar> buf = { s, static_cast<unsigned>(length) }; |
126 | HashSet<StringImpl*>::AddResult addResult = vm->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(buf); | |
6fe7ccc8 A |
127 | |
128 | // If the string is newly-translated, then we need to adopt it. | |
129 | // The boolean in the pair tells us if that is so. | |
130 | return addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator; | |
131 | } | |
14957cd0 | 132 | |
93a37866 | 133 | PassRefPtr<StringImpl> Identifier::addSlowCase(VM* vm, StringImpl* r) |
9dae56ea | 134 | { |
f9bf01c6 | 135 | ASSERT(!r->isIdentifier()); |
4e4e5a6f A |
136 | // The empty & null strings are static singletons, and static strings are handled |
137 | // in ::add() in the header, so we should never get here with a zero length string. | |
138 | ASSERT(r->length()); | |
139 | ||
140 | if (r->length() == 1) { | |
6fe7ccc8 | 141 | UChar c = (*r)[0]; |
14957cd0 | 142 | if (c <= maxSingleCharacterString) |
93a37866 | 143 | r = vm->smallStrings.singleCharacterStringRep(c); |
4e4e5a6f | 144 | if (r->isIdentifier()) |
9dae56ea | 145 | return r; |
9dae56ea | 146 | } |
4e4e5a6f | 147 | |
93a37866 | 148 | return *vm->identifierTable->add(r).iterator; |
9dae56ea A |
149 | } |
150 | ||
14957cd0 | 151 | PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r) |
9dae56ea | 152 | { |
93a37866 | 153 | return addSlowCase(&exec->vm(), r); |
9dae56ea A |
154 | } |
155 | ||
4e4e5a6f | 156 | Identifier Identifier::from(ExecState* exec, unsigned value) |
9dae56ea | 157 | { |
93a37866 | 158 | return Identifier(exec, exec->vm().numericStrings.add(value)); |
9dae56ea A |
159 | } |
160 | ||
4e4e5a6f | 161 | Identifier Identifier::from(ExecState* exec, int value) |
9dae56ea | 162 | { |
93a37866 | 163 | return Identifier(exec, exec->vm().numericStrings.add(value)); |
9dae56ea A |
164 | } |
165 | ||
4e4e5a6f | 166 | Identifier Identifier::from(ExecState* exec, double value) |
9dae56ea | 167 | { |
93a37866 | 168 | return Identifier(exec, exec->vm().numericStrings.add(value)); |
9dae56ea A |
169 | } |
170 | ||
93a37866 | 171 | Identifier Identifier::from(VM* vm, unsigned value) |
14957cd0 | 172 | { |
93a37866 | 173 | return Identifier(vm, vm->numericStrings.add(value)); |
14957cd0 A |
174 | } |
175 | ||
93a37866 | 176 | Identifier Identifier::from(VM* vm, int value) |
14957cd0 | 177 | { |
93a37866 | 178 | return Identifier(vm, vm->numericStrings.add(value)); |
14957cd0 A |
179 | } |
180 | ||
93a37866 | 181 | Identifier Identifier::from(VM* vm, double value) |
14957cd0 | 182 | { |
93a37866 | 183 | return Identifier(vm, vm->numericStrings.add(value)); |
14957cd0 A |
184 | } |
185 | ||
4e4e5a6f | 186 | #ifndef NDEBUG |
9dae56ea | 187 | |
93a37866 | 188 | void Identifier::checkCurrentIdentifierTable(VM* vm) |
9dae56ea | 189 | { |
4e4e5a6f | 190 | // Check the identifier table accessible through the threadspecific matches the |
93a37866 A |
191 | // vm's identifier table. |
192 | ASSERT_UNUSED(vm, vm->identifierTable == wtfThreadData().currentIdentifierTable()); | |
9dae56ea A |
193 | } |
194 | ||
4e4e5a6f | 195 | void Identifier::checkCurrentIdentifierTable(ExecState* exec) |
f9bf01c6 | 196 | { |
93a37866 | 197 | checkCurrentIdentifierTable(&exec->vm()); |
f9bf01c6 A |
198 | } |
199 | ||
4e4e5a6f | 200 | #else |
f9bf01c6 | 201 | |
4e4e5a6f | 202 | // These only exists so that our exports are the same for debug and release builds. |
93a37866 A |
203 | // This would be an RELEASE_ASSERT_NOT_REACHED(), but we're in NDEBUG only code here! |
204 | NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(VM*) { CRASH(); } | |
6fe7ccc8 | 205 | NO_RETURN_DUE_TO_CRASH void Identifier::checkCurrentIdentifierTable(ExecState*) { CRASH(); } |
f9bf01c6 A |
206 | |
207 | #endif | |
208 | ||
9dae56ea | 209 | } // namespace JSC |