mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-13 21:35:39 +00:00
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:
parent
30295f72b6
commit
7fd9e073e2
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user