Fixes bug 163540: allocation in bignum arithmetic does not garbage collect.

This commit is contained in:
Abdulaziz Ghuloum 2007-11-18 10:37:13 -05:00
parent 1afade6d43
commit 3b4d3097a1
4 changed files with 188 additions and 49 deletions

View File

@ -433,6 +433,9 @@ ik_collect(int mem_req, ikpcb* pcb){
pcb->gensym_table = add_object(&gc, pcb->gensym_table, "gensym_table");
pcb->arg_list = add_object(&gc, pcb->arg_list, "args_list_foo");
pcb->base_rtd = add_object(&gc, pcb->base_rtd, "base_rtd");
if(pcb->root0) *(pcb->root0) = add_object(&gc, *(pcb->root0), "root0");
if(pcb->root1) *(pcb->root1) = add_object(&gc, *(pcb->root1), "root1");
/* now we trace all live objects */
collect_loop(&gc);

View File

@ -138,6 +138,8 @@ typedef struct ikpcb{
ikp collect_key; /* offset = 48 */
/* the rest are not used by any scheme code */
/* they only support the runtime system (gc, etc.) */
ikp* root0;
ikp* root1;
unsigned int* segment_vector;
ikp weak_pairs_ap;
ikp weak_pairs_ep;
@ -199,6 +201,7 @@ ikp ik_asm_enter(ikpcb*, ikp code_object, ikp arg);
ikp ik_asm_reenter(ikpcb*, ikp code_object, ikp val);
ikp ik_underflow_handler(ikpcb*);
ikp ik_unsafe_alloc(ikpcb* pcb, int size);
ikp ik_safe_alloc(ikpcb* pcb, int size);
#define IK_FASL_HEADER "#@IK01"

View File

@ -128,7 +128,7 @@ ikrt_fxfxplus(ikp x, ikp y, ikpcb* pcb){
return q;
}
else {
ikp bn = ik_unsafe_alloc(pcb, align(disp_bignum_data + wordsize));
ikp bn = ik_safe_alloc(pcb, align(disp_bignum_data + wordsize));
if(r > 0){
ref(bn, 0) = (ikp)(bignum_tag | (1 << bignum_length_shift));
ref(bn, disp_bignum_data) = (ikp)r;
@ -153,7 +153,9 @@ ikrt_fxbnplus(ikp x, ikp y, ikpcb* pcb){
if(intx > 0){
if((bignum_sign_mask & (int)fst) == 0){
/* positive fx + positive bn = even bigger positive */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = 0;
int carry = mpn_add_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -176,7 +178,9 @@ ikrt_fxbnplus(ikp x, ikp y, ikpcb* pcb){
else {
//fprintf(stderr, "this case 0x%08x\n", intx);
/* positive fx + negative bn = smaller negative bn */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = 0;
int borrow = mpn_sub_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -209,7 +213,9 @@ ikrt_fxbnplus(ikp x, ikp y, ikpcb* pcb){
else {
if((bignum_sign_mask & (int)fst) == 0){
/* negative fx + positive bn = smaller positive */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = 0;
int borrow = mpn_sub_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -239,7 +245,9 @@ ikrt_fxbnplus(ikp x, ikp y, ikpcb* pcb){
return verify_bignum(r+vector_tag, "fxbn+4");
} else {
/* negative fx + negative bn = larger negative */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = 0;
int carry = mpn_add_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -281,7 +289,11 @@ ikrt_bnbnplus(ikp x, ikp y, ikpcb* pcb){
} else {
n1 = ylimbs; n2 = xlimbs; s1 = y; s2 = x;
}
ikp res = ik_unsafe_alloc(pcb, align(disp_bignum_data + (n1+1)*wordsize));
pcb->root0 = &s1;
pcb->root1 = &s2;
ikp res = ik_safe_alloc(pcb, align(disp_bignum_data + (n1+1)*wordsize));
pcb->root0 = 0;
pcb->root1 = 0;
mp_limb_t carry = mpn_add((mp_limb_t*) (res+disp_bignum_data),
(mp_limb_t*) (s1-vector_tag+disp_bignum_data),
n1,
@ -329,7 +341,11 @@ ikrt_bnbnplus(ikp x, ikp y, ikpcb* pcb){
}
}
/* |s1| > |s2| */
ikp res = ik_unsafe_alloc(pcb, align(disp_bignum_data + n1 * wordsize));
pcb->root0 = &s1;
pcb->root1 = &s2;
ikp res = ik_safe_alloc(pcb, align(disp_bignum_data + n1 * wordsize));
pcb->root0 = 0;
pcb->root1 = 0;
int burrow = mpn_sub((mp_limb_t*) (res + disp_bignum_data),
(mp_limb_t*) (s1 - vector_tag + disp_bignum_data),
n1,
@ -388,7 +404,7 @@ ikrt_fxfxminus(ikp x, ikp y, ikpcb* pcb){
if(((unsigned int)r) <= most_positive_fixnum){
return fix(r);
} else {
ikp bn = ik_unsafe_alloc(pcb, align(disp_bignum_data + wordsize));
ikp bn = ik_safe_alloc(pcb, align(disp_bignum_data + wordsize));
ref(bn, 0) = (ikp) (bignum_tag | (1 << bignum_length_shift));
ref(bn, disp_bignum_data) = (ikp)r;
return verify_bignum(bn+vector_tag,"fxfx-1");
@ -398,7 +414,7 @@ ikrt_fxfxminus(ikp x, ikp y, ikpcb* pcb){
if(unfix(fxr) == r){
return fxr;
} else {
ikp bn = ik_unsafe_alloc(pcb, align(disp_bignum_data + wordsize));
ikp bn = ik_safe_alloc(pcb, align(disp_bignum_data + wordsize));
ref(bn, 0) = (ikp)
(bignum_tag |
(1 << bignum_sign_shift) |
@ -423,7 +439,9 @@ ikrt_bnnegate(ikp x, ikpcb* pcb){
}
}
}
ikp bn = ik_unsafe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
pcb->root0 = &x;
ikp bn = ik_safe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
pcb->root0 = 0;
memcpy(bn+disp_bignum_data,
x-vector_tag+disp_bignum_data,
limb_count*wordsize);
@ -443,7 +461,9 @@ ikrt_fxbnminus(ikp x, ikp y, ikpcb* pcb){
if(intx > 0){
if(bignum_sign_mask & (int)fst){
/* positive fx - negative bn = positive bn */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = 0;
int carry = mpn_add_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -465,7 +485,9 @@ ikrt_fxbnminus(ikp x, ikp y, ikpcb* pcb){
}
else {
/* positive fx - positive bn = smaller negative bn/fx */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = 0;
int borrow = mpn_sub_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -498,7 +520,9 @@ ikrt_fxbnminus(ikp x, ikp y, ikpcb* pcb){
else {
if(bignum_sign_mask & (int)fst){
/* negative fx - negative bn = smaller positive */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = 0;
int borrow = mpn_sub_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -528,7 +552,9 @@ ikrt_fxbnminus(ikp x, ikp y, ikpcb* pcb){
return verify_bignum(r+vector_tag,"fxbn-");
} else {
/* negative fx - positive bn = larger negative */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = 0;
int carry = mpn_add_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y - vector_tag + disp_bignum_data),
limb_count,
@ -560,7 +586,9 @@ ikrt_bnfxminus(ikp x, ikp y, ikpcb* pcb){
if(inty < 0){
if((bignum_sign_mask & (int)fst) == 0){
/* - negative fx + positive bn = positive bn */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = 0;
int carry = mpn_add_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(x - vector_tag + disp_bignum_data),
limb_count,
@ -582,7 +610,9 @@ ikrt_bnfxminus(ikp x, ikp y, ikpcb* pcb){
}
else {
/* - negative fx + negative bn = smaller negative bn/fx */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = 0;
int borrow = mpn_sub_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(x - vector_tag + disp_bignum_data),
limb_count,
@ -615,7 +645,9 @@ ikrt_bnfxminus(ikp x, ikp y, ikpcb* pcb){
else {
if((bignum_sign_mask & (int)fst) == 0){
/* - positive fx + positive bn = smaller positive */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+limb_count*wordsize));
pcb->root0 = 0;
int borrow = mpn_sub_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(x - vector_tag + disp_bignum_data),
limb_count,
@ -645,7 +677,9 @@ ikrt_bnfxminus(ikp x, ikp y, ikpcb* pcb){
return verify_bignum(r+vector_tag, "bnfx-");
} else {
/* - positive fx + negative bn = larger negative */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+(limb_count+1)*wordsize));
pcb->root0 = 0;
int carry = mpn_add_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(x - vector_tag + disp_bignum_data),
limb_count,
@ -687,7 +721,11 @@ ikrt_bnbnminus(ikp x, ikp y, ikpcb* pcb){
} else {
n1 = ylimbs; n2 = xlimbs; s1 = y; s2 = x;
}
ikp res = ik_unsafe_alloc(pcb, align(disp_bignum_data + (n1+1)*wordsize));
pcb->root0 = &s1;
pcb->root0 = &s2;
ikp res = ik_safe_alloc(pcb, align(disp_bignum_data + (n1+1)*wordsize));
pcb->root0 = 0;
pcb->root0 = 0;
mp_limb_t carry = mpn_add((mp_limb_t*) (res+disp_bignum_data),
(mp_limb_t*) (s1-vector_tag+disp_bignum_data),
n1,
@ -737,7 +775,11 @@ ikrt_bnbnminus(ikp x, ikp y, ikpcb* pcb){
}
}
/* |s1| > |s2| */
ikp res = ik_unsafe_alloc(pcb, align(disp_bignum_data + n1 * wordsize));
pcb->root0 = &s1;
pcb->root0 = &s2;
ikp res = ik_safe_alloc(pcb, align(disp_bignum_data + n1 * wordsize));
pcb->root0 = 0;
pcb->root0 = 0;
int burrow = mpn_sub((mp_limb_t*) (res + disp_bignum_data),
(mp_limb_t*) (s1 - vector_tag + disp_bignum_data),
n1,
@ -812,7 +854,7 @@ ikrt_fxfxmult(ikp x, ikp y, ikpcb* pcb){
return fix((int)lo);
}
}
ikp r = ik_unsafe_alloc(pcb, disp_bignum_data + wordsize);
ikp r = ik_safe_alloc(pcb, disp_bignum_data + wordsize);
ref(r, 0) = (ikp)
(bignum_tag |
(sign << bignum_sign_shift) |
@ -820,7 +862,7 @@ ikrt_fxfxmult(ikp x, ikp y, ikpcb* pcb){
ref(r, disp_bignum_data) = (ikp)lo;
return BN(r+vector_tag);
} else {
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + 2*wordsize));
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + 2*wordsize));
ref(r, 0) = (ikp)
(bignum_tag |
(sign << bignum_sign_shift) |
@ -861,7 +903,9 @@ ikrt_fxbnmult(ikp x, ikp y, ikpcb* pcb){
mp_limb_t s2 = (n2>0) ? n2 : (- n2);
ikp fst = ref(y, -vector_tag);
int limb_count = ((unsigned int) fst) >> bignum_length_shift;
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + (limb_count+1)*wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + (limb_count+1)*wordsize));
pcb->root0 = 0;
mp_limb_t hi = mpn_mul_1((mp_limb_t*)(r+disp_bignum_data),
(mp_limb_t*)(y-vector_tag+disp_bignum_data),
limb_count,
@ -881,7 +925,11 @@ ikrt_bnbnmult(ikp x, ikp y, ikpcb* pcb){
int n1 = ((unsigned int)f1) >> bignum_length_shift;
int n2 = ((unsigned int)f2) >> bignum_length_shift;
int nr = n1 + n2;
ikp bn = ik_unsafe_alloc(pcb, align(disp_bignum_data + nr*wordsize));
pcb->root0 = &x;
pcb->root1 = &y;
ikp bn = ik_safe_alloc(pcb, align(disp_bignum_data + nr*wordsize));
pcb->root0 = 0;
pcb->root1 = 0;
mp_limb_t r;
if(n1 >= n2){
r = mpn_mul((mp_limb_t*)(bn+disp_bignum_data),
@ -992,7 +1040,9 @@ ikrt_fxbnlogand(ikp x, ikp y, ikpcb* pcb){
if((len == 1) && (nn <= most_negative_fixnum)){
return fix(-nn);
}
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + len * wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + len * wordsize));
pcb->root0 = 0;
ref(r, 0) = fst;
ref(r, disp_bignum_data) = (ikp) nn;
int i;
@ -1004,7 +1054,9 @@ ikrt_fxbnlogand(ikp x, ikp y, ikpcb* pcb){
} else {
/* y is positive */
int len = (((unsigned int) fst) >> bignum_length_shift);
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + len * wordsize));
pcb->root0 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + len * wordsize));
pcb->root0 = 0;
ref(r, 0) = fst;
ref(r, disp_bignum_data) = (ikp)
(((int)ref(y, disp_bignum_data - vector_tag)) & n1);
@ -1090,10 +1142,12 @@ ikp
ikrt_bnlognot(ikp x, ikpcb* pcb){
ikp fst = ref(x, -vector_tag);
int n = ((unsigned int)fst) >> bignum_length_shift;
unsigned int* s1 = ((unsigned int*)(x+disp_bignum_data-vector_tag));
if(bignum_sign_mask & (unsigned int) fst){
/* negative */
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + n*wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + n*wordsize));
pcb->root0 = 0;
unsigned int* s1 = ((unsigned int*)(x+disp_bignum_data-vector_tag));
unsigned int* rd = (unsigned int*)(r+disp_bignum_data);
int i;
for(i=0; (i<n) && (s1[i] == 0); i++) {
@ -1107,16 +1161,22 @@ ikrt_bnlognot(ikp x, ikpcb* pcb){
} else {
/* positive */
int i;
unsigned int* s1 = ((unsigned int*)(x+disp_bignum_data-vector_tag));
for(i=0; (i<n) && (s1[i] == -1); i++) {/*nothing*/}
if(i==n){
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + (n+1)*wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + (n+1)*wordsize));
pcb->root0 = 0;
bzero(r+disp_bignum_data, n*wordsize);
((unsigned int*)(r+disp_bignum_data))[n] = 1;
ref(r, 0) = (ikp)
(bignum_tag | (1<<bignum_sign_shift) | ((n+1) << bignum_length_shift));
return r+vector_tag;
} else {
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + n*wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + n*wordsize));
pcb->root0 = 0;
unsigned int* s1 = ((unsigned int*)(x+disp_bignum_data-vector_tag));
unsigned int* rd = (unsigned int*)(r+disp_bignum_data);
int j;
for(j=0; j<i; j++){ rd[j] = 0; }
@ -1138,10 +1198,14 @@ ikrt_bnbnlogand(ikp x, ikp y, ikpcb* pcb){
int n2 = ((unsigned int) yfst) >> bignum_length_shift;
if(bignum_sign_mask & (unsigned int) xfst){
if(bignum_sign_mask & (unsigned int) yfst){
unsigned int* s1 = ((unsigned int*)(x+disp_bignum_data-vector_tag));
unsigned int* s2 = ((unsigned int*)(y+disp_bignum_data-vector_tag));
if(n1 >= n2){
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + n1*wordsize));
pcb->root0 = &x;
pcb->root1 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + n1*wordsize));
pcb->root0 = 0;
pcb->root1 = 0;
unsigned int* s1 = ((unsigned int*)(x+disp_bignum_data-vector_tag));
unsigned int* s2 = ((unsigned int*)(y+disp_bignum_data-vector_tag));
unsigned int* s = ((unsigned int*)(r+disp_bignum_data));
bits_compliment(s1, s, n1);
bits_compliment_logand(s2, s, s, n2);
@ -1157,9 +1221,13 @@ ikrt_bnbnlogand(ikp x, ikp y, ikpcb* pcb){
if(bignum_sign_mask & (unsigned int) yfst){
/* x positive, y negative */
/* the result is at most n1 words long */
pcb->root0 = &x;
pcb->root1 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + n1*wordsize));
pcb->root0 = 0;
pcb->root1 = 0;
unsigned int* s1 = ((unsigned int*)(x+disp_bignum_data-vector_tag));
unsigned int* s2 = ((unsigned int*)(y+disp_bignum_data-vector_tag));
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + n1*wordsize));
unsigned int* s = ((unsigned int*)(r+disp_bignum_data));
bits_compliment_logand(s2, s1, s, n1);
return normalize_bignum(n1, 0, r);
@ -1177,7 +1245,11 @@ ikrt_bnbnlogand(ikp x, ikp y, ikpcb* pcb){
if((i == 0) && (last < most_positive_fixnum)){
return fix(last);
}
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data+(i+1)*wordsize));
pcb->root0 = &x;
pcb->root1 = &y;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data+(i+1)*wordsize));
pcb->root0 = 0;
pcb->root1 = 0;
ref(r, 0) = (ikp) (bignum_tag | ((i+1)<<bignum_length_shift));
ref(r, disp_bignum_data + i*wordsize) = (ikp)last;
int j;
@ -1237,7 +1309,9 @@ ikrt_bignum_shift_right(ikp x, ikp y, ikpcb* pcb){
return fix(-1);
}
if(bit_shift == 0){
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + new_limb_count * wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + new_limb_count * wordsize));
pcb->root0 = 0;
bits_compliment_with_carry(
(unsigned int*)(x+off_bignum_data+whole_limb_shift*wordsize),
(unsigned int*)(r+disp_bignum_data),
@ -1249,7 +1323,9 @@ ikrt_bignum_shift_right(ikp x, ikp y, ikpcb* pcb){
new_limb_count);
return normalize_bignum(new_limb_count, 1 << bignum_sign_shift, r);
} else {
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + new_limb_count * wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + new_limb_count * wordsize));
pcb->root0 = 0;
bits_compliment_with_carry(
(unsigned int*)(x+off_bignum_data+whole_limb_shift*wordsize),
(unsigned int*)(r+disp_bignum_data),
@ -1274,14 +1350,15 @@ ikrt_bignum_shift_right(ikp x, ikp y, ikpcb* pcb){
if(new_limb_count <= 0){
return 0;
}
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + new_limb_count * wordsize));
pcb->root0 = 0;
if(bit_shift == 0){
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + new_limb_count * wordsize));
memcpy(r+disp_bignum_data,
x+off_bignum_data+whole_limb_shift*wordsize,
new_limb_count * wordsize);
return normalize_bignum(new_limb_count, 0, r);
} else {
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + new_limb_count * wordsize));
copy_bits_shifting_right(
(unsigned int*)(x+off_bignum_data+whole_limb_shift*wordsize),
(unsigned int*)(r+disp_bignum_data),
@ -1299,7 +1376,7 @@ ikrt_fixnum_shift_left(ikp x, ikp y, ikpcb* pcb){
int n = unfix(x);
int limb_count = (m >> 5) + 2; /* FIXME: 5 are the bits in 32-bit num */
int bit_shift = m & 31;
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
unsigned int* s = (unsigned int*)(r+disp_bignum_data);
bzero(s, limb_count * wordsize);
if(n >= 0){
@ -1326,14 +1403,18 @@ ikrt_bignum_shift_left(ikp x, ikp y, ikpcb* pcb){
int bit_shift = m & 31;
if(bit_shift == 0){
int limb_count = n + whole_limb_shift;
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
pcb->root0 = 0;
unsigned int* s = (unsigned int*)(r+disp_bignum_data);
bzero(s, whole_limb_shift*wordsize);
memcpy(s+whole_limb_shift, x+off_bignum_data, n*wordsize);
return normalize_bignum(limb_count, (unsigned int)fst & bignum_sign_mask, r);
} else {
int limb_count = n + whole_limb_shift + 1;
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
pcb->root0 = &x;
ikp r = ik_safe_alloc(pcb, align(disp_bignum_data + limb_count * wordsize));
pcb->root0 = 0;
unsigned int* s = (unsigned int*)(r+disp_bignum_data);
bzero(s, whole_limb_shift*wordsize);
copy_bits_shifting_left(
@ -1374,15 +1455,29 @@ ikrt_bnbndivrem(ikp x, ikp y, ikpcb* pcb){
mp_size_t yn = ((unsigned int) yfst) >> bignum_length_shift;
if(xn < yn){
/* quotient is zero, remainder is x */
ikp rv = ik_unsafe_alloc(pcb, pair_size);
pcb->root0 = &x;
pcb->root1 = &y;
ikp rv = ik_safe_alloc(pcb, pair_size);
pcb->root0 = 0;
pcb->root1 = 0;
ref(rv, disp_car) = 0;
ref(rv, disp_cdr) = x;
return rv+pair_tag;
}
mp_size_t qn = xn - yn + 1;
mp_size_t rn = yn;
/*
ikp q = ik_unsafe_alloc(pcb, align(disp_bignum_data + qn*wordsize));
ikp r = ik_unsafe_alloc(pcb, align(disp_bignum_data + rn*wordsize));
*/
pcb->root0 = &x;
pcb->root1 = &y;
ikp q = ik_safe_alloc(pcb,
align(disp_bignum_data + qn*wordsize) +
align(disp_bignum_data + rn*wordsize));
ikp r = q + align(disp_bignum_data + qn*wordsize);
pcb->root0 = 0;
pcb->root1 = 0;
mpn_tdiv_qr (
(mp_limb_t*)(q+disp_bignum_data),
(mp_limb_t*)(r+disp_bignum_data),
@ -1409,7 +1504,11 @@ ikrt_bnbndivrem(ikp x, ikp y, ikpcb* pcb){
int sign = (((unsigned int)xfst) & bignum_sign_mask);
q = normalize_bignum(qn, sign, q);
}
ikp rv = ik_unsafe_alloc(pcb, pair_size);
pcb->root0 = &q;
pcb->root1 = &r;
ikp rv = ik_safe_alloc(pcb, pair_size);
pcb->root0 = 0;
pcb->root1 = 0;
ref(rv, disp_car) = q;
ref(rv, disp_cdr) = r;
return rv+pair_tag;
@ -1437,11 +1536,12 @@ usages, qxn will be zero.
ikp
ikrt_bnfxdivrem(ikp x, ikp y, ikpcb* pcb){
int yint = unfix(y);
mp_limb_t* s2p = (mp_limb_t*)(x+off_bignum_data);
ikp fst = ref(x, -vector_tag);
mp_size_t s2n = ((unsigned int) fst) >> bignum_length_shift;
ikp quot = ik_unsafe_alloc(pcb,
align(s2n*wordsize + disp_bignum_data));
pcb->root0 = &x;
ikp quot = ik_safe_alloc(pcb, align(s2n*wordsize + disp_bignum_data));
pcb->root0 = 0;
mp_limb_t* s2p = (mp_limb_t*)(x+off_bignum_data);
mp_limb_t rv = mpn_divrem_1(
(mp_limb_t*)(quot+disp_bignum_data),
0,
@ -1471,7 +1571,11 @@ ikrt_bnfxdivrem(ikp x, ikp y, ikpcb* pcb){
} else {
rem = fix(rv);
}
ikp p = ik_unsafe_alloc(pcb, pair_size);
pcb->root0 = &quot;
pcb->root0 = &rem;
ikp p = ik_safe_alloc(pcb, pair_size);
pcb->root0 = 0;
pcb->root0 = 0;
ref(p, disp_car) = quot;
ref(p, disp_cdr) = rem;
return p+pair_tag;
@ -1542,7 +1646,7 @@ ikrt_bignum_to_bytevector(ikp x, ikpcb* pcb){
string_start++;
bytes--;
}
ikp bv = ik_unsafe_alloc(pcb, align(bytes + disp_bytevector_data + (sign_bit?1:0)));
ikp bv = ik_safe_alloc(pcb, align(bytes + disp_bytevector_data + (sign_bit?1:0)));
ref(bv, 0) = fix(bytes + (sign_bit?1:0));
ikp dest = bv + disp_bytevector_data;
if(sign_bit){

View File

@ -394,6 +394,35 @@ void ik_delete_pcb(ikpcb* pcb){
ik_free(pcb, sizeof(ikpcb));
}
ikp
ik_safe_alloc(ikpcb* pcb, int size){
assert(size == align(size));
ikp ap = pcb->allocation_pointer;
ikp ep = pcb->heap_base + pcb->heap_size;
ikp nap = ap + size;
if(nap < ep){
pcb->allocation_pointer = nap;
return ap;
}
else {
ik_collect(size, pcb);
ikp ap = pcb->allocation_pointer;
ikp ep = pcb->heap_base + pcb->heap_size;
ikp nap = ap + size;
if(nap < ep){
pcb->allocation_pointer = nap;
return ap;
} else {
fprintf(stderr,
"ikaurs: BUG: collector did not leave enough room for %d\n",
size);
exit(-1);
}
}
}
ikp
ik_unsafe_alloc(ikpcb* pcb, int size){