Example #1
0
JSAtomListElement *
js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al)
{
    JSAtomListElement *ale, *ale2, *next;
    JSHashEntry **hep;

    ATOM_LIST_LOOKUP(ale, hep, al, atom);
    if (!ale) {
        if (al->count < 10) {
            /* Few enough for linear search, no hash table needed. */
            JS_ASSERT(!al->table);
            ale = (JSAtomListElement *)js_alloc_temp_entry(cx, atom);
            if (!ale)
                return NULL;
            ALE_SET_ATOM(ale, atom);
            ALE_SET_NEXT(ale, al->list);
            al->list = ale;
        } else {
            /* We want to hash.  Have we already made a hash table? */
            if (!al->table) {
                /* No hash table yet, so hep had better be null! */
                JS_ASSERT(!hep);
                al->table = JS_NewHashTable(al->count + 1, js_hash_atom_ptr,
                                            JS_CompareValues, JS_CompareValues,
                                            &temp_alloc_ops, cx);
                if (!al->table)
                    return NULL;

                /*
                 * Set ht->nentries explicitly, because we are moving entries
                 * from al to ht, not calling JS_HashTable(Raw|)Add.
                 */
                al->table->nentries = al->count;

                /* Insert each ale on al->list into the new hash table. */
                for (ale2 = al->list; ale2; ale2 = next) {
                    next = ALE_NEXT(ale2);
                    ale2->entry.keyHash = ALE_ATOM(ale2)->number;
                    hep = JS_HashTableRawLookup(al->table, ale2->entry.keyHash,
                                                ale2->entry.key);
                    ALE_SET_NEXT(ale2, *hep);
                    *hep = &ale2->entry;
                }
                al->list = NULL;

                /* Set hep for insertion of atom's ale, immediately below. */
                hep = JS_HashTableRawLookup(al->table, atom->number, atom);
            }

            /* Finally, add an entry for atom into the hash bucket at hep. */
            ale = (JSAtomListElement *)
                  JS_HashTableRawAdd(al->table, hep, atom->number, atom, NULL);
            if (!ale)
                return NULL;
        }

        ALE_SET_INDEX(ale, al->count++);
    }
    return ale;
}
Example #2
0
JSAtom *
js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags)
{
    jsdouble *dp;
    JSHashNumber keyHash;
    jsval key;
    JSAtomState *state;
    JSHashTable *table;
    JSHashEntry *he, **hep;
    JSAtom *atom;
    char buf[2 * ALIGNMENT(double)];

    dp = ALIGN(buf, double);
    *dp = d;
    keyHash = HASH_DOUBLE(dp);
    key = DOUBLE_TO_JSVAL(dp);
    state = &cx->runtime->atomState;
    JS_LOCK(&state->lock, cx);
    table = state->table;
    hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
    if ((he = *hep) == NULL) {
#ifdef JS_THREADSAFE
        uint32 gen = state->tablegen;
#endif
        JS_UNLOCK(&state->lock,cx);
        if (!js_NewDoubleValue(cx, d, &key))
            return NULL;
        JS_LOCK(&state->lock, cx);
#ifdef JS_THREADSAFE
        if (state->tablegen != gen) {
            hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
            if ((he = *hep) != NULL) {
                atom = (JSAtom *)he;
                goto out;
            }
        }
#endif
        he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
        if (!he) {
            JS_ReportOutOfMemory(cx);
            atom = NULL;
            goto out;
        }
    }

    atom = (JSAtom *)he;
    atom->flags |= flags;
    cx->lastAtom = atom;
out:
    JS_UNLOCK(&state->lock,cx);
    return atom;
}
Example #3
0
/*
 * Remove the mapping of a JS object from the hash table that maps JS objects
 * to Java objects.  This is called from the finalizer of an instance of
 * netscape.javascript.JSObject.
 */
