Skip to content
Browse files

change recursive mark to iterative

  • Loading branch information...
1 parent be1fe45 commit 0189595bd8838486e37623efc5f999568fb555e7 @cpylua committed May 3, 2012
Showing with 186 additions and 56 deletions.
  1. +55 −54 gc.c
  2. +2 −2 makefile
  3. +107 −0 queue.c
  4. +22 −0 queue.h
View
109 gc.c
@@ -9,11 +9,13 @@
#include "mem.h"
#include "sform.h"
#include "cont.h"
+#include "queue.h"
static gc_heap heap;
static gc_list free_list, active_list;
static int heap_empty = 0;
static stack *stack_root;
+static queue *obj_stack;
#define ACTIVE 1
#define FREE 0
@@ -286,67 +288,64 @@ static void gc_free(object *obj) {
}
/* garbage collection functions */
-static void mark_object(object *obj);
static void frame_marker(object *var, object *val) {
- mark_object(var);
- mark_object(val);
+ enqueue(obj_stack, var);
+ enqueue(obj_stack, val);
}
static void mark_object(object *obj) {
-tailcall:
- if (obj == NULL) {
- return;
- }
-
- /* skip marked objects, environments will recur */
- if (is_active(obj)) {
- return;
- }
+ do {
+ if (obj == NULL) {
+ continue;
+ }
+
+ /* skip marked objects, environments will recur */
+ if (is_active(obj)) {
+ continue;
+ }
- mark_active(obj);
+ mark_active(obj);
- if (is_pair(obj)) {
- object *car_obj, *cdr_obj;
- car_obj = car(obj);
- cdr_obj = cdr(obj);
- mark_object(car_obj);
- obj = cdr_obj;
- goto tailcall;
- }
- if (is_compound_proc(obj)) {
- object *params = obj_lvp(obj);
- object *body = obj_lvb(obj);
- object *env = obj_lve(obj);
- mark_object(params);
- mark_object(body);
- obj = env;
- goto tailcall;
- }
- if (is_env_frame(obj)) {
- env_frame_walk(obj, frame_marker);
- }
- if (is_vector(obj)) {
- int i, len;
- object **array;
- len = obj_vsv(obj);
- array = obj_vav(obj);
- for (i = 0; i < len; i++) {
- mark_object(array[i]);
+ if (is_pair(obj)) {
+ object *car_obj, *cdr_obj;
+ car_obj = car(obj);
+ cdr_obj = cdr(obj);
+ enqueue(obj_stack, car_obj);
+ enqueue(obj_stack, cdr_obj);
}
- }
- if (is_cont(obj)) {
- struct cont *c = obj_cont(obj);
- object **objs = c->capture;
- int n = c->gc_root_stack.size;
- int i = 0;
- for (; i < n; i++) {
- mark_object(objs[i]);
- }
- }
- if (is_macro(obj)) {
- obj = obj_mv(obj);
- goto tailcall;
- }
+ if (is_compound_proc(obj)) {
+ object *params = obj_lvp(obj);
+ object *body = obj_lvb(obj);
+ object *env = obj_lve(obj);
+ enqueue(obj_stack, params);
+ enqueue(obj_stack, body);
+ enqueue(obj_stack, env);
+ }
+ if (is_env_frame(obj)) {
+ env_frame_walk(obj, frame_marker);
+ }
+ if (is_vector(obj)) {
+ int i, len;
+ object **array;
+ len = obj_vsv(obj);
+ array = obj_vav(obj);
+ for (i = 0; i < len; i++) {
+ enqueue(obj_stack, array[i]);
+ }
+ }
+ if (is_cont(obj)) {
+ struct cont *c = obj_cont(obj);
+ object **objs = c->capture;
+ int n = c->gc_root_stack.size;
+ int i = 0;
+ for (; i < n; i++) {
+ enqueue(obj_stack, objs[i]);
+ }
+ }
+ if (is_macro(obj)) {
+ enqueue(obj_stack, obj_mv(obj));
+ }
+ } while ((obj = dequeue(obj_stack)) != NULL);
}
static void mark_stack_root(stack_elem elem) {
@@ -447,12 +446,14 @@ int gc_init(int heap_size) {
extend_freelist();
stack_root = stack_new();
+ obj_stack = queue_new();
return 0;
}
void gc_finalize(void) {
stack_dispose(stack_root);
+ queue_dispose(obj_stack);
sc_free(heap.segments);
heap.segments = NULL;
}
View
4 makefile
@@ -5,7 +5,7 @@ OBJS = eval.o mem.o reader.o fixnum.o charcache.o \
primitive.o procdef.o compound.o eof.o \
port.o ioproc.o gc.o stack.o intcache.o \
mathproc.o strproc.o objstream.o vector.o \
- vecproc.o frame.o cont.o macro.o
+ vecproc.o frame.o cont.o macro.o queue.o
CFLAG = -Wall -c
LFLAG = -lm -lrt
@@ -36,7 +36,7 @@ INSTALL_DATA = $(INSTALL) -m 0644
UNINSTALL = rm -f
UNINSTALL_DIR = $(UNINSTALL) -r
BIN = asc
-LIB = lib/core.scm
+LIB = lib/core.scm lib/stream.scm
install:
$(MKDIR) $(INSTALL_BIN) $(INSTALL_LIB)
$(INSTALL) $(BIN) $(INSTALL_BIN)
View
107 queue.c
@@ -0,0 +1,107 @@
+#include "mem.h"
+#include "log.h"
+#include "queue.h"
+
+#define QUEUE_CACHE_SIZE 1024
+
+queue *queue_new(void) {
+ queue *q;
+ queue_node **cache;
+
+ q = sc_malloc(sizeof(queue));
+ if (q == NULL) {
+ return NULL;
+ }
+ cache = sc_malloc(sizeof(queue_node*) * QUEUE_CACHE_SIZE);
+ if (cache == NULL) {
+ sc_free(q);
+ return NULL;
+ }
+
+ q->cache = cache;
+ q->cache_size = 0;
+ q->head = q->rear = NULL;
+ return q;
+}
+
+void queue_dispose(queue *q) {
+ int i;
+
+ if (q == NULL) {
+ return;
+ }
+ for (i = 0; i < q->cache_size; i++) {
+ sc_free(q->cache[i]);
+ }
+ sc_free(q->cache);
+ sc_free(q);
+}
+
+int queue_isempty(queue *q) {
+ if (q == NULL) {
+ return 1;
+ }
+ return q->head == NULL;
+}
+
+int enqueue(queue *q, object *elem) {
+ int sz;
+ queue_node *p;
+
+ if (q == NULL) {
+ return 1;
+ }
+
+ sz = q->cache_size;
+ if (sz > 0) {
+ p = q->cache[--sz];
+ q->cache_size = sz;
+ /* sc_log("queue cache hit, size=%d\n", sz+1); */
+ } else {
+ p = sc_malloc(sizeof(queue_node));
+ if (p == NULL) {
+ return -1;
+ }
+ }
+
+ p->elem = elem;
+ p->next = NULL;
+ if (q->rear != NULL) {
+ q->rear->next = p;
+ }
+ q->rear = p;
+ if (q->head == NULL) {
+ q->head = p;
+ }
+ return 0;
+}
+
+object* dequeue(queue *q) {
+ int sz;
+ queue_node *p;
+ object *obj = NULL;
+
+ if (q == NULL) {
+ return NULL;
+ }
+
+ if (!queue_isempty(q)) {
+ p = q->head;
+ q->head = q->head->next;
+ if (q->head == NULL) {
+ q->rear = NULL;
+ }
+ obj = p->elem;
+
+ sz = q->cache_size;
+ if (sz < QUEUE_CACHE_SIZE) {
+ /* cache this node */
+ q->cache[sz++] = p;
+ q->cache_size = sz;
+ } else {
+ sc_free(p);
+ }
+ }
+ return obj;
+}
+
View
22 queue.h
@@ -0,0 +1,22 @@
+#ifndef _QUEUE_H_
+#define _QUEUE_H_
+
+typedef struct queue_node {
+ object *elem;
+ struct queue_node *next;
+} queue_node;
+
+typedef struct queue {
+ queue_node **cache;
+ int cache_size;
+ queue_node *head;
+ queue_node *rear;
+} queue;
+
+queue *queue_new(void);
+void queue_dispose(queue *q);
+int enqueue(queue *q, object *e);
+object* dequeue(queue *q);
+int queue_isempty(queue *q);
+
+#endif

0 comments on commit 0189595

Please sign in to comment.
Something went wrong with that request. Please try again.