[pypy-commit] stmgc default: fix public ints (usage of public h_originals is not always right, they

Raemi noreply at buildbot.pypy.org
Mon Nov 18 11:20:03 CET 2013


Author: Remi Meier <remi.meier at gmail.com>
Branch: 
Changeset: r548:68677625f2be
Date: 2013-11-18 11:19 +0100
http://bitbucket.org/pypy/stmgc/changeset/68677625f2be/

Log:	fix public ints (usage of public h_originals is not always right,
	they need to be PREBUILT_ORIGINALs to be sure...)

diff --git a/c4/demo_random.c b/c4/demo_random.c
--- a/c4/demo_random.c
+++ b/c4/demo_random.c
@@ -278,8 +278,7 @@
         gcptr obj = (gcptr)ip;
         assert(obj->h_tid & GCFLAG_PUBLIC);
         assert((obj->h_tid & GCFLAG_SMALLSTUB)
-               || (obj->h_original == 0 
-                   || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
+               || (obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
         check(obj);
         if (obj->h_revision & 2)
             check((gcptr)(obj->h_revision - 2));
@@ -304,7 +303,9 @@
     if (td.num_public_ints == 0)
         return;
 
+    push_roots();
     stm_unregister_integer_address(td.public_ints[--td.num_public_ints]);
+    pop_roots();
 }
 
 gcptr read_barrier(gcptr p)
diff --git a/c4/et.c b/c4/et.c
--- a/c4/et.c
+++ b/c4/et.c
@@ -138,6 +138,7 @@
 
   d->count_reads++;
   assert(IMPLIES(!(P->h_tid & GCFLAG_OLD), stmgc_is_in_nursery(d, P)));
+  assert(G->h_revision != 0);
 
  restart_all:
   if (P->h_tid & GCFLAG_PRIVATE_FROM_PROTECTED)
@@ -355,7 +356,7 @@
   assert(P->h_tid & GCFLAG_PUBLIC);
   assert(IMPLIES(!(P->h_tid & GCFLAG_OLD), 
                  stmgc_is_in_nursery(thread_descriptor, P)));
-
+  assert(P->h_revision != 0);
 
   revision_t v = ACCESS_ONCE(P->h_revision);
   assert(IS_POINTER(v));  /* "is a pointer", "has a more recent revision" */
@@ -660,6 +661,7 @@
 
 gcptr stm_RepeatWriteBarrier(gcptr P)
 {
+  assert(P->h_revision != 0);
   assert(IMPLIES(!(P->h_tid & GCFLAG_OLD), 
                  stmgc_is_in_nursery(thread_descriptor, P)));
 
@@ -673,6 +675,7 @@
 
 gcptr stm_WriteBarrier(gcptr P)
 {
+  assert(P->h_revision != 0);
   assert(!(P->h_tid & GCFLAG_IMMUTABLE));
   assert((P->h_tid & GCFLAG_STUB) ||
          stmgc_size(P) > sizeof(struct stm_stub_s) - WORD);
diff --git a/c4/extra.c b/c4/extra.c
--- a/c4/extra.c
+++ b/c4/extra.c
@@ -65,7 +65,7 @@
 
 
 intptr_t stm_allocate_public_integer_address(gcptr obj)
-{
+{                               /* push roots! */
     struct tx_descriptor *d = thread_descriptor;
     gcptr stub;
     intptr_t result;
@@ -75,6 +75,12 @@
        During major collections, we visit them and update
        their references. */
 
+    /* stm_register_integer_address needs to run in inevitable
+       transaction */
+    stm_push_root(obj);
+    stm_become_inevitable("stm_allocate_public_integer_address");
+    obj = stm_pop_root();
+
     /* we don't want to deal with young objs */
     if (!(obj->h_tid & GCFLAG_OLD)) {
         stm_push_root(obj);
@@ -93,9 +99,11 @@
         orig = (gcptr)obj->h_original;
     }
     
-    if (orig->h_tid & GCFLAG_PUBLIC) {
-        /* the original is public, so we can take that as a non-movable
-         object to register */
+    if ((orig->h_tid & (GCFLAG_PUBLIC | GCFLAG_PREBUILT_ORIGINAL))
+        == (GCFLAG_PUBLIC | GCFLAG_PREBUILT_ORIGINAL)) {
+        /* public is not enough as public stubs may get replaced
+           by the protected object they point to, if they are in the 
+           same thread (I think...) */
         result = (intptr_t)orig;
     }
     else {
@@ -115,9 +123,11 @@
         result = (intptr_t)stub;
     }
     spinlock_release(d->public_descriptor->collection_lock);
+
+    dprintf(("allocate_public_int_adr(%p): %p", obj, (void*)result));
+
     stm_register_integer_address(result);
 
-    dprintf(("allocate_public_int_adr(%p): %p", obj, (void*)result));
     return result;
 }
 
diff --git a/c4/gcpage.c b/c4/gcpage.c
--- a/c4/gcpage.c
+++ b/c4/gcpage.c
@@ -218,10 +218,11 @@
 /***** registering of small stubs as integer addresses *****/
 
 void stm_register_integer_address(intptr_t adr)
-{
+{                               /* needs to be inevitable! */
     wlog_t *found;
     gcptr obj = (gcptr)adr;
     /* current limitations for 'adr': smallstub or h_original */
+    assert(stm_active == 2);
     assert((obj->h_tid & GCFLAG_SMALLSTUB)
            || (obj->h_original == 0 || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
     assert(obj->h_tid & GCFLAG_PUBLIC);
@@ -241,7 +242,7 @@
 }
 
 void stm_unregister_integer_address(intptr_t adr)
-{
+{                               /* push roots! */
     wlog_t *found;
     gcptr obj = (gcptr)adr;
 
@@ -249,6 +250,11 @@
            || (obj->h_original == 0 || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
     assert(obj->h_tid & GCFLAG_PUBLIC);
 
+    /* become inevitable because we would have to re-register them
+       on abort, but make sure only to re-register if not registered
+       in the same aborted transaction (XXX) */
+    stm_become_inevitable("stm_unregister_integer_address()");
+
     stmgcpage_acquire_global_lock();
 
     /* find and decrement refcount */
@@ -527,12 +533,18 @@
     G2L_LOOP_FORWARD(registered_objs, item) {
         gcptr R = item->addr;
         assert(R->h_tid & GCFLAG_PUBLIC);
-
-        if ((R->h_original == 0) || (R->h_tid & GCFLAG_PREBUILT_ORIGINAL)) {
-            /* the obj is an original and will therefore survive: */
-            gcptr V = stmgcpage_visit(R);
-            assert(V == R);
+        
+        if (R->h_tid & GCFLAG_PREBUILT_ORIGINAL) {
+            /* already done by mark_prebuilt_roots */
+            assert((R->h_tid & (GCFLAG_MARKED|GCFLAG_VISITED|GCFLAG_PUBLIC))
+                   == (GCFLAG_MARKED|GCFLAG_VISITED|GCFLAG_PUBLIC));
+            continue;
         }
+        /* else if (R->h_original == 0) { */
+        /*     /\* the obj is an original and will therefore survive: *\/ */
+        /*     gcptr V = visit_public(R, NULL); */
+        /*     assert(V == R); */
+        /* } */
         else {
             assert(R->h_tid & GCFLAG_SMALLSTUB); /* only case for now */
             /* make sure R stays valid: */
diff --git a/c4/stmgc.h b/c4/stmgc.h
--- a/c4/stmgc.h
+++ b/c4/stmgc.h
@@ -40,7 +40,7 @@
    not be freed until stm_unregister_integer_address is 
    called on the result (push roots!) */
 intptr_t stm_allocate_public_integer_address(gcptr);
-void stm_unregister_integer_address(intptr_t);
+void stm_unregister_integer_address(intptr_t); /* push roots too! */
 
 
 /* returns a never changing hash for the object */
@@ -193,6 +193,7 @@
 void stm_call_on_abort(void *key, void callback(void *));
 
 /* only user currently is stm_allocate_public_integer_address() */
+/* needs to be in an inevitable transaction! */
 void stm_register_integer_address(intptr_t);
 
 /* enter single-threaded mode. Used e.g. when patching assembler


More information about the pypy-commit mailing list