Merge backout.

This commit is contained in:
Robert Sayre 2009-07-23 22:08:05 -04:00
commit 3722b48ae2
7 changed files with 49 additions and 77 deletions

View File

@ -104,20 +104,9 @@ FinishThreadData(JSThreadData *data)
static void
PurgeThreadData(JSContext *cx, JSThreadData *data)
{
js_PurgeGSNCache(&data->gsnCache);
if (cx->runtime->gcRegenShapes)
js_PurgePropertyCache(cx, &data->propertyCache);
# ifdef JS_TRACER
JSTraceMonitor *tm = &data->traceMonitor;
tm->reservedDoublePoolPtr = tm->reservedDoublePool;
/*
* FIXME: bug 506117. We should flush only if (cx->runtime->gcRegenShapes),
* but we can't yet, because traces may embed sprop and object references,
* and we don't yet mark such embedded refs.
*/
tm->needFlush = JS_TRUE;
if (tm->recorder)
@ -134,6 +123,9 @@ PurgeThreadData(JSContext *cx, JSThreadData *data)
/* Destroy eval'ed scripts. */
js_DestroyScriptsToGC(cx, data);
js_PurgeGSNCache(&data->gsnCache);
js_PurgePropertyCache(cx, &data->propertyCache);
}
#ifdef JS_THREADSAFE

View File

