fix bug 70360 - adding an additional gchook event. r=shaver sr=brendan. fix bug 73761 - property cache does *bad* things if accessed during finalization. sr=brendan. checkin patch from vidur regarding off-by-on in result code iteration. sr=jband on vidur's patch

This commit is contained in:
jband%netscape.com 2001-04-09 23:22:07 +00:00
parent 30295f72b6
commit 7fd9e073e2
6 changed files with 81 additions and 36 deletions

View File

@ -1102,6 +1102,7 @@ js_GC(JSContext *cx, uintN gcflags)
rt->gcMallocBytes = 0;
/* Drop atoms held by the property cache, and clear property weak links. */
js_DisablePropertyCache(cx);
js_FlushPropertyCache(cx);
restart:
rt->gcNumber++;
@ -1275,6 +1276,9 @@ restart:
/* Terminate the new freelist. */
*flp = NULL;
if (rt->gcCallback)
(void) rt->gcCallback(cx, JSGC_FINALIZE_END);
out:
JS_LOCK_GC(rt);
if (rt->gcLevel > 1) {
@ -1282,6 +1286,7 @@ out:
JS_UNLOCK_GC(rt);
goto restart;
}
js_EnablePropertyCache(cx);
rt->gcLevel = 0;
rt->gcLastBytes = rt->gcBytes;
rt->gcRunning = JS_FALSE;

View File

