Fix slot leak that leads to allocSlot assert botch (597945, r=jorendorff).

This commit is contained in:
Brendan Eich 2010-09-20 15:21:41 -07:00
parent 0d369b900f
commit 2f94ccfb1e
4 changed files with 53 additions and 3 deletions

View File

@ -86,7 +86,7 @@ js_GenerateShape(JSContext *cx, bool gcLocked)
*/
rt->shapeGen = SHAPE_OVERFLOW_BIT;
shape = SHAPE_OVERFLOW_BIT;
#ifdef JS_THREADSAFE
Conditionally<AutoLockGC> lockIf(!gcLocked, rt);
#endif
@ -851,8 +851,10 @@ JSObject::putProperty(JSContext *cx, jsid id,
* care which slot, copy shape->slot into slot so we can match shape,
* if all other members match.
*/
if (!(attrs & JSPROP_SHARED) && slot == SHAPE_INVALID_SLOT && containsSlot(shape->slot))
slot = shape->slot;
bool hadSlot = !shape->isAlias() && containsSlot(shape->slot);
uint32 oldSlot = shape->slot;
if (!(attrs & JSPROP_SHARED) && slot == SHAPE_INVALID_SLOT && hadSlot)
slot = oldSlot;
if (shape->matchesParamsAfterId(getter, setter, slot, attrs, flags, shortid)) {
METER(redundantPuts);
return shape;
@ -929,6 +931,17 @@ JSObject::putProperty(JSContext *cx, jsid id,
lastProp->maybeHash(cx);
}
/*
* Can't fail now, so free the previous incarnation's slot if the new
* shape has no slot. But we do not need to free oldSlot (and must not,
* as trying to will botch an assertion in JSObject::freeSlot) if the
* new lastProp (shape here) has a slotSpan that does not cover it.
*/
if (hadSlot && !shape->hasSlot() && oldSlot < shape->slotSpan) {
freeSlot(cx, oldSlot);
JS_ATOMIC_INCREMENT(&cx->runtime->propertyRemovals);
}
CHECK_SHAPE_CONSISTENCY(this);
METER(puts);
return shape;

View File

@ -40,3 +40,5 @@ fails-if(!xulRuntime.shell) script regress-595365-2.js
script regress-569464.js
script regress-596103.js
script regress-597870.js
script regress-597945-1.js
script regress-597945-2.js

View File

@ -0,0 +1,22 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
function b(foo) {
delete foo.d
delete foo.w
foo.d = true
foo.w = Object
delete Object.defineProperty(foo, "d", ({
set: Math.w
})); {}
}
for each(e in [arguments, arguments]) {
try {
b(e)('')
} catch (e) {}
}
reportCompare(0, 0, "ok");

View File

@ -0,0 +1,13 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var a = {d: true, w: true};
Object.defineProperty(a, "d", {set: undefined});
delete a.d;
delete a.w;
a.d = true;
reportCompare(0, 0, "ok");