@ -390,8 +390,7 @@ struct JSRuntime {
*/
JSPackedBool gcPoke;
JSPackedBool gcRunning;
JSPackedBool gcRegenShapes;
uint8 gcPadding;
uint16 gcPadding;
#ifdef JS_GC_ZEAL
jsrefcount gcZeal;
#endif
@ -1559,7 +1558,6 @@ static JS_INLINE uint32
js_RegenerateShapeForGC(JSContext *cx)
{
JS_ASSERT(cx->runtime->gcRunning);
JS_ASSERT(cx->runtime->gcRegenShapes);
/*
* Under the GC, compared with js_GenerateShape, we don't need to use

View File

@ -3600,6 +3600,7 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
#ifdef JS_TRACER
js_PurgeJITOracle();
#endif
js_PurgeThreads(cx);
restart:
rt->gcNumber++;
@ -3611,13 +3612,8 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind)
* Same for the protoHazardShape proxy-shape standing in for all object
* prototypes having readonly or setter properties.
*/
if (rt->shapeGen & SHAPE_OVERFLOW_BIT) {
rt->gcRegenShapes = true;
rt->shapeGen = 0;
rt->protoHazardShape = 0;
}
js_PurgeThreads(cx);
rt->shapeGen = 0;
rt->protoHazardShape = 0;
/*
* Mark phase.
@ -3905,7 +3901,7 @@ out:
rt->setGCLastBytes(rt->gcBytes);
done_running:
rt->gcLevel = 0;
rt->gcRunning = rt->gcRegenShapes = false;
rt->gcRunning = JS_FALSE;
#ifdef JS_THREADSAFE
rt->gcThread = NULL;

View File

@ -5039,7 +5039,7 @@ js_TraceNativeEnumerators(JSTracer *trc)
* re-number completely when tracing is done for the GC.
*/
rt = trc->context->runtime;
if (IS_GC_MARKING_TRACER(trc) && rt->gcRegenShapes) {
if (IS_GC_MARKING_TRACER(trc)) {
memset(&rt->nativeEnumCache, 0, sizeof rt->nativeEnumCache);
#ifdef JS_DUMP_ENUM_CACHE_STATS
printf("nativeEnumCache hit rate %g%%\n",
@ -5743,22 +5743,23 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
MeterEntryCount(scope->entryCount);
#endif
sprop = scope->lastProp;
sprop = SCOPE_LAST_PROP(scope);
if (sprop) {
JS_ASSERT(scope->has(sprop));
/* Regenerate property cache shape ids if GC'ing. */
if (IS_GC_MARKING_TRACER(trc) && cx->runtime->gcRegenShapes) {
if (!(sprop->flags & SPROP_FLAG_SHAPE_REGEN)) {
sprop->shape = js_RegenerateShapeForGC(cx);
if (IS_GC_MARKING_TRACER(trc)) {
uint32 shape, oldshape;
shape = js_RegenerateShapeForGC(cx);
if (!(sprop->flags & SPROP_MARK)) {
oldshape = sprop->shape;
sprop->shape = shape;
sprop->flags |= SPROP_FLAG_SHAPE_REGEN;
if (scope->shape != oldshape)
shape = js_RegenerateShapeForGC(cx);
}
uint32 shape = sprop->shape;
if (scope->hasOwnShape()) {
shape = js_RegenerateShapeForGC(cx);
JS_ASSERT(shape != sprop->shape);
}
scope->shape = shape;
}

View File

@ -1032,14 +1032,12 @@ JSScope::reportReadOnlyScope(JSContext *cx)
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_READ_ONLY, bytes);
}
void
JSScope::generateOwnShape(JSContext *cx)
static inline void
js_MakeScopeShapeUnique(JSContext *cx, JSScope *scope)
{
if (object)
js_LeaveTraceIfGlobalObject(cx, object);
shape = js_GenerateShape(cx, false);
setOwnShape();
if (scope->object)
js_LeaveTraceIfGlobalObject(cx, scope->object);
scope->shape = js_GenerateShape(cx, false);
}
JSScopeProperty *
@ -1156,6 +1154,7 @@ JSScope::add(JSContext *cx, jsid id,
}
setMiddleDelete();
}
js_MakeScopeShapeUnique(cx, this);
/*
* If we fail later on trying to find or create a new sprop, we will
@ -1538,7 +1537,7 @@ JSScope::remove(JSContext *cx, jsid id)
} else if (!hadMiddleDelete()) {
setMiddleDelete();
}
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
CHECK_ANCESTOR_LINE(this, true);
/* Last, consider shrinking this->table if its load factor is <= .25. */
@ -1568,25 +1567,25 @@ JSScope::clear(JSContext *cx)
void
JSScope::brandingShapeChange(JSContext *cx, uint32 slot, jsval v)
{
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
}
void
JSScope::deletingShapeChange(JSContext *cx, JSScopeProperty *sprop)
{
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
}
void
JSScope::methodShapeChange(JSContext *cx, uint32 slot, jsval toval)
{
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
}
void
JSScope::protoShapeChange(JSContext *cx)
{
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
}
void
@ -1595,19 +1594,19 @@ JSScope::replacingShapeChange(JSContext *cx, JSScopeProperty *sprop, JSScopeProp
if (shape == sprop->shape)
shape = newsprop->shape;
else
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
}
void
JSScope::sealingShapeChange(JSContext *cx)
{
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
}
void
JSScope::shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop)
{
generateOwnShape(cx);
js_MakeScopeShapeUnique(cx, this);
}
void
@ -1827,12 +1826,10 @@ js_SweepScopeProperties(JSContext *cx)
*/
if (sprop->flags & SPROP_MARK) {
sprop->flags &= ~SPROP_MARK;
if (rt->gcRegenShapes) {
if (sprop->flags & SPROP_FLAG_SHAPE_REGEN)
sprop->flags &= ~SPROP_FLAG_SHAPE_REGEN;
else
sprop->shape = js_RegenerateShapeForGC(cx);
}
if (sprop->flags & SPROP_FLAG_SHAPE_REGEN)
sprop->flags &= ~SPROP_FLAG_SHAPE_REGEN;
else
sprop->shape = js_RegenerateShapeForGC(cx);
liveCount++;
continue;
}
@ -1872,7 +1869,7 @@ js_SweepScopeProperties(JSContext *cx)
sprop->kids = NULL;
parent = sprop->parent;
/* The grandparent must have either no kids or chunky kids. */
/* Assert that grandparent has no kids or chunky kids. */
JS_ASSERT(!parent || !parent->kids ||
KIDS_IS_CHUNKY(parent->kids));
if (KIDS_IS_CHUNKY(kids)) {
@ -1891,7 +1888,8 @@ js_SweepScopeProperties(JSContext *cx)
* re-use by InsertPropertyTreeChild.
*/
chunk->kids[i] = NULL;
if (!InsertPropertyTreeChild(rt, parent, kid, chunk)) {
if (!InsertPropertyTreeChild(rt, parent, kid,
chunk)) {
/*
* This can happen only if we failed to add an
* entry to the root property hash table.

View File

@ -219,7 +219,6 @@ struct JSScope {
bool createTable(JSContext *cx, bool report);
bool changeTable(JSContext *cx, int change);
void reportReadOnlyScope(JSContext *cx);
void generateOwnShape(JSContext *cx);
JSScopeProperty **searchTable(jsid id, bool adding);
inline JSScopeProperty **search(jsid id, bool adding);
JSScope *createEmptyScope(JSContext *cx, JSClass *clasp);
@ -282,14 +281,16 @@ struct JSScope {
MIDDLE_DELETE = 0x0001,
SEALED = 0x0002,
BRANDED = 0x0004,
INDEXED_PROPERTIES = 0x0008,
OWN_SHAPE = 0x0010
INDEXED_PROPERTIES = 0x0008
};
bool hadMiddleDelete() { return flags & MIDDLE_DELETE; }
void setMiddleDelete() { flags |= MIDDLE_DELETE; }
void clearMiddleDelete() { flags &= ~MIDDLE_DELETE; }
bool hadIndexedProperties() { return flags & INDEXED_PROPERTIES; }
void setIndexedProperties() { flags |= INDEXED_PROPERTIES; }
/*
* Don't define clearSealed, as it can't be done safely because JS_LOCK_OBJ
* will avoid taking the lock if the object owns its scope and the scope is
@ -305,12 +306,7 @@ struct JSScope {
*/
bool branded() { return flags & BRANDED; }
void setBranded() { flags |= BRANDED; }
bool hadIndexedProperties() { return flags & INDEXED_PROPERTIES; }
void setIndexedProperties() { flags |= INDEXED_PROPERTIES; }
bool hasOwnShape() { return flags & OWN_SHAPE; }
void setOwnShape() { flags |= OWN_SHAPE; }
void clearBranded() { flags &= ~BRANDED; }
bool owned() { return object != NULL; }
};

View File

@ -1606,17 +1606,8 @@ js_DestroyScript(JSContext *cx, JSScript *script)
JS_PURGE_GSN_CACHE(cx);
/*
* Worry about purging the property cache and any compiled traces related
* to its bytecode if this script is being destroyed from JS_DestroyScript
* or equivalent according to a mandatory "New/Destroy" protocol.
*
* The GC purges all property caches when regenerating shapes upon shape
* generator overflow, so no need in that event to purge just the entries
* for this script.
*
* The GC purges trace-JITted code on every GC activation, not just when
* regenerating shapes, so we don't have to purge fragments if the GC is
* currently running.
* The GC flushes all property caches, so no need to purge just the
* entries for this script.
*
* JS_THREADSAFE note: js_PurgePropertyCacheForScript purges only the
* current thread's property cache, so a script not owned by a function
@ -1632,7 +1623,7 @@ js_DestroyScript(JSContext *cx, JSScript *script)
JS_ASSERT_IF(cx->runtime->gcRunning, !script->owner);
#endif
if (!cx->runtime->gcRegenShapes) {
if (!cx->runtime->gcRunning) {
JSStackFrame *fp = js_GetTopStackFrame(cx);
if (!(fp && (fp->flags & JSFRAME_EVAL))) {
@ -1643,7 +1634,7 @@ js_DestroyScript(JSContext *cx, JSScript *script)
JS_ASSERT(script->owner == cx->thread);
#endif
#ifdef JS_TRACER
js_PurgeScriptFragments(cx, script);
js_PurgeScriptFragments(cx, script);
#endif
}
}