JSBool
jsj_remove_js_obj_reflection_from_hashtable(JSContext *cx, JSObject *js_obj)
{
    JSHashEntry *he, **hep;
    JSBool success = JS_FALSE;

#ifdef JSJ_THREADSAFE
    PR_EnterMonitor(js_obj_reflections_monitor);
#endif

    /* Get the hash-table entry for this wrapper object */
    hep = JS_HashTableRawLookup(js_obj_reflections, (JSHashNumber)js_obj, js_obj);
    he = *hep;

    JS_ASSERT(he);
    if (he) {
        /* Tell the JS GC that Java no longer keeps a reference to this
           JS object. */
        success = JS_RemoveRoot(cx, (void *)&he->key);

        JS_HashTableRawRemove(js_obj_reflections, hep, he);
    }

#ifdef JSJ_THREADSAFE
    PR_ExitMonitor(js_obj_reflections_monitor);
#endif

    return success;
}
Example #4
0
static JSAtom *
js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags)
{
    JSAtomState *state;
    JSHashTable *table;
    JSHashEntry *he, **hep;
    JSAtom *atom;

    state = &cx->runtime->atomState;
    JS_LOCK(&state->lock, cx);
    table = state->table;
    hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
    if ((he = *hep) == NULL) {
        he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
        if (!he) {
            JS_ReportOutOfMemory(cx);
            atom = NULL;
            goto out;
        }
    }

    atom = (JSAtom *)he;
    atom->flags |= flags;
out:
    JS_UNLOCK(&state->lock,cx);
    return atom;
}
Example #5
0
JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **&hep,
                   JSHashNumber keyHash, const void *key, void *value)
{
    uint32 n;
    JSHashEntry *he;

    /* Grow the table if it is overloaded */
    n = NBUCKETS(ht);
    if (ht->nentries >= OVERLOADED(n)) {
        if (!Resize(ht, ht->shift - 1))
            return NULL;
#ifdef JS_HASHMETER
        ht->ngrows++;
#endif
        hep = JS_HashTableRawLookup(ht, keyHash, key);
    }

    /* Make a new key value entry */
    he = ht->allocOps->allocEntry(ht->allocPriv, key);
    if (!he)
        return NULL;
    he->keyHash = keyHash;
    he->key = key;
    he->value = value;
    he->next = *hep;
    *hep = he;
    ht->nentries++;
    return he;
}
Example #6
0
JS_HashTableLookup(JSHashTable *ht, const void *key)
{
    JSHashNumber keyHash;
    JSHashEntry *he, **hep;

    keyHash = ht->keyHash(key);
    hep = JS_HashTableRawLookup(ht, keyHash, key);
    if ((he = *hep) != NULL) {
        return he->value;
    }
    return NULL;
}
Example #7
0
JS_HashTableRemove(JSHashTable *ht, const void *key)
{
    JSHashNumber keyHash;
    JSHashEntry *he, **hep;

    keyHash = ht->keyHash(key);
    hep = JS_HashTableRawLookup(ht, keyHash, key);
    if ((he = *hep) == NULL)
        return JS_FALSE;

    /* Hit; remove element */
    JS_HashTableRawRemove(ht, hep, he);
    return JS_TRUE;
}
Example #8
0
JS_HashTableAdd(JSHashTable *ht, const void *key, void *value)
{
    JSHashNumber keyHash;
    JSHashEntry *he, **hep;

    keyHash = ht->keyHash(key);
    hep = JS_HashTableRawLookup(ht, keyHash, key);
    if ((he = *hep) != NULL) {
        /* Hit; see if values match */
        if (ht->valueCompare(he->value, value)) {
            /* key,value pair is already present in table */
            return he;
        }
        if (he->value)
            ht->allocOps->freeEntry(ht->allocPriv, he, HT_FREE_VALUE);
        he->value = value;
        return he;
    }
    return JS_HashTableRawAdd(ht, hep, keyHash, key, value);
}
Example #9
0
JSAtomListElement *
JSAtomList::rawLookup(JSAtom *atom, JSHashEntry **&hep)
{
    JSAtomListElement *ale;

    if (table) {
        hep = JS_HashTableRawLookup(table, ATOM_HASH(atom), atom);
        ale = *hep ? (JSAtomListElement *) *hep : NULL;
    } else {
        JSHashEntry **alep = &list;
        hep = NULL;
        while ((ale = (JSAtomListElement *)*alep) != NULL) {
            if (ALE_ATOM(ale) == atom) {
                /* Hit, move atom's element to the front of the list. */
                *alep = ale->entry.next;
                ale->entry.next = list;
                list = &ale->entry;
                break;
            }
            alep = &ale->entry.next;
        }
    }
    return ale;
}
Example #10
0
JSAtomListElement *
JSAtomList::add(JSCompiler *jsc, JSAtom *atom, AddHow how)
{
    JS_ASSERT(!set);

    JSAtomListElement *ale, *ale2, *next;
    JSHashEntry **hep;

    ale = rawLookup(atom, hep);
    if (!ale || how != UNIQUE) {
        if (count < ATOM_LIST_HASH_THRESHOLD && !table) {
            /* Few enough for linear search and no hash table yet needed. */
            ale = (JSAtomListElement *)js_alloc_temp_entry(jsc, atom);
            if (!ale)
                return NULL;
            ALE_SET_ATOM(ale, atom);

            if (how == HOIST) {
                ale->entry.next = NULL;
                hep = (JSHashEntry **) &list;
                while (*hep)
                    hep = &(*hep)->next;
                *hep = &ale->entry;
            } else {
                ale->entry.next = list;
                list = &ale->entry;
            }
        } else {
            /*
             * We should hash, or else we already are hashing, but count was
             * reduced by JSAtomList::rawRemove below ATOM_LIST_HASH_THRESHOLD.
             * Check whether we should create the table.
             */
            if (!table) {
                /* No hash table yet, so hep had better be null! */
                JS_ASSERT(!hep);
                table = JS_NewHashTable(count + 1, js_hash_atom_ptr,
                                        JS_CompareValues, JS_CompareValues,
                                        &temp_alloc_ops, jsc);
                if (!table)
                    return NULL;

                /*
                 * Set ht->nentries explicitly, because we are moving entries
                 * from list to ht, not calling JS_HashTable(Raw|)Add.
                 */
                table->nentries = count;

                /*
                 * Insert each ale on list into the new hash table. Append to
                 * the hash chain rather than inserting at the bucket head, to
                 * preserve order among entries with the same key.
                 */
                for (ale2 = (JSAtomListElement *)list; ale2; ale2 = next) {
                    next = ALE_NEXT(ale2);
                    ale2->entry.keyHash = ATOM_HASH(ALE_ATOM(ale2));
                    hep = JS_HashTableRawLookup(table, ale2->entry.keyHash,
                                                ale2->entry.key);
                    while (*hep)
                        hep = &(*hep)->next;
                    *hep = &ale2->entry;
                    ale2->entry.next = NULL;
                }
                list = NULL;

                /* Set hep for insertion of atom's ale, immediately below. */
                hep = JS_HashTableRawLookup(table, ATOM_HASH(atom), atom);
            }

            /* Finally, add an entry for atom into the hash bucket at hep. */
            ale = (JSAtomListElement *)
                  JS_HashTableRawAdd(table, hep, ATOM_HASH(atom), atom, NULL);
            if (!ale)
                return NULL;

            /*
             * If hoisting, move ale to the end of its chain after we called
             * JS_HashTableRawAdd, since RawAdd may have grown the table and
             * then recomputed hep to refer to the pointer to the first entry
             * with the given key.
             */
            if (how == HOIST && ale->entry.next) {
                JS_ASSERT(*hep == &ale->entry);
                *hep = ale->entry.next;
                ale->entry.next = NULL;
                do {
                    hep = &(*hep)->next;
                } while (*hep);
                *hep = &ale->entry;
            }
        }

        ALE_SET_INDEX(ale, count++);
    }
    return ale;
}
Example #11
0
jobject
jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj)
{
    jobject java_wrapper_obj;
    JSHashEntry *he, **hep;

    java_wrapper_obj = NULL;

#ifdef JSJ_THREADSAFE
    PR_EnterMonitor(js_obj_reflections_monitor);
#endif

    /* First, look in the hash table for an existing reflection of the same
       JavaScript object.  If one is found, return it. */
    hep = JS_HashTableRawLookup(js_obj_reflections, (JSHashNumber)js_obj, js_obj);

    /* If the same JSObject is reflected into Java more than once then we should
       return the same Java object, both for efficiency and so that the '=='
       operator works as expected in Java when comparing two JSObjects.
       However, it is not possible to hold a reference to a Java object without
       inhibiting GC of that object, at least not in a portable way, i.e.
       a weak reference. So, for now, JSObject identity is broken. */

    he = *hep;
    if (he) {
        java_wrapper_obj = (jobject)he->value;
        JS_ASSERT(java_wrapper_obj);
        if (java_wrapper_obj)
            goto done;
    }

    /* No existing reflection found, so create a new Java object that wraps
       the JavaScript object by storing its address in a private integer field. */
#ifndef OJI
    java_wrapper_obj =
        (*jEnv)->NewObject(jEnv, njJSObject, njJSObject_JSObject, (jint)js_obj);
#else
    if (JSJ_callbacks && JSJ_callbacks->get_java_wrapper != NULL) {
        java_wrapper_obj = JSJ_callbacks->get_java_wrapper(jEnv, (jint)handle);
    }
#endif /*! OJI */

    if (!java_wrapper_obj) {
        jsj_UnexpectedJavaError(cx, jEnv, "Couldn't create new instance of "
                                          "netscape.javascript.JSObject");
        goto done;
    }

    /* Add the new reflection to the hash table. */
    he = JS_HashTableRawAdd(js_obj_reflections, hep, (JSHashNumber)js_obj,
                            js_obj, java_wrapper_obj);
    if (he) {
        /* Tell the JavaScript GC about this object since the only reference
           to it may be in Java-land. */
        JS_AddNamedRoot(cx, (void*)&he->key, "&he->key");
    } else {
        JS_ReportOutOfMemory(cx);
        /* No need to delete java_wrapper_obj because Java GC will reclaim it */
        java_wrapper_obj = NULL;
    }
    
    /*
     * Release local reference to wrapper object, since some JVMs seem reticent
     * about collecting it otherwise.
     */
    /* FIXME -- beard: this seems to make calls into Java with JSObject's fail. */
    /* We should really be creating a global ref if we are putting it in a hash table. */
    /* (*jEnv)->DeleteLocalRef(jEnv, java_wrapper_obj); */

done:
#ifdef JSJ_THREADSAFE
        PR_ExitMonitor(js_obj_reflections_monitor);
#endif
        
    return java_wrapper_obj;
}
Example #12
0
JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
{
    JSHashNumber keyHash;
    jsval key;
    JSAtomState *state;
    JSHashTable *table;
    JSHashEntry *he, **hep;
    JSAtom *atom;

    keyHash = js_HashString(str);
    key = STRING_TO_JSVAL(str);
    state = &cx->runtime->atomState;
    JS_LOCK(&state->lock, cx);
    table = state->table;
    hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
    if ((he = *hep) == NULL) {
#ifdef JS_THREADSAFE
        uint32 gen = state->tablegen;
        JS_UNLOCK(&state->lock, cx);
#endif

        if (flags & ATOM_TMPSTR) {
            str = (flags & ATOM_NOCOPY)
                  ? js_NewString(cx, str->chars, str->length, 0)
                  : js_NewStringCopyN(cx, str->chars, str->length, 0);
            if (!str)
                return NULL;
            key = STRING_TO_JSVAL(str);
        } else {
            if (!JS_MakeStringImmutable(cx, str))
                return NULL;
        }

#ifdef JS_THREADSAFE
        JS_LOCK(&state->lock, cx);
        if (state->tablegen != gen) {
            hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
            if ((he = *hep) != NULL) {
                atom = (JSAtom *)he;
                if (flags & ATOM_NOCOPY)
                    str->chars = NULL;
                goto out;
            }
        }
#endif

        he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
        if (!he) {
            JS_ReportOutOfMemory(cx);
            atom = NULL;
            goto out;
        }
    }

    atom = (JSAtom *)he;
    atom->flags |= flags & (ATOM_PINNED | ATOM_INTERNED);
out:
    JS_UNLOCK(&state->lock,cx);
    return atom;
}