Commits

Armin Rigo committed 26a9bd7

Finish the first version

  • Participants
  • Parent commits 0e454af
  • Branches gc-small-uniform

Comments (0)

Files changed (2)

File c7/stm/smallmalloc.c

 #endif
 }
 
-void sweep_small_page_full(char *page, long szword)
+static char *getbaseptr(struct small_free_loc_s *fl)
 {
-    abort();
+    return (char *)(((uintptr_t)fl) & ~4095);
 }
 
-void sweep_small_page_partial(struct small_free_loc_s *page, long szword)
+void sweep_small_page(char *baseptr, struct small_free_loc_s *page_free,
+                      long szword)
 {
-    check_order_inside_small_page(page);
+    if (page_free != NULL)
+        check_order_inside_small_page(page_free);
 
     /* for every non-free location, ask if we must free it */
-    char *baseptr = (char *)(((uintptr_t)page) & ~4095);
     uintptr_t i, size = szword * 8;
-    bool any_object_remaining = false;
-    struct small_free_loc_s *fl = page;
+    bool any_object_remaining = false, any_object_dying = false;
+    struct small_free_loc_s *fl = page_free;
     struct small_free_loc_s *flprev = NULL;
 
     /* XXX could optimize for the case where all objects die: we don't
             /* location is already free */
             flprev = fl;
             fl = fl->next;
+            any_object_dying = true;
         }
         else if (!_smallmalloc_sweep_keep(p)) {
             /* the location should be freed now */
             if (flprev == NULL) {
                 flprev = (struct small_free_loc_s *)p;
                 flprev->next = fl;
-                page = flprev;
+                page_free = flprev;
             }
             else {
                 assert(flprev->next == fl);
                 flprev = (struct small_free_loc_s *)p;
                 flprev->next = fl;
             }
+            any_object_dying = true;
         }
         else {
             any_object_remaining = true;
         }
     }
-    if (any_object_remaining) {
-        check_order_inside_small_page(page);
-        page->nextpage = small_page_lists[szword];
-        small_page_lists[szword] = page;
+    if (!any_object_remaining) {
+        ((struct small_free_loc_s *)baseptr)->nextpage = free_uniform_pages;
+        free_uniform_pages = (struct small_free_loc_s *)baseptr;
+    }
+    else if (!any_object_dying) {
+        get_fpsz(baseptr)->sz = szword;
     }
     else {
-        ((struct small_free_loc_s *)baseptr)->nextpage = free_uniform_pages;
-        free_uniform_pages = (struct small_free_loc_s *)baseptr;
+        check_order_inside_small_page(page_free);
+        page_free->nextpage = small_page_lists[szword];
+        small_page_lists[szword] = page_free;
     }
 }
 
                 fpsz_t *fpsz = get_fpsz((char *)*fl);
                 assert(fpsz->sz == szword);
                 fpsz->sz = 0;
-                sweep_small_page_partial(*fl, szword);
+                sweep_small_page(getbaseptr(*fl), *fl, szword);
                 *fl = NULL;
             }
         }
                corresponding full_pages_object_size[] entry is 0 */
             assert(get_fpsz((char *)page)->sz == 0);
             nextpage = page->nextpage;
-            sweep_small_page_partial(page, szword);
+            sweep_small_page(getbaseptr(page), page, szword);
             page = nextpage;
         }
     }
                                                PAGE_SMSIZE_START];
     fpsz_t *fpsz;
     for (fpsz = fpsz_start; fpsz < fpsz_end; fpsz++, pageptr += 4096) {
-        if (fpsz->sz != 0) {
-            sweep_small_page_full(pageptr, fpsz->sz);
+        uint8_t sz = fpsz->sz;
+        if (sz != 0) {
+            fpsz->sz = 0;
+            sweep_small_page(pageptr, NULL, sz);
         }
     }
 }

File c7/test/test_smallmalloc.py

 
     def test_sweep_freeing_random_subset(self):
         for i in range(50):
-            page0 = [stm_allocate_old_small(16) for i in range(0, 4096-16, 16)]
+            page0 = [stm_allocate_old_small(16) for i in range(0, 4096, 16)]
             assert len(set(map(pageof, page0))) == 1
             tid = lib._get_type_id(page0[0])
             while len(page0) > 0:
                     p = stm_allocate_old_small(16)
                     assert pageof(p) == pageof(page0[0])
                     page0.append(p)
+
+    def test_sweep_full_page_remains_full(self):
+        page0 = [stm_allocate_old_small(16) for i in range(0, 4096, 16)]
+        tid = lib._get_type_id(page0[0])
+        self.keep_me = set(page0)
+        lib._stm_smallmalloc_sweep()
+        for p in page0:
+            assert lib._get_type_id(p) == tid