diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e9379d92fcf..cc87e3b3b38 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -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 diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 63f1a692d11..0668897f90a 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -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 diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index dff601929d2..6af897192dd 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -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; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 6645f09d93a..8fdaafabef2 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -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; } diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 876bed4d357..f14a5b2914f 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -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. diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 481da6a4a5b..c501317cfad 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -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; } }; diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index bd46de7453e..b65b88995ce 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -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 } }