Bug 623301 - Properly root arguments names during a call to Function(). r=brendan

--HG--
extra : rebase_source : 4c397e75a23eca275c6fea1b50d675ff23fea2ba
This commit is contained in:
Jeff Walden 2011-01-05 16:50:30 -06:00
parent 00a9415e4d
commit 49b0d53f93
6 changed files with 142 additions and 18 deletions

View File

@ -2318,7 +2318,8 @@ class AutoGCRooter {
VALVECTOR = -12, /* js::AutoValueVector */
DESCRIPTOR = -13, /* js::AutoPropertyDescriptorRooter */
STRING = -14, /* js::AutoStringRooter */
IDVECTOR = -15 /* js::AutoIdVector */
IDVECTOR = -15, /* js::AutoIdVector */
BINDINGS = -16 /* js::Bindings */
};
private:
@ -2635,9 +2636,11 @@ class AutoEnumStateRooter : private AutoGCRooter
#ifdef JS_HAS_XML_SUPPORT
class AutoXMLRooter : private AutoGCRooter {
public:
AutoXMLRooter(JSContext *cx, JSXML *xml)
AutoXMLRooter(JSContext *cx, JSXML *xml
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, XML), xml(xml)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_ASSERT(xml);
}
@ -2646,30 +2649,69 @@ class AutoXMLRooter : private AutoGCRooter {
private:
JSXML * const xml;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
#endif /* JS_HAS_XML_SUPPORT */
class AutoBindingsRooter : private AutoGCRooter {
public:
AutoBindingsRooter(JSContext *cx, Bindings &bindings
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, BINDINGS), bindings(bindings)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
friend void AutoGCRooter::trace(JSTracer *trc);
private:
Bindings &bindings;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoLockGC {
public:
explicit AutoLockGC(JSRuntime *rt
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: rt(rt)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_LOCK_GC(rt);
}
~AutoLockGC() { JS_UNLOCK_GC(rt); }
private:
JSRuntime *rt;
public:
explicit AutoLockGC(JSRuntime *rt) : rt(rt) { JS_LOCK_GC(rt); }
~AutoLockGC() { JS_UNLOCK_GC(rt); }
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoUnlockGC {
private:
JSRuntime *rt;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
explicit AutoUnlockGC(JSRuntime *rt) : rt(rt) { JS_UNLOCK_GC(rt); }
explicit AutoUnlockGC(JSRuntime *rt
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: rt(rt)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_UNLOCK_GC(rt);
}
~AutoUnlockGC() { JS_LOCK_GC(rt); }
};
class AutoLockDefaultCompartment {
private:
JSContext *cx;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
AutoLockDefaultCompartment(JSContext *cx) : cx(cx) {
AutoLockDefaultCompartment(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: cx(cx)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_LOCK(cx, &cx->runtime->atomState.lock);
#ifdef JS_THREADSAFE
cx->runtime->defaultCompartmentIsLocked = true;
@ -2684,10 +2726,15 @@ class AutoLockDefaultCompartment {
};
class AutoUnlockDefaultCompartment {
private:
JSContext *cx;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
AutoUnlockDefaultCompartment(JSContext *cx) : cx(cx) {
AutoUnlockDefaultCompartment(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: cx(cx)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
#ifdef JS_THREADSAFE
cx->runtime->defaultCompartmentIsLocked = false;
#endif
@ -2703,16 +2750,31 @@ class AutoUnlockDefaultCompartment {
class AutoKeepAtoms {
JSRuntime *rt;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
explicit AutoKeepAtoms(JSRuntime *rt) : rt(rt) { JS_KEEP_ATOMS(rt); }
explicit AutoKeepAtoms(JSRuntime *rt
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: rt(rt)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
JS_KEEP_ATOMS(rt);
}
~AutoKeepAtoms() { JS_UNKEEP_ATOMS(rt); }
};
class AutoArenaAllocator {
JSArenaPool *pool;
void *mark;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
explicit AutoArenaAllocator(JSArenaPool *pool) : pool(pool) { mark = JS_ARENA_MARK(pool); }
explicit AutoArenaAllocator(JSArenaPool *pool
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: pool(pool), mark(JS_ARENA_MARK(pool))
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoArenaAllocator() { JS_ARENA_RELEASE(pool, mark); }
template <typename T>
@ -2726,9 +2788,17 @@ class AutoArenaAllocator {
class AutoReleasePtr {
JSContext *cx;
void *ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
AutoReleasePtr operator=(const AutoReleasePtr &other);
public:
explicit AutoReleasePtr(JSContext *cx, void *ptr) : cx(cx), ptr(ptr) {}
explicit AutoReleasePtr(JSContext *cx, void *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: cx(cx), ptr(ptr)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoReleasePtr() { cx->free(ptr); }
};
@ -2738,9 +2808,17 @@ class AutoReleasePtr {
class AutoReleaseNullablePtr {
JSContext *cx;
void *ptr;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
AutoReleaseNullablePtr operator=(const AutoReleaseNullablePtr &other);
public:
explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr) : cx(cx), ptr(ptr) {}
explicit AutoReleaseNullablePtr(JSContext *cx, void *ptr
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: cx(cx), ptr(ptr)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
void reset(void *ptr2) {
if (ptr)
cx->free(ptr);

View File

@ -2430,6 +2430,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
}
Bindings bindings(cx);
AutoBindingsRooter root(cx, bindings);
Value *argv = vp + 2;
uintN n = argc ? argc - 1 : 0;

View File

@ -1601,6 +1601,11 @@ AutoGCRooter::trace(JSTracer *trc)
MarkIdRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
return;
}
case BINDINGS: {
static_cast<js::AutoBindingsRooter *>(this)->bindings.trace(trc);
return;
}
}
JS_ASSERT(tag >= 0);

View File

@ -401,6 +401,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, JSBool *hasMagic)
JS_ASSERT(nupvars != Bindings::BINDING_COUNT_LIMIT);
Bindings bindings(cx);
AutoBindingsRooter rooter(cx, bindings);
uint32 nameCount = nargs + nvars + nupvars;
if (nameCount > 0) {
struct AutoMark {

View File

@ -0,0 +1,38 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
* Contributor:
* Christian Holler <decoder@own-hero.net>
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 623301;
var summary = "Properly root argument names during Function()";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
if (typeof gczeal === "function")
gczeal(2);
function crashMe(n)
{
var nasty = [];
while (n--)
nasty.push("a" + n);
return Function.apply(null, nasty);
}
var count = 64; // exact value not important
assertEq(crashMe(count + 1).length, count);
gczeal(0); // reset
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

View File

@ -9,3 +9,4 @@ script function-bind.js
script function-call.js
script redefine-arguments-length.js
script builtin-no-prototype.js
script Function-arguments-gc.js