|
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 js::AtomStateEntry::asPtr() const |
|
22 { |
|
23 JS_ASSERT(bits != 0); |
|
24 JSAtom *atom = reinterpret_cast<JSAtom *>(bits & NO_TAG_MASK); |
|
25 JSString::readBarrier(atom); |
|
26 return atom; |
|
27 } |
|
28 |
|
29 namespace js { |
|
30 |
|
31 inline jsid |
|
32 AtomToId(JSAtom *atom) |
|
33 { |
|
34 JS_STATIC_ASSERT(JSID_INT_MIN == 0); |
|
35 |
|
36 uint32_t index; |
|
37 if (atom->isIndex(&index) && index <= JSID_INT_MAX) |
|
38 return INT_TO_JSID(int32_t(index)); |
|
39 |
|
40 return JSID_FROM_BITS(size_t(atom)); |
|
41 } |
|
42 |
|
43 inline bool |
|
44 ValueToIdPure(const Value &v, jsid *id) |
|
45 { |
|
46 int32_t i; |
|
47 if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) { |
|
48 *id = INT_TO_JSID(i); |
|
49 return true; |
|
50 } |
|
51 |
|
52 if (!v.isString() || !v.toString()->isAtom()) |
|
53 return false; |
|
54 |
|
55 *id = AtomToId(&v.toString()->asAtom()); |
|
56 return true; |
|
57 } |
|
58 |
|
59 template <AllowGC allowGC> |
|
60 inline bool |
|
61 ValueToId(JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType v, |
|
62 typename MaybeRooted<jsid, allowGC>::MutableHandleType idp) |
|
63 { |
|
64 int32_t i; |
|
65 if (ValueFitsInInt32(v, &i) && INT_FITS_IN_JSID(i)) { |
|
66 idp.set(INT_TO_JSID(i)); |
|
67 return true; |
|
68 } |
|
69 |
|
70 JSAtom *atom = ToAtom<allowGC>(cx, v); |
|
71 if (!atom) |
|
72 return false; |
|
73 |
|
74 idp.set(AtomToId(atom)); |
|
75 return true; |
|
76 } |
|
77 |
|
78 /* |
|
79 * Write out character representing |index| to the memory just before |end|. |
|
80 * Thus |*end| is not touched, but |end[-1]| and earlier are modified as |
|
81 * appropriate. There must be at least js::UINT32_CHAR_BUFFER_LENGTH elements |
|
82 * before |end| to avoid buffer underflow. The start of the characters written |
|
83 * is returned and is necessarily before |end|. |
|
84 */ |
|
85 template <typename T> |
|
86 inline mozilla::RangedPtr<T> |
|
87 BackfillIndexInCharBuffer(uint32_t index, mozilla::RangedPtr<T> end) |
|
88 { |
|
89 #ifdef DEBUG |
|
90 /* |
|
91 * Assert that the buffer we're filling will hold as many characters as we |
|
92 * could write out, by dereferencing the index that would hold the most |
|
93 * significant digit. |
|
94 */ |
|
95 (void) *(end - UINT32_CHAR_BUFFER_LENGTH); |
|
96 #endif |
|
97 |
|
98 do { |
|
99 uint32_t next = index / 10, digit = index % 10; |
|
100 *--end = '0' + digit; |
|
101 index = next; |
|
102 } while (index > 0); |
|
103 |
|
104 return end; |
|
105 } |
|
106 |
|
107 bool |
|
108 IndexToIdSlow(ExclusiveContext *cx, uint32_t index, MutableHandleId idp); |
|
109 |
|
110 inline bool |
|
111 IndexToId(ExclusiveContext *cx, uint32_t index, MutableHandleId idp) |
|
112 { |
|
113 if (index <= JSID_INT_MAX) { |
|
114 idp.set(INT_TO_JSID(index)); |
|
115 return true; |
|
116 } |
|
117 |
|
118 return IndexToIdSlow(cx, index, idp); |
|
119 } |
|
120 |
|
121 static MOZ_ALWAYS_INLINE JSFlatString * |
|
122 IdToString(JSContext *cx, jsid id) |
|
123 { |
|
124 if (JSID_IS_STRING(id)) |
|
125 return JSID_TO_ATOM(id); |
|
126 |
|
127 if (MOZ_LIKELY(JSID_IS_INT(id))) |
|
128 return Int32ToString<CanGC>(cx, JSID_TO_INT(id)); |
|
129 |
|
130 RootedValue idv(cx, IdToValue(id)); |
|
131 JSString *str = ToStringSlow<CanGC>(cx, idv); |
|
132 if (!str) |
|
133 return nullptr; |
|
134 |
|
135 return str->ensureFlat(cx); |
|
136 } |
|
137 |
|
138 inline |
|
139 AtomHasher::Lookup::Lookup(const JSAtom *atom) |
|
140 : chars(atom->chars()), length(atom->length()), atom(atom) |
|
141 { |
|
142 hash = mozilla::HashString(chars, length); |
|
143 } |
|
144 |
|
145 inline bool |
|
146 AtomHasher::match(const AtomStateEntry &entry, const Lookup &lookup) |
|
147 { |
|
148 JSAtom *key = entry.asPtr(); |
|
149 if (lookup.atom) |
|
150 return lookup.atom == key; |
|
151 if (key->length() != lookup.length) |
|
152 return false; |
|
153 return mozilla::PodEqual(key->chars(), lookup.chars, lookup.length); |
|
154 } |
|
155 |
|
156 inline Handle<PropertyName*> |
|
157 TypeName(JSType type, const JSAtomState &names) |
|
158 { |
|
159 JS_ASSERT(type < JSTYPE_LIMIT); |
|
160 JS_STATIC_ASSERT(offsetof(JSAtomState, undefined) + |
|
161 JSTYPE_LIMIT * sizeof(FixedHeapPtr<PropertyName>) <= |
|
162 sizeof(JSAtomState)); |
|
163 JS_STATIC_ASSERT(JSTYPE_VOID == 0); |
|
164 return (&names.undefined)[type]; |
|
165 } |
|
166 |
|
167 inline Handle<PropertyName*> |
|
168 ClassName(JSProtoKey key, JSAtomState &atomState) |
|
169 { |
|
170 JS_ASSERT(key < JSProto_LIMIT); |
|
171 JS_STATIC_ASSERT(offsetof(JSAtomState, Null) + |
|
172 JSProto_LIMIT * sizeof(FixedHeapPtr<PropertyName>) <= |
|
173 sizeof(JSAtomState)); |
|
174 JS_STATIC_ASSERT(JSProto_Null == 0); |
|
175 return (&atomState.Null)[key]; |
|
176 } |
|
177 |
|
178 inline Handle<PropertyName*> |
|
179 ClassName(JSProtoKey key, JSRuntime *rt) |
|
180 { |
|
181 return ClassName(key, *rt->commonNames); |
|
182 } |
|
183 |
|
184 inline Handle<PropertyName*> |
|
185 ClassName(JSProtoKey key, ExclusiveContext *cx) |
|
186 { |
|
187 return ClassName(key, cx->names()); |
|
188 } |
|
189 |
|
190 } // namespace js |
|
191 |
|
192 #endif /* jsatominlines_h */ |