Bug 514222 - js_GetMutableScope gives the scope a unique shape. r=brendan.

This commit is contained in:
Jason Orendorff 2009-09-02 17:58:25 -05:00
parent 916f69fb76
commit 08626ce345
4 changed files with 55 additions and 14 deletions

View File

@ -1275,11 +1275,24 @@ JSClass js_SlowArrayClass = {
JSBool JSBool
js_MakeArraySlow(JSContext *cx, JSObject *obj) js_MakeArraySlow(JSContext *cx, JSObject *obj)
{ {
JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_ArrayClass); JS_ASSERT(obj->getClass() == &js_ArrayClass);
/* Create a native scope. */ /*
JSScope *scope = JSScope::create(cx, &js_SlowArrayObjectOps, * Create a native scope. All slow arrays other than Array.prototype get
&js_SlowArrayClass, obj); * the same initial shape.
*/
uint32 emptyShape;
JSObject *arrayProto = obj->getProto();
if (arrayProto->getClass() == &js_ObjectClass) {
/* obj is Array.prototype. */
emptyShape = js_GenerateShape(cx, false);
} else {
JS_ASSERT(arrayProto->getClass() == &js_SlowArrayClass);
if (!OBJ_SCOPE(arrayProto)->getEmptyScopeShape(cx, &js_SlowArrayClass, &emptyShape))
return JS_FALSE;
}
JSScope *scope = JSScope::create(cx, &js_SlowArrayObjectOps, &js_SlowArrayClass, obj,
emptyShape);
if (!scope) if (!scope)
return JS_FALSE; return JS_FALSE;

View File

@ -2025,7 +2025,7 @@ InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* o
if (!scope) if (!scope)
goto bad; goto bad;
} else { } else {
scope = JSScope::create(cx, ops, clasp, obj); scope = JSScope::create(cx, ops, clasp, obj, js_GenerateShape(cx, false));
if (!scope) if (!scope)
goto bad; goto bad;

View File

@ -99,7 +99,7 @@ js_GetMutableScope(JSContext *cx, JSObject *obj)
* birth, and runtime clone of a block objects are never mutated. * birth, and runtime clone of a block objects are never mutated.
*/ */
JS_ASSERT(STOBJ_GET_CLASS(obj) != &js_BlockClass); JS_ASSERT(STOBJ_GET_CLASS(obj) != &js_BlockClass);
newscope = JSScope::create(cx, scope->map.ops, obj->getClass(), obj); newscope = JSScope::create(cx, scope->map.ops, obj->getClass(), obj, scope->shape);
if (!newscope) if (!newscope)
return NULL; return NULL;
JS_LOCK_SCOPE(cx, newscope); JS_LOCK_SCOPE(cx, newscope);
@ -132,9 +132,9 @@ js_GetMutableScope(JSContext *cx, JSObject *obj)
#define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *)) #define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *))
void void
JSScope::initMinimal(JSContext *cx) JSScope::initMinimal(JSContext *cx, uint32 newShape)
{ {
shape = js_GenerateShape(cx, false); shape = newShape;
emptyScope = NULL; emptyScope = NULL;
hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2; hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;
entryCount = removedCount = 0; entryCount = removedCount = 0;
@ -183,7 +183,7 @@ JSScope::createTable(JSContext *cx, bool report)
} }
JSScope * JSScope *
JSScope::create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj) JSScope::create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj, uint32 shape)
{ {
JS_ASSERT(OPS_IS_NATIVE(ops)); JS_ASSERT(OPS_IS_NATIVE(ops));
JS_ASSERT(obj); JS_ASSERT(obj);
@ -198,7 +198,7 @@ JSScope::create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj)
scope->freeslot = JSSLOT_FREE(clasp); scope->freeslot = JSSLOT_FREE(clasp);
scope->flags = cx->runtime->gcRegenShapesScopeFlag; scope->flags = cx->runtime->gcRegenShapesScopeFlag;
js_LeaveTraceIfGlobalObject(cx, obj); js_LeaveTraceIfGlobalObject(cx, obj);
scope->initMinimal(cx); scope->initMinimal(cx, shape);
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
js_InitTitle(cx, &scope->title); js_InitTitle(cx, &scope->title);
@ -227,7 +227,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
scope->nrefs = 2; scope->nrefs = 2;
scope->freeslot = JSSLOT_FREE(clasp); scope->freeslot = JSSLOT_FREE(clasp);
scope->flags = OWN_SHAPE | cx->runtime->gcRegenShapesScopeFlag; scope->flags = OWN_SHAPE | cx->runtime->gcRegenShapesScopeFlag;
scope->initMinimal(cx); scope->initMinimal(cx, js_GenerateShape(cx, false));
#ifdef JS_THREADSAFE #ifdef JS_THREADSAFE
js_InitTitle(cx, &scope->title); js_InitTitle(cx, &scope->title);
@ -1559,7 +1559,21 @@ JSScope::clear(JSContext *cx)
js_free(table); js_free(table);
clearMiddleDelete(); clearMiddleDelete();
js_LeaveTraceIfGlobalObject(cx, object); js_LeaveTraceIfGlobalObject(cx, object);
initMinimal(cx);
JSClass *clasp = object->getClass();
JSObject *proto = object->getProto();
uint32 newShape;
if (proto && clasp == proto->getClass()) {
#ifdef DEBUG
bool ok =
#endif
OBJ_SCOPE(proto)->getEmptyScopeShape(cx, clasp, &newShape);
JS_ASSERT(ok);
} else {
newShape = js_GenerateShape(cx, false);
}
initMinimal(cx, newShape);
JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals); JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
} }

View File

@ -215,7 +215,7 @@ struct JSScope {
JSScopeProperty *lastProp; /* pointer to last property added */ JSScopeProperty *lastProp; /* pointer to last property added */
private: private:
void initMinimal(JSContext *cx); void initMinimal(JSContext *cx, uint32 newShape);
bool createTable(JSContext *cx, bool report); bool createTable(JSContext *cx, bool report);
bool changeTable(JSContext *cx, int change); bool changeTable(JSContext *cx, int change);
void reportReadOnlyScope(JSContext *cx); void reportReadOnlyScope(JSContext *cx);
@ -226,7 +226,8 @@ struct JSScope {
public: public:
/* Create a mutable, owned, empty scope. */ /* Create a mutable, owned, empty scope. */
static JSScope *create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj); static JSScope *create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj,
uint32 shape);
static void destroy(JSContext *cx, JSScope *scope); static void destroy(JSContext *cx, JSScope *scope);
@ -245,6 +246,19 @@ struct JSScope {
return createEmptyScope(cx, clasp); return createEmptyScope(cx, clasp);
} }
bool getEmptyScopeShape(JSContext *cx, JSClass *clasp, uint32 *shapep) {
if (emptyScope) {
*shapep = emptyScope->shape;
return true;
}
JSScope *e = getEmptyScope(cx, clasp);
if (!e)
return false;
*shapep = e->shape;
e->drop(cx, NULL);
return true;
}
inline void hold(); inline void hold();
inline bool drop(JSContext *cx, JSObject *obj); inline bool drop(JSContext *cx, JSObject *obj);