bug 667507 - r=gal, a=clegnitto
authorIgor Bukanov <igor@mir2.org>
Thu, 14 Jul 2011 21:47:36 +0200
changeset 72777 a1adc68984e1a50b0fcbfe0b74b091f646f1a410
parent 72776 e18e32c32fa99897c925cb397466b251f9648a26
child 72778 a3d8fc8034191faac33c39494ff5e5137713cc10
push id305
push userdmandelin@mozilla.com
push dateFri, 12 Aug 2011 00:50:44 +0000
treeherdermozilla-aurora@a1adc68984e1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgal, clegnitto
bugs667507
milestone7.0a2
bug 667507 - r=gal, a=clegnitto
js/src/jit-test/tests/basic/bug667507.js
js/src/jstracer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug667507.js
@@ -0,0 +1,6 @@
+for (i = 0; i < 10; i++) {
+    Object.defineProperty({}, "", {
+        get: function() {}
+    })
+    gc()
+}
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -2876,25 +2876,18 @@ TraceMonitor::flush()
 
     PodArrayZero(vmfragments);
     tracedScripts.clear();
 
     needFlush = JS_FALSE;
 }
 
 static bool
-HasUnreachableGCThingsImpl(JSContext *cx, TreeFragment *f)
-{
-    if (f->visiting)
-        return false;
-    f->visiting = true;
-    
-    if (!f->code())
-        return false;
-
+HasUnreachableGCThings(JSContext *cx, TreeFragment *f)
+{
     /*
      * We do not check here for dead scripts as JSScript is not a GC thing.
      * Instead PurgeScriptFragments is used to remove dead script fragments.
      * See bug 584860.
      */
     if (IsAboutToBeFinalized(cx, f->globalObj))
         return true;
     Value* vp = f->gcthings.data();
@@ -2906,27 +2899,43 @@ HasUnreachableGCThingsImpl(JSContext *cx
     }
     const Shape** shapep = f->shapes.data();
     for (unsigned len = f->shapes.length(); len; --len) {
         const Shape* shape = *shapep++;
         if (IsAboutToBeFinalized(cx, shape))
             return true;
     }
 
+    return false;
+}
+
+static bool
+ContainsUnrechableGCThingImpl(JSContext *cx, TreeFragment *f)
+{
+    if (f->visiting)
+        return false;
+    f->visiting = true;
+    
+    if (!f->code())
+        return false;
+
+    if (HasUnreachableGCThings(cx, f))
+        return true;
+
     TreeFragment** data = f->dependentTrees.data();
     unsigned length = f->dependentTrees.length();
     for (unsigned n = 0; n < length; ++n) {
-        if (HasUnreachableGCThingsImpl(cx, data[n]))
+        if (ContainsUnrechableGCThingImpl(cx, data[n]))
             return true;
     }
 
     data = f->linkedTrees.data();
     length = f->linkedTrees.length();
     for (unsigned n = 0; n < length; ++n) {
-        if (HasUnreachableGCThingsImpl(cx, data[n]))
+        if (ContainsUnrechableGCThingImpl(cx, data[n]))
             return true;
     }
 
     return false;
 }
 
 static void
 ClearVisitingFlag(TreeFragment *f)
@@ -2943,20 +2952,26 @@ ClearVisitingFlag(TreeFragment *f)
         ClearVisitingFlag(data[n]);
 
     data = f->linkedTrees.data();
     length = f->linkedTrees.length();
     for (unsigned n = 0; n < length; ++n)
         ClearVisitingFlag(data[n]);
 }
 
+/*
+ * Recursively check if the fragment and its dependent and linked trees has
+ * dead GC things. As the trees can point to each other we use the visiting
+ * flag to detect already visited fragments. The flag is cleared after we
+ * walked the whole graph in the separated ClearVisitingFlag function.  
+ */
 static bool
-HasUnreachableGCThings(JSContext *cx, TreeFragment *f)
-{
-    bool hasUnrechable = HasUnreachableGCThingsImpl(cx, f);
+ContainsUnrechableGCThing(JSContext *cx, TreeFragment *f)
+{
+    bool hasUnrechable = ContainsUnrechableGCThingImpl(cx, f);
     ClearVisitingFlag(f);
     return hasUnrechable;
 }
 
 void
 TraceMonitor::sweep(JSContext *cx)
 {
     JS_ASSERT(!ontrace());
@@ -2969,17 +2984,17 @@ TraceMonitor::sweep(JSContext *cx)
         shouldAbortRecording = HasUnreachableGCThings(cx, recorderTree);
     }
         
     for (size_t i = 0; i < FRAGMENT_TABLE_SIZE; ++i) {
         TreeFragment** fragp = &vmfragments[i];
         while (TreeFragment* frag = *fragp) {
             TreeFragment* peer = frag;
             do {
-                if (peer->code() && HasUnreachableGCThings(cx, peer))
+                if (peer->code() && ContainsUnrechableGCThing(cx, peer))
                     break;
                 peer = peer->peer;
             } while (peer);
             if (!peer) {
                 fragp = &frag->next;
                 continue;
             }