Give JSScope a proper flags member, without increasing its size (part of 196097, r=shaver).

This commit is contained in:
brendan%mozilla.org 2003-03-11 20:30:55 +00:00
Родитель d0f8bd9264
Коммит 67444da79d
3 изменённых файлов: 34 добавлений и 38 удалений

Просмотреть файл

@ -1109,7 +1109,7 @@ JS_GetObjectTotalSize(JSContext *cx, JSObject *obj)
scope = OBJ_SCOPE(obj);
if (scope->object == obj) {
nbytes += sizeof *scope;
nbytes += JS_BIT(scope->sizeLog2) * sizeof(JSScopeProperty *);
nbytes += SCOPE_CAPACITY(scope) * sizeof(JSScopeProperty *);
}
}
return nbytes;

Просмотреть файл

@ -90,7 +90,6 @@ static void
InitMinimalScope(JSScope *scope)
{
scope->hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;
scope->sizeLog2 = MIN_SCOPE_SIZE_LOG2;
scope->entryCount = scope->removedCount = 0;
scope->table = NULL;
scope->lastProp = NULL;
@ -111,7 +110,9 @@ CreateScopeTable(JSScope *scope)
* overallocating to hold at least twice the current population.
*/
sizeLog2 = JS_CeilingLog2(2 * scope->entryCount);
scope->hashShift = JS_DHASH_BITS - sizeLog2;
} else {
JS_ASSERT(scope->hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2);
sizeLog2 = MIN_SCOPE_SIZE_LOG2;
}
@ -120,7 +121,6 @@ CreateScopeTable(JSScope *scope)
if (!scope->table)
return JS_FALSE;
scope->sizeLog2 = sizeLog2;
scope->hashShift = JS_DHASH_BITS - sizeLog2;
for (sprop = scope->lastProp; sprop; sprop = sprop->parent) {
spp = js_SearchScope(scope, sprop->id, JS_TRUE);
@ -141,6 +141,7 @@ js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,
js_InitObjectMap(&scope->map, nrefs, ops, clasp);
scope->object = obj;
scope->flags = 0;
InitMinimalScope(scope);
#ifdef JS_THREADSAFE
@ -279,7 +280,7 @@ js_SearchScope(JSScope *scope, jsid id, JSBool adding)
}
/* Collision: double hash. */
sizeLog2 = scope->sizeLog2;
sizeLog2 = JS_DHASH_BITS - hashShift;
hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift);
sizeMask = JS_BITMASK(sizeLog2);
@ -331,7 +332,7 @@ ChangeScope(JSContext *cx, JSScope *scope, int change)
JSScopeProperty **table, **oldtable, **spp, **oldspp, *sprop;
/* Grow, shrink, or compress by changing scope->table. */
oldlog2 = scope->sizeLog2;
oldlog2 = JS_DHASH_BITS - scope->hashShift;
newlog2 = oldlog2 + change;
oldsize = JS_BIT(oldlog2);
newsize = JS_BIT(newlog2);
@ -344,7 +345,6 @@ ChangeScope(JSContext *cx, JSScope *scope, int change)
/* Now that we have a new table allocated, update scope members. */
scope->hashShift = JS_DHASH_BITS - newlog2;
scope->sizeLog2 = newlog2;
scope->removedCount = 0;
oldtable = scope->table;
scope->table = table;
@ -810,7 +810,7 @@ CheckAncestorLine(JSScope *scope, JSBool sparse)
JS_ASSERT(SCOPE_HAS_PROPERTY(scope, ancestorLine));
entryCount = 0;
size = JS_BIT(scope->sizeLog2);
size = SCOPE_CAPACITY(scope);
start = scope->table;
for (spp = start, end = start + size; spp < end; spp++) {
sprop = SPROP_FETCH(spp);
@ -869,7 +869,7 @@ js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
if (!sprop) {
/* Check whether we need to grow, if the load factor is >= .75. */
JS_ASSERT(JS_IS_SCOPE_LOCKED(scope));
size = JS_BIT(scope->sizeLog2);
size = SCOPE_CAPACITY(scope);
if (scope->entryCount + scope->removedCount >= size - (size >> 2)) {
if (scope->removedCount >= size >> 2) {
METER(compresses);
@ -986,7 +986,7 @@ js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
splen = scope->entryCount;
if (splen == 0) {
scope->lastProp = NULL;
JS_ASSERT(scope->lastProp == NULL);
} else {
/*
* Enumerate live entries in scope->table using a temporary
@ -1075,6 +1075,8 @@ js_AddScopeProperty(JSContext *cx, JSScope *scope, jsid id,
CHECK_ANCESTOR_LINE(scope, JS_FALSE);
JS_RUNTIME_METER(cx->runtime, middleDeleteFixups);
}
SCOPE_CLR_MIDDLE_DELETE(scope);
}
/*
@ -1165,12 +1167,12 @@ fail_overwrite:
if (!sprop) {
sprop = SCOPE_LAST_PROP(scope);
if (overwriting->parent == sprop) {
SCOPE_SET_LAST_PROP(scope, overwriting);
scope->lastProp = overwriting;
} else {
sprop = GetPropertyTreeChild(cx, sprop, overwriting);
if (sprop) {
JS_ASSERT(sprop != overwriting);
SCOPE_SET_LAST_PROP(scope, sprop);
scope->lastProp = sprop;
}
overwriting = sprop;
}
@ -1241,7 +1243,7 @@ js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,
if (scope->table)
SPROP_STORE_PRESERVING_COLLISION(spp, newsprop);
SCOPE_SET_LAST_PROP(scope, newsprop);
scope->lastProp = newsprop;
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
}
} else {
@ -1309,7 +1311,7 @@ js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id)
scope->entryCount--;
JS_RUNTIME_UNMETER(cx->runtime, liveScopeProps);
/* Update scope->lastProp directly, or set its deferred update tag. */
/* Update scope->lastProp directly, or set its deferred update flag. */
if (sprop == SCOPE_LAST_PROP(scope)) {
do {
SCOPE_REMOVE_LAST_PROP(scope);
@ -1323,7 +1325,7 @@ js_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id)
CHECK_ANCESTOR_LINE(scope, JS_TRUE);
/* Last, consider shrinking scope's table if its load factor is <= .25. */
size = JS_BIT(scope->sizeLog2);
size = SCOPE_CAPACITY(scope);
if (size > MIN_SCOPE_SIZE && scope->entryCount <= size >> 2) {
METER(shrinks);
(void) ChangeScope(cx, scope, -1);
@ -1343,6 +1345,7 @@ js_ClearScope(JSContext *cx, JSScope *scope)
if (scope->table)
free(scope->table);
SCOPE_CLR_MIDDLE_DELETE(scope);
InitMinimalScope(scope);
}

Просмотреть файл

@ -106,10 +106,8 @@
* What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice.
* Therefore we must fork in such a case, if not earlier. Because delete is
* "bursty", we should not fork eagerly. Delaying a fork till we are at risk
* of adding Y after it was deleted already requires a flag in the JSScope, at
* least. So we tag the scope->lastProp pointer with SCOPE_MIDDLE_DELETE_TAG,
* to avoid expanding the size of JSScope, and to penalize only the code that
* already must care about forking (js_{Add,Remove}ScopeProperty).
* of adding Y after it was deleted already requires a flag in the JSScope, to
* wit, SCOPE_MIDDLE_DELETE.
*
* What about thread safety? If the property tree operations done by requests
* are find-node and insert-node, then the only hazard is duplicate insertion.
@ -198,8 +196,8 @@
struct JSScope {
JSObjectMap map; /* base class state */
JSObject *object; /* object that owns this scope */
uint16 flags; /* flags, see below */
int16 hashShift; /* multiplicative hash shift */
int16 sizeLog2; /* log2(table size) */
uint32 entryCount; /* number of entries in table */
uint32 removedCount; /* removed entry sentinels in table */
JSScopeProperty **table; /* table of ptrs to shared tree nodes */
@ -220,28 +218,23 @@ struct JSScope {
#define OBJ_SCOPE(obj) ((JSScope *)(obj)->map)
#define SCOPE_MIDDLE_DELETE_TAG ((jsuword)1)
#define SCOPE_LAST_PROP_WORD(scope) ((jsuword)(scope)->lastProp)
/* By definition, hashShift = JS_DHASH_BITS - log2(capacity). */
#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
#define SCOPE_LAST_PROP(scope) \
((JSScopeProperty *) (SCOPE_LAST_PROP_WORD(scope) & \
~SCOPE_MIDDLE_DELETE_TAG))
/* Scope flags and some macros to hide them from other files than jsscope.c. */
#define SCOPE_MIDDLE_DELETE 0x0001
#define SCOPE_HAD_MIDDLE_DELETE(scope) \
(SCOPE_LAST_PROP_WORD(scope) & SCOPE_MIDDLE_DELETE_TAG)
#define SCOPE_HAD_MIDDLE_DELETE(scope) ((scope)->flags & SCOPE_MIDDLE_DELETE)
#define SCOPE_SET_MIDDLE_DELETE(scope) ((scope)->flags |= SCOPE_MIDDLE_DELETE)
#define SCOPE_CLR_MIDDLE_DELETE(scope) ((scope)->flags &= ~SCOPE_MIDDLE_DELETE)
#define SCOPE_SET_LAST_PROP(scope, sprop) \
((scope)->lastProp = (JSScopeProperty *) \
((jsuword) (sprop) | \
SCOPE_HAD_MIDDLE_DELETE(scope)))
#define SCOPE_REMOVE_LAST_PROP(scope) \
SCOPE_SET_LAST_PROP(scope, SCOPE_LAST_PROP(scope)->parent)
#define SCOPE_SET_MIDDLE_DELETE(scope) \
((scope)->lastProp = (JSScopeProperty *) \
(SCOPE_LAST_PROP_WORD(scope) | \
SCOPE_MIDDLE_DELETE_TAG))
/*
* A little information hiding for scope->lastProp, in case it ever becomes
* a tagged pointer again.
*/
#define SCOPE_LAST_PROP(scope) ((scope)->lastProp)
#define SCOPE_REMOVE_LAST_PROP(scope) ((scope)->lastProp = \
(scope)->lastProp->parent)
struct JSScopeProperty {
jsid id; /* int-tagged jsval/untagged JSAtom* */