michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jsatom_h michael@0: #define jsatom_h michael@0: michael@0: #include "mozilla/HashFunctions.h" michael@0: michael@0: #include "jsalloc.h" michael@0: michael@0: #include "gc/Barrier.h" michael@0: #include "gc/Rooting.h" michael@0: #include "vm/CommonPropertyNames.h" michael@0: michael@0: class JSAtom; michael@0: class JSAutoByteString; michael@0: michael@0: struct JSIdArray { michael@0: int length; michael@0: js::HeapId vector[1]; /* actually, length jsid words */ michael@0: }; michael@0: michael@0: namespace js { michael@0: michael@0: JS_STATIC_ASSERT(sizeof(HashNumber) == 4); michael@0: michael@0: static MOZ_ALWAYS_INLINE js::HashNumber michael@0: HashId(jsid id) michael@0: { michael@0: return mozilla::HashGeneric(JSID_BITS(id)); michael@0: } michael@0: michael@0: struct JsidHasher michael@0: { michael@0: typedef jsid Lookup; michael@0: static HashNumber hash(const Lookup &l) { michael@0: return HashNumber(JSID_BITS(l)); michael@0: } michael@0: static bool match(const jsid &id, const Lookup &l) { michael@0: return id == l; michael@0: } michael@0: }; michael@0: michael@0: /* michael@0: * Return a printable, lossless char[] representation of a string-type atom. michael@0: * The lifetime of the result matches the lifetime of bytes. michael@0: */ michael@0: extern const char * michael@0: AtomToPrintableString(ExclusiveContext *cx, JSAtom *atom, JSAutoByteString *bytes); michael@0: michael@0: class AtomStateEntry michael@0: { michael@0: uintptr_t bits; michael@0: michael@0: static const uintptr_t NO_TAG_MASK = uintptr_t(-1) - 1; michael@0: michael@0: public: michael@0: AtomStateEntry() : bits(0) {} michael@0: AtomStateEntry(const AtomStateEntry &other) : bits(other.bits) {} michael@0: AtomStateEntry(JSAtom *ptr, bool tagged) michael@0: : bits(uintptr_t(ptr) | uintptr_t(tagged)) michael@0: { michael@0: JS_ASSERT((uintptr_t(ptr) & 0x1) == 0); michael@0: } michael@0: michael@0: bool isTagged() const { michael@0: return bits & 0x1; michael@0: } michael@0: michael@0: /* michael@0: * Non-branching code sequence. Note that the const_cast is safe because michael@0: * the hash function doesn't consider the tag to be a portion of the key. michael@0: */ michael@0: void setTagged(bool enabled) const { michael@0: const_cast(this)->bits |= uintptr_t(enabled); michael@0: } michael@0: michael@0: JSAtom *asPtr() const; michael@0: }; michael@0: michael@0: struct AtomHasher michael@0: { michael@0: struct Lookup michael@0: { michael@0: const jschar *chars; michael@0: size_t length; michael@0: const JSAtom *atom; /* Optional. */ michael@0: michael@0: HashNumber hash; michael@0: michael@0: Lookup(const jschar *chars, size_t length) michael@0: : chars(chars), length(length), atom(nullptr) michael@0: { michael@0: hash = mozilla::HashString(chars, length); michael@0: } michael@0: inline Lookup(const JSAtom *atom); michael@0: }; michael@0: michael@0: static HashNumber hash(const Lookup &l) { return l.hash; } michael@0: static inline bool match(const AtomStateEntry &entry, const Lookup &lookup); michael@0: static void rekey(AtomStateEntry &k, const AtomStateEntry& newKey) { k = newKey; } michael@0: }; michael@0: michael@0: typedef HashSet AtomSet; michael@0: michael@0: class PropertyName; michael@0: michael@0: } /* namespace js */ michael@0: michael@0: extern bool michael@0: AtomIsInterned(JSContext *cx, JSAtom *atom); michael@0: michael@0: /* Well-known predefined C strings. */ michael@0: #define DECLARE_PROTO_STR(name,code,init,clasp) extern const char js_##name##_str[]; michael@0: JS_FOR_EACH_PROTOTYPE(DECLARE_PROTO_STR) michael@0: #undef DECLARE_PROTO_STR michael@0: michael@0: #define DECLARE_CONST_CHAR_STR(idpart, id, text) extern const char js_##idpart##_str[]; michael@0: FOR_EACH_COMMON_PROPERTYNAME(DECLARE_CONST_CHAR_STR) michael@0: #undef DECLARE_CONST_CHAR_STR michael@0: michael@0: /* Constant strings that are not atomized. */ michael@0: extern const char js_break_str[]; michael@0: extern const char js_case_str[]; michael@0: extern const char js_catch_str[]; michael@0: extern const char js_class_str[]; michael@0: extern const char js_close_str[]; michael@0: extern const char js_const_str[]; michael@0: extern const char js_continue_str[]; michael@0: extern const char js_debugger_str[]; michael@0: extern const char js_default_str[]; michael@0: extern const char js_do_str[]; michael@0: extern const char js_else_str[]; michael@0: extern const char js_enum_str[]; michael@0: extern const char js_export_str[]; michael@0: extern const char js_extends_str[]; michael@0: extern const char js_finally_str[]; michael@0: extern const char js_for_str[]; michael@0: extern const char js_getter_str[]; michael@0: extern const char js_if_str[]; michael@0: extern const char js_implements_str[]; michael@0: extern const char js_import_str[]; michael@0: extern const char js_in_str[]; michael@0: extern const char js_instanceof_str[]; michael@0: extern const char js_interface_str[]; michael@0: extern const char js_new_str[]; michael@0: extern const char js_package_str[]; michael@0: extern const char js_private_str[]; michael@0: extern const char js_protected_str[]; michael@0: extern const char js_public_str[]; michael@0: extern const char js_send_str[]; michael@0: extern const char js_setter_str[]; michael@0: extern const char js_static_str[]; michael@0: extern const char js_super_str[]; michael@0: extern const char js_switch_str[]; michael@0: extern const char js_this_str[]; michael@0: extern const char js_try_str[]; michael@0: extern const char js_typeof_str[]; michael@0: extern const char js_void_str[]; michael@0: extern const char js_while_str[]; michael@0: extern const char js_with_str[]; michael@0: michael@0: namespace js { michael@0: michael@0: extern const char * const TypeStrings[]; michael@0: michael@0: /* michael@0: * Atom tracing and garbage collection hooks. michael@0: */ michael@0: extern void michael@0: MarkAtoms(JSTracer *trc); michael@0: michael@0: extern void michael@0: MarkPermanentAtoms(JSTracer *trc); michael@0: michael@0: /* N.B. must correspond to boolean tagging behavior. */ michael@0: enum InternBehavior michael@0: { michael@0: DoNotInternAtom = false, michael@0: InternAtom = true michael@0: }; michael@0: michael@0: extern JSAtom * michael@0: Atomize(ExclusiveContext *cx, const char *bytes, size_t length, michael@0: js::InternBehavior ib = js::DoNotInternAtom); michael@0: michael@0: extern JSAtom * michael@0: AtomizeChars(ExclusiveContext *cx, const jschar *chars, size_t length, michael@0: js::InternBehavior ib = js::DoNotInternAtom); michael@0: michael@0: extern JSAtom * michael@0: AtomizeString(ExclusiveContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom); michael@0: michael@0: template michael@0: extern JSAtom * michael@0: ToAtom(ExclusiveContext *cx, typename MaybeRooted::HandleType v); michael@0: michael@0: enum XDRMode { michael@0: XDR_ENCODE, michael@0: XDR_DECODE michael@0: }; michael@0: michael@0: template michael@0: class XDRState; michael@0: michael@0: template michael@0: bool michael@0: XDRAtom(XDRState *xdr, js::MutableHandleAtom atomp); michael@0: michael@0: } /* namespace js */ michael@0: michael@0: #endif /* jsatom_h */