Support external string GC types so XPConnect and other systems can optimize away copies (50602, r=jband).

This commit is contained in:
brendan%mozilla.org 2000-09-02 20:37:37 +00:00
Родитель a1659d2bd2
Коммит 57422a219a
6 изменённых файлов: 121 добавлений и 18 удалений

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

@ -615,6 +615,13 @@ EXPORTS
JS_GetScriptPrincipals
JS_IsAssigning
JS_SetCharSetInfo
;brendan@mozilla.org, 2-Sept-2000
JS_SetCallReturnValue2
JS_SetGCCallback
JS_SetGCCallbackRT
JS_AddExternalStringFinalizer
JS_RemoveExternalStringFinalizer
JS_NewExternalString
;
;
;00023:prmjtime (OFFSET:0x000dae0f, SIZE:0x00008986):

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

@ -1547,6 +1547,34 @@ JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb)
return oldcb;
}
JS_PUBLIC_API(intN)
JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer)
{
return js_ChangeExternalStringFinalizer(NULL, finalizer);
}
JS_PUBLIC_API(intN)
JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer)
{
return js_ChangeExternalStringFinalizer(finalizer, NULL);
}
JS_PUBLIC_API(JSString *)
JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type)
{
JSString *str;
CHECK_REQUEST(cx);
JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES);
str = (JSString *) js_AllocGCThing(cx, (uintN) type);
if (!str)
return NULL;
str->length = length;
str->chars = chars;
return str;
}
/************************************************************************/
JS_PUBLIC_API(void)

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

@ -18,7 +18,7 @@
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU Public License (the "GPL"), in which case the
@ -551,6 +551,45 @@ JS_SetGCCallback(JSContext *cx, JSGCCallback cb);
extern JS_PUBLIC_API(JSGCCallback)
JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb);
/*
* Add an external string finalizer, one that understands struct JSString
* (from jsstr.h) and knows how to free or release the memory pointed at by
* its chars member.
*
* Return a nonnegative type index if there is room for finalizer in the
* global GC finalizers table, else return -1. If the engine is compiled
* JS_THREADSAFE and used in a multi-threaded environment, this function must
* be invoked on the primordial thread only, at startup -- or else the entire
* program must single-thread itself while loading a module that calls this
* function.
*/
extern JS_PUBLIC_API(intN)
JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer);
/*
* Remove finalizer from the global GC finalizers table, returning its type
* code if found, -1 if not found.
*
* As with JS_AddExternalStringFinalizer, there is a threading restriction
* if you compile the engine JS_THREADSAFE: this function may be called for a
* given finalizer pointer on only one thread; different threads may call to
* remove distinct finalizers safely.
*
* You must ensure that all strings with finalizer's type have been collected
* before calling this function. Otherwise, string data will be leaked by the
* GC, for want of a finalizer to call.
*/
extern JS_PUBLIC_API(intN)
JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer);
/*
* Create a new JSString whose chars member refers to external memory, i.e.,
* memory requiring special, type-specific finalization. The type code must
* be a nonnegative return value from JS_AddExternalStringFinalizer.
*/
extern JS_PUBLIC_API(JSString *)
JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type);
/************************************************************************/
/*
@ -1223,7 +1262,7 @@ extern JS_PUBLIC_API(void)
JS_SetLocaleCallbacks(JSContext *cx, JSLocaleCallbacks *callbacks);
/* Return the address of the current locale callbacks struct. May be NULL. */
extern JS_PUBLIC_API(JSLocaleCallbacks *)
extern JS_PUBLIC_API(JSLocaleCallbacks *)
JS_GetLocaleCallbacks(JSContext *cx);
/************************************************************************/

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

