зеркало из https://github.com/mozilla/gecko-dev.git
Try again for bug 41381, r=wtc@netscape.com
This commit is contained in:
Родитель
c5012b7094
Коммит
2566f33358
|
@ -684,6 +684,7 @@ JS_DestroyRuntime(JSRuntime *rt)
|
|||
JS_PUBLIC_API(void)
|
||||
JS_ShutDown(void)
|
||||
{
|
||||
JS_ArenaShutDown();
|
||||
js_FreeStringGlobals();
|
||||
#ifdef JS_THREADSAFE
|
||||
js_CleanupLocks();
|
||||
|
@ -2104,6 +2105,7 @@ JS_ClearScope(JSContext *cx, JSObject *obj)
|
|||
|
||||
CHECK_REQUEST(cx);
|
||||
/* XXXbe push this into jsobj.c or jsscope.c */
|
||||
/* XXXbe2 worse, assumes obj is native here, before MAP_IS_NATIVE! */
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
map = obj->map;
|
||||
if (MAP_IS_NATIVE(map)) {
|
||||
|
|
119
js/src/jsarena.c
119
js/src/jsarena.c
|
@ -44,13 +44,14 @@
|
|||
#include "jsbit.h"
|
||||
#include "jsarena.h" /* Added by JSIFY */
|
||||
#include "jsutil.h" /* Added by JSIFY */
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
extern int js_CompareAndSwap(jsword *, jsword, jsword);
|
||||
#endif
|
||||
#include "jslock.h"
|
||||
|
||||
static JSArena *arena_freelist;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
static JSLock *arena_freelist_lock;
|
||||
#endif
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
static JSArenaStats *arena_stats_list;
|
||||
|
||||
|
@ -64,6 +65,13 @@ static JSArenaStats *arena_stats_list;
|
|||
JS_PUBLIC_API(void)
|
||||
JS_InitArenaPool(JSArenaPool *pool, const char *name, JSUint32 size, JSUint32 align)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Must come through here once in primordial thread to init safely! */
|
||||
if (!arena_freelist_lock) {
|
||||
arena_freelist_lock = JS_NEW_LOCK();
|
||||
JS_ASSERT(arena_freelist_lock);
|
||||
}
|
||||
#endif
|
||||
if (align == 0)
|
||||
align = JS_ARENA_DEFAULT_ALIGN;
|
||||
pool->mask = JS_BITMASK(JS_CeilingLog2(align));
|
||||
|
@ -95,41 +103,37 @@ JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
|||
if (nb >= 60000U)
|
||||
return 0;
|
||||
#endif /* WIN16 */
|
||||
ap = &arena_freelist;
|
||||
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
|
||||
if (a->next) { /* move to next arena */
|
||||
a = a->next;
|
||||
continue;
|
||||
if (!a->next) {
|
||||
ap = &arena_freelist;
|
||||
JS_ACQUIRE_LOCK(arena_freelist_lock);
|
||||
while ((b = *ap) != NULL) { /* reclaim a free arena */
|
||||
if (b->avail + nb <= b->limit) {
|
||||
*ap = b->next;
|
||||
JS_RELEASE_LOCK(arena_freelist_lock);
|
||||
b->next = NULL;
|
||||
a = a->next = b;
|
||||
COUNT(pool, nreclaims);
|
||||
goto claim;
|
||||
}
|
||||
ap = &b->next;
|
||||
}
|
||||
JS_RELEASE_LOCK(arena_freelist_lock);
|
||||
sz = JS_MAX(pool->arenasize, nb); /* allocate a new arena */
|
||||
sz += sizeof *a + pool->mask; /* header and alignment slop */
|
||||
b = (JSArena *) malloc(sz);
|
||||
if (!b)
|
||||
return 0;
|
||||
a = a->next = b;
|
||||
a->next = NULL;
|
||||
a->limit = (jsuword)a + sz;
|
||||
JS_COUNT_ARENA(pool,++);
|
||||
COUNT(pool, nmallocs);
|
||||
claim:
|
||||
a->base = a->avail = (jsuword)JS_ARENA_ALIGN(pool, a + 1);
|
||||
continue;
|
||||
}
|
||||
while ((b = *ap) != NULL) { /* reclaim a free arena */
|
||||
if (b->limit - b->base == pool->arenasize) {
|
||||
#ifdef JS_THREADSAFE
|
||||
do {
|
||||
b = *ap;
|
||||
c = b->next;
|
||||
} while (!js_CompareAndSwap((jsword *)ap,(jsword)b,(jsword)c));
|
||||
#else
|
||||
*ap = b->next;
|
||||
#endif
|
||||
b->next = NULL;
|
||||
a = a->next = b;
|
||||
COUNT(pool, nreclaims);
|
||||
goto claim;
|
||||
}
|
||||
ap = &b->next;
|
||||
}
|
||||
sz = JS_MAX(pool->arenasize, nb); /* allocate a new arena */
|
||||
sz += sizeof *a + pool->mask; /* header and alignment slop */
|
||||
b = (JSArena *) malloc(sz);
|
||||
if (!b)
|
||||
return 0;
|
||||
a = a->next = b;
|
||||
a->next = NULL;
|
||||
a->limit = (jsuword)a + sz;
|
||||
JS_COUNT_ARENA(pool,++);
|
||||
COUNT(pool, nmallocs);
|
||||
claim:
|
||||
a->base = a->avail = (jsuword)JS_ARENA_ALIGN(pool, a + 1);
|
||||
a = a->next; /* move to next arena */
|
||||
}
|
||||
p = (void *)a->avail;
|
||||
a->avail += nb;
|
||||
|
@ -185,15 +189,10 @@ FreeArenaList(JSArenaPool *pool, JSArena *head, JSBool reallyFree)
|
|||
do {
|
||||
ap = &(*ap)->next;
|
||||
} while (*ap);
|
||||
#ifdef JS_THREADSAFE
|
||||
do {
|
||||
*ap = b = arena_freelist;
|
||||
} while (!js_CompareAndSwap((jsword *)&arena_freelist, (jsword)b,
|
||||
(jsword)a));
|
||||
#else
|
||||
JS_ACQUIRE_LOCK(arena_freelist_lock);
|
||||
*ap = arena_freelist;
|
||||
arena_freelist = a;
|
||||
#endif
|
||||
JS_RELEASE_LOCK(arena_freelist_lock);
|
||||
head->next = NULL;
|
||||
}
|
||||
|
||||
|
@ -205,8 +204,8 @@ JS_ArenaRelease(JSArenaPool *pool, char *mark)
|
|||
{
|
||||
JSArena *a;
|
||||
|
||||
for (a = pool->first.next; a; a = a->next) {
|
||||
if (JS_UPTRDIFF(mark, a->base) < JS_UPTRDIFF(a->avail, a->base)) {
|
||||
for (a = &pool->first; a; a = a->next) {
|
||||
if (JS_UPTRDIFF(mark, a->base) <= JS_UPTRDIFF(a->avail, a->base)) {
|
||||
a->avail = (jsuword)JS_ARENA_ALIGN(pool, mark);
|
||||
FreeArenaList(pool, a, JS_TRUE);
|
||||
return;
|
||||
|
@ -261,21 +260,25 @@ JS_ArenaFinish()
|
|||
{
|
||||
JSArena *a, *next;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
while (arena_freelist) {
|
||||
a = arena_freelist;
|
||||
next = a->next;
|
||||
if (js_CompareAndSwap((jsword *)&arena_freelist, (jsword)a,
|
||||
(jsword)next)) {
|
||||
free(a);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (a = arena_freelist; a; a = next) {
|
||||
JS_ACQUIRE_LOCK(arena_freelist_lock);
|
||||
a = arena_freelist;
|
||||
arena_freelist = NULL;
|
||||
JS_RELEASE_LOCK(arena_freelist_lock);
|
||||
for (; a; a = next) {
|
||||
next = a->next;
|
||||
free(a);
|
||||
}
|
||||
arena_freelist = NULL;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_ArenaShutDown(void)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
/* Must come through here once in the process's last thread! */
|
||||
if (arena_freelist_lock) {
|
||||
JS_DESTROY_LOCK(arena_freelist_lock);
|
||||
arena_freelist_lock = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -152,7 +152,8 @@ struct JSArenaPool {
|
|||
JS_BEGIN_MACRO \
|
||||
char *_m = (char *)(mark); \
|
||||
JSArena *_a = (pool)->current; \
|
||||
if (JS_UPTRDIFF(_m, _a->base) <= JS_UPTRDIFF(_a->avail, _a->base)) { \
|
||||
if (_a != &(pool)->first && \
|
||||
JS_UPTRDIFF(_m, _a->base) <= JS_UPTRDIFF(_a->avail, _a->base)) { \
|
||||
_a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \
|
||||
JS_CLEAR_UNUSED(_a); \
|
||||
JS_ArenaCountRetract(pool, _m); \
|
||||
|
@ -207,11 +208,26 @@ extern JS_PUBLIC_API(void)
|
|||
JS_CompactArenaPool(JSArenaPool *pool);
|
||||
|
||||
/*
|
||||
* Finish using arenas, freeing all memory associated with them.
|
||||
* Finish using arenas, freeing all memory associated with them except for
|
||||
* any locks needed for thread safety.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaFinish(void);
|
||||
|
||||
/*
|
||||
* Free any locks or other memory needed for thread safety, just before
|
||||
* shutting down. At that point, we must be called by a single thread.
|
||||
*
|
||||
* After shutting down, the next thread to call JS_InitArenaPool must not
|
||||
* race with any other thread. Once a pool has been initialized, threads
|
||||
* may safely call jsarena.c functions on thread-local pools. The upshot
|
||||
* is that pools are per-thread, but the underlying global freelist is
|
||||
* thread-safe, provided that both the first pool initialization and the
|
||||
* shut-down call are single-threaded.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaShutDown(void);
|
||||
|
||||
/*
|
||||
* Friend functions used by the JS_ARENA_*() macros.
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче