klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

commit 3dc00c1ca306e8be292e6dc16ffee7bb9ca75696
parent bf766979a05a3f2816234b856e556444804cd2cc
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Fri, 15 Apr 2011 16:57:39 -0300

Added gc rooting to kinteger.c

Diffstat:
Msrc/kinteger.c | 34+++++++++++++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/src/kinteger.c b/src/kinteger.c @@ -55,6 +55,7 @@ TValue kbigint_new(klisp_State *K, bool sign, uint32_t digit) } /* used in write to destructively get the digits */ +/* assumes src is rooted */ TValue kbigint_copy(klisp_State *K, TValue src) { TValue copy = kbigint_new(K, false, 0); @@ -66,6 +67,7 @@ TValue kbigint_copy(klisp_State *K, TValue src) /* This algorithm is like a fused multiply add on bignums, unlike any other function here it modifies bigint. It is used in read and it assumes that bigint is positive */ +/* assumes tv_bigint is rooted */ void kbigint_add_digit(klisp_State *K, TValue tv_bigint, int32_t base, int32_t digit) { @@ -76,6 +78,7 @@ void kbigint_add_digit(klisp_State *K, TValue tv_bigint, int32_t base, /* This is used by the writer to get the digits of a number tv_bigint must be positive */ +/* assumes tv_bigint is rooted */ int32_t kbigint_remove_digit(klisp_State *K, TValue tv_bigint, int32_t base) { UNUSED(K); @@ -94,6 +97,7 @@ bool kbigint_has_digits(klisp_State *K, TValue tv_bigint) /* Mutate the bigint to have the opposite sign, used in read and write*/ +/* assumes tv_bigint is rooted */ void kbigint_invert_sign(klisp_State *K, TValue tv_bigint) { Bigint *bigint = tv2bigint(tv_bigint); @@ -138,33 +142,43 @@ bool kbigint_gep(TValue tv_bigint1, TValue tv_bigint2) tv2bigint(tv_bigint2)) >= 0); } +/* +** GC: All of these assume the parameters are rooted +*/ TValue kbigint_plus(klisp_State *K, TValue n1, TValue n2) { TValue res = kbigint_new(K, false, 0); + krooted_tvs_push(K, res); UNUSED(mp_int_add(K, tv2bigint(n1), tv2bigint(n2), tv2bigint(res))); + krooted_tvs_pop(K); return kbigint_try_fixint(K, res); } TValue kbigint_times(klisp_State *K, TValue n1, TValue n2) { TValue res = kbigint_new(K, false, 0); + krooted_tvs_push(K, res); UNUSED(mp_int_mul(K, tv2bigint(n1), tv2bigint(n2), tv2bigint(res))); + krooted_tvs_pop(K); return kbigint_try_fixint(K, res); } TValue kbigint_minus(klisp_State *K, TValue n1, TValue n2) { TValue res = kbigint_new(K, false, 0); + krooted_tvs_push(K, res); UNUSED(mp_int_sub(K, tv2bigint(n1), tv2bigint(n2), tv2bigint(res))); + krooted_tvs_pop(K); return kbigint_try_fixint(K, res); } /* NOTE: n2 can't be zero, that case should be checked before calling this */ TValue kbigint_div_mod(klisp_State *K, TValue n1, TValue n2, TValue *res_r) { - /* GC: root bigints */ TValue tv_q = kbigint_new(K, false, 0); + krooted_tvs_push(K, tv_q); TValue tv_r = kbigint_new(K, false, 0); + krooted_tvs_push(K, tv_r); Bigint *n = tv2bigint(n1); Bigint *d = tv2bigint(n2); @@ -185,6 +199,9 @@ TValue kbigint_div_mod(klisp_State *K, TValue n1, TValue n2, TValue *res_r) } } + krooted_tvs_pop(K); + krooted_tvs_pop(K); + *res_r = kbigint_try_fixint(K, tv_r); return kbigint_try_fixint(K, tv_q); } @@ -193,7 +210,9 @@ TValue kbigint_div0_mod0(klisp_State *K, TValue n1, TValue n2, TValue *res_r) { /* GC: root bigints */ TValue tv_q = kbigint_new(K, false, 0); + krooted_tvs_push(K, tv_q); TValue tv_r = kbigint_new(K, false, 0); + krooted_tvs_push(K, tv_r); Bigint *n = tv2bigint(n1); Bigint *d = tv2bigint(n2); @@ -205,10 +224,12 @@ TValue kbigint_div0_mod0(klisp_State *K, TValue n1, TValue n2, TValue *res_r) /* Adjust q & r so that -|d/2| <= r < |d/2| */ /* It seems easier to check -|d| <= 2r < |d| */ TValue tv_two_r = kbigint_new(K, false, 0); + krooted_tvs_push(K, tv_two_r); Bigint *two_r = tv2bigint(tv_two_r); /* two_r = r * 2 = r * 2^1 */ UNUSED(mp_int_mul_pow2(K, r, 1, two_r)); TValue tv_abs_d = kbigint_new(K, false, 0); + krooted_tvs_push(K, tv_abs_d); /* NOTE: this makes a copy if d >= 0 */ Bigint *abs_d = tv2bigint(tv_abs_d); UNUSED(mp_int_abs(K, d, abs_d)); @@ -238,6 +259,11 @@ TValue kbigint_div0_mod0(klisp_State *K, TValue n1, TValue n2, TValue *res_r) } } + krooted_tvs_pop(K); + krooted_tvs_pop(K); + krooted_tvs_pop(K); + krooted_tvs_pop(K); + *res_r = kbigint_try_fixint(K, tv_r); return kbigint_try_fixint(K, tv_q); } @@ -266,7 +292,9 @@ TValue kbigint_abs(klisp_State *K, TValue tv_bigint) { if (kbigint_negativep(tv_bigint)) { TValue copy = kbigint_new(K, false, 0); + krooted_tvs_push(K, copy); UNUSED(mp_int_abs(K, tv2bigint(tv_bigint), tv2bigint(copy))); + krooted_tvs_pop(K); /* NOTE: this can never be a fixint if the parameter was a bigint */ return copy; } else { @@ -277,17 +305,21 @@ TValue kbigint_abs(klisp_State *K, TValue tv_bigint) TValue kbigint_gcd(klisp_State *K, TValue n1, TValue n2) { TValue res = kbigint_new(K, false, 0); + krooted_tvs_push(K, res); UNUSED(mp_int_gcd(K, tv2bigint(n1), tv2bigint(n2), tv2bigint(res))); + krooted_tvs_pop(K); return kbigint_try_fixint(K, res); } TValue kbigint_lcm(klisp_State *K, TValue n1, TValue n2) { TValue tv_res = kbigint_new(K, false, 0); + krooted_tvs_push(K, tv_res); Bigint *res = tv2bigint(tv_res); /* unlike in kernel, lcm in IMath can return a negative value (if sign a != sign b) */ UNUSED(mp_int_lcm(K, tv2bigint(n1), tv2bigint(n2), res)); UNUSED(mp_int_abs(K, res, res)); + krooted_tvs_pop(K); return kbigint_try_fixint(K, tv_res); }