зеркало из https://github.com/mozilla/gecko-dev.git
Support external string GC types so XPConnect and other systems can optimize away copies (50602, r=jband).
This commit is contained in:
Родитель
a1659d2bd2
Коммит
57422a219a
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче