mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 04:27:37 +00:00
Bug 514222 - js_GetMutableScope gives the scope a unique shape. r=brendan.
This commit is contained in:
parent
916f69fb76
commit
08626ce345
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user