@ -82,6 +82,21 @@ typedef void (*GCFinalizeOp)(JSContext *cx, JSGCThing *thing);
static GCFinalizeOp gc_finalizers[GCX_NTYPES];
intN
js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
JSStringFinalizeOp newop)
{
uintN i;
for (i = GCX_EXTERNAL_STRING; i < GCX_NTYPES; i++) {
if (gc_finalizers[i] == (GCFinalizeOp) oldop) {
gc_finalizers[i] = (GCFinalizeOp) newop;
return (intN) i;
}
}
return -1;
}
#ifdef JS_GCMETER
#define METER(x) x
#else
@ -94,7 +109,9 @@ js_InitGC(JSRuntime *rt, uint32 maxbytes)
if (!gc_finalizers[GCX_OBJECT]) {
gc_finalizers[GCX_OBJECT] = (GCFinalizeOp)js_FinalizeObject;
gc_finalizers[GCX_STRING] = (GCFinalizeOp)js_FinalizeString;
#ifdef DEBUG
gc_finalizers[GCX_DOUBLE] = (GCFinalizeOp)js_FinalizeDouble;
#endif
}
JS_InitArenaPool(&rt->gcArenaPool, "gc-arena", GC_ARENA_SIZE,
@ -479,13 +496,13 @@ gc_dump_thing(JSRuntime* rt, JSGCThing *thing, uint8 flags, GCMarkNode *prev,
break;
}
case GCX_STRING:
case GCX_EXTERNAL_STRING:
default:
fprintf(fp, "string %s", JS_GetStringBytes((JSString *)thing));
break;
case GCX_DOUBLE:
fprintf(fp, "double %g", *(jsdouble *)thing);
break;
case GCX_DECIMAL:
break;
}
fprintf(fp, " via %s\n", path);
free(path);
@ -686,9 +703,10 @@ gc_lock_marker(JSHashEntry *he, intN i, void *arg)
JS_FRIEND_API(void)
js_ForceGC(JSContext *cx)
{
cx->newborn[GCX_OBJECT] = NULL;
cx->newborn[GCX_STRING] = NULL;
cx->newborn[GCX_DOUBLE] = NULL;
uintN i;
for (i = 0; i < GCX_NTYPES; i++)
cx->newborn[i] = NULL;
cx->runtime->gcPoke = JS_TRUE;
js_GC(cx, 0);
JS_ArenaFinish();
@ -703,6 +721,7 @@ js_GC(JSContext *cx, uintN gcflags)
jsval v, *vp, *sp;
jsuword begin, end;
JSStackFrame *fp, *chain;
uintN i;
void *mark;
uint8 flags, *flagp;
JSGCThing *thing, *final, **flp, **oflp;
@ -913,6 +932,8 @@ restart:
GC_MARK(cx, acx->newborn[GCX_OBJECT], "newborn object", NULL);
GC_MARK(cx, acx->newborn[GCX_STRING], "newborn string", NULL);
GC_MARK(cx, acx->newborn[GCX_DOUBLE], "newborn double", NULL);
for (i = GCX_EXTERNAL_STRING; i < GCX_NTYPES; i++)
GC_MARK(cx, acx->newborn[i], "newborn external string", NULL);
#if JS_HAS_EXCEPTIONS
if (acx->throwing && JSVAL_IS_GCTHING(acx->exception))
GC_MARK(cx, JSVAL_TO_GCTHING(acx->exception), "exception", NULL);

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

@ -43,19 +43,20 @@
JS_BEGIN_EXTERN_C
/* GC thing type indexes. */
#define GCX_OBJECT 0 /* JSObject */
#define GCX_STRING 1 /* JSString */
#define GCX_DOUBLE 2 /* jsdouble */
#define GCX_DECIMAL 3 /* JSDecimal */
#define GCX_NTYPES 4
#define GCX_OBJECT 0 /* JSObject */
#define GCX_STRING 1 /* JSString */
#define GCX_DOUBLE 2 /* jsdouble */
#define GCX_EXTERNAL_STRING 3 /* JSString w/ external chars */
#define GCX_NTYPES_LOG2 3
#define GCX_NTYPES JS_BIT(GCX_NTYPES_LOG2)
/* GC flag definitions (type index goes in low bits). */
#define GCF_TYPEMASK JS_BITMASK(2) /* use low bits for type */
#define GCF_MARK JS_BIT(2) /* mark bit */
#define GCF_FINAL JS_BIT(3) /* in finalization bit */
#define GCF_LOCKBIT 4 /* lock bit shift and mask */
#define GCF_LOCKMASK (JS_BITMASK(4) << GCF_LOCKBIT)
#define GCF_LOCK JS_BIT(GCF_LOCKBIT) /* lock request bit in API */
#define GCF_TYPEMASK JS_BITMASK(GCX_NTYPES_LOG2)
#define GCF_MARK JS_BIT(GCX_NTYPES_LOG2)
#define GCF_FINAL JS_BIT(GCX_NTYPES_LOG2 + 1)
#define GCF_LOCKSHIFT (GCX_NTYPES_LOG2 + 2) /* lock bit shift and mask */
#define GCF_LOCKMASK (JS_BITMASK(8 - GCF_LOCKSHIFT) << GCF_LOCKSHIFT)
#define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */
#if 1
/*
@ -67,6 +68,10 @@ JS_BEGIN_EXTERN_C
#define GC_POKE(cx, oldval) ((cx)->runtime->gcPoke = JSVAL_IS_GCTHING(oldval))
#endif
extern intN
js_ChangeExternalStringFinalizer(JSStringFinalizeOp oldop,
JSStringFinalizeOp newop);
extern JSBool
js_InitGC(JSRuntime *rt, uint32 maxbytes);

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

@ -170,6 +170,9 @@ typedef JSBool
typedef void
(* CRT_CALL JSFinalizeOp)(JSContext *cx, JSObject *obj);
typedef void
(* CRT_CALL JSStringFinalizeOp)(JSContext *cx, JSString *str);
typedef JSObjectOps *
(* CRT_CALL JSGetObjectOps)(JSContext *cx, JSClass *clasp);