Various VM cleanups, new approach for bignum GC root registration
parent
e3592ca8f6
commit
ec28b1ef85
5
Makefile
5
Makefile
|
@ -179,6 +179,9 @@ clean:
|
||||||
rm -f vm/*.o
|
rm -f vm/*.o
|
||||||
rm -f factor*.dll libfactor.{a,so,dylib} libfactor-ffi-test.{a,so,dylib} Factor.app/Contents/Frameworks/libfactor.dylib
|
rm -f factor*.dll libfactor.{a,so,dylib} libfactor-ffi-test.{a,so,dylib} Factor.app/Contents/Frameworks/libfactor.dylib
|
||||||
|
|
||||||
|
tags:
|
||||||
|
etags vm/*.{cpp,hpp,mm,S,c}
|
||||||
|
|
||||||
vm/resources.o:
|
vm/resources.o:
|
||||||
$(WINDRES) vm/factor.rs vm/resources.o
|
$(WINDRES) vm/factor.rs vm/resources.o
|
||||||
|
|
||||||
|
@ -197,6 +200,6 @@ vm/ffi_test.o: vm/ffi_test.c
|
||||||
.mm.o:
|
.mm.o:
|
||||||
$(CPP) -c $(CFLAGS) -o $@ $<
|
$(CPP) -c $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
.PHONY: factor
|
.PHONY: factor tags clean
|
||||||
|
|
||||||
.SUFFIXES: .mm
|
.SUFFIXES: .mm
|
||||||
|
|
108
vm/bignum.cpp
108
vm/bignum.cpp
|
@ -505,6 +505,8 @@ bignum_compare_unsigned(F_BIGNUM * x, F_BIGNUM * y)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_add_unsigned(F_BIGNUM * x, F_BIGNUM * y, int negative_p)
|
bignum_add_unsigned(F_BIGNUM * x, F_BIGNUM * y, int negative_p)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(x); GC_BIGNUM(y);
|
||||||
|
|
||||||
if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
|
if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
|
||||||
{
|
{
|
||||||
F_BIGNUM * z = x;
|
F_BIGNUM * z = x;
|
||||||
|
@ -514,11 +516,7 @@ bignum_add_unsigned(F_BIGNUM * x, F_BIGNUM * y, int negative_p)
|
||||||
{
|
{
|
||||||
bignum_length_type x_length = (BIGNUM_LENGTH (x));
|
bignum_length_type x_length = (BIGNUM_LENGTH (x));
|
||||||
|
|
||||||
REGISTER_BIGNUM(x);
|
|
||||||
REGISTER_BIGNUM(y);
|
|
||||||
F_BIGNUM * r = (allot_bignum ((x_length + 1), negative_p));
|
F_BIGNUM * r = (allot_bignum ((x_length + 1), negative_p));
|
||||||
UNREGISTER_BIGNUM(y);
|
|
||||||
UNREGISTER_BIGNUM(x);
|
|
||||||
|
|
||||||
bignum_digit_type sum;
|
bignum_digit_type sum;
|
||||||
bignum_digit_type carry = 0;
|
bignum_digit_type carry = 0;
|
||||||
|
@ -575,6 +573,8 @@ bignum_add_unsigned(F_BIGNUM * x, F_BIGNUM * y, int negative_p)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_subtract_unsigned(F_BIGNUM * x, F_BIGNUM * y)
|
bignum_subtract_unsigned(F_BIGNUM * x, F_BIGNUM * y)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(x); GC_BIGNUM(y);
|
||||||
|
|
||||||
int negative_p = 0;
|
int negative_p = 0;
|
||||||
switch (bignum_compare_unsigned (x, y))
|
switch (bignum_compare_unsigned (x, y))
|
||||||
{
|
{
|
||||||
|
@ -595,11 +595,7 @@ bignum_subtract_unsigned(F_BIGNUM * x, F_BIGNUM * y)
|
||||||
{
|
{
|
||||||
bignum_length_type x_length = (BIGNUM_LENGTH (x));
|
bignum_length_type x_length = (BIGNUM_LENGTH (x));
|
||||||
|
|
||||||
REGISTER_BIGNUM(x);
|
|
||||||
REGISTER_BIGNUM(y);
|
|
||||||
F_BIGNUM * r = (allot_bignum (x_length, negative_p));
|
F_BIGNUM * r = (allot_bignum (x_length, negative_p));
|
||||||
UNREGISTER_BIGNUM(y);
|
|
||||||
UNREGISTER_BIGNUM(x);
|
|
||||||
|
|
||||||
bignum_digit_type difference;
|
bignum_digit_type difference;
|
||||||
bignum_digit_type borrow = 0;
|
bignum_digit_type borrow = 0;
|
||||||
|
@ -656,6 +652,8 @@ bignum_subtract_unsigned(F_BIGNUM * x, F_BIGNUM * y)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_multiply_unsigned(F_BIGNUM * x, F_BIGNUM * y, int negative_p)
|
bignum_multiply_unsigned(F_BIGNUM * x, F_BIGNUM * y, int negative_p)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(x); GC_BIGNUM(y);
|
||||||
|
|
||||||
if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
|
if ((BIGNUM_LENGTH (y)) > (BIGNUM_LENGTH (x)))
|
||||||
{
|
{
|
||||||
F_BIGNUM * z = x;
|
F_BIGNUM * z = x;
|
||||||
|
@ -674,12 +672,8 @@ bignum_multiply_unsigned(F_BIGNUM * x, F_BIGNUM * y, int negative_p)
|
||||||
bignum_length_type x_length = (BIGNUM_LENGTH (x));
|
bignum_length_type x_length = (BIGNUM_LENGTH (x));
|
||||||
bignum_length_type y_length = (BIGNUM_LENGTH (y));
|
bignum_length_type y_length = (BIGNUM_LENGTH (y));
|
||||||
|
|
||||||
REGISTER_BIGNUM(x);
|
|
||||||
REGISTER_BIGNUM(y);
|
|
||||||
F_BIGNUM * r =
|
F_BIGNUM * r =
|
||||||
(allot_bignum_zeroed ((x_length + y_length), negative_p));
|
(allot_bignum_zeroed ((x_length + y_length), negative_p));
|
||||||
UNREGISTER_BIGNUM(y);
|
|
||||||
UNREGISTER_BIGNUM(x);
|
|
||||||
|
|
||||||
bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
|
bignum_digit_type * scan_x = (BIGNUM_START_PTR (x));
|
||||||
bignum_digit_type * end_x = (scan_x + x_length);
|
bignum_digit_type * end_x = (scan_x + x_length);
|
||||||
|
@ -731,11 +725,11 @@ F_BIGNUM *
|
||||||
bignum_multiply_unsigned_small_factor(F_BIGNUM * x, bignum_digit_type y,
|
bignum_multiply_unsigned_small_factor(F_BIGNUM * x, bignum_digit_type y,
|
||||||
int negative_p)
|
int negative_p)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(x);
|
||||||
|
|
||||||
bignum_length_type length_x = (BIGNUM_LENGTH (x));
|
bignum_length_type length_x = (BIGNUM_LENGTH (x));
|
||||||
|
|
||||||
REGISTER_BIGNUM(x);
|
|
||||||
F_BIGNUM * p = (allot_bignum ((length_x + 1), negative_p));
|
F_BIGNUM * p = (allot_bignum ((length_x + 1), negative_p));
|
||||||
UNREGISTER_BIGNUM(x);
|
|
||||||
|
|
||||||
bignum_destructive_copy (x, p);
|
bignum_destructive_copy (x, p);
|
||||||
(BIGNUM_REF (p, length_x)) = 0;
|
(BIGNUM_REF (p, length_x)) = 0;
|
||||||
|
@ -813,23 +807,19 @@ bignum_divide_unsigned_large_denominator(F_BIGNUM * numerator,
|
||||||
int q_negative_p,
|
int q_negative_p,
|
||||||
int r_negative_p)
|
int r_negative_p)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(numerator); GC_BIGNUM(denominator);
|
||||||
|
|
||||||
bignum_length_type length_n = ((BIGNUM_LENGTH (numerator)) + 1);
|
bignum_length_type length_n = ((BIGNUM_LENGTH (numerator)) + 1);
|
||||||
bignum_length_type length_d = (BIGNUM_LENGTH (denominator));
|
bignum_length_type length_d = (BIGNUM_LENGTH (denominator));
|
||||||
|
|
||||||
REGISTER_BIGNUM(numerator);
|
|
||||||
REGISTER_BIGNUM(denominator);
|
|
||||||
|
|
||||||
F_BIGNUM * q =
|
F_BIGNUM * q =
|
||||||
((quotient != ((F_BIGNUM * *) 0))
|
((quotient != ((F_BIGNUM * *) 0))
|
||||||
? (allot_bignum ((length_n - length_d), q_negative_p))
|
? (allot_bignum ((length_n - length_d), q_negative_p))
|
||||||
: BIGNUM_OUT_OF_BAND);
|
: BIGNUM_OUT_OF_BAND);
|
||||||
|
GC_BIGNUM(q);
|
||||||
|
|
||||||
REGISTER_BIGNUM(q);
|
|
||||||
F_BIGNUM * u = (allot_bignum (length_n, r_negative_p));
|
F_BIGNUM * u = (allot_bignum (length_n, r_negative_p));
|
||||||
UNREGISTER_BIGNUM(q);
|
GC_BIGNUM(u);
|
||||||
|
|
||||||
UNREGISTER_BIGNUM(denominator);
|
|
||||||
UNREGISTER_BIGNUM(numerator);
|
|
||||||
|
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
BIGNUM_ASSERT (length_d > 1);
|
BIGNUM_ASSERT (length_d > 1);
|
||||||
|
@ -849,15 +839,7 @@ bignum_divide_unsigned_large_denominator(F_BIGNUM * numerator,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
REGISTER_BIGNUM(numerator);
|
|
||||||
REGISTER_BIGNUM(denominator);
|
|
||||||
REGISTER_BIGNUM(u);
|
|
||||||
REGISTER_BIGNUM(q);
|
|
||||||
F_BIGNUM * v = (allot_bignum (length_d, 0));
|
F_BIGNUM * v = (allot_bignum (length_d, 0));
|
||||||
UNREGISTER_BIGNUM(q);
|
|
||||||
UNREGISTER_BIGNUM(u);
|
|
||||||
UNREGISTER_BIGNUM(denominator);
|
|
||||||
UNREGISTER_BIGNUM(numerator);
|
|
||||||
|
|
||||||
bignum_destructive_normalization (numerator, u, shift);
|
bignum_destructive_normalization (numerator, u, shift);
|
||||||
bignum_destructive_normalization (denominator, v, shift);
|
bignum_destructive_normalization (denominator, v, shift);
|
||||||
|
@ -866,14 +848,10 @@ bignum_divide_unsigned_large_denominator(F_BIGNUM * numerator,
|
||||||
bignum_destructive_unnormalization (u, shift);
|
bignum_destructive_unnormalization (u, shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_BIGNUM(u);
|
|
||||||
if(q)
|
if(q)
|
||||||
q = bignum_trim (q);
|
q = bignum_trim (q);
|
||||||
UNREGISTER_BIGNUM(u);
|
|
||||||
|
|
||||||
REGISTER_BIGNUM(q);
|
|
||||||
u = bignum_trim (u);
|
u = bignum_trim (u);
|
||||||
UNREGISTER_BIGNUM(q);
|
|
||||||
|
|
||||||
if (quotient != ((F_BIGNUM * *) 0))
|
if (quotient != ((F_BIGNUM * *) 0))
|
||||||
(*quotient) = q;
|
(*quotient) = q;
|
||||||
|
@ -1047,9 +1025,13 @@ bignum_divide_unsigned_medium_denominator(F_BIGNUM * numerator,
|
||||||
int q_negative_p,
|
int q_negative_p,
|
||||||
int r_negative_p)
|
int r_negative_p)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(numerator);
|
||||||
|
|
||||||
bignum_length_type length_n = (BIGNUM_LENGTH (numerator));
|
bignum_length_type length_n = (BIGNUM_LENGTH (numerator));
|
||||||
bignum_length_type length_q;
|
bignum_length_type length_q;
|
||||||
F_BIGNUM * q;
|
F_BIGNUM * q = NULL;
|
||||||
|
GC_BIGNUM(q);
|
||||||
|
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
/* Because `bignum_digit_divide' requires a normalized denominator. */
|
/* Because `bignum_digit_divide' requires a normalized denominator. */
|
||||||
while (denominator < (BIGNUM_RADIX / 2))
|
while (denominator < (BIGNUM_RADIX / 2))
|
||||||
|
@ -1061,20 +1043,14 @@ bignum_divide_unsigned_medium_denominator(F_BIGNUM * numerator,
|
||||||
{
|
{
|
||||||
length_q = length_n;
|
length_q = length_n;
|
||||||
|
|
||||||
REGISTER_BIGNUM(numerator);
|
|
||||||
q = (allot_bignum (length_q, q_negative_p));
|
q = (allot_bignum (length_q, q_negative_p));
|
||||||
UNREGISTER_BIGNUM(numerator);
|
|
||||||
|
|
||||||
bignum_destructive_copy (numerator, q);
|
bignum_destructive_copy (numerator, q);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
length_q = (length_n + 1);
|
length_q = (length_n + 1);
|
||||||
|
|
||||||
REGISTER_BIGNUM(numerator);
|
|
||||||
q = (allot_bignum (length_q, q_negative_p));
|
q = (allot_bignum (length_q, q_negative_p));
|
||||||
UNREGISTER_BIGNUM(numerator);
|
|
||||||
|
|
||||||
bignum_destructive_normalization (numerator, q, shift);
|
bignum_destructive_normalization (numerator, q, shift);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -1096,9 +1072,7 @@ bignum_divide_unsigned_medium_denominator(F_BIGNUM * numerator,
|
||||||
if (shift != 0)
|
if (shift != 0)
|
||||||
r >>= shift;
|
r >>= shift;
|
||||||
|
|
||||||
REGISTER_BIGNUM(q);
|
|
||||||
(*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
|
(*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
|
||||||
UNREGISTER_BIGNUM(q);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (quotient != ((F_BIGNUM * *) 0))
|
if (quotient != ((F_BIGNUM * *) 0))
|
||||||
|
@ -1295,20 +1269,17 @@ bignum_divide_unsigned_small_denominator(F_BIGNUM * numerator,
|
||||||
int q_negative_p,
|
int q_negative_p,
|
||||||
int r_negative_p)
|
int r_negative_p)
|
||||||
{
|
{
|
||||||
REGISTER_BIGNUM(numerator);
|
GC_BIGNUM(numerator);
|
||||||
|
|
||||||
F_BIGNUM * q = (bignum_new_sign (numerator, q_negative_p));
|
F_BIGNUM * q = (bignum_new_sign (numerator, q_negative_p));
|
||||||
UNREGISTER_BIGNUM(numerator);
|
GC_BIGNUM(q);
|
||||||
|
|
||||||
bignum_digit_type r = (bignum_destructive_scale_down (q, denominator));
|
bignum_digit_type r = (bignum_destructive_scale_down (q, denominator));
|
||||||
|
|
||||||
q = (bignum_trim (q));
|
q = (bignum_trim (q));
|
||||||
|
|
||||||
if (remainder != ((F_BIGNUM * *) 0))
|
if (remainder != ((F_BIGNUM * *) 0))
|
||||||
{
|
|
||||||
REGISTER_BIGNUM(q);
|
|
||||||
(*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
|
(*remainder) = (bignum_digit_to_bignum (r, r_negative_p));
|
||||||
UNREGISTER_BIGNUM(q);
|
|
||||||
}
|
|
||||||
|
|
||||||
(*quotient) = q;
|
(*quotient) = q;
|
||||||
|
|
||||||
|
@ -1381,6 +1352,7 @@ bignum_digit_to_bignum(bignum_digit_type digit, int negative_p)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
allot_bignum(bignum_length_type length, int negative_p)
|
allot_bignum(bignum_length_type length, int negative_p)
|
||||||
{
|
{
|
||||||
|
gc();
|
||||||
BIGNUM_ASSERT ((length >= 0) || (length < BIGNUM_RADIX));
|
BIGNUM_ASSERT ((length >= 0) || (length < BIGNUM_RADIX));
|
||||||
F_BIGNUM * result = allot_array_internal<F_BIGNUM>(length + 1);
|
F_BIGNUM * result = allot_array_internal<F_BIGNUM>(length + 1);
|
||||||
BIGNUM_SET_NEGATIVE_P (result, negative_p);
|
BIGNUM_SET_NEGATIVE_P (result, negative_p);
|
||||||
|
@ -1441,10 +1413,8 @@ bignum_trim(F_BIGNUM * bignum)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_new_sign(F_BIGNUM * bignum, int negative_p)
|
bignum_new_sign(F_BIGNUM * bignum, int negative_p)
|
||||||
{
|
{
|
||||||
REGISTER_BIGNUM(bignum);
|
GC_BIGNUM(bignum);
|
||||||
F_BIGNUM * result =
|
F_BIGNUM * result = (allot_bignum ((BIGNUM_LENGTH (bignum)), negative_p));
|
||||||
(allot_bignum ((BIGNUM_LENGTH (bignum)), negative_p));
|
|
||||||
UNREGISTER_BIGNUM(bignum);
|
|
||||||
|
|
||||||
bignum_destructive_copy (bignum, result);
|
bignum_destructive_copy (bignum, result);
|
||||||
return (result);
|
return (result);
|
||||||
|
@ -1553,6 +1523,8 @@ bignum_bitwise_xor(F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_magnitude_ash(F_BIGNUM * arg1, F_FIXNUM n)
|
bignum_magnitude_ash(F_BIGNUM * arg1, F_FIXNUM n)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(arg1);
|
||||||
|
|
||||||
F_BIGNUM * result = NULL;
|
F_BIGNUM * result = NULL;
|
||||||
bignum_digit_type *scan1;
|
bignum_digit_type *scan1;
|
||||||
bignum_digit_type *scanr;
|
bignum_digit_type *scanr;
|
||||||
|
@ -1566,10 +1538,8 @@ bignum_magnitude_ash(F_BIGNUM * arg1, F_FIXNUM n)
|
||||||
digit_offset = n / BIGNUM_DIGIT_LENGTH;
|
digit_offset = n / BIGNUM_DIGIT_LENGTH;
|
||||||
bit_offset = n % BIGNUM_DIGIT_LENGTH;
|
bit_offset = n % BIGNUM_DIGIT_LENGTH;
|
||||||
|
|
||||||
REGISTER_BIGNUM(arg1);
|
|
||||||
result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) + digit_offset + 1,
|
result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) + digit_offset + 1,
|
||||||
BIGNUM_NEGATIVE_P(arg1));
|
BIGNUM_NEGATIVE_P(arg1));
|
||||||
UNREGISTER_BIGNUM(arg1);
|
|
||||||
|
|
||||||
scanr = BIGNUM_START_PTR (result) + digit_offset;
|
scanr = BIGNUM_START_PTR (result) + digit_offset;
|
||||||
scan1 = BIGNUM_START_PTR (arg1);
|
scan1 = BIGNUM_START_PTR (arg1);
|
||||||
|
@ -1591,10 +1561,8 @@ bignum_magnitude_ash(F_BIGNUM * arg1, F_FIXNUM n)
|
||||||
digit_offset = -n / BIGNUM_DIGIT_LENGTH;
|
digit_offset = -n / BIGNUM_DIGIT_LENGTH;
|
||||||
bit_offset = -n % BIGNUM_DIGIT_LENGTH;
|
bit_offset = -n % BIGNUM_DIGIT_LENGTH;
|
||||||
|
|
||||||
REGISTER_BIGNUM(arg1);
|
|
||||||
result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) - digit_offset,
|
result = allot_bignum_zeroed (BIGNUM_LENGTH (arg1) - digit_offset,
|
||||||
BIGNUM_NEGATIVE_P(arg1));
|
BIGNUM_NEGATIVE_P(arg1));
|
||||||
UNREGISTER_BIGNUM(arg1);
|
|
||||||
|
|
||||||
scanr = BIGNUM_START_PTR (result);
|
scanr = BIGNUM_START_PTR (result);
|
||||||
scan1 = BIGNUM_START_PTR (arg1) + digit_offset;
|
scan1 = BIGNUM_START_PTR (arg1) + digit_offset;
|
||||||
|
@ -1617,6 +1585,8 @@ bignum_magnitude_ash(F_BIGNUM * arg1, F_FIXNUM n)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_pospos_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
bignum_pospos_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(arg1); GC_BIGNUM(arg2);
|
||||||
|
|
||||||
F_BIGNUM * result;
|
F_BIGNUM * result;
|
||||||
bignum_length_type max_length;
|
bignum_length_type max_length;
|
||||||
|
|
||||||
|
@ -1627,11 +1597,7 @@ bignum_pospos_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
|
max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
|
||||||
? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2);
|
? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2);
|
||||||
|
|
||||||
REGISTER_BIGNUM(arg1);
|
|
||||||
REGISTER_BIGNUM(arg2);
|
|
||||||
result = allot_bignum(max_length, 0);
|
result = allot_bignum(max_length, 0);
|
||||||
UNREGISTER_BIGNUM(arg2);
|
|
||||||
UNREGISTER_BIGNUM(arg1);
|
|
||||||
|
|
||||||
scanr = BIGNUM_START_PTR(result);
|
scanr = BIGNUM_START_PTR(result);
|
||||||
scan1 = BIGNUM_START_PTR(arg1);
|
scan1 = BIGNUM_START_PTR(arg1);
|
||||||
|
@ -1654,6 +1620,8 @@ bignum_pospos_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_posneg_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
bignum_posneg_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(arg1); GC_BIGNUM(arg2);
|
||||||
|
|
||||||
F_BIGNUM * result;
|
F_BIGNUM * result;
|
||||||
bignum_length_type max_length;
|
bignum_length_type max_length;
|
||||||
|
|
||||||
|
@ -1666,11 +1634,7 @@ bignum_posneg_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2) + 1)
|
max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2) + 1)
|
||||||
? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2) + 1;
|
? BIGNUM_LENGTH(arg1) : BIGNUM_LENGTH(arg2) + 1;
|
||||||
|
|
||||||
REGISTER_BIGNUM(arg1);
|
|
||||||
REGISTER_BIGNUM(arg2);
|
|
||||||
result = allot_bignum(max_length, neg_p);
|
result = allot_bignum(max_length, neg_p);
|
||||||
UNREGISTER_BIGNUM(arg2);
|
|
||||||
UNREGISTER_BIGNUM(arg1);
|
|
||||||
|
|
||||||
scanr = BIGNUM_START_PTR(result);
|
scanr = BIGNUM_START_PTR(result);
|
||||||
scan1 = BIGNUM_START_PTR(arg1);
|
scan1 = BIGNUM_START_PTR(arg1);
|
||||||
|
@ -1709,6 +1673,8 @@ bignum_posneg_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_negneg_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
bignum_negneg_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(arg1); GC_BIGNUM(arg2);
|
||||||
|
|
||||||
F_BIGNUM * result;
|
F_BIGNUM * result;
|
||||||
bignum_length_type max_length;
|
bignum_length_type max_length;
|
||||||
|
|
||||||
|
@ -1721,11 +1687,7 @@ bignum_negneg_bitwise_op(int op, F_BIGNUM * arg1, F_BIGNUM * arg2)
|
||||||
max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
|
max_length = (BIGNUM_LENGTH(arg1) > BIGNUM_LENGTH(arg2))
|
||||||
? BIGNUM_LENGTH(arg1) + 1 : BIGNUM_LENGTH(arg2) + 1;
|
? BIGNUM_LENGTH(arg1) + 1 : BIGNUM_LENGTH(arg2) + 1;
|
||||||
|
|
||||||
REGISTER_BIGNUM(arg1);
|
|
||||||
REGISTER_BIGNUM(arg2);
|
|
||||||
result = allot_bignum(max_length, neg_p);
|
result = allot_bignum(max_length, neg_p);
|
||||||
UNREGISTER_BIGNUM(arg2);
|
|
||||||
UNREGISTER_BIGNUM(arg1);
|
|
||||||
|
|
||||||
scanr = BIGNUM_START_PTR(result);
|
scanr = BIGNUM_START_PTR(result);
|
||||||
scan1 = BIGNUM_START_PTR(arg1);
|
scan1 = BIGNUM_START_PTR(arg1);
|
||||||
|
@ -1800,12 +1762,12 @@ bignum_negate_magnitude(F_BIGNUM * arg)
|
||||||
F_BIGNUM *
|
F_BIGNUM *
|
||||||
bignum_integer_length(F_BIGNUM * bignum)
|
bignum_integer_length(F_BIGNUM * bignum)
|
||||||
{
|
{
|
||||||
|
GC_BIGNUM(bignum);
|
||||||
|
|
||||||
bignum_length_type index = ((BIGNUM_LENGTH (bignum)) - 1);
|
bignum_length_type index = ((BIGNUM_LENGTH (bignum)) - 1);
|
||||||
bignum_digit_type digit = (BIGNUM_REF (bignum, index));
|
bignum_digit_type digit = (BIGNUM_REF (bignum, index));
|
||||||
|
|
||||||
REGISTER_BIGNUM(bignum);
|
|
||||||
F_BIGNUM * result = (allot_bignum (2, 0));
|
F_BIGNUM * result = (allot_bignum (2, 0));
|
||||||
UNREGISTER_BIGNUM(bignum);
|
|
||||||
|
|
||||||
(BIGNUM_REF (result, 0)) = index;
|
(BIGNUM_REF (result, 0)) = index;
|
||||||
(BIGNUM_REF (result, 1)) = 0;
|
(BIGNUM_REF (result, 1)) = 0;
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
static void check_frame(F_STACK_FRAME *frame)
|
static void check_frame(F_STACK_FRAME *frame)
|
||||||
{
|
{
|
||||||
#ifdef FACTOR_DEBUG
|
#ifdef FACTOR_DEBUG
|
||||||
check_code_pointer(frame->xt);
|
check_code_pointer((CELL)frame->xt);
|
||||||
assert(frame->size != 0);
|
assert(frame->size != 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,8 @@ void iterate_callstack(CELL top, CELL bottom, CALLSTACK_ITER iterator)
|
||||||
|
|
||||||
while((CELL)frame >= top)
|
while((CELL)frame >= top)
|
||||||
{
|
{
|
||||||
F_STACK_FRAME *next = frame_successor(frame);
|
|
||||||
iterator(frame);
|
iterator(frame);
|
||||||
frame = next;
|
frame = frame_successor(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
275
vm/data_gc.cpp
275
vm/data_gc.cpp
|
@ -37,8 +37,109 @@ void init_data_gc(void)
|
||||||
collecting_aging_again = false;
|
collecting_aging_again = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Given a pointer to oldspace, copy it to newspace */
|
||||||
|
static void *copy_untagged_object(void *pointer, CELL size)
|
||||||
|
{
|
||||||
|
if(newspace->here + size >= newspace->end)
|
||||||
|
longjmp(gc_jmp,1);
|
||||||
|
allot_barrier(newspace->here);
|
||||||
|
void *newpointer = allot_zone(newspace,size);
|
||||||
|
|
||||||
|
F_GC_STATS *s = &gc_stats[collecting_gen];
|
||||||
|
s->object_count++;
|
||||||
|
s->bytes_copied += size;
|
||||||
|
|
||||||
|
memcpy(newpointer,pointer,size);
|
||||||
|
return newpointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void forward_object(CELL untagged, CELL newpointer)
|
||||||
|
{
|
||||||
|
put(untagged,RETAG(newpointer,GC_COLLECTED));
|
||||||
|
}
|
||||||
|
|
||||||
|
static CELL copy_object_impl(CELL untagged)
|
||||||
|
{
|
||||||
|
CELL newpointer = (CELL)copy_untagged_object(
|
||||||
|
(void*)untagged,
|
||||||
|
untagged_object_size(untagged));
|
||||||
|
forward_object(untagged,newpointer);
|
||||||
|
return newpointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool should_copy_p(CELL untagged)
|
||||||
|
{
|
||||||
|
if(in_zone(newspace,untagged))
|
||||||
|
return false;
|
||||||
|
if(collecting_gen == TENURED)
|
||||||
|
return true;
|
||||||
|
else if(HAVE_AGING_P && collecting_gen == AGING)
|
||||||
|
return !in_zone(&data_heap->generations[TENURED],untagged);
|
||||||
|
else if(collecting_gen == NURSERY)
|
||||||
|
return in_zone(&nursery,untagged);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
critical_error("Bug in should_copy_p",untagged);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Follow a chain of forwarding pointers */
|
||||||
|
static CELL resolve_forwarding(CELL untagged, CELL tag)
|
||||||
|
{
|
||||||
|
check_data_pointer(untagged);
|
||||||
|
|
||||||
|
CELL header = get(untagged);
|
||||||
|
/* another forwarding pointer */
|
||||||
|
if(TAG(header) == GC_COLLECTED)
|
||||||
|
return resolve_forwarding(UNTAG(header),tag);
|
||||||
|
/* we've found the destination */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
check_header(header);
|
||||||
|
CELL pointer = RETAG(untagged,tag);
|
||||||
|
if(should_copy_p(untagged))
|
||||||
|
pointer = RETAG(copy_object_impl(untagged),tag);
|
||||||
|
return pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Given a pointer to a tagged pointer to oldspace, copy it to newspace.
|
||||||
|
If the object has already been copied, return the forwarding
|
||||||
|
pointer address without copying anything; otherwise, install
|
||||||
|
a new forwarding pointer. While this preserves the tag, it does
|
||||||
|
not dispatch on it in any way. */
|
||||||
|
static CELL copy_object(CELL pointer)
|
||||||
|
{
|
||||||
|
check_data_pointer(pointer);
|
||||||
|
|
||||||
|
CELL tag = TAG(pointer);
|
||||||
|
CELL untagged = UNTAG(pointer);
|
||||||
|
CELL header = get(untagged);
|
||||||
|
|
||||||
|
if(TAG(header) == GC_COLLECTED)
|
||||||
|
return resolve_forwarding(UNTAG(header),tag);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
check_header(header);
|
||||||
|
return RETAG(copy_object_impl(untagged),tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_handle(CELL *handle)
|
||||||
|
{
|
||||||
|
CELL pointer = *handle;
|
||||||
|
|
||||||
|
if(!immediate_p(pointer))
|
||||||
|
{
|
||||||
|
check_data_pointer(pointer);
|
||||||
|
if(should_copy_p(pointer))
|
||||||
|
*handle = copy_object(pointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Scan all the objects in the card */
|
/* Scan all the objects in the card */
|
||||||
void copy_card(F_CARD *ptr, CELL gen, CELL here)
|
static void copy_card(F_CARD *ptr, CELL gen, CELL here)
|
||||||
{
|
{
|
||||||
CELL card_scan = (CELL)CARD_TO_ADDR(ptr) + CARD_OFFSET(ptr);
|
CELL card_scan = (CELL)CARD_TO_ADDR(ptr) + CARD_OFFSET(ptr);
|
||||||
CELL card_end = (CELL)CARD_TO_ADDR(ptr + 1);
|
CELL card_end = (CELL)CARD_TO_ADDR(ptr + 1);
|
||||||
|
@ -51,7 +152,7 @@ void copy_card(F_CARD *ptr, CELL gen, CELL here)
|
||||||
cards_scanned++;
|
cards_scanned++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_card_deck(F_DECK *deck, CELL gen, F_CARD mask, F_CARD unmask)
|
static void copy_card_deck(F_DECK *deck, CELL gen, F_CARD mask, F_CARD unmask)
|
||||||
{
|
{
|
||||||
F_CARD *first_card = DECK_TO_CARD(deck);
|
F_CARD *first_card = DECK_TO_CARD(deck);
|
||||||
F_CARD *last_card = DECK_TO_CARD(deck + 1);
|
F_CARD *last_card = DECK_TO_CARD(deck + 1);
|
||||||
|
@ -83,7 +184,7 @@ void copy_card_deck(F_DECK *deck, CELL gen, F_CARD mask, F_CARD unmask)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy all newspace objects referenced from marked cards to the destination */
|
/* Copy all newspace objects referenced from marked cards to the destination */
|
||||||
void copy_gen_cards(CELL gen)
|
static void copy_gen_cards(CELL gen)
|
||||||
{
|
{
|
||||||
F_DECK *first_deck = ADDR_TO_DECK(data_heap->generations[gen].start);
|
F_DECK *first_deck = ADDR_TO_DECK(data_heap->generations[gen].start);
|
||||||
F_DECK *last_deck = ADDR_TO_DECK(data_heap->generations[gen].end);
|
F_DECK *last_deck = ADDR_TO_DECK(data_heap->generations[gen].end);
|
||||||
|
@ -150,7 +251,7 @@ void copy_gen_cards(CELL gen)
|
||||||
|
|
||||||
/* Scan cards in all generations older than the one being collected, copying
|
/* Scan cards in all generations older than the one being collected, copying
|
||||||
old->new references */
|
old->new references */
|
||||||
void copy_cards(void)
|
static void copy_cards(void)
|
||||||
{
|
{
|
||||||
u64 start = current_micros();
|
u64 start = current_micros();
|
||||||
|
|
||||||
|
@ -162,7 +263,7 @@ void copy_cards(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy all tagged pointers in a range of memory */
|
/* Copy all tagged pointers in a range of memory */
|
||||||
void copy_stack_elements(F_SEGMENT *region, CELL top)
|
static void copy_stack_elements(F_SEGMENT *region, CELL top)
|
||||||
{
|
{
|
||||||
CELL ptr = region->start;
|
CELL ptr = region->start;
|
||||||
|
|
||||||
|
@ -170,17 +271,38 @@ void copy_stack_elements(F_SEGMENT *region, CELL top)
|
||||||
copy_handle((CELL*)ptr);
|
copy_handle((CELL*)ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_registered_locals(void)
|
static void copy_registered_locals(void)
|
||||||
{
|
{
|
||||||
CELL ptr = gc_locals_region->start;
|
CELL scan = gc_locals_region->start;
|
||||||
|
|
||||||
for(; ptr <= gc_locals; ptr += CELLS)
|
for(; scan <= gc_locals; scan += CELLS)
|
||||||
copy_handle(*(CELL **)ptr);
|
copy_handle(*(CELL **)scan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copy_registered_bignums(void)
|
||||||
|
{
|
||||||
|
CELL scan = gc_bignums_region->start;
|
||||||
|
|
||||||
|
for(; scan <= gc_bignums; scan += CELLS)
|
||||||
|
{
|
||||||
|
CELL *handle = *(CELL **)scan;
|
||||||
|
CELL pointer = *handle;
|
||||||
|
|
||||||
|
if(pointer)
|
||||||
|
{
|
||||||
|
check_data_pointer(pointer);
|
||||||
|
if(should_copy_p(pointer))
|
||||||
|
*handle = copy_object(pointer);
|
||||||
|
#ifdef FACTOR_DEBUG
|
||||||
|
assert(hi_tag(*handle) == BIGNUM_TYPE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy roots over at the start of GC, namely various constants, stacks,
|
/* Copy roots over at the start of GC, namely various constants, stacks,
|
||||||
the user environment and extra roots registered by local_roots.hpp */
|
the user environment and extra roots registered by local_roots.hpp */
|
||||||
void copy_roots(void)
|
static void copy_roots(void)
|
||||||
{
|
{
|
||||||
copy_handle(&T);
|
copy_handle(&T);
|
||||||
copy_handle(&bignum_zero);
|
copy_handle(&bignum_zero);
|
||||||
|
@ -188,7 +310,7 @@ void copy_roots(void)
|
||||||
copy_handle(&bignum_neg_one);
|
copy_handle(&bignum_neg_one);
|
||||||
|
|
||||||
copy_registered_locals();
|
copy_registered_locals();
|
||||||
copy_stack_elements(extra_roots_region,extra_roots);
|
copy_registered_bignums();
|
||||||
|
|
||||||
if(!performing_compaction)
|
if(!performing_compaction)
|
||||||
{
|
{
|
||||||
|
@ -214,107 +336,7 @@ void copy_roots(void)
|
||||||
copy_handle(&userenv[i]);
|
copy_handle(&userenv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given a pointer to oldspace, copy it to newspace */
|
static CELL copy_next_from_nursery(CELL scan)
|
||||||
INLINE void *copy_untagged_object(void *pointer, CELL size)
|
|
||||||
{
|
|
||||||
if(newspace->here + size >= newspace->end)
|
|
||||||
longjmp(gc_jmp,1);
|
|
||||||
allot_barrier(newspace->here);
|
|
||||||
void *newpointer = allot_zone(newspace,size);
|
|
||||||
|
|
||||||
F_GC_STATS *s = &gc_stats[collecting_gen];
|
|
||||||
s->object_count++;
|
|
||||||
s->bytes_copied += size;
|
|
||||||
|
|
||||||
memcpy(newpointer,pointer,size);
|
|
||||||
return newpointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE void forward_object(CELL pointer, CELL newpointer)
|
|
||||||
{
|
|
||||||
if(pointer != newpointer)
|
|
||||||
put(UNTAG(pointer),RETAG(newpointer,GC_COLLECTED));
|
|
||||||
}
|
|
||||||
|
|
||||||
INLINE CELL copy_object_impl(CELL pointer)
|
|
||||||
{
|
|
||||||
CELL newpointer = (CELL)copy_untagged_object(
|
|
||||||
(void*)UNTAG(pointer),
|
|
||||||
object_size(pointer));
|
|
||||||
forward_object(pointer,newpointer);
|
|
||||||
return newpointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool should_copy_p(CELL untagged)
|
|
||||||
{
|
|
||||||
if(in_zone(newspace,untagged))
|
|
||||||
return false;
|
|
||||||
if(collecting_gen == TENURED)
|
|
||||||
return true;
|
|
||||||
else if(HAVE_AGING_P && collecting_gen == AGING)
|
|
||||||
return !in_zone(&data_heap->generations[TENURED],untagged);
|
|
||||||
else if(collecting_gen == NURSERY)
|
|
||||||
return in_zone(&nursery,untagged);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
critical_error("Bug in should_copy_p",untagged);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Follow a chain of forwarding pointers */
|
|
||||||
CELL resolve_forwarding(CELL untagged, CELL tag)
|
|
||||||
{
|
|
||||||
check_data_pointer(untagged);
|
|
||||||
|
|
||||||
CELL header = get(untagged);
|
|
||||||
/* another forwarding pointer */
|
|
||||||
if(TAG(header) == GC_COLLECTED)
|
|
||||||
return resolve_forwarding(UNTAG(header),tag);
|
|
||||||
/* we've found the destination */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
check_header(header);
|
|
||||||
CELL pointer = RETAG(untagged,tag);
|
|
||||||
if(should_copy_p(untagged))
|
|
||||||
pointer = RETAG(copy_object_impl(pointer),tag);
|
|
||||||
return pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Given a pointer to a tagged pointer to oldspace, copy it to newspace.
|
|
||||||
If the object has already been copied, return the forwarding
|
|
||||||
pointer address without copying anything; otherwise, install
|
|
||||||
a new forwarding pointer. */
|
|
||||||
INLINE CELL copy_object(CELL pointer)
|
|
||||||
{
|
|
||||||
check_data_pointer(pointer);
|
|
||||||
|
|
||||||
CELL tag = TAG(pointer);
|
|
||||||
CELL header = get(UNTAG(pointer));
|
|
||||||
|
|
||||||
if(TAG(header) == GC_COLLECTED)
|
|
||||||
return resolve_forwarding(UNTAG(header),tag);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
check_header(header);
|
|
||||||
return RETAG(copy_object_impl(pointer),tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_handle(CELL *handle)
|
|
||||||
{
|
|
||||||
CELL pointer = *handle;
|
|
||||||
|
|
||||||
if(!immediate_p(pointer))
|
|
||||||
{
|
|
||||||
check_data_pointer(pointer);
|
|
||||||
if(should_copy_p(pointer))
|
|
||||||
*handle = copy_object(pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CELL copy_next_from_nursery(CELL scan)
|
|
||||||
{
|
{
|
||||||
CELL *obj = (CELL *)scan;
|
CELL *obj = (CELL *)scan;
|
||||||
CELL *end = (CELL *)(scan + binary_payload_start(scan));
|
CELL *end = (CELL *)(scan + binary_payload_start(scan));
|
||||||
|
@ -342,7 +364,7 @@ CELL copy_next_from_nursery(CELL scan)
|
||||||
return scan + untagged_object_size(scan);
|
return scan + untagged_object_size(scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
CELL copy_next_from_aging(CELL scan)
|
static CELL copy_next_from_aging(CELL scan)
|
||||||
{
|
{
|
||||||
CELL *obj = (CELL *)scan;
|
CELL *obj = (CELL *)scan;
|
||||||
CELL *end = (CELL *)(scan + binary_payload_start(scan));
|
CELL *end = (CELL *)(scan + binary_payload_start(scan));
|
||||||
|
@ -374,7 +396,7 @@ CELL copy_next_from_aging(CELL scan)
|
||||||
return scan + untagged_object_size(scan);
|
return scan + untagged_object_size(scan);
|
||||||
}
|
}
|
||||||
|
|
||||||
CELL copy_next_from_tenured(CELL scan)
|
static CELL copy_next_from_tenured(CELL scan)
|
||||||
{
|
{
|
||||||
CELL *obj = (CELL *)scan;
|
CELL *obj = (CELL *)scan;
|
||||||
CELL *end = (CELL *)(scan + binary_payload_start(scan));
|
CELL *end = (CELL *)(scan + binary_payload_start(scan));
|
||||||
|
@ -424,7 +446,7 @@ void copy_reachable_objects(CELL scan, CELL *end)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prepare to start copying reachable objects into an unused zone */
|
/* Prepare to start copying reachable objects into an unused zone */
|
||||||
void begin_gc(CELL requested_bytes)
|
static void begin_gc(CELL requested_bytes)
|
||||||
{
|
{
|
||||||
if(growing_data_heap)
|
if(growing_data_heap)
|
||||||
{
|
{
|
||||||
|
@ -457,7 +479,7 @@ void begin_gc(CELL requested_bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_gc(CELL gc_elapsed)
|
static void end_gc(CELL gc_elapsed)
|
||||||
{
|
{
|
||||||
F_GC_STATS *s = &gc_stats[collecting_gen];
|
F_GC_STATS *s = &gc_stats[collecting_gen];
|
||||||
|
|
||||||
|
@ -604,19 +626,19 @@ void primitive_gc_stats(void)
|
||||||
{
|
{
|
||||||
F_GC_STATS *s = &gc_stats[i];
|
F_GC_STATS *s = &gc_stats[i];
|
||||||
stats.add(allot_cell(s->collections));
|
stats.add(allot_cell(s->collections));
|
||||||
stats.add(tag_bignum(long_long_to_bignum(s->gc_time)));
|
stats.add(tag<F_BIGNUM>(long_long_to_bignum(s->gc_time)));
|
||||||
stats.add(tag_bignum(long_long_to_bignum(s->max_gc_time)));
|
stats.add(tag<F_BIGNUM>(long_long_to_bignum(s->max_gc_time)));
|
||||||
stats.add(allot_cell(s->collections == 0 ? 0 : s->gc_time / s->collections));
|
stats.add(allot_cell(s->collections == 0 ? 0 : s->gc_time / s->collections));
|
||||||
stats.add(allot_cell(s->object_count));
|
stats.add(allot_cell(s->object_count));
|
||||||
stats.add(tag_bignum(long_long_to_bignum(s->bytes_copied)));
|
stats.add(tag<F_BIGNUM>(long_long_to_bignum(s->bytes_copied)));
|
||||||
|
|
||||||
total_gc_time += s->gc_time;
|
total_gc_time += s->gc_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
stats.add(tag_bignum(ulong_long_to_bignum(total_gc_time)));
|
stats.add(tag<F_BIGNUM>(ulong_long_to_bignum(total_gc_time)));
|
||||||
stats.add(tag_bignum(ulong_long_to_bignum(cards_scanned)));
|
stats.add(tag<F_BIGNUM>(ulong_long_to_bignum(cards_scanned)));
|
||||||
stats.add(tag_bignum(ulong_long_to_bignum(decks_scanned)));
|
stats.add(tag<F_BIGNUM>(ulong_long_to_bignum(decks_scanned)));
|
||||||
stats.add(tag_bignum(ulong_long_to_bignum(card_scan_time)));
|
stats.add(tag<F_BIGNUM>(ulong_long_to_bignum(card_scan_time)));
|
||||||
stats.add(allot_cell(code_heap_scans));
|
stats.add(allot_cell(code_heap_scans));
|
||||||
|
|
||||||
stats.trim();
|
stats.trim();
|
||||||
|
@ -644,8 +666,8 @@ void primitive_clear_gc_stats(void)
|
||||||
to coalesce equal but distinct quotations and wrappers. */
|
to coalesce equal but distinct quotations and wrappers. */
|
||||||
void primitive_become(void)
|
void primitive_become(void)
|
||||||
{
|
{
|
||||||
F_ARRAY *new_objects = untag_array(dpop());
|
F_ARRAY *new_objects = untag_check<F_ARRAY>(dpop());
|
||||||
F_ARRAY *old_objects = untag_array(dpop());
|
F_ARRAY *old_objects = untag_check<F_ARRAY>(dpop());
|
||||||
|
|
||||||
CELL capacity = array_capacity(new_objects);
|
CELL capacity = array_capacity(new_objects);
|
||||||
if(capacity != array_capacity(old_objects))
|
if(capacity != array_capacity(old_objects))
|
||||||
|
@ -658,7 +680,8 @@ void primitive_become(void)
|
||||||
CELL old_obj = array_nth(old_objects,i);
|
CELL old_obj = array_nth(old_objects,i);
|
||||||
CELL new_obj = array_nth(new_objects,i);
|
CELL new_obj = array_nth(new_objects,i);
|
||||||
|
|
||||||
forward_object(old_obj,new_obj);
|
if(old_obj != new_obj)
|
||||||
|
forward_object(UNTAG(old_obj),new_obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
gc();
|
gc();
|
||||||
|
|
159
vm/data_gc.h
159
vm/data_gc.h
|
@ -1,159 +0,0 @@
|
||||||
void gc(void);
|
|
||||||
DLLEXPORT void minor_gc(void);
|
|
||||||
|
|
||||||
/* used during garbage collection only */
|
|
||||||
|
|
||||||
F_ZONE *newspace;
|
|
||||||
bool performing_gc;
|
|
||||||
bool performing_compaction;
|
|
||||||
CELL collecting_gen;
|
|
||||||
|
|
||||||
/* if true, we collecting AGING space for the second time, so if it is still
|
|
||||||
full, we go on to collect TENURED */
|
|
||||||
bool collecting_aging_again;
|
|
||||||
|
|
||||||
/* in case a generation fills up in the middle of a gc, we jump back
|
|
||||||
up to try collecting the next generation. */
|
|
||||||
jmp_buf gc_jmp;
|
|
||||||
|
|
||||||
/* statistics */
|
|
||||||
typedef struct {
|
|
||||||
CELL collections;
|
|
||||||
u64 gc_time;
|
|
||||||
u64 max_gc_time;
|
|
||||||
CELL object_count;
|
|
||||||
u64 bytes_copied;
|
|
||||||
} F_GC_STATS;
|
|
||||||
|
|
||||||
F_GC_STATS gc_stats[MAX_GEN_COUNT];
|
|
||||||
u64 cards_scanned;
|
|
||||||
u64 decks_scanned;
|
|
||||||
u64 card_scan_time;
|
|
||||||
CELL code_heap_scans;
|
|
||||||
|
|
||||||
/* What generation was being collected when copy_code_heap_roots() was last
|
|
||||||
called? Until the next call to add_code_block(), future
|
|
||||||
collections of younger generations don't have to touch the code
|
|
||||||
heap. */
|
|
||||||
CELL last_code_heap_scan;
|
|
||||||
|
|
||||||
/* sometimes we grow the heap */
|
|
||||||
bool growing_data_heap;
|
|
||||||
F_DATA_HEAP *old_data_heap;
|
|
||||||
|
|
||||||
INLINE bool collecting_accumulation_gen_p(void)
|
|
||||||
{
|
|
||||||
return ((HAVE_AGING_P
|
|
||||||
&& collecting_gen == AGING
|
|
||||||
&& !collecting_aging_again)
|
|
||||||
|| collecting_gen == TENURED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* test if the pointer is in generation being collected, or a younger one. */
|
|
||||||
INLINE bool should_copy(CELL untagged)
|
|
||||||
{
|
|
||||||
if(in_zone(newspace,untagged))
|
|
||||||
return false;
|
|
||||||
if(collecting_gen == TENURED)
|
|
||||||
return true;
|
|
||||||
else if(HAVE_AGING_P && collecting_gen == AGING)
|
|
||||||
return !in_zone(&data_heap->generations[TENURED],untagged);
|
|
||||||
else if(collecting_gen == NURSERY)
|
|
||||||
return in_zone(&nursery,untagged);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
critical_error("Bug in should_copy",untagged);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_handle(CELL *handle);
|
|
||||||
|
|
||||||
void garbage_collection(volatile CELL gen,
|
|
||||||
bool growing_data_heap_,
|
|
||||||
CELL requested_bytes);
|
|
||||||
|
|
||||||
/* We leave this many bytes free at the top of the nursery so that inline
|
|
||||||
allocation (which does not call GC because of possible roots in volatile
|
|
||||||
registers) does not run out of memory */
|
|
||||||
#define ALLOT_BUFFER_ZONE 1024
|
|
||||||
|
|
||||||
/* If this is defined, we GC every allocation. This catches missing local roots */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It is up to the caller to fill in the object's fields in a meaningful
|
|
||||||
* fashion!
|
|
||||||
*/
|
|
||||||
|
|
||||||
INLINE void *allot_object(CELL type, CELL a)
|
|
||||||
{
|
|
||||||
#ifdef GC_DEBUG
|
|
||||||
if(!gc_off)
|
|
||||||
gc();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CELL *object;
|
|
||||||
|
|
||||||
if(nursery.size - ALLOT_BUFFER_ZONE > a)
|
|
||||||
{
|
|
||||||
/* If there is insufficient room, collect the nursery */
|
|
||||||
if(nursery.here + ALLOT_BUFFER_ZONE + a > nursery.end)
|
|
||||||
garbage_collection(NURSERY,false,0);
|
|
||||||
|
|
||||||
CELL h = nursery.here;
|
|
||||||
nursery.here = h + align8(a);
|
|
||||||
object = (CELL*)h;
|
|
||||||
}
|
|
||||||
/* If the object is bigger than the nursery, allocate it in
|
|
||||||
tenured space */
|
|
||||||
else
|
|
||||||
{
|
|
||||||
F_ZONE *tenured = &data_heap->generations[TENURED];
|
|
||||||
|
|
||||||
/* If tenured space does not have enough room, collect */
|
|
||||||
if(tenured->here + a > tenured->end)
|
|
||||||
{
|
|
||||||
gc();
|
|
||||||
tenured = &data_heap->generations[TENURED];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If it still won't fit, grow the heap */
|
|
||||||
if(tenured->here + a > tenured->end)
|
|
||||||
{
|
|
||||||
garbage_collection(TENURED,true,a);
|
|
||||||
tenured = &data_heap->generations[TENURED];
|
|
||||||
}
|
|
||||||
|
|
||||||
object = (CELL *)allot_zone(tenured,a);
|
|
||||||
|
|
||||||
/* We have to do this */
|
|
||||||
allot_barrier((CELL)object);
|
|
||||||
|
|
||||||
/* Allows initialization code to store old->new pointers
|
|
||||||
without hitting the write barrier in the common case of
|
|
||||||
a nursery allocation */
|
|
||||||
write_barrier((CELL)object);
|
|
||||||
}
|
|
||||||
|
|
||||||
*object = tag_header(type);
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
void copy_reachable_objects(CELL scan, CELL *end);
|
|
||||||
|
|
||||||
void primitive_gc(void);
|
|
||||||
void primitive_gc_stats(void);
|
|
||||||
void clear_gc_stats(void);
|
|
||||||
void primitive_clear_gc_stats(void);
|
|
||||||
void primitive_become(void);
|
|
||||||
|
|
||||||
INLINE void check_data_pointer(CELL pointer)
|
|
||||||
{
|
|
||||||
#ifdef FACTOR_DEBUG
|
|
||||||
if(!growing_data_heap)
|
|
||||||
{
|
|
||||||
assert(pointer >= data_heap->segment->start
|
|
||||||
&& pointer < data_heap->segment->end);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
|
@ -28,9 +28,6 @@ INLINE bool collecting_accumulation_gen_p(void)
|
||||||
|
|
||||||
extern CELL last_code_heap_scan;
|
extern CELL last_code_heap_scan;
|
||||||
|
|
||||||
/* test if the pointer is in generation being collected, or a younger one. */
|
|
||||||
bool should_copy_p(CELL untagged);
|
|
||||||
|
|
||||||
void copy_handle(CELL *handle);
|
void copy_handle(CELL *handle);
|
||||||
|
|
||||||
void garbage_collection(volatile CELL gen,
|
void garbage_collection(volatile CELL gen,
|
||||||
|
|
|
@ -224,7 +224,7 @@ CELL unaligned_object_size(CELL pointer)
|
||||||
case STRING_TYPE:
|
case STRING_TYPE:
|
||||||
return string_size(string_capacity((F_STRING*)pointer));
|
return string_size(string_capacity((F_STRING*)pointer));
|
||||||
case TUPLE_TYPE:
|
case TUPLE_TYPE:
|
||||||
tuple = untag<F_TUPLE>(pointer);
|
tuple = (F_TUPLE *)pointer;
|
||||||
layout = untag<F_TUPLE_LAYOUT>(tuple->layout);
|
layout = untag<F_TUPLE_LAYOUT>(tuple->layout);
|
||||||
return tuple_size(layout);
|
return tuple_size(layout);
|
||||||
case QUOTATION_TYPE:
|
case QUOTATION_TYPE:
|
||||||
|
@ -284,7 +284,7 @@ CELL binary_payload_start(CELL pointer)
|
||||||
case ARRAY_TYPE:
|
case ARRAY_TYPE:
|
||||||
return array_size<F_ARRAY>(array_capacity((F_ARRAY*)pointer));
|
return array_size<F_ARRAY>(array_capacity((F_ARRAY*)pointer));
|
||||||
case TUPLE_TYPE:
|
case TUPLE_TYPE:
|
||||||
tuple = untag<F_TUPLE>(pointer);
|
tuple = (F_TUPLE *)pointer;
|
||||||
layout = untag<F_TUPLE_LAYOUT>(tuple->layout);
|
layout = untag<F_TUPLE_LAYOUT>(tuple->layout);
|
||||||
return tuple_size(layout);
|
return tuple_size(layout);
|
||||||
case WRAPPER_TYPE:
|
case WRAPPER_TYPE:
|
||||||
|
|
|
@ -113,7 +113,6 @@ void memory_protection_error(CELL addr, F_STACK_FRAME *native_stack)
|
||||||
general_error(ERROR_RS_OVERFLOW,F,F,native_stack);
|
general_error(ERROR_RS_OVERFLOW,F,F,native_stack);
|
||||||
else if(in_page(addr, nursery.end, 0, 0))
|
else if(in_page(addr, nursery.end, 0, 0))
|
||||||
critical_error("allot_object() missed GC check",0);
|
critical_error("allot_object() missed GC check",0);
|
||||||
else if(in_page(addr, gc_locals_region->start, 0, -1))
|
|
||||||
else
|
else
|
||||||
general_error(ERROR_MEMORY,allot_cell(addr),F,native_stack);
|
general_error(ERROR_MEMORY,allot_cell(addr),F,native_stack);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
F_SEGMENT *gc_locals_region;
|
F_SEGMENT *gc_locals_region;
|
||||||
CELL gc_locals;
|
CELL gc_locals;
|
||||||
|
|
||||||
F_SEGMENT *extra_roots_region;
|
F_SEGMENT *gc_bignums_region;
|
||||||
CELL extra_roots;
|
CELL gc_bignums;
|
||||||
|
|
|
@ -20,12 +20,18 @@ struct gc_root : public tagged<T>
|
||||||
~gc_root() { CELL old = gc_local_pop(); assert(old == (CELL)this); }
|
~gc_root() { CELL old = gc_local_pop(); assert(old == (CELL)this); }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Extra roots: stores pointers to objects in the heap. Requires extra work
|
/* A similar hack for the bignum implementation */
|
||||||
(you have to unregister before accessing the object) but more flexible. */
|
extern F_SEGMENT *gc_bignums_region;
|
||||||
extern F_SEGMENT *extra_roots_region;
|
extern CELL gc_bignums;
|
||||||
extern CELL extra_roots;
|
|
||||||
|
|
||||||
DEFPUSHPOP(root_,extra_roots)
|
DEFPUSHPOP(gc_bignum_,gc_bignums)
|
||||||
|
|
||||||
#define REGISTER_BIGNUM(obj) if(obj) root_push(tag_bignum(obj))
|
struct gc_bignum
|
||||||
#define UNREGISTER_BIGNUM(obj) if(obj) obj = (untag_bignum_fast(root_pop()))
|
{
|
||||||
|
F_BIGNUM **addr;
|
||||||
|
|
||||||
|
gc_bignum(F_BIGNUM **addr_) : addr(addr_) { if(*addr_) check_data_pointer((CELL)*addr_); gc_bignum_push((CELL)addr); }
|
||||||
|
~gc_bignum() { assert((CELL)addr == gc_bignum_pop()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GC_BIGNUM(x) gc_bignum x##__gc_root(&x)
|
||||||
|
|
|
@ -51,9 +51,9 @@ F_FASTCALL void overflow_fixnum_subtract(F_FIXNUM x, F_FIXNUM y)
|
||||||
F_FASTCALL void overflow_fixnum_multiply(F_FIXNUM x, F_FIXNUM y)
|
F_FASTCALL void overflow_fixnum_multiply(F_FIXNUM x, F_FIXNUM y)
|
||||||
{
|
{
|
||||||
F_BIGNUM *bx = fixnum_to_bignum(x);
|
F_BIGNUM *bx = fixnum_to_bignum(x);
|
||||||
REGISTER_BIGNUM(bx);
|
GC_BIGNUM(bx);
|
||||||
F_BIGNUM *by = fixnum_to_bignum(y);
|
F_BIGNUM *by = fixnum_to_bignum(y);
|
||||||
UNREGISTER_BIGNUM(bx);
|
GC_BIGNUM(by);
|
||||||
drepl(tag<F_BIGNUM>(bignum_multiply(bx,by)));
|
drepl(tag<F_BIGNUM>(bignum_multiply(bx,by)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue