commit b2d273fdd9a85af093465d6a1c56a7f858a20155
parent 8f304536670df184a1d73f226187082ed9ee92c8
Author: Andres Navarro <canavarro82@gmail.com>
Date: Fri, 15 Apr 2011 14:54:23 -0300
Added two stacks for rooting both values and variables, and added them to the gc root scanning code.
Diffstat:
3 files changed, 59 insertions(+), 12 deletions(-)
diff --git a/src/kgc.c b/src/kgc.c
@@ -568,10 +568,14 @@ static void markroot (klisp_State *K) {
markvalue(K, K->shared_dict);
/* Mark all objects in the auxiliary stack,
- all valid indexes are below top */
- TValue *ptr = K->sbuf;
- for (int i = 0, top = K->stop; i < top; i++, ptr++) {
- markvalue(K, *ptr);
+ (all valid indexes are below top) and all the objects in
+ the two protected areas */
+ markvaluearray(K, K->sbuf, K->stop);
+ markvaluearray(K, K->rootedtv_buf, K->rootedtv_top);
+ /* the area protecting variables is an array of type TValue *[] */
+ TValue **ptr = K->rootedv_buf;
+ for (int i = 0, top = K->rootedv_top; i < top; i++, ptr++) {
+ markvalue(K, **ptr);
}
/* markmt(g); */
diff --git a/src/kstate.c b/src/kstate.c
@@ -100,14 +100,11 @@ klisp_State *klisp_newstate (klisp_Alloc f, void *ud) {
K->grayagain = NULL;
K->weak = NULL;
K->tmudata = NULL;
- /* how to init other gc values ?? */
K->totalbytes = state_size() + KS_ISSIZE * sizeof(TValue) +
KS_ITBSIZE;
- /* CHECK this when implementing incremental collector */
- K->GCthreshold = 4*K->totalbytes; /* this is from lua, but we
- still have a lot of allocation
- to do... */
-
+ K->GCthreshold = UINT32_MAX; /* we still have a lot of allocation
+ to do, put a very high value to
+ avoid collection */
K->estimate = 0; /* doesn't matter, it is set by gc later */
K->gcdept = 0;
K->gcpause = KLISPI_GCPAUSE;
@@ -166,9 +163,16 @@ klisp_State *klisp_newstate (klisp_Alloc f, void *ud) {
K->list_app = kwrap(K, kmake_operative(K, KNIL, KNIL, list, 0));
K->ground_env = kmake_empty_environment(K);
K->module_params_sym = ksymbol_new(K, "module-parameters");
+
+ /* init the stacks used to protect variables & values from gc */
+ K->rootedtv_top = 0;
+ K->rootedv_top = 0;
kinit_ground_env(K);
+ /* set the threshold for gc start now that we have allocated all mem */
+ K->GCthreshold = 4*K->totalbytes;
+
return K;
}
@@ -480,5 +484,3 @@ void klisp_close (klisp_State *K)
/* NOTE: this needs to be done "by hand" */
(*(K->frealloc))(K->ud, K, state_size(), 0);
}
-
-
diff --git a/src/kstate.h b/src/kstate.h
@@ -34,6 +34,9 @@ typedef struct {
int32_t saved_col;
} ksource_info_t;
+/* We would probably do with 3 or 4, but have a little extra just in case */
+#define GC_PROTECT_SIZE 16
+
/* NOTE: when adding TValues here, remember to add them to
markroot in kgc.c!! */
struct klisp_State {
@@ -125,6 +128,16 @@ struct klisp_State {
int32_t ssize; /* total size of array */
int32_t stop; /* top of the stack (all elements are below this index) */
TValue *sbuf;
+
+ /* TValue stack to protect values from gc, must not grow, otherwise
+ it may call the gc */
+ int32_t rootedtv_top;
+ TValue rootedtv_buf[GC_PROTECT_SIZE];
+
+ /* TValue * stack to protect c variables from gc. This is used when the
+ object pointed to by a variable may change */
+ int32_t rootedv_top;
+ TValue *rootedv_buf[GC_PROTECT_SIZE];
};
/* some size related macros */
@@ -269,6 +282,34 @@ inline bool ks_tbisempty(klisp_State *K)
return ks_tbidx(K) == 0;
}
+/*
+** Functions to protect values from GC
+** TODO: add write barriers
+*/
+inline void krootedtv_push(klisp_State *K, TValue tv)
+{
+ klisp_assert(K->rootedtv_top < GC_PROTECT_SIZE);
+ K->rootedtv_buf[K->rootedtv_top++] = tv;
+}
+
+inline void krootedtv_pop(klisp_State *K)
+{
+ klisp_assert(K->rootedtv_top > 0);
+ --(K->rootedtv_top);
+}
+
+inline void krootedv_push(klisp_State *K, TValue *v)
+{
+ klisp_assert(K->rootedv_top < GC_PROTECT_SIZE);
+ K->rootedv_buf[K->rootedv_top++] = v;
+}
+
+inline void krootedv_pop(klisp_State *K)
+{
+ klisp_assert(K->rootedv_top > 0);
+ --(K->rootedv_top);
+}
+
/*
** prototypes for underlying c functions of continuations &