Exemple #1
0
JSAtom *
js::AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib /* = js::DoNotInternAtom */)
{
    if (str->isAtom()) {
        JSAtom &atom = str->asAtom();
        /* N.B. static atoms are effectively always interned. */
        if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
            return &atom;

        AtomSet::Ptr p = cx->runtime->atoms.lookup(AtomHasher::Lookup(&atom));
        JS_ASSERT(p); /* Non-static atom must exist in atom state set. */
        JS_ASSERT(p->asPtr() == &atom);
        JS_ASSERT(ib == InternAtom);
        p->setTagged(bool(ib));
        return &atom;
    }

    const jschar *chars = str->getChars(cx);
    if (!chars)
        return NULL;

    if (JSAtom *atom = AtomizeAndCopyChars<NoGC>(cx, chars, str->length(), ib))
        return atom;

    if (!allowGC)
        return NULL;

    JSLinearString *linear = str->ensureLinear(cx);
    if (!linear)
        return NULL;

    JS_ASSERT(linear->length() <= JSString::MAX_LENGTH);
    return AtomizeAndCopyChars<CanGC>(cx, linear->chars(), linear->length(), ib);
}
Exemple #2
0
JSAtom *
js::AtomizeString(ExclusiveContext *cx, JSString *str,
                  js::InternBehavior ib /* = js::DoNotInternAtom */)
{
    if (str->isAtom()) {
        JSAtom &atom = str->asAtom();
        /* N.B. static atoms are effectively always interned. */
        if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
            return &atom;

        AtomHasher::Lookup lookup(&atom);

        /* Likewise, permanent atoms are always interned. */
        AtomSet::Ptr p = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
        if (p)
            return &atom;

        AutoLockForExclusiveAccess lock(cx);

        p = cx->atoms().lookup(lookup);
        JS_ASSERT(p); /* Non-static atom must exist in atom state set. */
        JS_ASSERT(p->asPtr() == &atom);
        JS_ASSERT(ib == InternAtom);
        p->setTagged(bool(ib));
        return &atom;
    }

    const jschar *chars = str->getChars(cx);
    if (!chars)
        return nullptr;

    return AtomizeAndCopyChars(cx, chars, str->length(), ib);
}
Exemple #3
0
JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, InternBehavior ib)
{
    if (str->isAtom()) {
        JSAtom &atom = str->asAtom();
        /* N.B. static atoms are effectively always interned. */
        if (ib != InternAtom || atom.isStaticAtom())
            return &atom;

        /* Here we have to check whether the atom is already interned. */
        AutoLockAtomsCompartment lock(cx);

        AtomSet &atoms = cx->runtime->atomState.atoms;
        AtomSet::Ptr p = atoms.lookup(AtomHasher::Lookup(&atom));
        JS_ASSERT(p); /* Non-static atom must exist in atom state set. */
        JS_ASSERT(p->asPtr() == &atom);
        JS_ASSERT(ib == InternAtom);
        p->setTagged(bool(ib));
        return &atom;
    }

    if (str->isAtom())
        return &str->asAtom();

    size_t length = str->length();
    const jschar *chars = str->getChars(cx);
    if (!chars)
        return NULL;

    JS_ASSERT(length <= JSString::MAX_LENGTH);
    return Atomize(cx, &chars, length, ib);
}
Exemple #4
0
JSAtom *
js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
{
    if (JSAtom *atom = JSAtom::lookupStatic(chars, length))
        return atom;
    AutoLockAtomsCompartment lock(cx);
    AtomSet::Ptr p = cx->runtime->atomState.atoms.lookup(AtomHasher::Lookup(chars, length));
    return p ? p->asPtr() : NULL;
}
Exemple #5
0
/*
 * When the jschars reside in a freshly allocated buffer the memory can be used
 * as a new JSAtom's storage without copying. The contract is that the caller no
 * longer owns the memory and this method is responsible for freeing the memory.
 */
