1. Pypy
  2. Untitled project
  3. stmgc

Commits

Remi Meier  committed ba0819e

make allocate_public_integer_address use the h_original (not always allocate stubs) if it is already public

  • Participants
  • Parent commits d92fcb9
  • Branches default

Comments (0)

Files changed (5)

File c4/demo_random.c

View file
  • Ignore whitespace
         intptr_t ip = td.public_ints[i];
         gcptr obj = (gcptr)ip;
         assert(obj->h_tid & GCFLAG_PUBLIC);
-        assert(obj->h_tid & GCFLAG_SMALLSTUB);
+        assert((obj->h_tid & GCFLAG_SMALLSTUB)
+               || (obj->h_original == 0 
+                   || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
         check(obj);
-        check((gcptr)(obj->h_revision - 2));
+        if (obj->h_revision & 2)
+            check((gcptr)(obj->h_revision - 2));
+        else if ((obj->h_revision & 3) == 0)
+            check((gcptr)(obj->h_revision));
     }
 }
 

File c4/et.c

View file
  • Ignore whitespace
                 a transaction) */
 
   /* XXX */
-  fprintf(stderr, "[%lx] inevitable: %s\n",
-           (long)d->public_descriptor_index, why);
+  /* fprintf(stderr, "[%lx] inevitable: %s\n", */
+  /*          (long)d->public_descriptor_index, why); */
   dprintf(("[%lx] inevitable: %s\n",
            (long)d->public_descriptor_index, why));
 

File c4/extra.c

View file
  • Ignore whitespace
 
     spinlock_acquire(d->public_descriptor->collection_lock, 'P');
 
-    stub = stm_stub_malloc(d->public_descriptor, 0);
-    stub->h_tid = (obj->h_tid & STM_USER_TID_MASK)
-        | GCFLAG_PUBLIC | GCFLAG_STUB | GCFLAG_SMALLSTUB
-        | GCFLAG_OLD;
-
-    stub->h_revision = ((revision_t)obj) | 2;
-    if (!(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL) && obj->h_original) {
-        stub->h_original = obj->h_original;
+    /* it must have a h_original */
+    gcptr orig;
+    if (obj->h_original == 0 || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL) {
+        orig = obj;
+    } else {
+        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 */
+        result = (intptr_t)orig;
     }
     else {
-        stub->h_original = (revision_t)obj;
+        stub = stm_stub_malloc(d->public_descriptor, 0);
+        stub->h_tid = (obj->h_tid & STM_USER_TID_MASK)
+            | GCFLAG_PUBLIC | GCFLAG_STUB | GCFLAG_SMALLSTUB
+            | GCFLAG_OLD;
+
+        stub->h_revision = ((revision_t)obj) | 2;
+        if (!(obj->h_tid & GCFLAG_PREBUILT_ORIGINAL) && obj->h_original) {
+            stub->h_original = obj->h_original;
+        }
+        else {
+            stub->h_original = (revision_t)obj;
+        }
+
+        result = (intptr_t)stub;
     }
-
-    result = (intptr_t)stub;
     spinlock_release(d->public_descriptor->collection_lock);
     stm_register_integer_address(result);
 
-    dprintf(("allocate_public_int_adr(%p): %p", obj, stub));
+    dprintf(("allocate_public_int_adr(%p): %p", obj, (void*)result));
     return result;
 }
 

File c4/gcpage.c

View file
  • Ignore whitespace
 /* Only computed during a major collection */
 static size_t mc_total_in_use, mc_total_reserved;
 
-/* keeps track of registered smallstubs that will survive unless unregistered */
-static struct G2L registered_stubs;
+/* keeps track of registered *public* objects that will survive
+unless unregistered. For now, only smallstubs and h_originals allowed */
+static struct G2L registered_objs;
 
 /* For tests */
 long stmgcpage_count(int quantity)
             (GC_PAGE_SIZE - sizeof(page_header_t)) / (WORD * i);
     }
 
