Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : * This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef jsatominlines_h
8 : #define jsatominlines_h
9 :
10 : #include "jsatom.h"
11 :
12 : #include "mozilla/PodOperations.h"
13 : #include "mozilla/RangedPtr.h"
14 :
15 : #include "jscntxt.h"
16 : #include "jsnum.h"
17 :
18 : #include "vm/String.h"
19 :
20 : inline JSAtom*
21 48039 : js::AtomStateEntry::asPtr(JSContext* cx) const
22 : {
23 48039 : JSAtom* atom = asPtrUnbarriered();
24 48039 : if (!cx->helperThread())
25 40383 : JSString::readBarrier(atom);
26 48040 : return atom;
27 : }
28 :
29 : inline JSAtom*
30 1233272 : js::AtomStateEntry::asPtrUnbarriered() const
31 : {
32 1233272 : MOZ_ASSERT(bits != 0);
33 1233272 : return reinterpret_cast<JSAtom*>(bits & NO_TAG_MASK);
34 : }
35 :
36 : namespace js {
37 :
38 : inline jsid
39 448813 : AtomToId(JSAtom* atom)
40 : {
41 : JS_STATIC_ASSERT(JSID_INT_MIN == 0);
42 :
43 : uint32_t index;
44 448813 : if (atom->isIndex(&index) && index <= JSID_INT_MAX)
45 16 : return INT_TO_JSID(int32_t(index));
46 :
47 448799 : return JSID_FROM_BITS(size_t(atom));
48 : }
49 :
50 : inline bool
51 4 : ValueToIdPure(const Value& v, jsid* id)
52 : {
53 4 : if (v.isString()) {
54 1 : if (v.toString()->isAtom()) {
55 1 : *id = AtomToId(&v.toString()->asAtom());
56 1 : return true;
57 : }
58 0 : return false;
59 : }
60 :
61 : int32_t i;
62 3 : if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) {
63 0 : *id = INT_TO_JSID(i);
64 0 : return true;
65 : }
66 :
67 3 : if (js::IsSymbolOrSymbolWrapper(v)) {
68 3 : *id = SYMBOL_TO_JSID(js::ToSymbolPrimitive(v));
69 3 : return true;
70 : }
71 :
72 0 : return false;
73 : }
74 :
75 : template <AllowGC allowGC>
76 : inline bool
77 30120 : ValueToId(JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType v,
78 : typename MaybeRooted<jsid, allowGC>::MutableHandleType idp)
79 : {
80 30120 : if (v.isString()) {
81 27503 : if (v.toString()->isAtom()) {
82 22947 : idp.set(AtomToId(&v.toString()->asAtom()));
83 22947 : return true;
84 : }
85 : } else {
86 : int32_t i;
87 2617 : if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) {
88 1359 : idp.set(INT_TO_JSID(i));
89 3967 : return true;
90 : }
91 :
92 1258 : if (js::IsSymbolOrSymbolWrapper(v)) {
93 1249 : idp.set(SYMBOL_TO_JSID(js::ToSymbolPrimitive(v)));
94 1249 : return true;
95 : }
96 : }
97 :
98 4565 : JSAtom* atom = ToAtom<allowGC>(cx, v);
99 4565 : if (!atom)
100 0 : return false;
101 :
102 4565 : idp.set(AtomToId(atom));
103 4565 : return true;
104 : }
105 :
106 : /*
107 : * Write out character representing |index| to the memory just before |end|.
108 : * Thus |*end| is not touched, but |end[-1]| and earlier are modified as
109 : * appropriate. There must be at least js::UINT32_CHAR_BUFFER_LENGTH elements
110 : * before |end| to avoid buffer underflow. The start of the characters written
111 : * is returned and is necessarily before |end|.
112 : */
113 : template <typename T>
114 : inline mozilla::RangedPtr<T>
115 463 : BackfillIndexInCharBuffer(uint32_t index, mozilla::RangedPtr<T> end)
116 : {
117 : #ifdef DEBUG
118 : /*
119 : * Assert that the buffer we're filling will hold as many characters as we
120 : * could write out, by dereferencing the index that would hold the most
121 : * significant digit.
122 : */
123 463 : (void) *(end - UINT32_CHAR_BUFFER_LENGTH);
124 : #endif
125 :
126 1163 : do {
127 1626 : uint32_t next = index / 10, digit = index % 10;
128 1626 : *--end = '0' + digit;
129 1626 : index = next;
130 1626 : } while (index > 0);
131 :
132 463 : return end;
133 : }
134 :
135 : bool
136 : IndexToIdSlow(JSContext* cx, uint32_t index, MutableHandleId idp);
137 :
138 : inline bool
139 6784 : IndexToId(JSContext* cx, uint32_t index, MutableHandleId idp)
140 : {
141 6784 : if (index <= JSID_INT_MAX) {
142 6784 : idp.set(INT_TO_JSID(index));
143 6784 : return true;
144 : }
145 :
146 0 : return IndexToIdSlow(cx, index, idp);
147 : }
148 :
149 : static MOZ_ALWAYS_INLINE JSFlatString*
150 945 : IdToString(JSContext* cx, jsid id)
151 : {
152 945 : if (JSID_IS_STRING(id))
153 944 : return JSID_TO_ATOM(id);
154 :
155 1 : if (MOZ_LIKELY(JSID_IS_INT(id)))
156 1 : return Int32ToString<CanGC>(cx, JSID_TO_INT(id));
157 :
158 0 : RootedValue idv(cx, IdToValue(id));
159 0 : JSString* str = ToStringSlow<CanGC>(cx, idv);
160 0 : if (!str)
161 0 : return nullptr;
162 :
163 0 : return str->ensureFlat(cx);
164 : }
165 :
166 : inline
167 488040 : AtomHasher::Lookup::Lookup(const JSAtom* atom)
168 488040 : : isLatin1(atom->hasLatin1Chars()), length(atom->length()), atom(atom)
169 : {
170 488043 : hash = atom->hash();
171 488043 : if (isLatin1) {
172 488040 : latin1Chars = atom->latin1Chars(nogc);
173 488041 : MOZ_ASSERT(mozilla::HashString(latin1Chars, length) == hash);
174 : } else {
175 3 : twoByteChars = atom->twoByteChars(nogc);
176 3 : MOZ_ASSERT(mozilla::HashString(twoByteChars, length) == hash);
177 : }
178 488040 : }
179 :
180 : MOZ_ALWAYS_INLINE bool
181 850145 : AtomHasher::match(const AtomStateEntry& entry, const Lookup& lookup)
182 : {
183 850145 : JSAtom* key = entry.asPtrUnbarriered();
184 850189 : if (lookup.atom)
185 488044 : return lookup.atom == key;
186 362145 : if (key->length() != lookup.length || key->hash() != lookup.hash)
187 0 : return false;
188 :
189 362148 : if (key->hasLatin1Chars()) {
190 362147 : const Latin1Char* keyChars = key->latin1Chars(lookup.nogc);
191 362151 : if (lookup.isLatin1)
192 222807 : return mozilla::PodEqual(keyChars, lookup.latin1Chars, lookup.length);
193 139344 : return EqualChars(keyChars, lookup.twoByteChars, lookup.length);
194 : }
195 :
196 1 : const char16_t* keyChars = key->twoByteChars(lookup.nogc);
197 1 : if (lookup.isLatin1)
198 0 : return EqualChars(lookup.latin1Chars, keyChars, lookup.length);
199 1 : return mozilla::PodEqual(keyChars, lookup.twoByteChars, lookup.length);
200 : }
201 :
202 : inline Handle<PropertyName*>
203 1133 : TypeName(JSType type, const JSAtomState& names)
204 : {
205 1133 : MOZ_ASSERT(type < JSTYPE_LIMIT);
206 : JS_STATIC_ASSERT(offsetof(JSAtomState, undefined) +
207 : JSTYPE_LIMIT * sizeof(ImmutablePropertyNamePtr) <=
208 : sizeof(JSAtomState));
209 : JS_STATIC_ASSERT(JSTYPE_UNDEFINED == 0);
210 1133 : return (&names.undefined)[type];
211 : }
212 :
213 : inline Handle<PropertyName*>
214 1748 : ClassName(JSProtoKey key, JSAtomState& atomState)
215 : {
216 1748 : MOZ_ASSERT(key < JSProto_LIMIT);
217 : JS_STATIC_ASSERT(offsetof(JSAtomState, Null) +
218 : JSProto_LIMIT * sizeof(ImmutablePropertyNamePtr) <=
219 : sizeof(JSAtomState));
220 : JS_STATIC_ASSERT(JSProto_Null == 0);
221 1748 : return (&atomState.Null)[key];
222 : }
223 :
224 : inline Handle<PropertyName*>
225 1748 : ClassName(JSProtoKey key, JSContext* cx)
226 : {
227 1748 : return ClassName(key, cx->names());
228 : }
229 :
230 : } // namespace js
231 :
232 : #endif /* jsatominlines_h */
|