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:
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);
}