bug 667507 - r=gal
authorIgor Bukanov <igor@mir2.org>
Thu, 14 Jul 2011 21:47:36 +0200
changeset 72841 eb800178da45f18c0c7a16957a082afeefdb1b69
parent 72840 3cd0a17b27bf7176c3d7d720c84feaab3b17bfe7
child 72842 61f0230a4a2857d021c0fa58fdb125438809ec41
push id20776
push usereakhgari@mozilla.com
push dateFri, 15 Jul 2011 12:13:35 +0000
treeherdermozilla-central@9349ae9094f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgal
bugs667507
milestone8.0a1
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 667507 - r=gal
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;
             }