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
|
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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user