Author: Remi Meier <[email protected]>
Branch: copy-over-original
Changeset: r381:c1d5e6f19828
Date: 2013-07-10 08:59 +0200
http://bitbucket.org/pypy/stmgc/changeset/c1d5e6f19828/

Log:    do a bit more

diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -367,68 +367,70 @@
     gcptr *pobj = stm_prebuilt_gcroots.items;
     gcptr *pend = stm_prebuilt_gcroots.items + stm_prebuilt_gcroots.size;
     gcptr obj;
+
     for (; pobj != pend; pobj++) {
         obj = *pobj;
         assert(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL);
-        //assert(IS_POINTER(obj->h_revision));
+                
+        if (IS_POINTER(obj->h_revision)) {
+            visit((gcptr *)&obj->h_revision);
+            gcptr next = (gcptr)obj->h_revision;
+        
+            if (IS_POINTER((revision_t)next) /* needs to be an object */
+                && (next->h_revision & 1) /* needs to be a head rev */
+                && !(obj->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)) {
+                
+                /* XXX: WHY? */
+                assert(!(next->h_tid & GCFLAG_PUBLIC_TO_PRIVATE));
+                
+                assert(next->h_tid & GCFLAG_OLD); /* not moved already */
+                assert(next->h_original == (revision_t)obj);
+                assert(next->h_tid & GCFLAG_PUBLIC);
+                assert(!(next->h_tid & GCFLAG_STUB));
+                assert(!(obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
+                assert(!(next->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
+                assert(!(obj->h_tid & GCFLAG_BACKUP_COPY));
+                assert(!(next->h_tid & GCFLAG_BACKUP_COPY));
+                
+                /* copy next over obj but preserve possibly existing
+                   pre-hash value and tid (prebuilt-flag) */
+                revision_t pre_hash = obj->h_original;
+                revision_t old_tid = obj->h_tid;
+                memcpy(obj, next, stmgc_size(next));
+                assert(!((obj->h_tid ^ old_tid)
+                         & (GCFLAG_BACKUP_COPY | GCFLAG_STUB
+                            | GCFLAG_PUBLIC | GCFLAG_HAS_ID
+                            | GCFLAG_PRIVATE_FROM_PROTECTED)));
+                obj->h_original = pre_hash;
+                obj->h_tid = old_tid;
+                
+                fprintf(stdout, "copy %p over prebuilt %p\n", next, obj);
+                
+                /* Add this copied-over head revision to objects_to_trace
+                   because it (next) was added by the preceeding visit() 
+                   but not at its new location (obj): */
+                gcptrlist_insert(&objects_to_trace, obj);
 
-        gcptr next = (gcptr)obj->h_revision;
-        /* XXX: do better. visit obj first and then
-           copy over if possible: */
-        if (!(obj->h_revision & 1)
-            && (next->h_revision & 1)
-            && !(next->h_tid & GCFLAG_VISITED)
-            && (next->h_tid & GCFLAG_OLD)
-            && !(next->h_tid & GCFLAG_PUBLIC_TO_PRIVATE) /* XXX */
-            && !(obj->h_tid & GCFLAG_PUBLIC_TO_PRIVATE)) {
+                /* For those visiting later: */
+                next->h_revision = (revision_t)obj;            
 
-            assert(next->h_original == (revision_t)obj);
-            assert(next->h_tid & GCFLAG_PUBLIC);
-            assert(!(next->h_tid & GCFLAG_STUB));
-            assert(!(obj->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
-            assert(!(next->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED));
-            assert(!(obj->h_tid & GCFLAG_BACKUP_COPY));
-            assert(!(next->h_tid & GCFLAG_BACKUP_COPY));
+                /* mark somehow so that we can update pub_to_priv
+                   for inevitable transactions and others ignore
+                   it during tracing. Otherwise, inev transactions
+                   will think 'next' is outdated. */
+                next->h_tid &= ~GCFLAG_OLD;
 
-            
-            revision_t pre_hash = obj->h_original;
-            revision_t old_tid = obj->h_tid;
-            memcpy(obj, next, stmgc_size(next));
-            assert(!((obj->h_tid ^ old_tid)
-                     & (GCFLAG_BACKUP_COPY | GCFLAG_STUB
-                        | GCFLAG_PUBLIC | GCFLAG_HAS_ID
-                        | GCFLAG_PRIVATE_FROM_PROTECTED)));
-            obj->h_original = pre_hash;
-            obj->h_tid = old_tid;
+            }
+            /* obj does not need tracing if it can't
+               be reached from somewhere else*/
+        }
+        else {
+            gcptrlist_insert(&objects_to_trace, obj);
+        }
 
-            fprintf(stdout, "copy %p over prebuilt %p\n", next, obj);
-
-            /* will not be freed anyway and visit() only traces
-               head revision if not visited already */
-            obj->h_tid &= ~GCFLAG_VISITED;
-            /* For those visiting later:
-               XXX: don't: they will think that they are outdated*/
-            next->h_revision = (revision_t)obj;            
-            //if (next->h_tid & GCFLAG_PUBLIC_TO_PRIVATE) {
-            // may have already lost it
-                /* mark somehow so that we can update pub_to_priv
-                 for inevitable transactions and others ignore
-                 it during tracing. Otherwise, inev transactions
-                 will think 'next' is outdated. */
-                next->h_tid &= ~GCFLAG_OLD;
-                //}
-        }
-        else if (IS_POINTER(obj->h_revision)) {
-            visit((gcptr *)&obj->h_revision);
-        }
-        
-        // prebuilt originals will always be traced
-        // in visit_keep. And otherwise, they may
-        // not lose their pub_to_priv flag
-        // I think because transactions abort
-        // without clearing the flags.
+        /* prebuilt objects need to lose this flag.
+           aborted transactions do not clear it themselves */
         obj->h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE;
-            gcptrlist_insert(&objects_to_trace, obj);
     }
 }
 
diff --git a/c4/test/support.py b/c4/test/support.py
--- a/c4/test/support.py
+++ b/c4/test/support.py
@@ -583,7 +583,9 @@
         lib.stm_add_prebuilt_root(p1)
 
 def delegate_original(p1, p2):
-    assert p1.h_original == 0
+    # no h_original or it is a prebuilt with a specified hash in h_original
+    assert (p1.h_original == 0) or (p1.h_tid & GCFLAG_PREBUILT_ORIGINAL)
+    assert p1.h_tid & GCFLAG_OLD
     assert p2.h_original == 0
     assert p1 != p2
     p2.h_original = ffi.cast("revision_t", p1)
diff --git a/c4/test/test_gcpage.py b/c4/test/test_gcpage.py
--- a/c4/test/test_gcpage.py
+++ b/c4/test/test_gcpage.py
@@ -309,20 +309,23 @@
     check_not_free(p3)     # XXX replace with p1
 
 def test_prebuilt_version_2_copy_over_prebuilt():
-    p1 = lib.pseudoprebuilt(HDR, 42 + HDR)
+    p1 = lib.pseudoprebuilt_with_hash(HDR, 42 + HDR, 99)
     p2 = oalloc(HDR); make_public(p2)
     p3 = oalloc(HDR); make_public(p3)
     delegate(p1, p2)
     delegate_original(p1, p2)
     delegate(p2, p3)
     delegate_original(p1, p3)
-    major_collect()
-    # XXX: current approach requires 2 major collections.
-    # the first to compress the path
-    # the second to do the copy
+    # added by delegate, remove, otherwise
+    # major_collect will not copy over prebuilt p1:
+    p1.h_tid &= ~GCFLAG_PUBLIC_TO_PRIVATE
     major_collect()
     check_prebuilt(p1)
+    assert lib.stm_hash(p1) == 99
     check_free_old(p2)
+    check_not_free(p3)
+    # XXX: takes another major collection to free p3
+    major_collect()
     check_free_old(p3)
 
 def test_prebuilt_version_to_protected():
@@ -340,7 +343,7 @@
 
 def test_prebuilt_version_to_protected_copy_over_prebuilt():
     py.test.skip("""current copy-over-prebuilt-original approach
-    does not work with public_prebuilt->protected""")
+    does not work with public_prebuilt->stub->protected""")
     p1 = lib.pseudoprebuilt(HDR, 42 + HDR)
     p2 = lib.stm_write_barrier(p1)
     lib.stm_commit_transaction()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to