commit 1c712fbdc7a85d2e74442e0d1c07c1eb88710714
parent 1d9aa20ee51615c66af4ebe5ef2201854c15b622
Author: Andres Navarro <canavarro82@gmail.com>
Date: Fri, 15 Apr 2011 18:31:15 -0300
Added gc rooting to reader. Added two helpers to clear the tvs and vars stacks on error.
Diffstat:
4 files changed, 46 insertions(+), 30 deletions(-)
diff --git a/src/kerror.c b/src/kerror.c
@@ -21,8 +21,8 @@ void clear_buffers(klisp_State *K)
K->shared_dict = KNIL;
/* is it okay to do this in all cases? */
- K->rooted_tvs_top = 0;
- K->rooted_vars_top = 0;
+ krooted_tvs_clear(K);
+ krooted_vars_clear(K);
}
void klispE_throw(klisp_State *K, char *msg)
diff --git a/src/kread.c b/src/kread.c
@@ -69,6 +69,12 @@ void kread_error(klisp_State *K, char *str)
ks_tbclear(K);
ks_sclear(K);
clear_shared_dict(K);
+
+ /* this is needed because it would be too complicated to
+ pop manually on each kind of error */
+ krooted_tvs_clear(K);
+ krooted_vars_clear(K);
+
klispE_throw(K, str);
}
@@ -95,7 +101,8 @@ TValue try_shared_ref(klisp_State *K, TValue ref_token)
return KINERT;
}
-TValue try_shared_def(klisp_State *K, TValue def_token, TValue value)
+/* GC: def token is rooted */
+void try_shared_def(klisp_State *K, TValue def_token, TValue value)
{
/* IMPLEMENTATION RESTRICTION: only allow fixints in shared tokens */
int32_t ref_num = ivalue(kcdr(def_token));
@@ -105,15 +112,14 @@ TValue try_shared_def(klisp_State *K, TValue def_token, TValue value)
if (ref_num == ivalue(kcar(head))) {
kread_error(K, "duplicate shared def found");
/* avoid warning */
- return KINERT;
+ return;
}
tail = kcdr(tail);
}
- /* XXX: what happens on out of mem? & gc? (inner cons is not rooted) */
K->shared_dict = kcons(K, kcons(K, kcdr(def_token), value),
- K->shared_dict);
- return KINERT;
+ K->shared_dict); /* value is protected by cons */
+ return;
}
/* This overwrites a previouly made def, it is used in '() */
@@ -152,9 +158,13 @@ TValue kread_fsm(klisp_State *K)
/* the source code information of that obj */
TValue obj_si;
+ krooted_vars_push(K, &obj);
+ krooted_vars_push(K, &obj_si);
+
while (!(get_state(K) == ST_READ && !read_next_token)) {
if (read_next_token) {
- TValue tok = ktok_read_token(K);
+ TValue tok = ktok_read_token(K); /* only root it when necessary */
+
if (ttispair(tok)) { /* special token */
switch (chvalue(kcar(tok))) {
case '(': {
@@ -166,6 +176,7 @@ TValue kread_fsm(klisp_State *K)
}
/* construct the list with the correct type of pair */
TValue np = kcons_g(K, K->read_mconsp, KINERT, KNIL);
+ krooted_tvs_push(K, np);
/*
** NOTE: the source info of the '(' is temporarily saved
** in np (later it will be replace by the source info
@@ -187,6 +198,8 @@ TValue kread_fsm(klisp_State *K)
push_data(K, np);
push_state(K, ST_FIRST_LIST);
read_next_token = true;
+
+ krooted_tvs_pop(K);
break;
}
case ')': {
@@ -289,18 +302,15 @@ TValue kread_fsm(klisp_State *K)
/* avoid warning */
return KINERT;
default: {
- TValue res = try_shared_def(K, tok, KNIL);
- /* TEMP: while error returns EOF */
- if (ttiseof(res)) {
- return res;
- } else {
- /* token ok, read defined object */
- /* NOTE: save the source info to return it
- after the defined object is read */
- push_data(K, kcons(K, tok, ktok_get_source_info(K)));
- push_state(K, ST_SHARED_DEF);
- read_next_token = true;
- }
+ krooted_tvs_push(K, tok);
+ try_shared_def(K, tok, KNIL);
+ /* token ok, read defined object */
+ /* NOTE: save the source info to return it
+ after the defined object is read */
+ push_data(K, kcons(K, tok, ktok_get_source_info(K)));
+ push_state(K, ST_SHARED_DEF);
+ read_next_token = true;
+ krooted_tvs_pop(K);
}
}
break;
@@ -319,16 +329,11 @@ TValue kread_fsm(klisp_State *K)
return KINERT;
default: {
TValue res = try_shared_ref(K, tok);
- /* TEMP: while error returns EOF */
- if (ttiseof(res)) {
- return res;
- } else {
- /* ref ok, process it in next iteration */
- obj = res;
- /* NOTE: use source info of ref token */
- obj_si = ktok_get_source_info(K);
- read_next_token = false;
- }
+ /* ref ok, process it in next iteration */
+ obj = res;
+ /* NOTE: use source info of ref token */
+ obj_si = ktok_get_source_info(K);
+ read_next_token = false;
}
}
break;
@@ -390,6 +395,8 @@ TValue kread_fsm(klisp_State *K)
TValue fp = get_data(K);
/* replace source info in fp with the saved one */
/* NOTE: the old one will be returned when list is complete */
+ /* GC: the way things are done here fp is rooted at all
+ times */
TValue fp_old_si = kget_source_info(fp);
kset_source_info(fp, obj_si);
kset_car(fp, obj);
@@ -408,6 +415,7 @@ TValue kread_fsm(klisp_State *K)
/* get the state out of the way */
pop_state(K);
/* construct the list with the correct type of pair */
+ /* GC: np is rooted by push_data */
TValue np = kcons_g(K, K->read_mconsp, obj, KNIL);
kset_source_info(np, obj_si);
kset_cdr(get_data(K), np);
diff --git a/src/kstate.h b/src/kstate.h
@@ -307,6 +307,8 @@ inline void krooted_tvs_pop(klisp_State *K)
--(K->rooted_tvs_top);
}
+inline void krooted_tvs_clear(klisp_State *K) { K->rooted_tvs_top = 0; }
+
inline void krooted_vars_push(klisp_State *K, TValue *v)
{
klisp_assert(K->rooted_vars_top < GC_PROTECT_SIZE);
@@ -319,6 +321,8 @@ inline void krooted_vars_pop(klisp_State *K)
--(K->rooted_vars_top);
}
+inline void krooted_vars_clear(klisp_State *K) { K->rooted_vars_top = 0; }
+
/* dummy functions will be in kpair.h, because we can't include
it from here */
diff --git a/src/ktoken.c b/src/ktoken.c
@@ -214,6 +214,10 @@ void ktok_error(klisp_State *K, char *str)
ks_tbclear(K);
ks_sclear(K);
clear_shared_dict(K);
+
+ krooted_tvs_clear(K);
+ krooted_vars_clear(K);
+
klispE_throw(K, str);
}