Bug 623301 - Properly root arguments names during a call to Function(). r=brendan
☠☠ backed out by a4f53230b322 ☠ ☠
authorJeff Walden <jwalden@mit.edu>
Wed, 05 Jan 2011 16:50:30 -0600
changeset 60176 2025b4eeca14c61c730462e1faa068c5673d6ffe
parent 60175 feb6682a10afbd56ad2f0006f9f8308266dca8b8
child 60177 2215b740bca4c03f8ec8e90070ef48693982c306
child 60198 a4f53230b32230b82336aefc431156bb677ad8bd
push id17881
push usercleary@mozilla.com
push dateFri, 07 Jan 2011 19:57:21 +0000
treeherdermozilla-central@54576be62860 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs623301
milestone2.0b9pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 623301 - Properly root arguments names during a call to Function(). r=brendan
js/src/jscntxt.h
js/src/jsfun.cpp
js/src/jsgc.cpp
js/src/jsscript.cpp
js/src/tests/ecma_5/Function/Function-arguments-gc.js
js/src/tests/ecma_5/Function/jstests.list
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -2281,17 +2281,18 @@ class AutoGCRooter {
         DESCRIPTORS =  -7, /* js::AutoPropDescArrayRooter */
         NAMESPACES =   -8, /* js::AutoNamespaceArray */
         XML =          -9, /* js::AutoXMLRooter */
         OBJECT =      -10, /* js::AutoObjectRooter */
         ID =          -11, /* js::AutoIdRooter */
         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:
     /* No copy or assignment semantics. */
     AutoGCRooter(AutoGCRooter &ida);
     void operator=(AutoGCRooter &ida);
 };
 
@@ -2598,122 +2599,200 @@ class AutoEnumStateRooter : private Auto
   private:
     Value stateValue;
     JS_DECL_USE_GUARD_OBJECT_NOTIFIER
 };
 
 #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);
     }
 
     friend void AutoGCRooter::trace(JSTracer *trc);
     friend void MarkRuntime(JSTracer *trc);
 
   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 {
-private:
+  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:
+  private:
     JSRuntime *rt;
-public:
-    explicit AutoUnlockGC(JSRuntime *rt) : rt(rt) { JS_UNLOCK_GC(rt); }
+    JS_DECL_USE_GUARD_OBJECT_NOTIFIER
+
+  public:
+    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;
+    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;
 #endif
     }
     ~AutoLockDefaultCompartment() {
 #ifdef JS_THREADSAFE
         cx->runtime->defaultCompartmentIsLocked = false;
 #endif
         JS_UNLOCK(cx, &cx->runtime->atomState.lock);
     }
 };
 
 class AutoUnlockDefaultCompartment {
   private:
-      JSContext *cx;
+    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;
         JS_UNLOCK(cx, &cx->runtime->atomState.lock);
 #ifdef JS_THREADSAFE
         cx->runtime->defaultCompartmentIsLocked = false;
 #endif
     }
     ~AutoUnlockDefaultCompartment() {
 #ifdef JS_THREADSAFE
         cx->runtime->defaultCompartmentIsLocked = true;
 #endif
         JS_LOCK(cx, &cx->runtime->atomState.lock);
     }
 };
 
 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>
     T *alloc(size_t elems) {
         void *ptr;
         JS_ARENA_ALLOCATE(ptr, pool, elems * sizeof(T));
         return static_cast<T *>(ptr);
     }
 };
 
 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); }
 };
 
 /*
  * FIXME: bug 602774: cleaner API for AutoReleaseNullablePtr
  */
 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);
         ptr = ptr2;
     }
     ~AutoReleaseNullablePtr() { if (ptr) cx->free(ptr); }
 };
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -2431,16 +2431,17 @@ Function(JSContext *cx, uintN argc, Valu
      * js_CheckContentSecurityPolicy is defined in jsobj.cpp
      */
     if (!js_CheckContentSecurityPolicy(cx)) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
         return JS_FALSE;
     }
 
     Bindings bindings(cx);
+    AutoBindingsRooter root(cx, bindings);
 
     Value *argv = vp + 2;
     uintN n = argc ? argc - 1 : 0;
     if (n > 0) {
         enum { OK, BAD, BAD_FORMAL } state;
 
         /*
          * Collect the function-argument arguments into one string, separated
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1556,16 +1556,21 @@ AutoGCRooter::trace(JSTracer *trc)
             MarkString(trc, str, "js::AutoStringRooter.str");
         return;
 
       case IDVECTOR: {
         Vector<jsid, 8> &vector = static_cast<js::AutoIdVector *>(this)->vector;
         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);
     MarkValueRange(trc, tag, static_cast<AutoArrayRooter *>(this)->array, "js::AutoArrayRooter.array");
 }
 
 namespace js {
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -396,16 +396,17 @@ js_XDRScript(JSXDRState *xdr, JSScript *
         JS_ASSERT((paddingUpvars >> 16) == 0);
         nupvars = paddingUpvars & 0xFFFF;
     }
     JS_ASSERT(nargs != Bindings::BINDING_COUNT_LIMIT);
     JS_ASSERT(nvars != Bindings::BINDING_COUNT_LIMIT);
     JS_ASSERT(nupvars != Bindings::BINDING_COUNT_LIMIT);
 
     Bindings bindings(cx);
+    AutoBindingsRooter rooter(cx, bindings);
     uint32 nameCount = nargs + nvars + nupvars;
     if (nameCount > 0) {
         struct AutoMark {
           JSArenaPool * const pool;
           void * const mark;
           AutoMark(JSArenaPool *pool) : pool(pool), mark(JS_ARENA_MARK(pool)) { }
           ~AutoMark() {
             JS_ARENA_RELEASE(pool, mark);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/Function/Function-arguments-gc.js
@@ -0,0 +1,36 @@
+/*
+ * 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);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("All tests passed!");
--- a/js/src/tests/ecma_5/Function/jstests.list
+++ b/js/src/tests/ecma_5/Function/jstests.list
@@ -4,8 +4,9 @@ script 15.3.4.3-01.js
 script arguments-caller-callee.js
 script function-caller.js
 script strict-arguments.js
 script arguments-property-attributes.js
 script function-bind.js
 script function-call.js
 script redefine-arguments-length.js
 script builtin-no-prototype.js
+script Function-arguments-gc.js