@ -70,14 +70,33 @@
#include "jsjit.h"
#endif
#ifdef DEBUG
#define ASSERT_CACHE_IS_EMPTY(cache) \
JS_BEGIN_MACRO \
JSPropertyCacheEntry *end_, *pce_, entry_; \
JSPropertyCache *cache_ = (cache); \
JS_ASSERT(cache_->empty); \
end_ = &cache_->table[PROPERTY_CACHE_SIZE]; \
for (pce_ = &cache_->table[0]; pce_ < end_; pce_++) { \
PCE_LOAD(cache_, pce_, entry_); \
JS_ASSERT(!PCE_OBJECT(entry_)); \
JS_ASSERT(!PCE_PROPERTY(entry_)); \
} \
JS_END_MACRO
#else
#define ASSERT_CACHE_IS_EMPTY(cache) ((void)0)
#endif
void
js_FlushPropertyCache(JSContext *cx)
{
JSPropertyCache *cache;
cache = &cx->runtime->propertyCache;
if (cache->empty)
if (cache->empty) {
ASSERT_CACHE_IS_EMPTY(cache);
return;
}
memset(cache->table, 0, sizeof cache->table);
cache->empty = JS_TRUE;
cache->flushes++;
@ -87,7 +106,6 @@ void
js_FlushPropertyCacheByProp(JSContext *cx, JSProperty *prop)
{
JSPropertyCache *cache;
JSBool empty;
JSPropertyCacheEntry *end, *pce, entry;
JSProperty *pce_prop;
@ -95,22 +113,31 @@ js_FlushPropertyCacheByProp(JSContext *cx, JSProperty *prop)
if (cache->empty)
return;
empty = JS_TRUE;
end = &cache->table[PROPERTY_CACHE_SIZE];
for (pce = &cache->table[0]; pce < end; pce++) {
PCE_LOAD(cache, pce, entry);
pce_prop = PCE_PROPERTY(entry);
if (pce_prop) {
if (pce_prop == prop) {
PCE_OBJECT(entry) = NULL;
PCE_PROPERTY(entry) = NULL;
PCE_STORE(cache, pce, entry);
} else {
empty = JS_FALSE;
}
if (pce_prop == prop) {
PCE_OBJECT(entry) = NULL;
PCE_PROPERTY(entry) = NULL;
PCE_STORE(cache, pce, entry);
}
}
cache->empty = empty;
}
void
js_DisablePropertyCache(JSContext *cx)
{
JS_ASSERT(!cx->runtime->propertyCache.disabled);
cx->runtime->propertyCache.disabled = JS_TRUE;
}
void
js_EnablePropertyCache(JSContext *cx)
{
JS_ASSERT(cx->runtime->propertyCache.disabled);
ASSERT_CACHE_IS_EMPTY(&cx->runtime->propertyCache);
cx->runtime->propertyCache.disabled = JS_FALSE;
}
/*

View File

@ -147,6 +147,7 @@ typedef union JSPropertyCacheEntry {
typedef struct JSPropertyCache {
JSPropertyCacheEntry table[PROPERTY_CACHE_SIZE];
JSBool empty;
JSBool disabled;
uint32 fills;
uint32 recycles;
uint32 tests;
@ -156,20 +157,22 @@ typedef struct JSPropertyCache {
#define PROPERTY_CACHE_FILL(cx, cache, obj, id, prop) \
JS_BEGIN_MACRO \
uintN _hashIndex = (uintN)PROPERTY_CACHE_HASH(obj, id); \
JSPropertyCache *_cache = (cache); \
JSPropertyCacheEntry *_pce = &_cache->table[_hashIndex]; \
JSPropertyCacheEntry _entry; \
JSProperty *_pce_prop; \
PCE_LOAD(_cache, _pce, _entry); \
_pce_prop = PCE_PROPERTY(_entry); \
if (_pce_prop && _pce_prop != prop) \
_cache->recycles++; \
PCE_OBJECT(_entry) = obj; \
PCE_PROPERTY(_entry) = prop; \
_cache->empty = JS_FALSE; \
_cache->fills++; \
PCE_STORE(_cache, _pce, _entry); \
JSPropertyCache *_cache = (cache); \
if (!_cache->disabled) { \
uintN _hashIndex = (uintN)PROPERTY_CACHE_HASH(obj, id); \
JSPropertyCacheEntry *_pce = &_cache->table[_hashIndex]; \
JSPropertyCacheEntry _entry; \
JSProperty *_pce_prop; \
PCE_LOAD(_cache, _pce, _entry); \
_pce_prop = PCE_PROPERTY(_entry); \
if (_pce_prop && _pce_prop != prop) \
_cache->recycles++; \
PCE_OBJECT(_entry) = obj; \
PCE_PROPERTY(_entry) = prop; \
_cache->empty = JS_FALSE; \
_cache->fills++; \
PCE_STORE(_cache, _pce, _entry); \
} \
JS_END_MACRO
#define PROPERTY_CACHE_TEST(cache, obj, id, prop) \
@ -198,6 +201,12 @@ js_FlushPropertyCache(JSContext *cx);
extern void
js_FlushPropertyCacheByProp(JSContext *cx, JSProperty *prop);
extern void
js_DisablePropertyCache(JSContext *cx);
extern void
js_EnablePropertyCache(JSContext *cx);
extern JS_FRIEND_API(jsval *)
js_AllocStack(JSContext *cx, uintN nslots, void **markp);

View File

@ -451,7 +451,8 @@ typedef JSBool
typedef enum JSGCStatus {
JSGC_BEGIN,
JSGC_END,
JSGC_MARK_END
JSGC_MARK_END,
JSGC_FINALIZE_END
} JSGCStatus;
typedef JSBool

View File

@ -381,7 +381,7 @@ typedef JSIntn JSBool;
/************************************************************************
** TYPES: JSPackedBool
** DESCRIPTION:
** Use PRPackedBOol within structs where bitfields are not desireable
** Use JSPackedBool within structs where bitfields are not desireable
** but minimum and consistant overhead matters.
************************************************************************/
typedef JSUint8 JSPackedBool;

View File

@ -84,16 +84,19 @@ nsXPCException::IterateNSResults(nsresult* rv,
ResultMap* p = (ResultMap*) *iterp;
if(!p)
p = map;
NS_ASSERTION(p->name, "iterated off the end of the array");
if(rv)
*rv = p->rv;
if(name)
*name = p->name;
if(format)
*format = p->format;
p++;
else
p++;
if(!p->name)
p = nsnull;
else
{
if(rv)
*rv = p->rv;
if(name)
*name = p->name;
if(format)
*format = p->format;
}
*iterp = p;
return p;
}