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