void gc_test_alloc4(CuTest *T) { PN ptr = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN ptr2 = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN ptr3 = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN ptr4 = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN_SIZE count = potion_mark_stack(P, 0); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr)); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr2)); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr3)); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr4)); CuAssertIntEquals(T, "four allocations should be found", 5, count); }
void gc_test_forward(CuTest *T) { PN_SIZE count; char *fj = "frances johnson."; PN ptr = potion_data_alloc(P, 16); register unsigned long old = ptr & 0xFFFF; memcpy(((struct PNData *)ptr)->data, fj, 16); count = potion_mark_stack(P, 1); CuAssert(T, "copied location identical to original", (old & 0xFFFF) != ptr); CuAssertIntEquals(T, "copied object not still PN_TUSER", ((struct PNData *)ptr)->vt, PN_TUSER); CuAssert(T, "copied data not identical to original", strncmp(((struct PNData *)ptr)->data, fj, 16) == 0); }
// // Both this function and potion_gc_major embody a simple // Cheney loop (also called a "two-finger collector.") // http://en.wikipedia.org/wiki/Cheney%27s_algorithm // (Again, many thanks to Basile Starynkevitch for // his tutelage in this matter.) // static int potion_gc_minor(Potion *P, int sz) { struct PNMemory *M = P->mem; void *scanptr = 0; void **storead = 0, **wb = 0; if (sz < 0) sz = 0; else if (sz >= POTION_MAX_BIRTH_SIZE) return POTION_NO_MEM; scanptr = (void *) M->old_cur; info("running gc_minor\n" "(young: %p -> %p = %ld)\n" "(old: %p -> %p = %ld)\n" "(storeptr len = %ld)\n", M->birth_lo, M->birth_hi, (long)(M->birth_hi - M->birth_lo), M->old_lo, M->old_hi, (long)(M->old_hi - M->old_lo), (long)((void *)M->birth_hi - (void *)M->birth_storeptr)); potion_mark_stack(P, 1); GC_MINOR_STRINGS(); wb = (void **)M->birth_storeptr; for (storead = wb; storead < (void **)M->birth_hi; storead++) { PN v = (PN)*storead; if (PN_IS_PTR(v)) potion_mark_minor(P, (const struct PNObject *)v); } storead = 0; while ((PN)scanptr < (PN)M->old_cur) scanptr = potion_mark_minor(P, scanptr); scanptr = 0; sz += 2 * POTION_PAGESIZE; sz = max(sz, potion_birth_suggest(sz, M->old_lo, M->old_cur)); sz = NEW_BIRTH_REGION(M, wb, sz); M->minors++; info("(new young: %p -> %p = %d)\n", M->birth_lo, M->birth_hi, (long)(M->birth_hi - M->birth_lo)); return POTION_OK; }
static int potion_gc_major(Potion *P, int siz) { struct PNMemory *M = P->mem; void *prevoldlo = 0; void *prevoldhi = 0; void *prevoldcur = 0; void *newold = 0; void *protptr = (void *)M + PN_ALIGN(sizeof(struct PNMemory), 8); void *scanptr = 0; void **wb = 0; int birthest = 0; int birthsiz = 0; int newoldsiz = 0; int oldsiz = 0; if (siz < 0) siz = 0; else if (siz >= POTION_MAX_BIRTH_SIZE) return POTION_NO_MEM; prevoldlo = (void *)M->old_lo; prevoldhi = (void *)M->old_hi; prevoldcur = (void *)M->old_cur; info("running gc_major\n" "(young: %p -> %p = %ld)\n" "(old: %p -> %p = %ld)\n", M->birth_lo, M->birth_hi, (long)(M->birth_hi - M->birth_lo), M->old_lo, M->old_hi, (long)(M->old_hi - M->old_lo)); birthest = potion_birth_suggest(siz, prevoldlo, prevoldcur); newoldsiz = (((char *)prevoldcur - (char *)prevoldlo) + siz + birthest + POTION_GC_THRESHOLD + 16 * POTION_PAGESIZE) + ((char *)M->birth_cur - (char *)M->birth_lo); newold = pngc_page_new(&newoldsiz, 0); M->old_cur = scanptr = newold + (sizeof(PN) * 2); info("(new old: %p -> %p = %d)\n", newold, (char *)newold + newoldsiz, newoldsiz); potion_mark_stack(P, 2); wb = (void **)M->birth_storeptr; if (M->birth_lo != M) { while ((PN)protptr < (PN)M->protect) protptr = potion_mark_major(P, protptr); } while ((PN)scanptr < (PN)M->old_cur) scanptr = potion_mark_major(P, scanptr); scanptr = 0; GC_MAJOR_STRINGS(); pngc_page_delete((void *)prevoldlo, (char *)prevoldhi - (char *)prevoldlo); prevoldlo = 0; prevoldhi = 0; prevoldcur = 0; birthsiz = NEW_BIRTH_REGION(M, wb, siz + birthest); oldsiz = ((char *)M->old_cur - (char *)newold) + (birthsiz + 2 * birthest + 4 * POTION_PAGESIZE); oldsiz = PN_ALIGN(oldsiz, POTION_PAGESIZE); if (oldsiz < newoldsiz) { pngc_page_delete((void *)newold + oldsiz, newoldsiz - oldsiz); newoldsiz = oldsiz; } M->old_lo = newold; M->old_hi = (char *)newold + newoldsiz; M->majors++; newold = 0; return POTION_OK; }
// // everything allocated in alloc1 and alloc4 tests goes out of scope, so will // not be moved to the old generation. data in the `forward` test will be copied. // void gc_test_alloc1(CuTest *T) { PN ptr = (PN)potion_gc_alloc(P, PN_TUSER, 16); PN_SIZE count = potion_mark_stack(P, 0); CuAssert(T, "couldn't allocate 16 bytes from GC", PN_IS_PTR(ptr)); CuAssertIntEquals(T, "only one allocation should be found", 2, count); }