- Keep interned string atoms around across zero-context episodes on a runtime,

until JS_DestroyRuntime is called (68450, r=rginda, sr=jband).
- NUL-terminate tagbuf in tagify, for the HTML helpers such as string.big()
  (66648, r=timeless, sr=jband).
This commit is contained in:
brendan%mozilla.org 2001-02-13 00:57:10 +00:00
Родитель 5c61971304
Коммит 5fcc8a1adc
5 изменённых файлов: 71 добавлений и 13 удалений

Просмотреть файл

@ -691,6 +691,7 @@ JS_DestroyRuntime(JSRuntime *rt)
#endif
#endif
js_FinishAtomState(&rt->atomState);
js_FinishGC(rt);
#ifdef JS_THREADSAFE
if (rt->gcLock)
@ -3392,7 +3393,7 @@ JS_InternString(JSContext *cx, const char *s)
JSAtom *atom;
CHECK_REQUEST(cx);
atom = js_Atomize(cx, s, strlen(s), ATOM_PINNED);
atom = js_Atomize(cx, s, strlen(s), ATOM_INTERNED);
if (!atom)
return NULL;
return ATOM_TO_STRING(atom);
@ -3427,7 +3428,7 @@ JS_InternUCStringN(JSContext *cx, const jschar *s, size_t length)
JSAtom *atom;
CHECK_REQUEST(cx);
atom = js_AtomizeChars(cx, s, length, ATOM_PINNED);
atom = js_AtomizeChars(cx, s, length, ATOM_INTERNED);
if (!atom)
return NULL;
return ATOM_TO_STRING(atom);

Просмотреть файл

