Commits

Armin Rigo committed 19703dd

Fixes

  • Participants
  • Parent commits 26a9bd7
  • Branches gc-small-uniform

Comments (0)

Files changed (2)

            the common case. Otherwise, we need to compute it based on
            its location and size. */
         if (is_small_uniform(obj)) {
-            abort();
             page_privatize(first_page);
         }
         else {
 
     uintptr_t start = (uintptr_t)obj;
     uintptr_t first_page = start / 4096UL;
+    char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+    long i, myself = STM_SEGMENT->segment_num;
 
     if (is_small_uniform(obj)) {
-        abort();//XXX WRITE THE FAST CASE
+        /* First copy the object into the shared page, if needed */
+        char *src = REAL_ADDRESS(STM_SEGMENT->segment_base, start);
+        char *dst = REAL_ADDRESS(stm_object_pages, start);
+        ssize_t obj_size = 0;   /* computed lazily, only if needed */
+
+        if (is_private_page(myself, first_page)) {
+            obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
+            memcpy(dst, src, obj_size);
+        }
+        else {
+            assert(memcmp(dst, src,          /* already identical */
+                stmcb_size_rounded_up((struct object_s *)realobj)) == 0);
+        }
+
+        for (i = 1; i <= NB_SEGMENTS; i++) {
+            if (i == myself)
+                continue;
+
+            src = REAL_ADDRESS(stm_object_pages, start);
+            dst = REAL_ADDRESS(get_segment_base(i), start);
+            if (is_private_page(i, first_page)) {
+                /* The page is a private page.  We need to diffuse this
+                   object from the shared page to this private page. */
+                if (obj_size == 0) {
+                    obj_size =
+                        stmcb_size_rounded_up((struct object_s *)src);
+                }
+                memcpy(dst, src, obj_size);
+            }
+            else {
+                assert(memcmp(dst, src,      /* already identical */
+                    stmcb_size_rounded_up((struct object_s *)src)) == 0);
+            }
+        }
     }
     else {
-        char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
         ssize_t obj_size = stmcb_size_rounded_up((struct object_s *)realobj);
         assert(obj_size >= 16);
         uintptr_t end = start + obj_size;
         uintptr_t last_page = (end - 1) / 4096UL;
-        long i, myself = STM_SEGMENT->segment_num;
 
         for (; first_page <= last_page; first_page++) {
 
     /* takes a normal pointer to a thread-local pointer to an object */
     object_t *obj = *pobj;
     object_t *nobj;
-    uintptr_t nobj_sync_now;
 
     if (obj == NULL)
         return;
                 obj->stm_flags &= ~GCFLAG_HAS_SHADOW;
                 realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
                 size = stmcb_size_rounded_up((struct object_s *)realobj);
-                goto handle_large_object;
             }
         }
-        /* We need to make a copy of this object.  It goes either in
-           a largemalloc.c-managed area, or if it's small enough, in
-           one of the small uniform pages from gcpage.c.
-        */
-        realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
-        size = stmcb_size_rounded_up((struct object_s *)realobj);
+        else {
+            /* We need to make a copy of this object.  It goes either in
+               a largemalloc.c-managed area, or if it's small enough, in
+               one of the small uniform pages from gcpage.c.
+            */
+            realobj = REAL_ADDRESS(STM_SEGMENT->segment_base, obj);
+            size = stmcb_size_rounded_up((struct object_s *)realobj);
 
-        if (size > GC_LAST_SMALL_SIZE) {
+            if (size > GC_LAST_SMALL_SIZE) {
 
-            /* case 1: object is not small enough.
-               Ask gcpage.c for an allocation via largemalloc. */
-            char *allocated = allocate_outside_nursery_large(size);
-            nobj = (object_t *)(allocated - stm_object_pages);
-
-         handle_large_object:
-            nobj_sync_now = ((uintptr_t)nobj) | FLAG_SYNC_LARGE;
-        }
-        else {
-            /* case "small enough" */
-            char *allocated = allocate_outside_nursery_small(size);
-            nobj = (object_t *)(allocated - stm_object_pages);
-            nobj_sync_now = (uintptr_t)nobj;
+                /* case 1: object is not small enough.
+                   Ask gcpage.c for an allocation via largemalloc. */
+                char *allocated = allocate_outside_nursery_large(size);
+                nobj = (object_t *)(allocated - stm_object_pages);
+            }
+            else {
+                /* case "small enough" */
+                char *allocated = allocate_outside_nursery_small(size);
+                nobj = (object_t *)(allocated - stm_object_pages);
+            }
         }
 
         /* Copy the object */
         /* a young object outside the nursery */
         nobj = obj;
         tree_delete_item(STM_PSEGMENT->young_outside_nursery, (uintptr_t)nobj);
-        nobj_sync_now = ((uintptr_t)nobj) | FLAG_SYNC_LARGE;
     }
 
     /* Set the overflow_number if nedeed */
     }
 
     /* Must trace the object later */
+    uintptr_t nobj_sync_now = (uintptr_t)nobj | !is_small_uniform(nobj);
     LIST_APPEND(STM_PSEGMENT->objects_pointing_to_nursery, nobj_sync_now);
-    assert(nobj_sync_now == ((uintptr_t)nobj | is_small_uniform(nobj)));
 }
 
 static void collect_roots_in_nursery(void)