MOZ_ALWAYS_INLINE
static JSAtom *
AtomizeAndtake(ExclusiveContext *cx, jschar *tbchars, size_t length, InternBehavior ib)
{
    JS_ASSERT(tbchars[length] == 0);

    if (JSAtom *s = cx->staticStrings().lookup(tbchars, length)) {
        js_free(tbchars);
        return s;
    }

    AtomHasher::Lookup lookup(tbchars, length);

    AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
    if (pp) {
        js_free(tbchars);
        return pp->asPtr();
    }

    AutoLockForExclusiveAccess lock(cx);

    /*
     * If a GC occurs at js_NewStringCopy then |p| will still have the correct
     * hash, allowing us to avoid rehashing it. Even though the hash is
     * unchanged, we need to re-lookup the table position because a last-ditch
     * GC will potentially free some table entries.
     */
    AtomSet& atoms = cx->atoms();
    AtomSet::AddPtr p = atoms.lookupForAdd(lookup);
    if (p) {
        JSAtom *atom = p->asPtr();
        p->setTagged(bool(ib));
        js_free(tbchars);
        return atom;
    }

    AutoCompartment ac(cx, cx->atomsCompartment());

    JSFlatString *flat = js_NewString<NoGC>(cx, tbchars, length);
    if (!flat) {
        js_free(tbchars);
        js_ReportOutOfMemory(cx);
        return nullptr;
    }

    JSAtom *atom = flat->morphAtomizedStringIntoAtom();

    if (!atoms.relookupOrAdd(p, lookup, AtomStateEntry(atom, bool(ib)))) {
        js_ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
        return nullptr;
    }

    return atom;
}
Exemple #6
0
MOZ_ALWAYS_INLINE
static JSAtom *
AtomizeAndCopyChars(ExclusiveContext *cx, const CharT *tbchars, size_t length, InternBehavior ib)
{
    if (JSAtom *s = cx->staticStrings().lookup(tbchars, length))
         return s;

    AtomHasher::Lookup lookup(tbchars, length);

    // Note: when this function is called while the permanent atoms table is
    // being initialized (in initializeAtoms()), |permanentAtoms| is not yet
    // initialized so this lookup is always skipped. Only once
    // transformToPermanentAtoms() is called does |permanentAtoms| get
    // initialized and then this lookup will go ahead.
    if (cx->isPermanentAtomsInitialized()) {
        AtomSet::Ptr pp = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
        if (pp)
            return pp->asPtr();
    }

    AutoLockForExclusiveAccess lock(cx);

    AtomSet& atoms = cx->atoms();
    AtomSet::AddPtr p = atoms.lookupForAdd(lookup);
    if (p) {
        JSAtom *atom = p->asPtr();
        p->setTagged(bool(ib));
        return atom;
    }

    AutoCompartment ac(cx, cx->atomsCompartment());

    JSFlatString *flat = NewStringCopyN<NoGC>(cx, tbchars, length);
    if (!flat) {
        // Grudgingly forgo last-ditch GC. The alternative would be to release
        // the lock, manually GC here, and retry from the top. If you fix this,
        // please also fix or comment the similar case in Symbol::new_.
        ReportOutOfMemory(cx);
        return nullptr;
    }

    JSAtom *atom = flat->morphAtomizedStringIntoAtom();

    // We have held the lock since looking up p, and the operations we've done
    // since then can't GC; therefore the atoms table has not been modified and
    // p is still valid.
    if (!atoms.add(p, AtomStateEntry(atom, bool(ib)))) {
        ReportOutOfMemory(cx); /* SystemAllocPolicy does not report OOM. */
        return nullptr;
    }

    return atom;
}
Exemple #7
0
bool
AtomIsInterned(JSContext *cx, JSAtom *atom)
{
    /* We treat static strings as interned because they're never collected. */
    if (StaticStrings::isStatic(atom))
        return true;

    AtomSet::Ptr p = cx->runtime->atoms.lookup(atom);
    if (!p)
        return false;

    return p->isTagged();
}
Exemple #8
0
bool
AtomIsInterned(JSContext *cx, JSAtom *atom)
{
    if (atom->isStaticAtom())
        return true;

    AutoLockAtomsCompartment lock(cx);
    AtomSet::Ptr p = cx->runtime->atomState.atoms.lookup(atom);
    if (!p)
        return false;

    return p->isTagged();
}
Exemple #9
0
bool
AtomIsInterned(JSContext *cx, JSAtom *atom)
{
    /* We treat static strings as interned because they're never collected. */
    if (StaticStrings::isStatic(atom))
        return true;

    AtomHasher::Lookup lookup(atom);

    /* Likewise, permanent strings are considered to be interned. */
    AtomSet::Ptr p = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
    if (p)
        return true;

    AutoLockForExclusiveAccess lock(cx);

    p = cx->runtime()->atoms().lookup(lookup);
    if (!p)
        return false;

    return p->isTagged();
}
Exemple #10
0
JSAtom *
js::AtomizeString(ExclusiveContext *cx, JSString *str,
                  js::InternBehavior ib /* = js::DoNotInternAtom */)
{
    if (str->isAtom()) {
        JSAtom &atom = str->asAtom();
        /* N.B. static atoms are effectively always interned. */
        if (ib != InternAtom || js::StaticStrings::isStatic(&atom))
            return &atom;

        AtomHasher::Lookup lookup(&atom);

        /* Likewise, permanent atoms are always interned. */
        MOZ_ASSERT(cx->isPermanentAtomsInitialized());
        AtomSet::Ptr p = cx->permanentAtoms().readonlyThreadsafeLookup(lookup);
        if (p)
            return &atom;

        AutoLockForExclusiveAccess lock(cx);

        p = cx->atoms().lookup(lookup);
        MOZ_ASSERT(p); /* Non-static atom must exist in atom state set. */
        MOZ_ASSERT(p->asPtr() == &atom);
        MOZ_ASSERT(ib == InternAtom);
        p->setTagged(bool(ib));
        return &atom;
    }

    JSLinearString *linear = str->ensureLinear(cx);
    if (!linear)
        return nullptr;

    JS::AutoCheckCannotGC nogc;
    return linear->hasLatin1Chars()
           ? AtomizeAndCopyChars(cx, linear->latin1Chars(nogc), linear->length(), ib)
           : AtomizeAndCopyChars(cx, linear->twoByteChars(nogc), linear->length(), ib);
}