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 jsatom_h
8 : #define jsatom_h
9 :
10 : #include "mozilla/HashFunctions.h"
11 : #include "mozilla/Maybe.h"
12 :
13 : #include "jsalloc.h"
14 :
15 : #include "gc/Barrier.h"
16 : #include "gc/Marking.h"
17 : #include "gc/Rooting.h"
18 : #include "js/GCAPI.h"
19 : #include "js/GCHashTable.h"
20 : #include "vm/CommonPropertyNames.h"
21 :
22 : class JSAtom;
23 : class JSAutoByteString;
24 :
25 : namespace js {
26 :
27 : /*
28 : * Return a printable, lossless char[] representation of a string-type atom.
29 : * The lifetime of the result matches the lifetime of bytes.
30 : */
31 : extern const char*
32 : AtomToPrintableString(JSContext* cx, JSAtom* atom, JSAutoByteString* bytes);
33 :
34 : class AtomStateEntry
35 : {
36 : uintptr_t bits;
37 :
38 : static const uintptr_t NO_TAG_MASK = uintptr_t(-1) - 1;
39 :
40 : public:
41 : AtomStateEntry() : bits(0) {}
42 335789 : AtomStateEntry(const AtomStateEntry& other) : bits(other.bits) {}
43 143258 : AtomStateEntry(JSAtom* ptr, bool tagged)
44 143258 : : bits(uintptr_t(ptr) | uintptr_t(tagged))
45 : {
46 143258 : MOZ_ASSERT((uintptr_t(ptr) & 0x1) == 0);
47 143258 : }
48 :
49 526331 : bool isPinned() const {
50 526331 : return bits & 0x1;
51 : }
52 :
53 : /*
54 : * Non-branching code sequence. Note that the const_cast is safe because
55 : * the hash function doesn't consider the tag to be a portion of the key.
56 : */
57 32707 : void setPinned(bool pinned) const {
58 32707 : const_cast<AtomStateEntry*>(this)->bits |= uintptr_t(pinned);
59 32707 : }
60 :
61 : JSAtom* asPtr(JSContext* cx) const;
62 : JSAtom* asPtrUnbarriered() const;
63 :
64 0 : bool needsSweep() {
65 0 : JSAtom* atom = asPtrUnbarriered();
66 0 : return gc::IsAboutToBeFinalizedUnbarriered(&atom);
67 : }
68 : };
69 :
70 : struct AtomHasher
71 : {
72 912682 : struct Lookup
73 : {
74 : union {
75 : const JS::Latin1Char* latin1Chars;
76 : const char16_t* twoByteChars;
77 : };
78 : bool isLatin1;
79 : size_t length;
80 : const JSAtom* atom; /* Optional. */
81 : JS::AutoCheckCannotGC nogc;
82 :
83 : HashNumber hash;
84 :
85 160106 : MOZ_ALWAYS_INLINE Lookup(const char16_t* chars, size_t length)
86 160106 : : twoByteChars(chars), isLatin1(false), length(length), atom(nullptr)
87 : {
88 160106 : hash = mozilla::HashString(chars, length);
89 160106 : }
90 264610 : MOZ_ALWAYS_INLINE Lookup(const JS::Latin1Char* chars, size_t length)
91 264610 : : latin1Chars(chars), isLatin1(true), length(length), atom(nullptr)
92 : {
93 264615 : hash = mozilla::HashString(chars, length);
94 264612 : }
95 : inline explicit Lookup(const JSAtom* atom);
96 : };
97 :
98 1110698 : static HashNumber hash(const Lookup& l) { return l.hash; }
99 : static MOZ_ALWAYS_INLINE bool match(const AtomStateEntry& entry, const Lookup& lookup);
100 : static void rekey(AtomStateEntry& k, const AtomStateEntry& newKey) { k = newKey; }
101 : };
102 :
103 : using AtomSet = JS::GCHashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy>;
104 :
105 : // This class is a wrapper for AtomSet that is used to ensure the AtomSet is
106 : // not modified. It should only expose read-only methods from AtomSet.
107 : // Note however that the atoms within the table can be marked during GC.
108 : class FrozenAtomSet
109 : {
110 : AtomSet* mSet;
111 :
112 : public:
113 : // This constructor takes ownership of the passed-in AtomSet.
114 3 : explicit FrozenAtomSet(AtomSet* set) { mSet = set; }
115 :
116 0 : ~FrozenAtomSet() { js_delete(mSet); }
117 :
118 : MOZ_ALWAYS_INLINE AtomSet::Ptr readonlyThreadsafeLookup(const AtomSet::Lookup& l) const;
119 :
120 0 : size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
121 0 : return mSet->sizeOfIncludingThis(mallocSizeOf);
122 : }
123 :
124 : typedef AtomSet::Range Range;
125 :
126 4 : AtomSet::Range all() const { return mSet->all(); }
127 : };
128 :
129 : class PropertyName;
130 :
131 : } /* namespace js */
132 :
133 : extern bool
134 : AtomIsPinned(JSContext* cx, JSAtom* atom);
135 :
136 : #ifdef DEBUG
137 :
138 : // This may be called either with or without the atoms lock held.
139 : extern bool
140 : AtomIsPinnedInRuntime(JSRuntime* rt, JSAtom* atom);
141 :
142 : #endif // DEBUG
143 :
144 : /* Well-known predefined C strings. */
145 : #define DECLARE_PROTO_STR(name,code,init,clasp) extern const char js_##name##_str[];
146 : JS_FOR_EACH_PROTOTYPE(DECLARE_PROTO_STR)
147 : #undef DECLARE_PROTO_STR
148 :
149 : #define DECLARE_CONST_CHAR_STR(idpart, id, text) extern const char js_##idpart##_str[];
150 : FOR_EACH_COMMON_PROPERTYNAME(DECLARE_CONST_CHAR_STR)
151 : #undef DECLARE_CONST_CHAR_STR
152 :
153 : /* Constant strings that are not atomized. */
154 : extern const char js_getter_str[];
155 : extern const char js_send_str[];
156 : extern const char js_setter_str[];
157 :
158 : namespace js {
159 :
160 : class AutoLockForExclusiveAccess;
161 :
162 : /*
163 : * Atom tracing and garbage collection hooks.
164 : */
165 : void
166 : TraceAtoms(JSTracer* trc, AutoLockForExclusiveAccess& lock);
167 :
168 : void
169 : TracePermanentAtoms(JSTracer* trc);
170 :
171 : void
172 : TraceWellKnownSymbols(JSTracer* trc);
173 :
174 : /* N.B. must correspond to boolean tagging behavior. */
175 : enum PinningBehavior
176 : {
177 : DoNotPinAtom = false,
178 : PinAtom = true
179 : };
180 :
181 : extern JSAtom*
182 : Atomize(JSContext* cx, const char* bytes, size_t length,
183 : js::PinningBehavior pin = js::DoNotPinAtom,
184 : const mozilla::Maybe<uint32_t>& indexValue = mozilla::Nothing());
185 :
186 : template <typename CharT>
187 : extern JSAtom*
188 : AtomizeChars(JSContext* cx, const CharT* chars, size_t length,
189 : js::PinningBehavior pin = js::DoNotPinAtom);
190 :
191 : extern JSAtom*
192 : AtomizeUTF8Chars(JSContext* cx, const char* utf8Chars, size_t utf8ByteLength);
193 :
194 : extern JSAtom*
195 : AtomizeString(JSContext* cx, JSString* str, js::PinningBehavior pin = js::DoNotPinAtom);
196 :
197 : template <AllowGC allowGC>
198 : extern JSAtom*
199 : ToAtom(JSContext* cx, typename MaybeRooted<Value, allowGC>::HandleType v);
200 :
201 : enum XDRMode {
202 : XDR_ENCODE,
203 : XDR_DECODE
204 : };
205 :
206 : template <XDRMode mode>
207 : class XDRState;
208 :
209 : template<XDRMode mode>
210 : bool
211 : XDRAtom(XDRState<mode>* xdr, js::MutableHandleAtom atomp);
212 :
213 : #ifdef DEBUG
214 :
215 : bool AtomIsMarked(Zone* zone, JSAtom* atom);
216 : bool AtomIsMarked(Zone* zone, jsid id);
217 : bool AtomIsMarked(Zone* zone, const Value& value);
218 :
219 : #endif // DEBUG
220 :
221 : } /* namespace js */
222 :
223 : #endif /* jsatom_h */
|