@ -293,9 +293,12 @@ bad:
return JS_FALSE;
}
/* NB: cx unused; js_FinishAtomState calls us with null cx. */
void
js_FreeAtomState(JSContext *cx, JSAtomState *state)
{
if (state->interns != 0)
return;
state->runtime = NULL;
JS_HashTableDestroy(state->table);
state->table = NULL;
@ -305,6 +308,29 @@ js_FreeAtomState(JSContext *cx, JSAtomState *state)
#endif
}
JS_STATIC_DLL_CALLBACK(intN)
js_atom_uninterner(JSHashEntry *he, intN i, void *arg)
{
JSAtom *atom;
atom = (JSAtom *)he;
JS_ASSERT(atom->flags & ATOM_INTERNED);
JS_ASSERT(ATOM_IS_STRING(atom));
js_FinalizeStringRT(arg, ATOM_TO_STRING(atom));
return HT_ENUMERATE_NEXT;
}
void
js_FinishAtomState(JSAtomState *state)
{
if (state->interns == 0)
return;
JS_HashTableEnumerateEntries(state->table, js_atom_uninterner,
state->runtime);
state->interns = 0;
js_FreeAtomState(NULL, state);
}
typedef struct MarkArgs {
uintN gcflags;
JSGCThingMarker mark;
@ -320,7 +346,8 @@ js_atom_marker(JSHashEntry *he, intN i, void *arg)
atom = (JSAtom *)he;
args = (MarkArgs *) arg;
if ((atom->flags & ATOM_PINNED) || (args->gcflags & GC_KEEP_ATOMS)) {
if ((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) ||
(args->gcflags & GC_KEEP_ATOMS)) {
atom->flags |= ATOM_MARK;
key = ATOM_KEY(atom);
if (JSVAL_IS_GCTHING(key)) {
@ -352,7 +379,7 @@ js_atom_sweeper(JSHashEntry *he, intN i, void *arg)
atom->flags &= ~ATOM_MARK;
return HT_ENUMERATE_NEXT;
}
JS_ASSERT((atom->flags & ATOM_PINNED) == 0);
JS_ASSERT((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) == 0);
atom->entry.key = NULL;
atom->flags = 0;
return HT_ENUMERATE_REMOVE;
@ -548,7 +575,9 @@ js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
}
atom = (JSAtom *)he;
atom->flags |= flags & ATOM_PINNED;
atom->flags |= flags & (ATOM_PINNED | ATOM_INTERNED);
if (flags & ATOM_INTERNED)
state->interns++;
out:
JS_UNLOCK(&state->lock,cx);
return atom;

Просмотреть файл

@ -50,14 +50,15 @@
JS_BEGIN_EXTERN_C
#define ATOM_NOCOPY 0x01 /* don't copy atom string bytes */
#define ATOM_TMPSTR 0x02 /* internal, to avoid extra string */
#define ATOM_PINNED 0x01 /* atom is pinned against GC */
#define ATOM_INTERNED 0x02 /* pinned variant for JS_Intern* API */
#define ATOM_MARK 0x04 /* atom is reachable via GC */
#define ATOM_PINNED 0x08 /* atom is pinned against GC */
#define ATOM_NOCOPY 0x40 /* don't copy atom string bytes */
#define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */
struct JSAtom {
JSHashEntry entry; /* key is jsval, value keyword info */
uint8 flags; /* flags, PINNED and/or MARK for now */
uint8 flags; /* pinned, interned, and mark flags */
int8 kwindex; /* keyword index, -1 if not keyword */
jsatomid number; /* atom serial number and hash code */
};
@ -134,6 +135,7 @@ struct JSAtomState {
JSRuntime *runtime; /* runtime that owns us */
JSHashTable *table; /* hash table containing all atoms */
jsatomid number; /* one beyond greatest atom number */
jsatomid interns; /* number of interned strings */
/* Type names and value literals. */
JSAtom *typeAtoms[JSTYPE_LIMIT];
@ -232,11 +234,27 @@ extern JSBool
js_InitAtomState(JSContext *cx, JSAtomState *state);
/*
* Free and clear atom state.
* Free and clear atom state (except for any interned string atoms).
*/
extern void
js_FreeAtomState(JSContext *cx, JSAtomState *state);
/*
* Interned strings are atoms that live until state's runtime is destroyed.
* This function frees all interned string atoms, and then frees and clears
* state's members (just as js_FreeAtomState does), unless there aren't any
* interned strings in state -- in which case state must be "free" already.
*
* NB: js_FreeAtomState is called for each "last" context being destroyed in
* a runtime, where there may yet be another context created in the runtime;
* whereas js_FinishAtomState is called from JS_DestroyRuntime, when we know
* that no more contexts will be created. Thus we minimize garbage during
* context-free episodes on a runtime, while preserving atoms created by the
* JS_Intern*String APIs for the life of the runtime.
*/
extern void
js_FinishAtomState(JSAtomState *state);
/*
* Atom garbage collection hooks.
*/

Просмотреть файл

@ -1998,6 +1998,7 @@ tagify(JSContext *cx, JSObject *obj, jsval *argv,
tagbuf[j++] = (jschar)end[i];
tagbuf[j++] = '>';
JS_ASSERT(j == taglen);
tagbuf[j] = 0;
str = js_NewString(cx, tagbuf, taglen, 0);
if (!str) {
@ -2377,13 +2378,19 @@ js_hash_string_pointer(const void *key)
void
js_FinalizeString(JSContext *cx, JSString *str)
{
js_FinalizeStringRT(cx->runtime, str);
}
void
js_FinalizeStringRT(JSRuntime *rt, JSString *str)
{
JSHashNumber hash;
JSHashEntry *he, **hep;
JS_RUNTIME_UNMETER(cx->runtime, liveStrings);
JS_RUNTIME_UNMETER(rt, liveStrings);
if (str->chars) {
JS_free(cx, str->chars);
free(str->chars);
str->chars = NULL;
if (deflated_string_cache) {
hash = js_hash_string_pointer(str);
@ -2391,7 +2398,7 @@ js_FinalizeString(JSContext *cx, JSString *str)
hep = JS_HashTableRawLookup(deflated_string_cache, hash, str);
he = *hep;
if (he) {
JS_free(cx, he->value);
free(he->value);
JS_HashTableRawRemove(deflated_string_cache, hep, he);
deflated_string_cache_bytes -= str->length;
}

Просмотреть файл

@ -219,6 +219,9 @@ js_NewStringCopyZ(JSContext *cx, const jschar *s, uintN gcflag);
extern void
js_FinalizeString(JSContext *cx, JSString *str);
extern void
js_FinalizeStringRT(JSRuntime *rt, JSString *str);
/* Wrap a string value in a String object. */
extern JSObject *
js_StringToObject(JSContext *cx, JSString *str);