DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (d1ed7de67f5a)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef jsatom_h
#define jsatom_h

#include "mozilla/HashFunctions.h"

#include "jsalloc.h"

#include "gc/Barrier.h"
#include "gc/Rooting.h"
#include "js/GCAPI.h"
#include "vm/CommonPropertyNames.h"

class JSAtom;
class JSAutoByteString;

struct JSIdArray {
    int length;
    js::HeapId vector[1];    /* actually, length jsid words */
};

namespace js {

JS_STATIC_ASSERT(sizeof(HashNumber) == 4);

static MOZ_ALWAYS_INLINE js::HashNumber
HashId(jsid id)
{
    return mozilla::HashGeneric(JSID_BITS(id));
}

struct JsidHasher
{
    typedef jsid Lookup;
    static HashNumber hash(const Lookup& l) {
        return HashNumber(JSID_BITS(l));
    }
    static bool match(const jsid& id, const Lookup& l) {
        return id == l;
    }
};

/*
 * Return a printable, lossless char[] representation of a string-type atom.
 * The lifetime of the result matches the lifetime of bytes.
 */
extern const char*
AtomToPrintableString(ExclusiveContext* cx, JSAtom* atom, JSAutoByteString* bytes);

class AtomStateEntry
{
    uintptr_t bits;

    static const uintptr_t NO_TAG_MASK = uintptr_t(-1) - 1;

  public:
    AtomStateEntry() : bits(0) {}
    AtomStateEntry(const AtomStateEntry& other) : bits(other.bits) {}
    AtomStateEntry(JSAtom* ptr, bool tagged)
      : bits(uintptr_t(ptr) | uintptr_t(tagged))
    {
        JS_ASSERT((uintptr_t(ptr) & 0x1) == 0);
    }

    bool isTagged() const {
        return bits & 0x1;
    }

    /*
     * Non-branching code sequence. Note that the const_cast is safe because
     * the hash function doesn't consider the tag to be a portion of the key.
     */
    void setTagged(bool enabled) const {
        const_cast<AtomStateEntry*>(this)->bits |= uintptr_t(enabled);
    }

    JSAtom* asPtr() const;
};

struct AtomHasher
{
    struct Lookup
    {
        union {
            const JS::Latin1Char* latin1Chars;
            const jschar* twoByteChars;
        };
        bool isLatin1;
        size_t length;
        const JSAtom* atom; /* Optional. */
        JS::AutoCheckCannotGC nogc;

        HashNumber hash;

        Lookup(const jschar* chars, size_t length)
          : twoByteChars(chars), isLatin1(false), length(length), atom(nullptr)
        {
            hash = mozilla::HashString(chars, length);
        }
        Lookup(const JS::Latin1Char* chars, size_t length)
          : latin1Chars(chars), isLatin1(true), length(length), atom(nullptr)
        {
            hash = mozilla::HashString(chars, length);
        }
        inline explicit Lookup(const JSAtom* atom);
    };

    static HashNumber hash(const Lookup& l) { return l.hash; }
    static inline bool match(const AtomStateEntry& entry, const Lookup& lookup);
    static void rekey(AtomStateEntry& k, const AtomStateEntry& newKey) { k = newKey; }
};

typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;

class PropertyName;

}  /* namespace js */

extern bool
AtomIsInterned(JSContext* cx, JSAtom* atom);

/* Well-known predefined C strings. */
#define DECLARE_PROTO_STR(name,code,init,clasp) extern const char js_##name##_str[];
JS_FOR_EACH_PROTOTYPE(DECLARE_PROTO_STR)
#undef DECLARE_PROTO_STR

#define DECLARE_CONST_CHAR_STR(idpart, id, text)  extern const char js_##idpart##_str[];
FOR_EACH_COMMON_PROPERTYNAME(DECLARE_CONST_CHAR_STR)
#undef DECLARE_CONST_CHAR_STR

/* Constant strings that are not atomized. */
extern const char js_break_str[];
extern const char js_case_str[];
extern const char js_catch_str[];
extern const char js_class_str[];
extern const char js_close_str[];
extern const char js_const_str[];
extern const char js_continue_str[];
extern const char js_debugger_str[];
extern const char js_default_str[];
extern const char js_do_str[];
extern const char js_else_str[];
extern const char js_enum_str[];
extern const char js_export_str[];
extern const char js_extends_str[];
extern const char js_finally_str[];
extern const char js_for_str[];
extern const char js_getter_str[];
extern const char js_if_str[];
extern const char js_implements_str[];
extern const char js_import_str[];
extern const char js_in_str[];
extern const char js_instanceof_str[];
extern const char js_interface_str[];
extern const char js_new_str[];
extern const char js_package_str[];
extern const char js_private_str[];
extern const char js_protected_str[];
extern const char js_public_str[];
extern const char js_send_str[];
extern const char js_setter_str[];
extern const char js_static_str[];
extern const char js_super_str[];
extern const char js_switch_str[];
extern const char js_this_str[];
extern const char js_try_str[];
extern const char js_typeof_str[];
extern const char js_void_str[];
extern const char js_while_str[];
extern const char js_with_str[];

namespace js {

/*
 * Atom tracing and garbage collection hooks.
 */
void
MarkAtoms(JSTracer* trc);

void
MarkPermanentAtoms(JSTracer* trc);

void
MarkWellKnownSymbols(JSTracer* trc);

/* N.B. must correspond to boolean tagging behavior. */
enum InternBehavior
{
    DoNotInternAtom = false,
    InternAtom = true
};

extern JSAtom*
Atomize(ExclusiveContext* cx, const char* bytes, size_t length,
        js::InternBehavior ib = js::DoNotInternAtom);

template <typename CharT>
extern JSAtom*
AtomizeChars(ExclusiveContext* cx, const CharT* chars, size_t length,
             js::InternBehavior ib = js::DoNotInternAtom);

extern JSAtom*
AtomizeString(ExclusiveContext* cx, JSString* str, js::InternBehavior ib = js::DoNotInternAtom);

extern JSAtom*
AtomizeSubstring(ExclusiveContext* cx, JSString* str, size_t start, size_t length,
                 InternBehavior ib = DoNotInternAtom);

template <AllowGC allowGC>
extern JSAtom*
ToAtom(ExclusiveContext* cx, typename MaybeRooted<Value, allowGC>::HandleType v);

enum XDRMode {
    XDR_ENCODE,
    XDR_DECODE
};

template <XDRMode mode>
class XDRState;

template<XDRMode mode>
bool
XDRAtom(XDRState<mode>* xdr, js::MutableHandleAtom atomp);

} /* namespace js */

#endif /* jsatom_h */