Rework GCF_DONT_BLOCK to be cx->gcDontBlock, assert it's set, set before entering trace and clear on exit.

This commit is contained in:
Brendan Eich 2008-08-11 11:18:16 -07:00
parent a56862bdff
commit 13cfac8f97
5 changed files with 21 additions and 19 deletions

View File

@ -90,8 +90,7 @@ js_BoxDouble(JSContext* cx, jsdouble d)
jsint i;
if (JSDOUBLE_IS_INT(d, i))
return INT_TO_JSVAL(i);
if (!cx->doubleFreeList) /* we must be certain the GC won't kick in */
return JSVAL_ERROR_COOKIE;
JS_ASSERT(cx->gcDontBlock);
jsval v; /* not rooted but ok here because we know GC won't run */
if (!js_NewDoubleInRootedValue(cx, d, &v))
return JSVAL_ERROR_COOKIE;
@ -103,8 +102,7 @@ js_BoxInt32(JSContext* cx, jsint i)
{
if (JS_LIKELY(INT_FITS_IN_JSVAL(i)))
return INT_TO_JSVAL(i);
if (!cx->doubleFreeList) /* we must be certain the GC won't kick in */
return JSVAL_ERROR_COOKIE;
JS_ASSERT(cx->gcDontBlock);
jsval v; /* not rooted but ok here because we know GC won't run */
jsdouble d = (jsdouble)i;
if (!js_NewDoubleInRootedValue(cx, d, &v))
@ -209,6 +207,7 @@ JSString* FASTCALL
js_String_p_substring(JSContext* cx, JSString* str, jsint begin, jsint end)
{
JS_ASSERT(end >= begin);
JS_ASSERT(cx->gcDontBlock);
return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
}
@ -217,6 +216,7 @@ js_String_p_substring_1(JSContext* cx, JSString* str, jsint begin)
{
jsint end = JSSTRING_LENGTH(str);
JS_ASSERT(end >= begin);
JS_ASSERT(cx->gcDontBlock);
return js_NewDependentString(cx, str, (size_t)begin, (size_t)(end - begin));
}
@ -225,15 +225,14 @@ js_String_getelem(JSContext* cx, JSString* str, jsint i)
{
if ((size_t)i >= JSSTRING_LENGTH(str))
return NULL;
/* XXX check for string freelist space */
return js_GetUnitString(cx, str, (size_t)i);
}
JSString* FASTCALL
js_String_fromCharCode(JSContext* cx, jsint i)
{
JS_ASSERT(cx->gcDontBlock);
jschar c = (jschar)i;
/* XXX check for string freelist space */
if (c < UNIT_STRING_LIMIT)
return js_GetUnitStringForChar(cx, c);
return js_NewStringCopyN(cx, &c, 1);
@ -342,7 +341,8 @@ js_FastNewObject(JSContext* cx, JSObject* ctor)
JSFunction* fun = GET_FUNCTION_PRIVATE(cx, ctor);
JSClass* clasp = FUN_INTERPRETED(fun) ? &js_ObjectClass : fun->u.n.clasp;
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCF_DONT_BLOCK | GCX_OBJECT, sizeof(JSObject));
JS_ASSERT(cx->gcDontBlock);
JSObject* obj = (JSObject*) js_NewGCThing(cx, GCX_OBJECT, sizeof(JSObject));
if (!obj)
return NULL;

View File

@ -705,11 +705,17 @@ struct JSContext {
* property values associated with this context's global object.
*/
uint8 xmlSettingFlags;
uint8 padding;
#else
uint16 padding;
uint8 padding;
#endif
/*
* Flag to prevent last-ditch garbage collection when up against runtime
* memory limits. This also suppresses calls to JS_ReportOutOfMemory when
* failing due to runtime limits.
*/
JSPackedBool gcDontBlock;
/* Runtime version control identifier. */
uint16 version;

View File

@ -1749,7 +1749,7 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
arenaList = &rt->gcArenaList[flindex];
for (;;) {
if (doGC && !(flags & GCF_DONT_BLOCK)) {
if (doGC && !cx->gcDontBlock) {
/*
* Keep rt->gcLock across the call into js_GC so we don't starve
* and lose to racing threads who deplete the heap just after
@ -1809,7 +1809,7 @@ js_NewGCThing(JSContext *cx, uintN flags, size_t nbytes)
} else {
a = NewGCArena(rt);
if (!a) {
if (doGC || (flags & GCF_DONT_BLOCK))
if (doGC || cx->gcDontBlock)
goto fail;
doGC = JS_TRUE;
continue;
@ -1912,7 +1912,7 @@ fail:
JS_UNLOCK_GC(rt);
#endif
METER(astats->fail++);
if (!(flags & GCF_DONT_BLOCK))
if (!cx->gcDontBlock)
JS_ReportOutOfMemory(cx);
return NULL;
}

View File

@ -93,13 +93,6 @@ JS_STATIC_ASSERT(GCX_NTYPES <= GCX_LIMIT);
#define GCF_LOCKSHIFT (GCX_LIMIT_LOG2 + 2) /* lock bit shift */
#define GCF_LOCK JS_BIT(GCF_LOCKSHIFT) /* lock request bit in API */
/*
* Pseudo-flag, not stored but passed into js_NewGCThing, to prevent last-ditch
* collection when up against runtime memory limits. This also suppresses calls
* to JS_ReportOutOfMemory when failing due to runtime limits.
*/
#define GCF_DONT_BLOCK 0x100
/*
* Get the type of the external string or -1 if the string was not created
* with JS_NewExternalString.

View File

@ -1651,7 +1651,10 @@ js_ExecuteTree(JSContext* cx, Fragment* f, uintN& inlineCallCount)
uint64 start = rdtsc();
#endif
JS_ASSERT(!cx->gcDontBlock);
cx->gcDontBlock = JS_TRUE;
GuardRecord* lr = u.func(&state, NULL);
cx->gcDontBlock = JS_FALSE;
for (int32 i = 0; i < lr->calldepth; i++)
js_SynthesizeFrame(cx, callstack[i]);