-    memset(&registered_stubs, 0, sizeof(registered_stubs));
+    memset(&registered_objs, 0, sizeof(registered_objs));
 }
 
 void stmgcpage_init_tls(void)
 
 void stm_register_integer_address(intptr_t adr)
 {
+    wlog_t *found;
     gcptr obj = (gcptr)adr;
-    assert(obj->h_tid & GCFLAG_SMALLSTUB);
+    /* current limitations for 'adr': smallstub or h_original */
+    assert((obj->h_tid & GCFLAG_SMALLSTUB)
+           || (obj->h_original == 0 || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
     assert(obj->h_tid & GCFLAG_PUBLIC);
 
     stmgcpage_acquire_global_lock();
-    g2l_insert(&registered_stubs, obj, NULL);
+
+    /* find and increment refcount; or insert */
+    G2L_FIND(registered_objs, obj, found, goto not_found);
+    found->val = (gcptr)(((revision_t)found->val) + 1);
+    goto finish;
+ not_found:
+    g2l_insert(&registered_objs, obj, (gcptr)1);
+
+ finish:
     stmgcpage_release_global_lock();
     dprintf(("registered %p\n", obj));
 }
 
 void stm_unregister_integer_address(intptr_t adr)
 {
+    wlog_t *found;
     gcptr obj = (gcptr)adr;
-    assert(obj->h_tid & GCFLAG_SMALLSTUB);
+
+    assert((obj->h_tid & GCFLAG_SMALLSTUB)
+           || (obj->h_original == 0 || obj->h_tid & GCFLAG_PREBUILT_ORIGINAL));
     assert(obj->h_tid & GCFLAG_PUBLIC);
 
     stmgcpage_acquire_global_lock();
-    int deleted = g2l_delete_item(&registered_stubs, obj);
-    assert(deleted);
+
+    /* find and decrement refcount */
+    G2L_FIND(registered_objs, obj, found, goto not_found);
+    found->val = (gcptr)(((revision_t)found->val) - 1);
+    if (found->val == NULL)
+        found->addr = NULL;     /* delete it */
+
     stmgcpage_release_global_lock();
     dprintf(("unregistered %p\n", obj));
+    return;
+
+ not_found:
+    assert(0);                  /* unmatched unregister */
 }
 
 
     }
 }
 
-static void mark_registered_stubs(void)
+static void mark_registered_objs(void)
 {
     wlog_t *item;
     gcptr L;
 
-    G2L_LOOP_FORWARD(registered_stubs, item) {
+    G2L_LOOP_FORWARD(registered_objs, item) {
         gcptr R = item->addr;
-        assert(R->h_tid & GCFLAG_SMALLSTUB);
-        /* The following assert can fail if we have a stub pointing to
-           a stub and both are registered_stubs.  This case is benign. */
-        //assert(!(R->h_tid & (GCFLAG_VISITED | GCFLAG_MARKED)));
+        assert(R->h_tid & GCFLAG_PUBLIC);
 
-        R->h_tid |= (GCFLAG_MARKED | GCFLAG_VISITED);
-
-        if (R->h_revision & 2) {
-            L = (gcptr)(R->h_revision - 2);
-            L = stmgcpage_visit(L);
-            R->h_revision = ((revision_t)L) | 2;
+        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);
         }
         else {
-            L = (gcptr)R->h_revision;
-            L = stmgcpage_visit(L);
-            R->h_revision = (revision_t)L;
+            assert(R->h_tid & GCFLAG_SMALLSTUB); /* only case for now */
+            /* make sure R stays valid: */
+            R->h_tid |= (GCFLAG_MARKED | GCFLAG_VISITED);
+
+            if (R->h_revision & 2) {
+                L = (gcptr)(R->h_revision - 2);
+                L = stmgcpage_visit(L);
+                R->h_revision = ((revision_t)L) | 2;
+            }
+            else {
+                L = (gcptr)R->h_revision;
+                L = stmgcpage_visit(L);
+                R->h_revision = (revision_t)L;
+            }
+
+            /* h_original will be kept up-to-date because
+               it is either == L or L's h_original. And
+               h_originals don't move */
         }
-
-        /* h_original will be kept up-to-date because
-           it is either == L or L's h_original. And
-           h_originals don't move */
     } G2L_LOOP_END;
 
 }
 
     assert(gcptrlist_size(&objects_to_trace) == 0);
     mark_prebuilt_roots();
-    mark_registered_stubs();
+    mark_registered_objs();
     mark_all_stack_roots();
     
     /* weakrefs: */

File c4/test/test_extra.py

View file
  • Ignore whitespace
 
     # we have stubs here:
     assert ffi.cast("gcptr", p1p).h_tid & GCFLAG_PUBLIC
-    assert classify(ffi.cast("gcptr", p1p)) == 'stub'
+    p1pp = ffi.cast("gcptr", p1p)
+    assert p1 == p1pp
+    assert classify(p1pp) == 'public'
     assert classify(ffi.cast("gcptr", p2p)) == 'stub'
     assert classify(ffi.cast("gcptr", p3p)) == 'stub'