summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog20
-rw-r--r--gc.c44
2 files changed, 45 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 3bbbceae..1bf6cf19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,29 @@
2014-03-29 Kaz Kylheku <kaz@kylheku.com>
+ * gc.c (make_obj): If we have room in the freshobj array,
+ but are out of objects, then call more. Without this,
+ we don't take proper advantage of this nursing area.
+ (gc): Set the full_gc flag after doing gc, in preparation
+ for next time. If we know full GC is coming, we can
+ adjust some behaviors. Increase the threshold for calling the more()
+ function to be the same as in the non-generational case:
+ less than 3/4 of the size of a heap scavenged.
+ (gc_set): Now does nothing if it is known that
+ a full gc is coming. Also, in the checkobj array overflow
+ case when we invoke gc, there is no point in adding obj
+ to the array, since it must have been promoted to the mature
+ generation.
+ (gc_mutated): Don't bother storing the object in the
+ array if a full GC is coming.
+
+2014-03-29 Kaz Kylheku <kaz@kylheku.com>
+
* lib.c (string_time): If possible, change the timezone in the
struct tm from "GMT" to "UTC", so that the time_string_utc
function will use UTC for the %Z format.
+ Generational GC tweaks.
+
2014-03-27 Kaz Kylheku <kaz@kylheku.com>
Fix a bug arising from putting generation 1 objects into the
diff --git a/gc.c b/gc.c
index d58f2a59..2c11d678 100644
--- a/gc.c
+++ b/gc.c
@@ -187,6 +187,13 @@ val make_obj(void)
return ret;
}
+#if CONFIG_GEN_GC
+ if (freshobj_idx < FRESHOBJ_VEC_SIZE) {
+ more();
+ continue;
+ }
+#endif
+
switch (tries) {
case 0: gc(); break;
case 1: more(); break;
@@ -541,17 +548,12 @@ void gc(void)
val gc_stack_top = nil;
#if CONFIG_GEN_GC
int exhausted = (free_list == 0);
+ int full_gc_next_time = 0;
+ static int gc_counter;
#endif
if (gc_enabled) {
int swept;
-#if CONFIG_GEN_GC
- static int gc_counter;
- if (++gc_counter >= FULL_GC_INTERVAL) {
- full_gc = 1;
- gc_counter = 0;
- }
-#endif
mach_context_t mc;
save_context(mc);
@@ -564,9 +566,11 @@ void gc(void)
printf("sweep: freed %d full_gc == %d exhausted == %d\n",
(int) swept, full_gc, exhausted);
#endif
- if (full_gc && swept < 3 * HEAP_SIZE / 4)
- more();
- else if (!full_gc && swept < HEAP_SIZE / 4 && exhausted)
+ if (++gc_counter >= FULL_GC_INTERVAL - 1) {
+ full_gc_next_time = 1;
+ gc_counter = 0;
+ }
+ if (exhausted && full_gc && swept < 3 * HEAP_SIZE / 4)
more();
#else
if (swept < 3 * HEAP_SIZE / 4)
@@ -577,7 +581,7 @@ void gc(void)
checkobj_idx = 0;
mutobj_idx = 0;
freshobj_idx = 0;
- full_gc = 0;
+ full_gc = full_gc_next_time;
#endif
gc_enabled = 1;
}
@@ -621,12 +625,14 @@ int gc_is_reachable(val obj)
val gc_set(val *ptr, val obj)
{
- if (checkobj_idx >= CHECKOBJ_VEC_SIZE) {
- gc();
- /* obj can't be in gen 0 because there are no baby objects after gc */
- } else if (in_malloc_range((mem_t *) ptr) && is_ptr(obj) && obj->t.gen == 0) {
- obj->t.gen = -1;
- checkobj[checkobj_idx++] = obj;
+ if (!full_gc) {
+ if (checkobj_idx >= CHECKOBJ_VEC_SIZE) {
+ gc();
+ /* obj can't be in gen 0 because there are no baby objects after gc */
+ } else if (in_malloc_range((mem_t *) ptr) && is_ptr(obj) && obj->t.gen == 0) {
+ obj->t.gen = -1;
+ checkobj[checkobj_idx++] = obj;
+ }
}
*ptr = obj;
return obj;
@@ -635,8 +641,8 @@ val gc_set(val *ptr, val obj)
val gc_mutated(val obj)
{
/* We care only about mature generation objects that have not
- already been noted. */
- if (obj->t.gen <= 0)
+ already been noted. And if a full gc is coming, don't bother. */
+ if (full_gc || obj->t.gen <= 0)
return obj;
obj->t.gen = -1;
/* Store in mutobj array *before* triggering gc, otherwise