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 5c14309cd1
commit d41212b7a6
4 changed files with 55 additions and 14 deletions

View File

@ -1275,11 +1275,24 @@ JSClass js_SlowArrayClass = {
JSBool
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,
&js_SlowArrayClass, obj);
/*
* Create a native scope. All slow arrays other than Array.prototype get
* 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)
return JS_FALSE;

View File

@ -2025,7 +2025,7 @@ InitScopeForObject(JSContext* cx, JSObject* obj, JSObject* proto, JSObjectOps* o
if (!scope)
goto bad;
} else {
scope = JSScope::create(cx, ops, clasp, obj);
scope = JSScope::create(cx, ops, clasp, obj, js_GenerateShape(cx, false));
if (!scope)
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.
*/
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)
return NULL;
JS_LOCK_SCOPE(cx, newscope);
@ -132,9 +132,9 @@ js_GetMutableScope(JSContext *cx, JSObject *obj)
#define SCOPE_TABLE_NBYTES(n) ((n) * sizeof(JSScopeProperty *))
void
JSScope::initMinimal(JSContext *cx)
JSScope::initMinimal(JSContext *cx, uint32 newShape)
{
shape = js_GenerateShape(cx, false);
shape = newShape;
emptyScope = NULL;
hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;
entryCount = removedCount = 0;
@ -183,7 +183,7 @@ JSScope::createTable(JSContext *cx, bool report)
}
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(obj);
@ -198,7 +198,7 @@ JSScope::create(JSContext *cx, JSObjectOps *ops, JSClass *clasp, JSObject *obj)
scope->freeslot = JSSLOT_FREE(clasp);
scope->flags = cx->runtime->gcRegenShapesScopeFlag;
js_LeaveTraceIfGlobalObject(cx, obj);
scope->initMinimal(cx);
scope->initMinimal(cx, shape);
#ifdef JS_THREADSAFE
js_InitTitle(cx, &scope->title);
@ -227,7 +227,7 @@ JSScope::createEmptyScope(JSContext *cx, JSClass *clasp)
scope->nrefs = 2;
scope->freeslot = JSSLOT_FREE(clasp);
scope->flags = OWN_SHAPE | cx->runtime->gcRegenShapesScopeFlag;
scope->initMinimal(cx);
scope->initMinimal(cx, js_GenerateShape(cx, false));
#ifdef JS_THREADSAFE
js_InitTitle(cx, &scope->title);
@ -1559,7 +1559,21 @@ JSScope::clear(JSContext *cx)
js_free(table);
clearMiddleDelete();
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);
}

View File

@ -215,7 +215,7 @@ struct JSScope {
JSScopeProperty *lastProp; /* pointer to last property added */
private:
void initMinimal(JSContext *cx);
void initMinimal(JSContext *cx, uint32 newShape);
bool createTable(JSContext *cx, bool report);
bool changeTable(JSContext *cx, int change);
void reportReadOnlyScope(JSContext *cx);
@ -226,7 +226,8 @@ struct JSScope {
public:
/* 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);
@ -245,6 +246,19 @@ struct JSScope {
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 bool drop(JSContext *cx, JSObject *obj);