switching GC from semi-space copying to mark-sweep
This commit is contained in:
		
							
								
								
									
										224
									
								
								hcl/lib/bigint.c
									
									
									
									
									
								
							
							
						
						
									
										224
									
								
								hcl/lib/bigint.c
									
									
									
									
									
								
							| @ -679,9 +679,9 @@ static HCL_INLINE hcl_oop_t expand_bigint (hcl_t* hcl, hcl_oop_t oop, hcl_oow_t | |||||||
| 		return HCL_NULL; | 		return HCL_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &oop); | 	hcl_pushvolat (hcl, &oop); | ||||||
| 	z = hcl_makebigint(hcl, HCL_OBJ_GET_FLAGS_BRAND(oop), HCL_NULL, count + inc); | 	z = hcl_makebigint(hcl, HCL_OBJ_GET_FLAGS_BRAND(oop), HCL_NULL, count + inc); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 	for (i = 0; i < count; i++) | 	for (i = 0; i < count; i++) | ||||||
| @ -699,9 +699,9 @@ static HCL_INLINE hcl_oop_t _clone_bigint (hcl_t* hcl, hcl_oop_t oop, hcl_oow_t | |||||||
| 	HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop)); | 	HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop)); | ||||||
| 	if (count <= 0) count = HCL_OBJ_GET_SIZE(oop); | 	if (count <= 0) count = HCL_OBJ_GET_SIZE(oop); | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &oop); | 	hcl_pushvolat (hcl, &oop); | ||||||
| 	z = hcl_makebigint(hcl, brand, HCL_NULL, count); | 	z = hcl_makebigint(hcl, brand, HCL_NULL, count); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 	for (i = 0; i < count; i++) | 	for (i = 0; i < count; i++) | ||||||
| @ -2044,10 +2044,10 @@ static hcl_oop_t add_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 	} | 	} | ||||||
| 	zs++; | 	zs++; | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &x); | 	hcl_pushvolat (hcl, &x); | ||||||
| 	hcl_pushtmp (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = hcl_makebigint(hcl, HCL_OBJ_GET_FLAGS_BRAND(x), HCL_NULL, zs); | 	z = hcl_makebigint(hcl, HCL_OBJ_GET_FLAGS_BRAND(x), HCL_NULL, zs); | ||||||
| 	hcl_poptmps (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 	add_unsigned_array ( | 	add_unsigned_array ( | ||||||
| @ -2065,10 +2065,10 @@ static hcl_oop_t subtract_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t | |||||||
|  |  | ||||||
| 	HCL_ASSERT (hcl, !is_less_unsigned(x, y)); | 	HCL_ASSERT (hcl, !is_less_unsigned(x, y)); | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &x); | 	hcl_pushvolat (hcl, &x); | ||||||
| 	hcl_pushtmp (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, HCL_OBJ_GET_SIZE(x)); | 	z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, HCL_OBJ_GET_SIZE(x)); | ||||||
| 	hcl_poptmps (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 	subtract_unsigned_array (hcl,  | 	subtract_unsigned_array (hcl,  | ||||||
| @ -2092,10 +2092,10 @@ static hcl_oop_t multiply_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t | |||||||
| 		return HCL_NULL; | 		return HCL_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &x); | 	hcl_pushvolat (hcl, &x); | ||||||
| 	hcl_pushtmp (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, xs + ys); | 	z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, xs + ys); | ||||||
| 	hcl_poptmps (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| #if defined(HCL_ENABLE_KARATSUBA) | #if defined(HCL_ENABLE_KARATSUBA) | ||||||
| @ -2129,9 +2129,9 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
| 		rr = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | 		rr = clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
| 		if (!rr) return HCL_NULL; | 		if (!rr) return HCL_NULL; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &rr); | 		hcl_pushvolat (hcl, &rr); | ||||||
| 		qq = make_bigint_with_ooi(hcl, 0); /* TODO: inefficient. no need to create a bigint object for zero. */ | 		qq = make_bigint_with_ooi(hcl, 0); /* TODO: inefficient. no need to create a bigint object for zero. */ | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
|  |  | ||||||
| 		if (qq) *r = rr; | 		if (qq) *r = rr; | ||||||
| 		return qq; | 		return qq; | ||||||
| @ -2141,9 +2141,9 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
| 		rr = make_bigint_with_ooi(hcl, 0); /* TODO: inefficient. no need to create a bigint object for zero. */ | 		rr = make_bigint_with_ooi(hcl, 0); /* TODO: inefficient. no need to create a bigint object for zero. */ | ||||||
| 		if (!rr) return HCL_NULL; | 		if (!rr) return HCL_NULL; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &rr); | 		hcl_pushvolat (hcl, &rr); | ||||||
| 		qq = make_bigint_with_ooi(hcl, 1); /* TODO: inefficient. no need to create a bigint object for zero. */ | 		qq = make_bigint_with_ooi(hcl, 1); /* TODO: inefficient. no need to create a bigint object for zero. */ | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
|  |  | ||||||
| 		if (qq) *r = rr; | 		if (qq) *r = rr; | ||||||
| 		return qq; | 		return qq; | ||||||
| @ -2151,8 +2151,8 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
|  |  | ||||||
| 	/* the caller must ensure that x >= y */ | 	/* the caller must ensure that x >= y */ | ||||||
| 	HCL_ASSERT (hcl, !is_less_unsigned(x, y));  | 	HCL_ASSERT (hcl, !is_less_unsigned(x, y));  | ||||||
| 	hcl_pushtmp (hcl, &x); | 	hcl_pushvolat (hcl, &x); | ||||||
| 	hcl_pushtmp (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
|  |  | ||||||
| #define USE_DIVIDE_UNSIGNED_ARRAY2 | #define USE_DIVIDE_UNSIGNED_ARRAY2 | ||||||
| /*#define USE_DIVIDE_UNSIGNED_ARRAY3*/ | /*#define USE_DIVIDE_UNSIGNED_ARRAY3*/ | ||||||
| @ -2166,11 +2166,11 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
| #endif | #endif | ||||||
| 	if (!qq)  | 	if (!qq)  | ||||||
| 	{ | 	{ | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		return HCL_NULL; | 		return HCL_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &qq); | 	hcl_pushvolat (hcl, &qq); | ||||||
| #if defined(USE_DIVIDE_UNSIGNED_ARRAY3) | #if defined(USE_DIVIDE_UNSIGNED_ARRAY3) | ||||||
| 	rr = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, HCL_OBJ_GET_SIZE(y)); | 	rr = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, HCL_OBJ_GET_SIZE(y)); | ||||||
| #elif defined(USE_DIVIDE_UNSIGNED_ARRAY2) | #elif defined(USE_DIVIDE_UNSIGNED_ARRAY2) | ||||||
| @ -2178,7 +2178,7 @@ static hcl_oop_t divide_unsigned_integers (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, | |||||||
| #else | #else | ||||||
| 	rr = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, HCL_OBJ_GET_SIZE(y) + 1); | 	rr = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, HCL_OBJ_GET_SIZE(y) + 1); | ||||||
| #endif | #endif | ||||||
| 	hcl_poptmps (hcl, 3); | 	hcl_popvolats (hcl, 3); | ||||||
| 	if (!rr) return HCL_NULL; | 	if (!rr) return HCL_NULL; | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -2228,9 +2228,9 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			v = HCL_OOP_TO_SMOOI(x); | 			v = HCL_OOP_TO_SMOOI(x); | ||||||
| 			if (v == 0) return clone_bigint (hcl, y, HCL_OBJ_GET_SIZE(y)); | 			if (v == 0) return clone_bigint (hcl, y, HCL_OBJ_GET_SIZE(y)); | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi (hcl, v); | 			x = make_bigint_with_ooi (hcl, v); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (!x) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else if (HCL_OOP_IS_SMOOI(y)) | 		else if (HCL_OOP_IS_SMOOI(y)) | ||||||
| @ -2240,9 +2240,9 @@ hcl_oop_t hcl_addints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			v = HCL_OOP_TO_SMOOI(y); | 			v = HCL_OOP_TO_SMOOI(y); | ||||||
| 			if (v == 0) return clone_bigint (hcl, x, HCL_OBJ_GET_SIZE(x)); | 			if (v == 0) return clone_bigint (hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			y = make_bigint_with_ooi (hcl, v); | 			y = make_bigint_with_ooi (hcl, v); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (!y) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @ -2336,9 +2336,9 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 				return clone_bigint_negated (hcl, y, HCL_OBJ_GET_SIZE(y)); | 				return clone_bigint_negated (hcl, y, HCL_OBJ_GET_SIZE(y)); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi (hcl, v); | 			x = make_bigint_with_ooi (hcl, v); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (!x) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else if (HCL_OOP_IS_SMOOI(y)) | 		else if (HCL_OOP_IS_SMOOI(y)) | ||||||
| @ -2348,9 +2348,9 @@ hcl_oop_t hcl_subints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			v = HCL_OOP_TO_SMOOI(y); | 			v = HCL_OOP_TO_SMOOI(y); | ||||||
| 			if (v == 0) return clone_bigint (hcl, x, HCL_OBJ_GET_SIZE(x)); | 			if (v == 0) return clone_bigint (hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			y = make_bigint_with_ooi (hcl, v); | 			y = make_bigint_with_ooi (hcl, v); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (!y) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @ -2414,14 +2414,14 @@ hcl_oop_t hcl_mulints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		{ | 		{ | ||||||
| 			/* overflowed - convert x and y normal objects and carry on */ | 			/* overflowed - convert x and y normal objects and carry on */ | ||||||
|  |  | ||||||
| 			/* no need to call hcl_pushtmp before creating x because | 			/* no need to call hcl_pushvolat before creating x because | ||||||
| 			 * xv and yv contains actual values needed */ | 			 * xv and yv contains actual values needed */ | ||||||
| 			x = make_bigint_with_ooi (hcl, xv); | 			x = make_bigint_with_ooi (hcl, xv); | ||||||
| 			if (!x) return HCL_NULL; | 			if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &x); /* protect x made above */ | 			hcl_pushvolat (hcl, &x); /* protect x made above */ | ||||||
| 			y = make_bigint_with_ooi (hcl, yv); | 			y = make_bigint_with_ooi (hcl, yv); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (!y) return HCL_NULL; | ||||||
|  |  | ||||||
| 			goto full_multiply; | 			goto full_multiply; | ||||||
| @ -2453,9 +2453,9 @@ hcl_oop_t hcl_mulints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 					return clone_bigint_negated (hcl, y, HCL_OBJ_GET_SIZE(y)); | 					return clone_bigint_negated (hcl, y, HCL_OBJ_GET_SIZE(y)); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi (hcl, v); | 			x = make_bigint_with_ooi (hcl, v); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (!x) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else if (HCL_OOP_IS_SMOOI(y)) | 		else if (HCL_OOP_IS_SMOOI(y)) | ||||||
| @ -2473,9 +2473,9 @@ hcl_oop_t hcl_mulints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 					return clone_bigint_negated (hcl, x, HCL_OBJ_GET_SIZE(x)); | 					return clone_bigint_negated (hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			y = make_bigint_with_ooi (hcl, v); | 			y = make_bigint_with_ooi (hcl, v); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (!y) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @ -2627,9 +2627,9 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 			} | 			} | ||||||
|   |   | ||||||
| 			/* carry on to the full bigint division */ | 			/* carry on to the full bigint division */ | ||||||
| 			hcl_pushtmp (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi(hcl, xv); | 			x = make_bigint_with_ooi(hcl, xv); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (!x) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else if (HCL_OOP_IS_SMOOI(y)) | 		else if (HCL_OOP_IS_SMOOI(y)) | ||||||
| @ -2706,10 +2706,10 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 							if (!z) return HCL_NULL; | 							if (!z) return HCL_NULL; | ||||||
| 							if (rem) | 							if (rem) | ||||||
| 							{ | 							{ | ||||||
|  								hcl_pushtmp (hcl, &z); |  								hcl_pushvolat (hcl, &z); | ||||||
| 								r = hcl_addints(hcl, HCL_SMOOI_TO_OOP(ri), HCL_SMOOI_TO_OOP(yv)); | 								r = hcl_addints(hcl, HCL_SMOOI_TO_OOP(ri), HCL_SMOOI_TO_OOP(yv)); | ||||||
|   |   | ||||||
| 								hcl_poptmp (hcl); | 								hcl_popvolat (hcl); | ||||||
| 								if (!r) return HCL_NULL; | 								if (!r) return HCL_NULL; | ||||||
|   |   | ||||||
| 								*rem = r; | 								*rem = r; | ||||||
| @ -2725,9 +2725,9 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			/* carry on to the full bigint division */ | 			/* carry on to the full bigint division */ | ||||||
| 			hcl_pushtmp (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			y = make_bigint_with_ooi (hcl, yv); | 			y = make_bigint_with_ooi (hcl, yv); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!y) return HCL_NULL; | 			if (!y) return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		else | 		else | ||||||
| @ -2740,10 +2740,10 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 	x_neg_sign = HCL_IS_NBIGINT(hcl, x); | 	x_neg_sign = HCL_IS_NBIGINT(hcl, x); | ||||||
| 	y_neg_sign = HCL_IS_NBIGINT(hcl, y); | 	y_neg_sign = HCL_IS_NBIGINT(hcl, y); | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &x); | 	hcl_pushvolat (hcl, &x); | ||||||
| 	hcl_pushtmp (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = divide_unsigned_integers (hcl, x, y, &r); | 	z = divide_unsigned_integers (hcl, x, y, &r); | ||||||
| 	hcl_poptmps (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 	if (x_neg_sign)  | 	if (x_neg_sign)  | ||||||
| @ -2757,30 +2757,30 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 	{ | 	{ | ||||||
| 		HCL_OBJ_SET_FLAGS_BRAND (z, HCL_BRAND_NBIGINT); | 		HCL_OBJ_SET_FLAGS_BRAND (z, HCL_BRAND_NBIGINT); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &z); | 		hcl_pushvolat (hcl, &z); | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		r = normalize_bigint (hcl, r); | 		r = normalize_bigint (hcl, r); | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!r) return HCL_NULL; | 		if (!r) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (r != HCL_SMOOI_TO_OOP(0) && modulo) | 		if (r != HCL_SMOOI_TO_OOP(0) && modulo) | ||||||
| 		{ | 		{ | ||||||
| 			if (rem) | 			if (rem) | ||||||
| 			{ | 			{ | ||||||
| 				hcl_pushtmp (hcl, &z); | 				hcl_pushvolat (hcl, &z); | ||||||
| 				hcl_pushtmp (hcl, &y); | 				hcl_pushvolat (hcl, &y); | ||||||
| 				r = hcl_addints (hcl, r, y); | 				r = hcl_addints (hcl, r, y); | ||||||
| 				hcl_poptmps (hcl, 2); | 				hcl_popvolats (hcl, 2); | ||||||
| 				if (!r) return HCL_NULL; | 				if (!r) return HCL_NULL; | ||||||
|  |  | ||||||
| 				hcl_pushtmp (hcl, &r); | 				hcl_pushvolat (hcl, &r); | ||||||
| 				z = normalize_bigint (hcl, z); | 				z = normalize_bigint (hcl, z); | ||||||
| 				hcl_poptmp (hcl); | 				hcl_popvolat (hcl); | ||||||
| 				if (!z) return HCL_NULL; | 				if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 				hcl_pushtmp (hcl, &r); | 				hcl_pushvolat (hcl, &r); | ||||||
| 				z = hcl_subints (hcl, z, HCL_SMOOI_TO_OOP(1)); | 				z = hcl_subints (hcl, z, HCL_SMOOI_TO_OOP(1)); | ||||||
| 				hcl_poptmp (hcl); | 				hcl_popvolat (hcl); | ||||||
| 				if (!z) return HCL_NULL; | 				if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 				*rem = r; | 				*rem = r; | ||||||
| @ -2798,15 +2798,15 @@ hcl_oop_t hcl_divints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, int modulo, hcl_oop | |||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| 		hcl_pushtmp (hcl, &z); | 		hcl_pushvolat (hcl, &z); | ||||||
| 		r = normalize_bigint (hcl, r); | 		r = normalize_bigint (hcl, r); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!r) return HCL_NULL; | 		if (!r) return HCL_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &r); | 	hcl_pushvolat (hcl, &r); | ||||||
| 	z = normalize_bigint(hcl, z); | 	z = normalize_bigint(hcl, z); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
|  |  | ||||||
| 	if (z && rem) *rem = r; | 	if (z && rem) *rem = r; | ||||||
| 	return z; | 	return z; | ||||||
| @ -2952,9 +2952,9 @@ hcl_oop_t hcl_bitatint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
|  |  | ||||||
| 			HCL_ASSERT (hcl, sign == 0); | 			HCL_ASSERT (hcl, sign == 0); | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &x); | 			hcl_pushvolat (hcl, &x); | ||||||
| 			quo = hcl_divints (hcl, y, HCL_SMOOI_TO_OOP(HCL_LIW_BITS), 0, &rem); | 			quo = hcl_divints (hcl, y, HCL_SMOOI_TO_OOP(HCL_LIW_BITS), 0, &rem); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!quo) return HCL_NULL; | 			if (!quo) return HCL_NULL; | ||||||
|  |  | ||||||
| 			sign = integer_to_oow (hcl, quo, &wp); | 			sign = integer_to_oow (hcl, quo, &wp); | ||||||
| @ -3023,9 +3023,9 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		v = HCL_OOP_TO_SMOOI(x); | 		v = HCL_OOP_TO_SMOOI(x); | ||||||
| 		if (v == 0) return HCL_SMOOI_TO_OOP(0); | 		if (v == 0) return HCL_SMOOI_TO_OOP(0); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = make_bigint_with_ooi (hcl, v); | 		x = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| @ -3039,9 +3039,9 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		v = HCL_OOP_TO_SMOOI(y); | 		v = HCL_OOP_TO_SMOOI(y); | ||||||
| 		if (v == 0) return HCL_SMOOI_TO_OOP(0); | 		if (v == 0) return HCL_SMOOI_TO_OOP(0); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = make_bigint_with_ooi (hcl, v); | 		y = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| @ -3093,10 +3093,10 @@ hcl_oop_t hcl_bitandints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			zs = ys; | 			zs = ys; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!z) return HCL_NULL; | 		if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (negx && negy) | 		if (negx && negy) | ||||||
| @ -3236,9 +3236,9 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		v = HCL_OOP_TO_SMOOI(x); | 		v = HCL_OOP_TO_SMOOI(x); | ||||||
| 		if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y)); | 		if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y)); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = make_bigint_with_ooi (hcl, v); | 		x = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| @ -3252,9 +3252,9 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		v = HCL_OOP_TO_SMOOI(y); | 		v = HCL_OOP_TO_SMOOI(y); | ||||||
| 		if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | 		if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = make_bigint_with_ooi (hcl, v); | 		y = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| @ -3313,10 +3313,10 @@ hcl_oop_t hcl_bitorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!z) return HCL_NULL; | 		if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (negx && negy) | 		if (negx && negy) | ||||||
| @ -3454,9 +3454,9 @@ hcl_oop_t hcl_bitxorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		v = HCL_OOP_TO_SMOOI(x); | 		v = HCL_OOP_TO_SMOOI(x); | ||||||
| 		if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y)); | 		if (v == 0) return clone_bigint(hcl, y, HCL_OBJ_GET_SIZE(y)); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = make_bigint_with_ooi (hcl, v); | 		x = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| @ -3470,9 +3470,9 @@ hcl_oop_t hcl_bitxorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		v = HCL_OOP_TO_SMOOI(y); | 		v = HCL_OOP_TO_SMOOI(y); | ||||||
| 		if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | 		if (v == 0) return clone_bigint(hcl, x, HCL_OBJ_GET_SIZE(x)); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = make_bigint_with_ooi (hcl, v); | 		y = make_bigint_with_ooi (hcl, v); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		goto bigint_and_bigint; | 		goto bigint_and_bigint; | ||||||
| @ -3531,10 +3531,10 @@ hcl_oop_t hcl_bitxorints (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!z) return HCL_NULL; | 		if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (negx && negy) | 		if (negx && negy) | ||||||
| @ -3690,9 +3690,9 @@ hcl_oop_t hcl_bitinvint (hcl_t* hcl, hcl_oop_t x) | |||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | 		z = hcl_makebigint(hcl, HCL_BRAND_PBIGINT, HCL_NULL, zalloc); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!z) return HCL_NULL; | 		if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (negx) | 		if (negx) | ||||||
| @ -3761,10 +3761,10 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint (hcl_t* hcl, hcl_oop_t x, hcl | |||||||
| 	HCL_ASSERT (hcl, HCL_IS_NBIGINT(hcl, x)); | 	HCL_ASSERT (hcl, HCL_IS_NBIGINT(hcl, x)); | ||||||
| 	xs = HCL_OBJ_GET_SIZE(x); | 	xs = HCL_OBJ_GET_SIZE(x); | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &x); | 	hcl_pushvolat (hcl, &x); | ||||||
| 	/* +1 for the second inversion below */ | 	/* +1 for the second inversion below */ | ||||||
| 	z = hcl_makebigint(hcl, HCL_BRAND_NBIGINT, HCL_NULL, xs + 1); | 	z = hcl_makebigint(hcl, HCL_BRAND_NBIGINT, HCL_NULL, xs + 1); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 	/* the following lines roughly for 'z = hcl_bitinv (hcl, x)' */ | 	/* the following lines roughly for 'z = hcl_bitinv (hcl, x)' */ | ||||||
| @ -3832,15 +3832,15 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc | |||||||
| 	shift = HCL_SMOOI_MAX; | 	shift = HCL_SMOOI_MAX; | ||||||
| 	do | 	do | ||||||
| 	{ | 	{ | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = rshift_negative_bigint (hcl, x, shift); | 		z = rshift_negative_bigint (hcl, x, shift); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!z) return HCL_NULL; | 		if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 		/* y is a negative number. use hcl_addints() until it becomes 0 */ | 		/* y is a negative number. use hcl_addints() until it becomes 0 */ | ||||||
| 		hcl_pushtmp (hcl, &z); | 		hcl_pushvolat (hcl, &z); | ||||||
| 		y = hcl_addints (hcl, y, HCL_SMOOI_TO_OOP(shift)); | 		y = hcl_addints (hcl, y, HCL_SMOOI_TO_OOP(shift)); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!y) return HCL_NULL; | 		if (!y) return HCL_NULL; | ||||||
|  |  | ||||||
| 		sign = integer_to_oow (hcl, y, &shift); | 		sign = integer_to_oow (hcl, y, &shift); | ||||||
| @ -3855,9 +3855,9 @@ static HCL_INLINE hcl_oop_t rshift_negative_bigint_and_normalize (hcl_t* hcl, hc | |||||||
| 			HCL_ASSERT (hcl, sign <= -1); | 			HCL_ASSERT (hcl, sign <= -1); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = normalize_bigint (hcl, z); | 		x = normalize_bigint (hcl, z); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (HCL_OOP_IS_SMOOI(x)) | 		if (HCL_OOP_IS_SMOOI(x)) | ||||||
| @ -3905,9 +3905,9 @@ static HCL_INLINE hcl_oop_t rshift_positive_bigint_and_normalize (hcl_t* hcl, hc | |||||||
|  |  | ||||||
| 	zs = HCL_OBJ_GET_SIZE(x); | 	zs = HCL_OBJ_GET_SIZE(x); | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &y); | 	hcl_pushvolat (hcl, &y); | ||||||
| 	z = clone_bigint (hcl, x, zs); | 	z = clone_bigint (hcl, x, zs); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!z) return HCL_NULL; | 	if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 	/* for convenience in subtraction below.  | 	/* for convenience in subtraction below.  | ||||||
| @ -3926,9 +3926,9 @@ static HCL_INLINE hcl_oop_t rshift_positive_bigint_and_normalize (hcl_t* hcl, hc | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		/* y is a negative number. use hcl_addints() until it becomes 0 */ | 		/* y is a negative number. use hcl_addints() until it becomes 0 */ | ||||||
| 		hcl_pushtmp (hcl, &z); | 		hcl_pushvolat (hcl, &z); | ||||||
| 		y = hcl_addints (hcl, y, HCL_SMOOI_TO_OOP(shift)); | 		y = hcl_addints (hcl, y, HCL_SMOOI_TO_OOP(shift)); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!y) return HCL_NULL; | 		if (!y) return HCL_NULL; | ||||||
|  |  | ||||||
| 		sign = integer_to_oow (hcl, y, &shift); | 		sign = integer_to_oow (hcl, y, &shift); | ||||||
| @ -3967,21 +3967,21 @@ static HCL_INLINE hcl_oop_t lshift_bigint_and_normalize (hcl_t* hcl, hcl_oop_t x | |||||||
| 		wshift = shift / HCL_LIW_BITS; | 		wshift = shift / HCL_LIW_BITS; | ||||||
| 		if (shift > wshift * HCL_LIW_BITS) wshift++; | 		if (shift > wshift * HCL_LIW_BITS) wshift++; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		z = expand_bigint (hcl, x, wshift); | 		z = expand_bigint (hcl, x, wshift); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!z) return HCL_NULL; | 		if (!z) return HCL_NULL; | ||||||
|  |  | ||||||
| 		lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | 		lshift_unsigned_array (((hcl_oop_liword_t)z)->slot, HCL_OBJ_GET_SIZE(z), shift); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
| 		x = normalize_bigint (hcl, z); | 		x = normalize_bigint (hcl, z); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!x) return HCL_NULL; | 		if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		y = hcl_subints (hcl, y, HCL_SMOOI_TO_OOP(shift)); | 		y = hcl_subints (hcl, y, HCL_SMOOI_TO_OOP(shift)); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!y) return HCL_NULL; | 		if (!y) return HCL_NULL; | ||||||
|  |  | ||||||
| 		sign = integer_to_oow (hcl, y, &shift); | 		sign = integer_to_oow (hcl, y, &shift); | ||||||
| @ -4103,9 +4103,9 @@ hcl_oop_t hcl_bitshiftint (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 				return (v < 0)? HCL_SMOOI_TO_OOP(-1): HCL_SMOOI_TO_OOP(0); | 				return (v < 0)? HCL_SMOOI_TO_OOP(-1): HCL_SMOOI_TO_OOP(0); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			hcl_pushtmp (hcl, &y); | 			hcl_pushvolat (hcl, &y); | ||||||
| 			x = make_bigint_with_ooi (hcl, v); | 			x = make_bigint_with_ooi (hcl, v); | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			if (!x) return HCL_NULL; | 			if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| 			goto bigint_and_bigint; | 			goto bigint_and_bigint; | ||||||
| @ -4642,11 +4642,11 @@ hcl_oop_t hcl_sqrtint (hcl_t* hcl, hcl_oop_t x) | |||||||
| 	m = hcl->_nil; | 	m = hcl->_nil; | ||||||
| 	m2 = hcl->_nil; | 	m2 = hcl->_nil; | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &x); | 	hcl_pushvolat (hcl, &x); | ||||||
| 	hcl_pushtmp (hcl, &a); | 	hcl_pushvolat (hcl, &a); | ||||||
| 	hcl_pushtmp (hcl, &b); | 	hcl_pushvolat (hcl, &b); | ||||||
| 	hcl_pushtmp (hcl, &m); | 	hcl_pushvolat (hcl, &m); | ||||||
| 	hcl_pushtmp (hcl, &m2); | 	hcl_pushvolat (hcl, &m2); | ||||||
|  |  | ||||||
| 	a = hcl_ltints(hcl, x, HCL_SMOOI_TO_OOP(0)); | 	a = hcl_ltints(hcl, x, HCL_SMOOI_TO_OOP(0)); | ||||||
| 	if (!a) goto oops; | 	if (!a) goto oops; | ||||||
| @ -4692,7 +4692,7 @@ hcl_oop_t hcl_sqrtint (hcl_t* hcl, hcl_oop_t x) | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_poptmps (hcl, 5); | 	hcl_popvolats (hcl, 5); | ||||||
| 	x = hcl_subints(hcl, a, HCL_SMOOI_TO_OOP(1)); | 	x = hcl_subints(hcl, a, HCL_SMOOI_TO_OOP(1)); | ||||||
| 	if (!x) return HCL_NULL; | 	if (!x) return HCL_NULL; | ||||||
|  |  | ||||||
| @ -4700,7 +4700,7 @@ hcl_oop_t hcl_sqrtint (hcl_t* hcl, hcl_oop_t x) | |||||||
| 	return x; | 	return x; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	hcl_poptmps (hcl, 5); | 	hcl_popvolats (hcl, 5); | ||||||
| 	return HCL_NULL; | 	return HCL_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -66,9 +66,9 @@ static hcl_oop_oop_t expand_bucket (hcl_t* hcl, hcl_oop_oop_t oldbuc) | |||||||
| 		newsz = oldsz + inc; | 		newsz = oldsz + inc; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&oldbuc); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&oldbuc); | ||||||
| 	newbuc = (hcl_oop_oop_t)hcl_makearray (hcl, newsz, 0);  | 	newbuc = (hcl_oop_oop_t)hcl_makearray (hcl, newsz, 0);  | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!newbuc) return HCL_NULL; | 	if (!newbuc) return HCL_NULL; | ||||||
|  |  | ||||||
| 	while (oldsz > 0) | 	while (oldsz > 0) | ||||||
| @ -172,9 +172,9 @@ static hcl_oop_cons_t find_or_upsert (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t k | |||||||
| 		return HCL_NULL; | 		return HCL_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&dic); tmp_count++; | 	hcl_pushvolat (hcl, (hcl_oop_t*)&dic); tmp_count++; | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&key); tmp_count++; | 	hcl_pushvolat (hcl, (hcl_oop_t*)&key); tmp_count++; | ||||||
| 	hcl_pushtmp (hcl, &value); tmp_count++; | 	hcl_pushvolat (hcl, &value); tmp_count++; | ||||||
|  |  | ||||||
| 	/* no conversion to hcl_oow_t is necessary for tally + 1. | 	/* no conversion to hcl_oow_t is necessary for tally + 1. | ||||||
| 	 * the maximum value of tally is checked to be HCL_SMOOI_MAX - 1. | 	 * the maximum value of tally is checked to be HCL_SMOOI_MAX - 1. | ||||||
| @ -220,11 +220,11 @@ static hcl_oop_cons_t find_or_upsert (hcl_t* hcl, hcl_oop_dic_t dic, hcl_oop_t k | |||||||
| 	dic->tally = HCL_SMOOI_TO_OOP(tally + 1); | 	dic->tally = HCL_SMOOI_TO_OOP(tally + 1); | ||||||
| 	dic->bucket->slot[index] = (hcl_oop_t)ass; | 	dic->bucket->slot[index] = (hcl_oop_t)ass; | ||||||
|  |  | ||||||
| 	hcl_poptmps (hcl, tmp_count); | 	hcl_popvolats (hcl, tmp_count); | ||||||
| 	return ass; | 	return ass; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	hcl_poptmps (hcl, tmp_count); | 	hcl_popvolats (hcl, tmp_count); | ||||||
| 	return HCL_NULL; | 	return HCL_NULL; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -370,9 +370,9 @@ hcl_oop_t hcl_makedic (hcl_t* hcl, hcl_oow_t inisize) | |||||||
|  |  | ||||||
| 		obj->tally = HCL_SMOOI_TO_OOP(0); | 		obj->tally = HCL_SMOOI_TO_OOP(0); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, (hcl_oop_t*)&obj); | 		hcl_pushvolat (hcl, (hcl_oop_t*)&obj); | ||||||
| 		bucket = (hcl_oop_oop_t)hcl_makearray(hcl, inisize, 0); | 		bucket = (hcl_oop_oop_t)hcl_makearray(hcl, inisize, 0); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
|  |  | ||||||
| 		if (!bucket) obj = HCL_NULL; | 		if (!bucket) obj = HCL_NULL; | ||||||
| 		else obj->bucket = bucket; | 		else obj->bucket = bucket; | ||||||
| @ -385,7 +385,7 @@ int hcl_walkdic (hcl_t* hcl, hcl_oop_dic_t dic, hcl_dic_walker_t walker, void* c | |||||||
| { | { | ||||||
| 	hcl_oow_t i; | 	hcl_oow_t i; | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&dic); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&dic); | ||||||
|  |  | ||||||
| 	for (i = 0; i < HCL_OBJ_GET_SIZE(dic->bucket); i++) | 	for (i = 0; i < HCL_OBJ_GET_SIZE(dic->bucket); i++) | ||||||
| 	{ | 	{ | ||||||
| @ -393,7 +393,7 @@ int hcl_walkdic (hcl_t* hcl, hcl_oop_dic_t dic, hcl_dic_walker_t walker, void* c | |||||||
| 		if (HCL_IS_CONS(hcl, tmp) && walker(hcl, dic, (hcl_oop_cons_t)tmp, ctx) <= -1) return -1; | 		if (HCL_IS_CONS(hcl, tmp) && walker(hcl, dic, (hcl_oop_cons_t)tmp, ctx) <= -1) return -1; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -413,9 +413,9 @@ static hcl_oop_process_t make_process (hcl_t* hcl, hcl_oop_context_t c) | |||||||
| 	if (stksize > HCL_TYPE_MAX(hcl_oow_t) - HCL_PROCESS_NAMED_INSTVARS) | 	if (stksize > HCL_TYPE_MAX(hcl_oow_t) - HCL_PROCESS_NAMED_INSTVARS) | ||||||
| 		stksize = HCL_TYPE_MAX(hcl_oow_t) - HCL_PROCESS_NAMED_INSTVARS; | 		stksize = HCL_TYPE_MAX(hcl_oow_t) - HCL_PROCESS_NAMED_INSTVARS; | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&c); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&c); | ||||||
| 	proc = (hcl_oop_process_t)hcl_allocoopobj(hcl, HCL_BRAND_PROCESS, HCL_PROCESS_NAMED_INSTVARS + stksize); | 	proc = (hcl_oop_process_t)hcl_allocoopobj(hcl, HCL_BRAND_PROCESS, HCL_PROCESS_NAMED_INSTVARS + stksize); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (HCL_UNLIKELY(!proc)) return HCL_NULL; | 	if (HCL_UNLIKELY(!proc)) return HCL_NULL; | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
| @ -1070,7 +1070,7 @@ static hcl_oop_process_t signal_semaphore (hcl_t* hcl, hcl_oop_semaphore_t sem) | |||||||
| 	{ | 	{ | ||||||
| 		proc = sem->waiting.first; | 		proc = sem->waiting.first; | ||||||
|  |  | ||||||
| 		/* [NOTE] no GC must occur as 'proc' isn't protected with hcl_pushtmp(). */ | 		/* [NOTE] no GC must occur as 'proc' isn't protected with hcl_pushvolat(). */ | ||||||
|  |  | ||||||
| 		/* detach a process from a semaphore's waiting list and  | 		/* detach a process from a semaphore's waiting list and  | ||||||
| 		 * make it runnable */ | 		 * make it runnable */ | ||||||
| @ -1451,9 +1451,9 @@ static int add_sem_to_sem_io_tuple (hcl_t* hcl, hcl_oop_semaphore_t sem, hcl_ooi | |||||||
|  |  | ||||||
| 		new_mask = ((hcl_ooi_t)1 << io_type); | 		new_mask = ((hcl_ooi_t)1 << io_type); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, (hcl_oop_t*)&sem); | 		hcl_pushvolat (hcl, (hcl_oop_t*)&sem); | ||||||
| 		n = hcl->vmprim.vm_muxadd(hcl, io_handle, new_mask); | 		n = hcl->vmprim.vm_muxadd(hcl, io_handle, new_mask); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 	} | 	} | ||||||
| 	else | 	else | ||||||
| 	{ | 	{ | ||||||
| @ -1466,9 +1466,9 @@ static int add_sem_to_sem_io_tuple (hcl_t* hcl, hcl_oop_semaphore_t sem, hcl_ooi | |||||||
| 		new_mask = hcl->sem_io_tuple[index].mask; /* existing mask */ | 		new_mask = hcl->sem_io_tuple[index].mask; /* existing mask */ | ||||||
| 		new_mask |= ((hcl_ooi_t)1 << io_type); | 		new_mask |= ((hcl_ooi_t)1 << io_type); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, (hcl_oop_t*)&sem); | 		hcl_pushvolat (hcl, (hcl_oop_t*)&sem); | ||||||
| 		n = hcl->vmprim.vm_muxmod(hcl, io_handle, new_mask); | 		n = hcl->vmprim.vm_muxmod(hcl, io_handle, new_mask); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (n <= -1)  | 	if (n <= -1)  | ||||||
| @ -1534,10 +1534,10 @@ static int delete_sem_from_sem_io_tuple (hcl_t* hcl, hcl_oop_semaphore_t sem, in | |||||||
| 	new_mask = hcl->sem_io_tuple[index].mask; | 	new_mask = hcl->sem_io_tuple[index].mask; | ||||||
| 	new_mask &= ~((hcl_ooi_t)1 << io_type); /* this is the new mask after deletion */ | 	new_mask &= ~((hcl_ooi_t)1 << io_type); /* this is the new mask after deletion */ | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&sem); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&sem); | ||||||
| 	x = new_mask? hcl->vmprim.vm_muxmod(hcl, io_handle, new_mask): | 	x = new_mask? hcl->vmprim.vm_muxmod(hcl, io_handle, new_mask): | ||||||
| 	              hcl->vmprim.vm_muxdel(hcl, io_handle);  | 	              hcl->vmprim.vm_muxdel(hcl, io_handle);  | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (x <= -1)  | 	if (x <= -1)  | ||||||
| 	{ | 	{ | ||||||
| 		HCL_LOG3 (hcl, HCL_LOG_WARN, "Failed to delete IO semaphore at index %zd handle %zd for %hs\n", index, io_handle, io_type_str[io_type]); | 		HCL_LOG3 (hcl, HCL_LOG_WARN, "Failed to delete IO semaphore at index %zd handle %zd for %hs\n", index, io_handle, io_type_str[io_type]); | ||||||
| @ -1742,9 +1742,9 @@ static int __activate_block (hcl_t* hcl, hcl_oop_block_t rcv_blk, hcl_ooi_t narg | |||||||
| 	HCL_ASSERT (hcl, local_ntmprs >= nargs); | 	HCL_ASSERT (hcl, local_ntmprs >= nargs); | ||||||
|  |  | ||||||
| 	/* create a new block context to clone rcv_blk */ | 	/* create a new block context to clone rcv_blk */ | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&rcv_blk); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&rcv_blk); | ||||||
| 	blkctx = make_context(hcl, local_ntmprs);  | 	blkctx = make_context(hcl, local_ntmprs);  | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (HCL_UNLIKELY(!blkctx)) return -1; | 	if (HCL_UNLIKELY(!blkctx)) return -1; | ||||||
|  |  | ||||||
| #if 0 | #if 0 | ||||||
| @ -1829,9 +1829,9 @@ static int __activate_function (hcl_t* hcl, hcl_oop_function_t rcv_func, hcl_ooi | |||||||
| 	HCL_ASSERT (hcl, local_ntmprs >= nargs); | 	HCL_ASSERT (hcl, local_ntmprs >= nargs); | ||||||
|  |  | ||||||
| 	/* create a new block context to clone rcv_func */ | 	/* create a new block context to clone rcv_func */ | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&rcv_func); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&rcv_func); | ||||||
| 	functx = make_context(hcl, local_ntmprs);  | 	functx = make_context(hcl, local_ntmprs);  | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (HCL_UNLIKELY(!functx)) return -1; | 	if (HCL_UNLIKELY(!functx)) return -1; | ||||||
|  |  | ||||||
| 	functx->ip = HCL_SMOOI_TO_OOP(0); | 	functx->ip = HCL_SMOOI_TO_OOP(0); | ||||||
| @ -2137,9 +2137,9 @@ static int start_initial_process_and_context (hcl_t* hcl, hcl_ooi_t initial_ip) | |||||||
| 	 * let's force set active_context to ctx directly. */ | 	 * let's force set active_context to ctx directly. */ | ||||||
| 	hcl->active_context = ctx; | 	hcl->active_context = ctx; | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&ctx); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&ctx); | ||||||
| 	proc = start_initial_process(hcl, ctx);  | 	proc = start_initial_process(hcl, ctx);  | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (HCL_UNLIKELY(!proc)) return -1; | 	if (HCL_UNLIKELY(!proc)) return -1; | ||||||
|  |  | ||||||
| 	/* the stack must contain nothing as it should emulate the expresssion - (the-initial-function).  | 	/* the stack must contain nothing as it should emulate the expresssion - (the-initial-function).  | ||||||
| @ -2550,6 +2550,14 @@ static HCL_INLINE void do_return_from_block (hcl_t* hcl) | |||||||
| } | } | ||||||
| /* ------------------------------------------------------------------------- */ | /* ------------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
|  | static void xma_dumper (void* ctx, const char* fmt, ...) | ||||||
|  | { | ||||||
|  | 	va_list ap; | ||||||
|  | 	va_start (ap, fmt); | ||||||
|  | 	hcl_logbfmtv ((hcl_t*)ctx, HCL_LOG_IC | HCL_LOG_INFO, fmt, ap); | ||||||
|  | 	va_end (ap); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int execute (hcl_t* hcl) | static int execute (hcl_t* hcl) | ||||||
| { | { | ||||||
| 	hcl_oob_t bcode; | 	hcl_oob_t bcode; | ||||||
| @ -2570,6 +2578,11 @@ static int execute (hcl_t* hcl) | |||||||
| 	if (vm_startup(hcl) <= -1) return -1; | 	if (vm_startup(hcl) <= -1) return -1; | ||||||
| 	hcl->proc_switched = 0; | 	hcl->proc_switched = 0; | ||||||
|  |  | ||||||
|  | 	hcl->gci.lazy_sweep = 1; /* TODO: make it configurable?? */ | ||||||
|  | 	HCL_INIT_NTIME (&hcl->gci.stat.alloc, 0, 0); | ||||||
|  | 	HCL_INIT_NTIME (&hcl->gci.stat.mark, 0, 0); | ||||||
|  | 	HCL_INIT_NTIME (&hcl->gci.stat.sweep, 0, 0); | ||||||
|  |  | ||||||
| 	while (1) | 	while (1) | ||||||
| 	{ | 	{ | ||||||
| 		/* stop requested or no more runnable process */ | 		/* stop requested or no more runnable process */ | ||||||
| @ -3395,6 +3408,8 @@ static int execute (hcl_t* hcl) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| done: | done: | ||||||
|  | 	hcl->gci.lazy_sweep = 1; | ||||||
|  |  | ||||||
| 	vm_cleanup (hcl); | 	vm_cleanup (hcl); | ||||||
| #if defined(HCL_PROFILE_VM) | #if defined(HCL_PROFILE_VM) | ||||||
| 	HCL_LOG1 (hcl, HCL_LOG_IC | HCL_LOG_INFO, "TOTAL INST COUTNER = %zu\n", inst_counter); | 	HCL_LOG1 (hcl, HCL_LOG_IC | HCL_LOG_INFO, "TOTAL INST COUTNER = %zu\n", inst_counter); | ||||||
| @ -3402,6 +3417,8 @@ done: | |||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
|  | 	hcl->gci.lazy_sweep = 1; | ||||||
|  |  | ||||||
| 	/* TODO: anything to do here? */ | 	/* TODO: anything to do here? */ | ||||||
| 	if (hcl->processor->active != hcl->nil_process)  | 	if (hcl->processor->active != hcl->nil_process)  | ||||||
| 	{ | 	{ | ||||||
| @ -3489,6 +3506,14 @@ hcl_oop_t hcl_execute (hcl_t* hcl) | |||||||
| 	hcl->initial_context = HCL_NULL; | 	hcl->initial_context = HCL_NULL; | ||||||
| 	hcl->active_context = HCL_NULL; | 	hcl->active_context = HCL_NULL; | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_INFO, "GC - gci.bsz: %zu, gci.stack.max: %zu\n", hcl->gci.bsz, hcl->gci.stack.max); | ||||||
|  | 	if (hcl->heap->xma) hcl_xma_dump (hcl->heap->xma, xma_dumper, hcl); | ||||||
|  | 	HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_INFO, "GC - gci.stat.alloc: %ld.%09u\n", (unsigned long int)hcl->gci.stat.alloc.sec, (unsigned int)hcl->gci.stat.alloc.nsec); | ||||||
|  | 	HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_INFO, "GC - gci.stat.mark: %ld.%09u\n", (unsigned long int)hcl->gci.stat.mark.sec, (unsigned int)hcl->gci.stat.mark.nsec); | ||||||
|  | 	HCL_LOG2 (hcl, HCL_LOG_IC | HCL_LOG_INFO, "GC - gci.stat.sweep: %ld.%09u\n", (unsigned long int)hcl->gci.stat.sweep.sec, (unsigned int)hcl->gci.stat.sweep.nsec); | ||||||
|  | #endif | ||||||
|  |  | ||||||
| 	hcl->log.default_type_mask = log_default_type_mask; | 	hcl->log.default_type_mask = log_default_type_mask; | ||||||
| 	return (n <= -1)? HCL_NULL: hcl->last_retv; | 	return (n <= -1)? HCL_NULL: hcl->last_retv; | ||||||
| } | } | ||||||
|  | |||||||
| @ -2650,9 +2650,9 @@ static HCL_INLINE int format_stack_args (hcl_fmtout_t* fmtout, hcl_ooi_t nargs, | |||||||
|  |  | ||||||
| 				/* the given number for integer output is a fixed-point decimal. | 				/* the given number for integer output is a fixed-point decimal. | ||||||
| 				 * i will drop all digits after the fixed point */ | 				 * i will drop all digits after the fixed point */ | ||||||
| 				hcl_pushtmp (hcl, &arg); | 				hcl_pushvolat (hcl, &arg); | ||||||
| 				nv = hcl_truncfpdecval(hcl, fa->value, HCL_OOP_TO_SMOOI(fa->scale), 0); | 				nv = hcl_truncfpdecval(hcl, fa->value, HCL_OOP_TO_SMOOI(fa->scale), 0); | ||||||
| 				hcl_poptmp (hcl); | 				hcl_popvolat (hcl); | ||||||
| 				if (!nv) | 				if (!nv) | ||||||
| 				{ | 				{ | ||||||
| 					HCL_LOG1 (hcl, HCL_LOG_WARN | HCL_LOG_UNTYPED, "unable to truncate a fixed-point number %O to an integer for output\n", arg); | 					HCL_LOG1 (hcl, HCL_LOG_WARN | HCL_LOG_UNTYPED, "unable to truncate a fixed-point number %O to an integer for output\n", arg); | ||||||
|  | |||||||
							
								
								
									
										439
									
								
								hcl/lib/gc.c
									
									
									
									
									
								
							
							
						
						
									
										439
									
								
								hcl/lib/gc.c
									
									
									
									
									
								
							| @ -26,6 +26,11 @@ | |||||||
|  |  | ||||||
| #include "hcl-prv.h" | #include "hcl-prv.h" | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | #include <sys/time.h> | ||||||
|  | #include <sys/resource.h> /* getrusage */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
| static struct  | static struct  | ||||||
| { | { | ||||||
| 	hcl_oow_t  len; | 	hcl_oow_t  len; | ||||||
| @ -84,7 +89,7 @@ static void compact_symbol_table (hcl_t* hcl, hcl_oop_t _nil) | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		HCL_ASSERT (hcl, hcl->symtab->bucket->slot[index] != _nil); | 		HCL_ASSERT (hcl, hcl->symtab->bucket->slot[index] != _nil); | ||||||
|  | 	 | ||||||
| 		for (i = 0, x = index, y = index; i < bucket_size; i++) | 		for (i = 0, x = index, y = index; i < bucket_size; i++) | ||||||
| 		{ | 		{ | ||||||
| 			y = (y + 1) % bucket_size; | 			y = (y + 1) % bucket_size; | ||||||
| @ -118,7 +123,7 @@ static void compact_symbol_table (hcl_t* hcl, hcl_oop_t _nil) | |||||||
| 	hcl->symtab->tally = HCL_SMOOI_TO_OOP(tally); | 	hcl->symtab->tally = HCL_SMOOI_TO_OOP(tally); | ||||||
| } | } | ||||||
|  |  | ||||||
| static HCL_INLINE hcl_oow_t get_payload_bytes (hcl_t* hcl, hcl_oop_t oop) | hcl_oow_t hcl_getobjpayloadbytes (hcl_t* hcl, hcl_oop_t oop) | ||||||
| { | { | ||||||
| 	hcl_oow_t nbytes_aligned; | 	hcl_oow_t nbytes_aligned; | ||||||
|  |  | ||||||
| @ -154,86 +159,88 @@ static HCL_INLINE hcl_oow_t get_payload_bytes (hcl_t* hcl, hcl_oop_t oop) | |||||||
| 	return nbytes_aligned; | 	return nbytes_aligned; | ||||||
| } | } | ||||||
|  |  | ||||||
| hcl_oop_t hcl_moveoop (hcl_t* hcl, hcl_oop_t oop) |  | ||||||
|  | /* ----------------------------------------------------------------------- */ | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
|  | static HCL_INLINE void gc_ms_mark (hcl_t* hcl, hcl_oop_t oop) | ||||||
| { | { | ||||||
|  | 	hcl_oow_t i, sz; | ||||||
|  |  | ||||||
| #if defined(HCL_SUPPORT_GC_DURING_IGNITION) | #if defined(HCL_SUPPORT_GC_DURING_IGNITION) | ||||||
| 	if (!oop) return oop; | 	if (!oop) return; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	if (!HCL_OOP_IS_POINTER(oop)) return oop; | 	if (!HCL_OOP_IS_POINTER(oop)) return; | ||||||
| 	if (HCL_OBJ_GET_FLAGS_NGC(oop)) return oop; /* non-GC object */ | 	if (HCL_OBJ_GET_FLAGS_MOVED(oop)) return; /* already marked */ | ||||||
|  |  | ||||||
| 	if (HCL_OBJ_GET_FLAGS_MOVED(oop)) | 	HCL_OBJ_SET_FLAGS_MOVED(oop, 1); /* mark */ | ||||||
|  |  | ||||||
|  | 	gc_ms_mark (hcl, (hcl_oop_t)HCL_OBJ_GET_CLASS(oop)); /* TODO: remove recursion */ | ||||||
|  |  | ||||||
|  | 	if (HCL_OBJ_GET_FLAGS_TYPE(oop) == HCL_OBJ_TYPE_OOP) | ||||||
| 	{ | 	{ | ||||||
| 		/* this object has migrated to the new heap.  | 		hcl_oow_t size, i; | ||||||
| 		 * the class field has been updated to the new object |  | ||||||
| 		 * in the 'else' block below. i can simply return it |  | ||||||
| 		 * without further migration. */ |  | ||||||
| 		return HCL_OBJ_GET_CLASS(oop); |  | ||||||
| 	} |  | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		hcl_oow_t nbytes_aligned; |  | ||||||
| 		hcl_oop_t tmp; |  | ||||||
|  |  | ||||||
| 		nbytes_aligned = get_payload_bytes(hcl, oop); | 		/* is it really better to use a flag bit in the header to | ||||||
|  | 		 * determine that it is an instance of process? */ | ||||||
|  | 		if (HCL_UNLIKELY(HCL_OBJ_GET_FLAGS_PROC(oop))) | ||||||
|  | 		{ | ||||||
|  | 			/* the stack in a process object doesn't need to be  | ||||||
|  | 			 * scanned in full. the slots above the stack pointer  | ||||||
|  | 			 * are garbages. */ | ||||||
|  | 			size = HCL_PROCESS_NAMED_INSTVARS + HCL_OOP_TO_SMOOI(((hcl_oop_process_t)oop)->sp) + 1; | ||||||
|  | 			HCL_ASSERT (hcl, size <= HCL_OBJ_GET_SIZE(oop)); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			size = HCL_OBJ_GET_SIZE(oop); | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		/* allocate space in the new heap */ | 		for (i = 0; i < size; i++) | ||||||
| 		tmp = (hcl_oop_t)hcl_allocheapmem(hcl, hcl->newheap, HCL_SIZEOF(hcl_obj_t) + nbytes_aligned); | 		{ | ||||||
|  | 			hcl_oop_t tmp = HCL_OBJ_GET_OOP_VAL(oop, i); | ||||||
| 		/* allocation here must not fail because | 			if (HCL_OOP_IS_POINTER(tmp)) gc_ms_mark (hcl, tmp);  /* TODO: no resursion */ | ||||||
| 		 * i'm allocating the new space in a new heap for  | 		} | ||||||
| 		 * moving an existing object in the current heap.  |  | ||||||
| 		 * |  | ||||||
| 		 * assuming the new heap is as large as the old heap, |  | ||||||
| 		 * and garbage collection doesn't allocate more objects |  | ||||||
| 		 * than in the old heap, it must not fail. */ |  | ||||||
| 		HCL_ASSERT (hcl, tmp != HCL_NULL);  |  | ||||||
|  |  | ||||||
| 		/* copy the payload to the new object */ |  | ||||||
| 		HCL_MEMCPY (tmp, oop, HCL_SIZEOF(hcl_obj_t) + nbytes_aligned); |  | ||||||
|  |  | ||||||
| 		/* mark the old object that it has migrated to the new heap */ |  | ||||||
| 		HCL_OBJ_SET_FLAGS_MOVED(oop, 1); |  | ||||||
|  |  | ||||||
| 		/* let the class field of the old object point to the new  |  | ||||||
| 		 * object allocated in the new heap. it is returned in  |  | ||||||
| 		 * the 'if' block at the top of this function. */ |  | ||||||
| 		HCL_OBJ_SET_CLASS (oop, tmp); |  | ||||||
|  |  | ||||||
| 		/* return the new object */ |  | ||||||
| 		return tmp; |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | #else | ||||||
| static hcl_uint8_t* scan_new_heap (hcl_t* hcl, hcl_uint8_t* ptr) | static HCL_INLINE void gc_ms_mark_object (hcl_t* hcl, hcl_oop_t oop) | ||||||
| { | { | ||||||
| 	while (ptr < hcl->newheap->ptr) | #if defined(HCL_SUPPORT_GC_DURING_IGNITION) | ||||||
|  | 	if (!oop) return; | ||||||
|  | #endif | ||||||
|  | 	if (!HCL_OOP_IS_POINTER(oop) || HCL_OBJ_GET_FLAGS_MOVED(oop)) return; /* non-pointer or already marked */ | ||||||
|  |  | ||||||
|  | 	HCL_OBJ_SET_FLAGS_MOVED(oop, 1); /* mark */ | ||||||
|  | HCL_ASSERT (hcl, hcl->gci.stack.len < hcl->gci.stack.capa); | ||||||
|  | 	hcl->gci.stack.ptr[hcl->gci.stack.len++] = oop; /* push */ | ||||||
|  | if (hcl->gci.stack.len > hcl->gci.stack.max) hcl->gci.stack.max = hcl->gci.stack.len; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static HCL_INLINE void gc_ms_scan_stack (hcl_t* hcl) | ||||||
|  | { | ||||||
|  | 	hcl_oop_t oop; | ||||||
|  |  | ||||||
|  | 	while (hcl->gci.stack.len > 0) | ||||||
| 	{ | 	{ | ||||||
| 		hcl_oow_t i; | 		oop = hcl->gci.stack.ptr[--hcl->gci.stack.len]; | ||||||
| 		hcl_oow_t nbytes_aligned; |  | ||||||
| 		hcl_oop_t oop, tmp; |  | ||||||
|  |  | ||||||
| 		oop = (hcl_oop_t)ptr; | 		gc_ms_mark_object (hcl, (hcl_oop_t)HCL_OBJ_GET_CLASS(oop)); | ||||||
| 		HCL_ASSERT (hcl, HCL_OOP_IS_POINTER(oop)); |  | ||||||
|  |  | ||||||
| 		nbytes_aligned = get_payload_bytes(hcl, oop); |  | ||||||
|  |  | ||||||
| 		tmp = hcl_moveoop(hcl, HCL_OBJ_GET_CLASS(oop)); |  | ||||||
| 		HCL_OBJ_SET_CLASS (oop, tmp); |  | ||||||
|  |  | ||||||
| 		if (HCL_OBJ_GET_FLAGS_TYPE(oop) == HCL_OBJ_TYPE_OOP) | 		if (HCL_OBJ_GET_FLAGS_TYPE(oop) == HCL_OBJ_TYPE_OOP) | ||||||
| 		{ | 		{ | ||||||
| 			hcl_oop_oop_t xtmp; | 			hcl_oow_t size, i; | ||||||
| 			hcl_oow_t size; |  | ||||||
|  |  | ||||||
|  | 			/* is it really better to use a flag bit in the header to | ||||||
|  | 			 * determine that it is an instance of process? */ | ||||||
|  | 			/* if (HCL_UNLIKELY(HCL_OBJ_GET_FLAGS_PROC(oop))) */ | ||||||
| 			if (HCL_OBJ_GET_FLAGS_BRAND(oop) == HCL_BRAND_PROCESS) | 			if (HCL_OBJ_GET_FLAGS_BRAND(oop) == HCL_BRAND_PROCESS) | ||||||
| 			{ | 			{ | ||||||
| 				/* the stack in a process object doesn't need to be  | 				/* the stack in a process object doesn't need to be  | ||||||
| 				 * scanned in full. the slots above the stack pointer  | 				 * scanned in full. the slots above the stack pointer  | ||||||
| 				 * are garbages. */ | 				 * are garbages. */ | ||||||
| 				size = HCL_PROCESS_NAMED_INSTVARS + | 				size = HCL_PROCESS_NAMED_INSTVARS + HCL_OOP_TO_SMOOI(((hcl_oop_process_t)oop)->sp) + 1; | ||||||
| 				       HCL_OOP_TO_SMOOI(((hcl_oop_process_t)oop)->sp) + 1; |  | ||||||
| 				HCL_ASSERT (hcl, size <= HCL_OBJ_GET_SIZE(oop)); | 				HCL_ASSERT (hcl, size <= HCL_OBJ_GET_SIZE(oop)); | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| @ -241,21 +248,285 @@ static hcl_uint8_t* scan_new_heap (hcl_t* hcl, hcl_uint8_t* ptr) | |||||||
| 				size = HCL_OBJ_GET_SIZE(oop); | 				size = HCL_OBJ_GET_SIZE(oop); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			xtmp = (hcl_oop_oop_t)oop; |  | ||||||
| 			for (i = 0; i < size; i++) | 			for (i = 0; i < size; i++) | ||||||
| 			{ | 			{ | ||||||
| 				if (HCL_OOP_IS_POINTER(xtmp->slot[i])) | 				gc_ms_mark_object (hcl, HCL_OBJ_GET_OOP_VAL(oop, i)); | ||||||
| 					xtmp->slot[i] = hcl_moveoop (hcl, xtmp->slot[i]); | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static HCL_INLINE void gc_ms_mark (hcl_t* hcl, hcl_oop_t oop) | ||||||
|  | { | ||||||
|  | 	gc_ms_mark_object (hcl, oop); | ||||||
|  | 	gc_ms_scan_stack (hcl); | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | static HCL_INLINE void gc_ms_mark_roots (hcl_t* hcl) | ||||||
|  | { | ||||||
|  | 	hcl_oow_t i; | ||||||
|  | #if defined(ENABLE_GCFIN) | ||||||
|  | 	hcl_oow_t gcfin_count; | ||||||
|  | #endif | ||||||
|  | 	hcl_cb_t* cb; | ||||||
|  |   | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	struct rusage ru; | ||||||
|  | 	hcl_ntime_t rut; | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_INIT_NTIME (&rut,  ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	if (hcl->processor && hcl->processor->active) | ||||||
|  | 	{ | ||||||
|  | 		HCL_ASSERT (hcl, (hcl_oop_t)hcl->processor != hcl->_nil); | ||||||
|  | 		HCL_ASSERT (hcl, (hcl_oop_t)hcl->processor->active != hcl->_nil); | ||||||
|  |  | ||||||
|  | 		/* commit the stack pointer to the active process because | ||||||
|  | 		 * gc needs the correct stack pointer for a process object */ | ||||||
|  | 		hcl->processor->active->sp = HCL_SMOOI_TO_OOP(hcl->sp); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	gc_ms_mark (hcl, hcl->_nil); | ||||||
|  | 	gc_ms_mark (hcl, hcl->_true); | ||||||
|  | 	gc_ms_mark (hcl, hcl->_false); | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < HCL_COUNTOF(syminfo); i++) | ||||||
|  | 	{ | ||||||
|  | 		gc_ms_mark (hcl, *(hcl_oop_t*)((hcl_uint8_t*)hcl + syminfo[i].offset)); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	gc_ms_mark (hcl, (hcl_oop_t)hcl->sysdic); | ||||||
|  | 	gc_ms_mark (hcl, (hcl_oop_t)hcl->processor); | ||||||
|  | 	gc_ms_mark (hcl, (hcl_oop_t)hcl->nil_process); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < hcl->code.lit.len; i++) | ||||||
|  | 	{ | ||||||
|  | 		/* the literal array ia a NGC object. but the literal objects  | ||||||
|  | 		 * pointed by the elements of this array must be gabage-collected. */ | ||||||
|  | 		gc_ms_mark (hcl, ((hcl_oop_oop_t)hcl->code.lit.arr)->slot[i]); | ||||||
|  | 	} | ||||||
|  | 	gc_ms_mark (hcl, hcl->p.e); | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < hcl->sem_list_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		gc_ms_mark (hcl, (hcl_oop_t)hcl->sem_list[i]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < hcl->sem_heap_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		gc_ms_mark (hcl, (hcl_oop_t)hcl->sem_heap[i]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < hcl->sem_io_tuple_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		if (hcl->sem_io_tuple[i].sem[HCL_SEMAPHORE_IO_TYPE_INPUT]) | ||||||
|  | 			gc_ms_mark (hcl, (hcl_oop_t)hcl->sem_io_tuple[i].sem[HCL_SEMAPHORE_IO_TYPE_INPUT]); | ||||||
|  | 		if (hcl->sem_io_tuple[i].sem[HCL_SEMAPHORE_IO_TYPE_OUTPUT]) | ||||||
|  | 			gc_ms_mark (hcl, (hcl_oop_t)hcl->sem_io_tuple[i].sem[HCL_SEMAPHORE_IO_TYPE_OUTPUT]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(ENABLE_GCFIN) | ||||||
|  | 	gc_ms_mark (hcl, (hcl_oop_t)hcl->sem_gcfin); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < hcl->proc_map_capa; i++) | ||||||
|  | 	{ | ||||||
|  | 		gc_ms_mark (hcl, hcl->proc_map[i]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (i = 0; i < hcl->volat_count; i++) | ||||||
|  | 	{ | ||||||
|  | 		gc_ms_mark (hcl, *hcl->volat_stack[i]); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (hcl->initial_context) gc_ms_mark (hcl, (hcl_oop_t)hcl->initial_context); | ||||||
|  | 	if (hcl->active_context) gc_ms_mark (hcl, (hcl_oop_t)hcl->active_context); | ||||||
|  | 	if (hcl->initial_function) gc_ms_mark (hcl, (hcl_oop_t)hcl->initial_function); | ||||||
|  | 	if (hcl->active_function) gc_ms_mark (hcl, (hcl_oop_t)hcl->active_function); | ||||||
|  |  | ||||||
|  | 	if (hcl->last_retv) gc_ms_mark (hcl, hcl->last_retv); | ||||||
|  |  | ||||||
|  | 	/*hcl_rbt_walk (&hcl->modtab, call_module_gc, hcl); */ | ||||||
|  |  | ||||||
|  | 	for (cb = hcl->cblist; cb; cb = cb->next) | ||||||
|  | 	{ | ||||||
|  | 		if (cb->gc) cb->gc (hcl); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(ENABLE_GCFIN) | ||||||
|  | 	gcfin_count = move_finalizable_objects(hcl); /* mark finalizable objects */ | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	if (hcl->symtab) | ||||||
|  | 	{ | ||||||
|  | 		compact_symbol_table (hcl, hcl->_nil); /* delete symbol table entries that are not marked */ | ||||||
|  | 	#if 0 | ||||||
|  | 		gc_ms_mark (hcl, (hcl_oop_t)hcl->symtab); /* mark the symbol table */ | ||||||
|  | 	#else | ||||||
|  | 		HCL_OBJ_SET_FLAGS_MOVED(hcl->symtab, 1); /* mark */ | ||||||
|  | 		HCL_OBJ_SET_FLAGS_MOVED(hcl->symtab->bucket, 1); /* mark */ | ||||||
|  | 	#endif | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | #if defined(ENABLE_GCFIN) | ||||||
|  | 	if (gcfin_count > 0) hcl->sem_gcfin_sigreq = 1; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	if (hcl->active_function) hcl->active_code = HCL_FUNCTION_GET_CODE_BYTE(hcl->active_function); /* update hcl->active_code */ | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_SUB_NTIME_SNS (&rut, &rut, ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | 	HCL_SUB_NTIME (&hcl->gci.stat.mark, &hcl->gci.stat.mark, &rut); /* do subtraction because rut is negative */ | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hcl_gc_ms_sweep_lazy (hcl_t* hcl, hcl_oow_t allocsize) | ||||||
|  | { | ||||||
|  | 	hcl_gchdr_t* curr, * next, * prev; | ||||||
|  | 	hcl_oop_t obj; | ||||||
|  | 	hcl_oow_t freed_size; | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	struct rusage ru; | ||||||
|  | 	hcl_ntime_t rut; | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_INIT_NTIME (&rut,  ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	if (!hcl->gci.ls.curr) goto done; | ||||||
|  |  | ||||||
|  | 	freed_size = 0; | ||||||
|  |  | ||||||
|  | 	prev = hcl->gci.ls.prev; | ||||||
|  | 	curr = hcl->gci.ls.curr; | ||||||
|  |  | ||||||
|  | 	while (curr) | ||||||
|  | 	{ | ||||||
|  | 		next = curr->next; | ||||||
|  | 		obj = (hcl_oop_t)(curr + 1); | ||||||
|  |  | ||||||
|  | 		if (HCL_OBJ_GET_FLAGS_MOVED(obj)) /* if marked */ | ||||||
|  | 		{ | ||||||
|  | 			HCL_OBJ_SET_FLAGS_MOVED (obj, 0); /* unmark */ | ||||||
|  | 			prev = curr; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			hcl_oow_t objsize; | ||||||
|  |  | ||||||
|  | 			if (prev) prev->next = next; | ||||||
|  | 			else hcl->gci.b = next; | ||||||
|  |  | ||||||
|  | 			objsize = HCL_SIZEOF(hcl_obj_t) + hcl_getobjpayloadbytes(hcl, obj); | ||||||
|  | 			freed_size += objsize; | ||||||
|  | 			hcl->gci.bsz -= objsize; | ||||||
|  | 			hcl_freeheapmem (hcl, hcl->heap, curr); /* destroy */ | ||||||
|  |  | ||||||
|  | 			/*if (freed_size > allocsize)*/  /* TODO: can it secure large enough space? */ | ||||||
|  | 			if (objsize == allocsize) | ||||||
|  | 			{ | ||||||
|  | 				hcl->gci.ls.prev = prev; | ||||||
|  | 				hcl->gci.ls.curr = next; /* let the next lazy sweeping begin at this point */ | ||||||
|  | 				goto done; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		ptr = ptr + HCL_SIZEOF(hcl_obj_t) + nbytes_aligned; | 		curr = next; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* return the pointer to the beginning of the free space in the heap */ | 	hcl->gci.ls.curr = HCL_NULL; | ||||||
| 	return ptr;  |  | ||||||
|  | done: | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_SUB_NTIME_SNS (&rut, &rut, ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | 	HCL_SUB_NTIME (&hcl->gci.stat.sweep, &hcl->gci.stat.sweep, &rut); /* do subtraction because rut is negative */ | ||||||
|  | #endif | ||||||
|  | 	return; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static HCL_INLINE void gc_ms_sweep (hcl_t* hcl) | ||||||
|  | { | ||||||
|  | 	hcl_gchdr_t* curr, * next, * prev; | ||||||
|  | 	hcl_oop_t obj; | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	struct rusage ru; | ||||||
|  | 	hcl_ntime_t rut; | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_INIT_NTIME (&rut,  ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	prev = HCL_NULL; | ||||||
|  | 	curr = hcl->gci.b; | ||||||
|  | 	while (curr) | ||||||
|  | 	{ | ||||||
|  | 		next = curr->next; | ||||||
|  | 		obj = (hcl_oop_t)(curr + 1); | ||||||
|  |  | ||||||
|  | 		if (HCL_OBJ_GET_FLAGS_MOVED(obj)) /* if marked */ | ||||||
|  | 		{ | ||||||
|  | 			HCL_OBJ_SET_FLAGS_MOVED (obj, 0); 	/* unmark */ | ||||||
|  | 			prev = curr; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			if (prev) prev->next = next; | ||||||
|  | 			else hcl->gci.b = next; | ||||||
|  |  | ||||||
|  | 			hcl->gci.bsz -= HCL_SIZEOF(hcl_obj_t) + hcl_getobjpayloadbytes(hcl, obj); | ||||||
|  | 			hcl_freeheapmem (hcl, hcl->heap, curr); /* destroy */ | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		curr = next; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hcl->gci.ls.curr = HCL_NULL; | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_SUB_NTIME_SNS (&rut, &rut, ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | 	HCL_SUB_NTIME (&hcl->gci.stat.sweep, &hcl->gci.stat.sweep, &rut); /* do subtraction because rut is negative */ | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hcl_gc (hcl_t* hcl, int full) | ||||||
|  | { | ||||||
|  | 	if (hcl->gci.lazy_sweep) hcl_gc_ms_sweep_lazy (hcl, HCL_TYPE_MAX(hcl_oow_t)); | ||||||
|  |  | ||||||
|  | 	HCL_LOG1 (hcl, HCL_LOG_GC | HCL_LOG_INFO, "Starting GC (mark-sweep) - gci.bsz = %zu\n", hcl->gci.bsz); | ||||||
|  |  | ||||||
|  | 	hcl->gci.stack.len = 0; | ||||||
|  | 	/*hcl->gci.stack.max = 0;*/ | ||||||
|  | 	gc_ms_mark_roots (hcl); | ||||||
|  |  | ||||||
|  | 	if (!full && hcl->gci.lazy_sweep) | ||||||
|  | 	{ | ||||||
|  | 		/* set the lazy sweeping point to the head of the allocated blocks. | ||||||
|  | 		 * hawk_allocbytes() updates hcl->gci.ls.prev if it is called while | ||||||
|  | 		 * hcl->gci.ls.curr stays at hcl->gci.b */ | ||||||
|  | 		hcl->gci.ls.prev = HCL_NULL; | ||||||
|  | 		hcl->gci.ls.curr = hcl->gci.b; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 	    gc_ms_sweep (hcl); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	HCL_LOG2 (hcl, HCL_LOG_GC | HCL_LOG_INFO, "Finished GC (mark-sweep) - gci.bsz = %zu, gci.stack.max %zu\n", hcl->gci.bsz, hcl->gci.stack.max); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | hcl_oop_t hcl_moveoop (hcl_t* hcl, hcl_oop_t oop) | ||||||
|  | { | ||||||
|  | 	if (oop) gc_ms_mark (hcl, oop); | ||||||
|  | 	return oop; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #if 0 | ||||||
| void hcl_gc (hcl_t* hcl) | void hcl_gc (hcl_t* hcl) | ||||||
| { | { | ||||||
| 	/*  | 	/*  | ||||||
| @ -343,9 +614,9 @@ void hcl_gc (hcl_t* hcl) | |||||||
| 		hcl->proc_map[i] = hcl_moveoop(hcl, hcl->proc_map[i]); | 		hcl->proc_map[i] = hcl_moveoop(hcl, hcl->proc_map[i]); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for (i = 0; i < hcl->tmp_count; i++) | 	for (i = 0; i < hcl->volat_count; i++) | ||||||
| 	{ | 	{ | ||||||
| 		*hcl->tmp_stack[i] = hcl_moveoop(hcl, *hcl->tmp_stack[i]); | 		*hcl->volat_stack[i] = hcl_moveoop(hcl, *hcl->volat_stack[i]); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (hcl->initial_context) | 	if (hcl->initial_context) | ||||||
| @ -417,26 +688,26 @@ void hcl_gc (hcl_t* hcl) | |||||||
| 		"Finished GC curheap base %p ptr %p newheap base %p ptr %p\n", | 		"Finished GC curheap base %p ptr %p newheap base %p ptr %p\n", | ||||||
| 		hcl->curheap->base, hcl->curheap->ptr, hcl->newheap->base, hcl->newheap->ptr);  | 		hcl->curheap->base, hcl->curheap->ptr, hcl->newheap->base, hcl->newheap->ptr);  | ||||||
| } | } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | void hcl_pushvolat (hcl_t* hcl, hcl_oop_t* oop_ptr) | ||||||
| void hcl_pushtmp (hcl_t* hcl, hcl_oop_t* oop_ptr) |  | ||||||
| { | { | ||||||
| 	/* if you have too many temporaries pushed, something must be wrong. | 	/* if you have too many temporaries pushed, something must be wrong. | ||||||
| 	 * change your code not to exceede the stack limit */ | 	 * change your code not to exceede the stack limit */ | ||||||
| 	HCL_ASSERT (hcl, hcl->tmp_count < HCL_COUNTOF(hcl->tmp_stack)); | 	HCL_ASSERT (hcl, hcl->volat_count < HCL_COUNTOF(hcl->volat_stack)); | ||||||
| 	hcl->tmp_stack[hcl->tmp_count++] = oop_ptr; | 	hcl->volat_stack[hcl->volat_count++] = oop_ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
| void hcl_poptmp (hcl_t* hcl) | void hcl_popvolat (hcl_t* hcl) | ||||||
| { | { | ||||||
| 	HCL_ASSERT (hcl, hcl->tmp_count > 0); | 	HCL_ASSERT (hcl, hcl->volat_count > 0); | ||||||
| 	hcl->tmp_count--; | 	hcl->volat_count--; | ||||||
| } | } | ||||||
|  |  | ||||||
| void hcl_poptmps (hcl_t* hcl, hcl_oow_t count) | void hcl_popvolats (hcl_t* hcl, hcl_oow_t count) | ||||||
| { | { | ||||||
| 	HCL_ASSERT (hcl, hcl->tmp_count >= count); | 	HCL_ASSERT (hcl, hcl->volat_count >= count); | ||||||
| 	hcl->tmp_count -= count; | 	hcl->volat_count -= count; | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -447,11 +718,11 @@ hcl_oop_t hcl_shallowcopy (hcl_t* hcl, hcl_oop_t oop) | |||||||
| 		hcl_oop_t z; | 		hcl_oop_t z; | ||||||
| 		hcl_oow_t total_bytes; | 		hcl_oow_t total_bytes; | ||||||
|  |  | ||||||
| 		total_bytes = HCL_SIZEOF(hcl_obj_t) + get_payload_bytes(hcl, oop); | 		total_bytes = HCL_SIZEOF(hcl_obj_t) + hcl_getobjpayloadbytes(hcl, oop); | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &oop); | 		hcl_pushvolat (hcl, &oop); | ||||||
| 		z = (hcl_oop_t)hcl_allocbytes (hcl, total_bytes); | 		z = (hcl_oop_t)hcl_allocbytes (hcl, total_bytes); | ||||||
| 		hcl_poptmp(hcl); | 		hcl_popvolat(hcl); | ||||||
|  |  | ||||||
| 		HCL_MEMCPY (z, oop, total_bytes); | 		HCL_MEMCPY (z, oop, total_bytes); | ||||||
| 		return z; | 		return z; | ||||||
| @ -526,12 +797,15 @@ int hcl_ignite (hcl_t* hcl) | |||||||
| 		hcl->processor->total_count = HCL_SMOOI_TO_OOP(0); | 		hcl->processor->total_count = HCL_SMOOI_TO_OOP(0); | ||||||
| 		hcl->processor->runnable.count = HCL_SMOOI_TO_OOP(0); | 		hcl->processor->runnable.count = HCL_SMOOI_TO_OOP(0); | ||||||
| 		hcl->processor->suspended.count = HCL_SMOOI_TO_OOP(0); | 		hcl->processor->suspended.count = HCL_SMOOI_TO_OOP(0); | ||||||
|  |  | ||||||
|  | 		/* commit the sp field of the initial active context to hcl->sp */ | ||||||
|  | 		hcl->sp = HCL_OOP_TO_SMOOI(hcl->processor->active->sp); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* TODO: move code.bc.ptr creation to hcl_init? */ | 	/* TODO: move code.bc.ptr creation to hcl_init? */ | ||||||
| 	if (!hcl->code.bc.ptr) | 	if (!hcl->code.bc.ptr) | ||||||
| 	{ | 	{ | ||||||
| 		hcl->code.bc.ptr = (hcl_oop_byte_t)hcl_allocmem(hcl, HCL_SIZEOF(*hcl->code.bc.ptr) * HCL_BC_BUFFER_INIT); /* TODO: set a proper intial size */ | 		hcl->code.bc.ptr = (hcl_oob_t*)hcl_allocmem(hcl, HCL_SIZEOF(*hcl->code.bc.ptr) * HCL_BC_BUFFER_INIT); /* TODO: set a proper intial size */ | ||||||
| 		if (HCL_UNLIKELY(!hcl->code.bc.ptr)) return -1; | 		if (HCL_UNLIKELY(!hcl->code.bc.ptr)) return -1; | ||||||
| 		HCL_ASSERT (hcl, hcl->code.bc.len == 0); | 		HCL_ASSERT (hcl, hcl->code.bc.len == 0); | ||||||
| 		hcl->code.bc.capa = HCL_BC_BUFFER_INIT; | 		hcl->code.bc.capa = HCL_BC_BUFFER_INIT; | ||||||
| @ -546,6 +820,5 @@ int hcl_ignite (hcl_t* hcl) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl->p.e = hcl->_nil; | 	hcl->p.e = hcl->_nil; | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | |||||||
| @ -689,16 +689,26 @@ void hcl_killheap ( | |||||||
| 	hcl_heap_t* heap | 	hcl_heap_t* heap | ||||||
| ); | ); | ||||||
|  |  | ||||||
| /** | /**  | ||||||
|  * The hcl_allocheapmem() function allocates \a size bytes in the heap pointed |  * The hcl_allocheapmem() function allocates \a size bytes from the given heap | ||||||
|  * to by \a heap. |  * and clears it with zeros. | ||||||
|  * |  | ||||||
|  * \return memory pointer on success and #HCL_NULL on failure. |  | ||||||
|  */ |  */ | ||||||
| void* hcl_allocheapmem ( | void* hcl_callocheapmem ( | ||||||
| 	hcl_t*      hcl, | 	hcl_t*       hcl, | ||||||
| 	hcl_heap_t* heap, | 	hcl_heap_t*  heap, | ||||||
| 	hcl_oow_t   size | 	hcl_oow_t    size | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | void* hcl_callocheapmem_noerr ( | ||||||
|  | 	hcl_t*       hcl, | ||||||
|  | 	hcl_heap_t*  heap, | ||||||
|  | 	hcl_oow_t    size | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | void hcl_freeheapmem ( | ||||||
|  | 	hcl_t*       hcl, | ||||||
|  | 	hcl_heap_t*  heap, | ||||||
|  | 	void*        ptr | ||||||
| ); | ); | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
| @ -778,6 +788,20 @@ hcl_oop_process_t hcl_makeproc ( | |||||||
| 	hcl_t* hcl | 	hcl_t* hcl | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  | /* ========================================================================= */ | ||||||
|  | /* gc.c                                                                    */ | ||||||
|  | /* ========================================================================= */ | ||||||
|  |  | ||||||
|  | hcl_oow_t hcl_getobjpayloadbytes ( | ||||||
|  | 	hcl_t*    hcl, | ||||||
|  | 	hcl_oop_t oop | ||||||
|  | ); | ||||||
|  |  | ||||||
|  | void hcl_gc_ms_sweep_lazy ( | ||||||
|  | 	hcl_t*    moo, | ||||||
|  | 	hcl_oow_t allocsize | ||||||
|  | ); | ||||||
|  |  | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
| /* utf8.c                                                                    */ | /* utf8.c                                                                    */ | ||||||
| /* ========================================================================= */ | /* ========================================================================= */ | ||||||
|  | |||||||
| @ -138,6 +138,10 @@ int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t | |||||||
| 	hcl->log.ptr = (hcl_ooch_t*)hcl_allocmem(hcl, (hcl->log.capa + 1) * HCL_SIZEOF(*hcl->log.ptr));  | 	hcl->log.ptr = (hcl_ooch_t*)hcl_allocmem(hcl, (hcl->log.capa + 1) * HCL_SIZEOF(*hcl->log.ptr));  | ||||||
| 	if (HCL_UNLIKELY(!hcl->log.ptr)) goto oops; | 	if (HCL_UNLIKELY(!hcl->log.ptr)) goto oops; | ||||||
|  |  | ||||||
|  | 	hcl->gci.stack.capa = HCL_ALIGN_POW2(1, 1024); /* TODO: is this a good initial size? */ | ||||||
|  | 	hcl->gci.stack.ptr = hcl_allocmem(hcl, (hcl->gci.stack.capa + 1) * HCL_SIZEOF(*hcl->gci.stack.ptr)); | ||||||
|  | 	if (HCL_UNLIKELY(!hcl->gci.stack.ptr)) goto oops; | ||||||
|  |  | ||||||
| 	n = hcl_rbt_init(&hcl->modtab, hcl, HCL_SIZEOF(hcl_ooch_t), 1); | 	n = hcl_rbt_init(&hcl->modtab, hcl, HCL_SIZEOF(hcl_ooch_t), 1); | ||||||
| 	if (HCL_UNLIKELY(n <= -1)) goto oops; | 	if (HCL_UNLIKELY(n <= -1)) goto oops; | ||||||
| 	modtab_inited = 1; | 	modtab_inited = 1; | ||||||
| @ -153,21 +157,20 @@ int hcl_init (hcl_t* hcl, hcl_mmgr_t* mmgr, hcl_oow_t heapsz, const hcl_vmprim_t | |||||||
| 	hcl->proc_map_free_first = -1; | 	hcl->proc_map_free_first = -1; | ||||||
| 	hcl->proc_map_free_last = -1; | 	hcl->proc_map_free_last = -1; | ||||||
|  |  | ||||||
| 	/*hcl->permheap = hcl_makeheap (hcl, what is the best size???); | 	hcl->heap = hcl_makeheap(hcl, heapsz); | ||||||
| 	if (!hcl->curheap) goto oops; */ | 	if (HCL_UNLIKELY(!hcl->heap)) goto oops; | ||||||
| 	hcl->curheap = hcl_makeheap(hcl, heapsz); |  | ||||||
| 	if (HCL_UNLIKELY(!hcl->curheap)) goto oops; |  | ||||||
| 	hcl->newheap = hcl_makeheap(hcl, heapsz); |  | ||||||
| 	if (HCL_UNLIKELY(!hcl->newheap)) goto oops; |  | ||||||
|  |  | ||||||
| 	if (hcl->vmprim.dl_startup) hcl->vmprim.dl_startup (hcl); | 	if (hcl->vmprim.dl_startup) hcl->vmprim.dl_startup (hcl); | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
| oops: | oops: | ||||||
| 	if (hcl->newheap) hcl_killheap (hcl, hcl->newheap); | 	if (hcl->heap) hcl_killheap (hcl, hcl->heap); | ||||||
| 	if (hcl->curheap) hcl_killheap (hcl, hcl->curheap); |  | ||||||
| 	if (hcl->permheap) hcl_killheap (hcl, hcl->permheap); |  | ||||||
| 	if (modtab_inited) hcl_rbt_fini (&hcl->modtab); | 	if (modtab_inited) hcl_rbt_fini (&hcl->modtab); | ||||||
|  | 	if (hcl->gci.stack.ptr) | ||||||
|  | 	{ | ||||||
|  | 		hcl_freemem (hcl, hcl->gci.stack.ptr); | ||||||
|  | 		hcl->gci.stack.capa = 0; | ||||||
|  | 	} | ||||||
| 	if (hcl->log.ptr) hcl_freemem (hcl, hcl->log.ptr); | 	if (hcl->log.ptr) hcl_freemem (hcl, hcl->log.ptr); | ||||||
| 	hcl->log.capa = 0; | 	hcl->log.capa = 0; | ||||||
| 	return -1; | 	return -1; | ||||||
| @ -277,9 +280,30 @@ void hcl_fini (hcl_t* hcl) | |||||||
| 		hcl->p.s.size = 0; | 		hcl->p.s.size = 0; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_killheap (hcl, hcl->newheap); | 	if (hcl->gci.b) | ||||||
| 	hcl_killheap (hcl, hcl->curheap); | 	{ | ||||||
| 	if (hcl->permheap) hcl_killheap (hcl, hcl->permheap); | 		hcl_gchdr_t* next; | ||||||
|  | 		do | ||||||
|  | 		{ | ||||||
|  | 			next = hcl->gci.b->next; | ||||||
|  | 			hcl->gci.bsz -= HCL_SIZEOF(hcl_obj_t) + hcl_getobjpayloadbytes(hcl, (hcl_oop_t)(hcl->gci.b + 1)); | ||||||
|  | 			hcl_freeheapmem (hcl, hcl->heap, hcl->gci.b); | ||||||
|  | 			hcl->gci.b = next; | ||||||
|  | 		} | ||||||
|  | 		while (hcl->gci.b); | ||||||
|  |  | ||||||
|  | 		HCL_ASSERT (hcl, hcl->gci.bsz == 0); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (hcl->gci.stack.ptr) | ||||||
|  | 	{ | ||||||
|  | 		hcl_freemem (hcl, hcl->gci.stack.ptr); | ||||||
|  | 		hcl->gci.stack.ptr = 0; | ||||||
|  | 		hcl->gci.stack.capa = 0; | ||||||
|  | 		hcl->gci.stack.len = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	hcl_killheap (hcl, hcl->heap); | ||||||
|  |  | ||||||
| 	if (hcl->log.ptr)  | 	if (hcl->log.ptr)  | ||||||
| 	{ | 	{ | ||||||
| @ -337,7 +361,7 @@ void hcl_reset (hcl_t* hcl) | |||||||
| 	hcl->code.lit.len = 0; | 	hcl->code.lit.len = 0; | ||||||
|  |  | ||||||
| 	/* clean up object memory */ | 	/* clean up object memory */ | ||||||
| 	hcl_gc (hcl); | 	hcl_gc (hcl, 1); | ||||||
| } | } | ||||||
|  |  | ||||||
| void hcl_setinloc (hcl_t* hcl, hcl_oow_t line, hcl_oow_t colm) | void hcl_setinloc (hcl_t* hcl, hcl_oow_t line, hcl_oow_t colm) | ||||||
|  | |||||||
| @ -27,8 +27,9 @@ | |||||||
| #ifndef _HCL_H_ | #ifndef _HCL_H_ | ||||||
| #define _HCL_H_ | #define _HCL_H_ | ||||||
|  |  | ||||||
| #include "hcl-cmn.h" | #include <hcl-cmn.h> | ||||||
| #include "hcl-rbt.h" | #include <hcl-rbt.h> | ||||||
|  | #include <hcl-xma.h> | ||||||
| #include <stdarg.h> | #include <stdarg.h> | ||||||
|  |  | ||||||
| /* TODO: move this macro out to the build files.... */ | /* TODO: move this macro out to the build files.... */ | ||||||
| @ -255,6 +256,16 @@ typedef struct hcl_obj_word_t*     hcl_oop_word_t; | |||||||
|  |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | /* ========================================================================= | ||||||
|  |  * HEADER FOR GC IMPLEMENTATION | ||||||
|  |  * ========================================================================= */ | ||||||
|  | typedef struct hcl_gchdr_t hcl_gchdr_t; | ||||||
|  | struct hcl_gchdr_t | ||||||
|  | { | ||||||
|  |         hcl_gchdr_t* next; | ||||||
|  | }; | ||||||
|  | /* The size of hcl_gchdr_t must be aligned to HCL_SIZEOF_OOP_T */ | ||||||
|  |  | ||||||
| /* ========================================================================= | /* ========================================================================= | ||||||
|  * OBJECT STRUCTURE |  * OBJECT STRUCTURE | ||||||
|  * ========================================================================= */ |  * ========================================================================= */ | ||||||
| @ -335,7 +346,7 @@ typedef enum hcl_obj_type_t hcl_obj_type_t; | |||||||
| #define HCL_OBJ_FLAGS_UNIT_BITS     5 | #define HCL_OBJ_FLAGS_UNIT_BITS     5 | ||||||
| #define HCL_OBJ_FLAGS_EXTRA_BITS    1 | #define HCL_OBJ_FLAGS_EXTRA_BITS    1 | ||||||
| #define HCL_OBJ_FLAGS_KERNEL_BITS   2 | #define HCL_OBJ_FLAGS_KERNEL_BITS   2 | ||||||
| #define HCL_OBJ_FLAGS_MOVED_BITS    1 | #define HCL_OBJ_FLAGS_MOVED_BITS    2 | ||||||
| #define HCL_OBJ_FLAGS_NGC_BITS      1 | #define HCL_OBJ_FLAGS_NGC_BITS      1 | ||||||
| #define HCL_OBJ_FLAGS_TRAILER_BITS  1 | #define HCL_OBJ_FLAGS_TRAILER_BITS  1 | ||||||
| #define HCL_OBJ_FLAGS_SYNCODE_BITS  4 | #define HCL_OBJ_FLAGS_SYNCODE_BITS  4 | ||||||
| @ -803,8 +814,9 @@ typedef struct hcl_heap_t hcl_heap_t; | |||||||
| struct hcl_heap_t | struct hcl_heap_t | ||||||
| { | { | ||||||
| 	hcl_uint8_t* base;  /* start of a heap */ | 	hcl_uint8_t* base;  /* start of a heap */ | ||||||
| 	hcl_uint8_t* limit; /* end of a heap */ | 	hcl_oow_t    size; | ||||||
| 	hcl_uint8_t* ptr;   /* next allocation pointer */ | 	hcl_xma_t*   xma; | ||||||
|  | 	hcl_mmgr_t   xmmgr; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /* ========================================================================= | /* ========================================================================= | ||||||
| @ -1344,9 +1356,7 @@ struct hcl_t | |||||||
| 	} log; | 	} log; | ||||||
| 	/* ========================= */ | 	/* ========================= */ | ||||||
|  |  | ||||||
| 	hcl_heap_t* permheap; /* TODO: put kernel objects to here */ | 	hcl_heap_t* heap; | ||||||
| 	hcl_heap_t* curheap; |  | ||||||
| 	hcl_heap_t* newheap; |  | ||||||
|  |  | ||||||
| 	/* ========================= */ | 	/* ========================= */ | ||||||
| 	hcl_oop_t _nil;  /* pointer to the nil object */ | 	hcl_oop_t _nil;  /* pointer to the nil object */ | ||||||
| @ -1400,9 +1410,6 @@ struct hcl_t | |||||||
| 	hcl_oow_t sem_io_map_capa; | 	hcl_oow_t sem_io_map_capa; | ||||||
| 	/* ============================================================================= */ | 	/* ============================================================================= */ | ||||||
|  |  | ||||||
| 	hcl_oop_t* tmp_stack[256]; /* stack for temporaries */ |  | ||||||
| 	hcl_oow_t tmp_count; |  | ||||||
|  |  | ||||||
| 	hcl_oop_t* proc_map; | 	hcl_oop_t* proc_map; | ||||||
| 	hcl_oow_t proc_map_capa; | 	hcl_oow_t proc_map_capa; | ||||||
| 	hcl_oow_t proc_map_used; | 	hcl_oow_t proc_map_used; | ||||||
| @ -1414,6 +1421,9 @@ struct hcl_t | |||||||
| 	 * are 3 */ | 	 * are 3 */ | ||||||
| 	int tagged_brands[16]; | 	int tagged_brands[16]; | ||||||
|  |  | ||||||
|  | 	hcl_oop_t* volat_stack[256]; /* stack for temporaries */ | ||||||
|  | 	hcl_oow_t volat_count; | ||||||
|  |  | ||||||
| 	/* == EXECUTION REGISTERS == */ | 	/* == EXECUTION REGISTERS == */ | ||||||
| 	hcl_oop_function_t initial_function; | 	hcl_oop_function_t initial_function; | ||||||
| 	hcl_oop_context_t initial_context; /* fake initial context */ | 	hcl_oop_context_t initial_context; /* fake initial context */ | ||||||
| @ -1493,6 +1503,34 @@ struct hcl_t | |||||||
| 	} p; | 	} p; | ||||||
| 	/* == PRINTER == */ | 	/* == PRINTER == */ | ||||||
|  |  | ||||||
|  | 	struct | ||||||
|  | 	{ | ||||||
|  | 		hcl_gchdr_t* b; /* object blocks allocated */ | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			hcl_gchdr_t* curr; | ||||||
|  | 			hcl_gchdr_t* prev; | ||||||
|  | 		} ls; | ||||||
|  | 		hcl_oow_t bsz; /* total size of object blocks allocated */ | ||||||
|  | 		hcl_oow_t threshold; | ||||||
|  | 		int lazy_sweep; | ||||||
|  |  | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			hcl_oop_t* ptr; | ||||||
|  | 			hcl_oow_t capa; | ||||||
|  | 			hcl_oow_t len; | ||||||
|  | 			hcl_oow_t max; | ||||||
|  | 		} stack; | ||||||
|  |  | ||||||
|  | 		struct | ||||||
|  | 		{ | ||||||
|  | 			hcl_ntime_t alloc; | ||||||
|  | 			hcl_ntime_t mark; | ||||||
|  | 			hcl_ntime_t sweep; | ||||||
|  | 		} stat; | ||||||
|  | 	} gci; | ||||||
|  |  | ||||||
| #if defined(HCL_INCLUDE_COMPILER) | #if defined(HCL_INCLUDE_COMPILER) | ||||||
| 	hcl_compiler_t* c; | 	hcl_compiler_t* c; | ||||||
| #endif | #endif | ||||||
| @ -1797,7 +1835,8 @@ HCL_EXPORT void hcl_deregcb ( | |||||||
|  * It is not affected by #HCL_TRAIT_NOGC. |  * It is not affected by #HCL_TRAIT_NOGC. | ||||||
|  */ |  */ | ||||||
| HCL_EXPORT void hcl_gc ( | HCL_EXPORT void hcl_gc ( | ||||||
| 	hcl_t* hcl | 	hcl_t* hcl, | ||||||
|  | 	int    full | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -1812,12 +1851,6 @@ hcl_oop_t hcl_moveoop ( | |||||||
| 	hcl_oop_t  oop | 	hcl_oop_t  oop | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  |  | ||||||
| HCL_EXPORT hcl_oow_t hcl_getpayloadbytes ( |  | ||||||
| 	hcl_t*    hcl, |  | ||||||
| 	hcl_oop_t oop |  | ||||||
| ); |  | ||||||
|  |  | ||||||
| HCL_EXPORT hcl_oop_t hcl_shallowcopy ( | HCL_EXPORT hcl_oop_t hcl_shallowcopy ( | ||||||
| 	hcl_t*          hcl, | 	hcl_t*          hcl, | ||||||
| 	hcl_oop_t       oop | 	hcl_oop_t       oop | ||||||
| @ -1974,16 +2007,16 @@ HCL_EXPORT void hcl_setsynerrufmt ( | |||||||
| /* ========================================================================= | /* ========================================================================= | ||||||
|  * TEMPORARY OOP MANAGEMENT FUNCTIONS |  * TEMPORARY OOP MANAGEMENT FUNCTIONS | ||||||
|  * ========================================================================= */ |  * ========================================================================= */ | ||||||
| HCL_EXPORT void hcl_pushtmp ( | HCL_EXPORT void hcl_pushvolat ( | ||||||
| 	hcl_t*     hcl, | 	hcl_t*     hcl, | ||||||
| 	hcl_oop_t* oop_ptr | 	hcl_oop_t* oop_ptr | ||||||
| ); | ); | ||||||
|  |  | ||||||
| HCL_EXPORT void hcl_poptmp ( | HCL_EXPORT void hcl_popvolat ( | ||||||
| 	hcl_t*     hcl | 	hcl_t*     hcl | ||||||
| ); | ); | ||||||
|  |  | ||||||
| HCL_EXPORT void hcl_poptmps ( | HCL_EXPORT void hcl_popvolats ( | ||||||
| 	hcl_t*     hcl, | 	hcl_t*     hcl, | ||||||
| 	hcl_oow_t  count | 	hcl_oow_t  count | ||||||
| ); | ); | ||||||
|  | |||||||
| @ -26,55 +26,96 @@ | |||||||
|  |  | ||||||
| #include "hcl-prv.h" | #include "hcl-prv.h" | ||||||
|  |  | ||||||
|  | static void* xma_alloc (hcl_mmgr_t* mmgr, hcl_oow_t size) | ||||||
|  | { | ||||||
|  | 	return hcl_xma_alloc(mmgr->ctx, size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void* xma_realloc (hcl_mmgr_t* mmgr, void* ptr, hcl_oow_t size) | ||||||
|  | { | ||||||
|  | 	return hcl_xma_realloc(mmgr->ctx, ptr, size); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void xma_free (hcl_mmgr_t* mmgr, void* ptr) | ||||||
|  | { | ||||||
|  | 	return hcl_xma_free (mmgr->ctx, ptr); | ||||||
|  | } | ||||||
|  |  | ||||||
| hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size) | hcl_heap_t* hcl_makeheap (hcl_t* hcl, hcl_oow_t size) | ||||||
| { | { | ||||||
| 	hcl_heap_t* heap; | 	hcl_heap_t* heap; | ||||||
|  |  | ||||||
| 	heap = (hcl_heap_t*)hcl->vmprim.alloc_heap(hcl, HCL_SIZEOF(*heap) + size); | 	heap = (hcl_heap_t*)hcl->vmprim.alloc_heap(hcl, HCL_SIZEOF(*heap) + size); | ||||||
| 	if (!heap) | 	if (HCL_UNLIKELY(!heap)) | ||||||
| 	{ | 	{ | ||||||
| 		hcl_seterrnum (hcl, HCL_ESYSMEM); | 		const hcl_ooch_t* oldmsg = hcl_backuperrmsg(hcl); | ||||||
|  | 		hcl_seterrbfmt (hcl, hcl_geterrnum(hcl), "unable to allocate a heap - %js", oldmsg); | ||||||
| 		return HCL_NULL; | 		return HCL_NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	HCL_MEMSET (heap, 0, HCL_SIZEOF(*heap) + size); | 	HCL_MEMSET (heap, 0, HCL_SIZEOF(*heap) + size); | ||||||
|  |  | ||||||
| 	heap->base = (hcl_uint8_t*)(heap + 1); | 	heap->base = (hcl_uint8_t*)(heap + 1); | ||||||
| 	/* adjust the initial allocation pointer to a multiple of the oop size */ | 	heap->size = size; | ||||||
| 	heap->ptr = (hcl_uint8_t*)HCL_ALIGN(((hcl_uintptr_t)heap->base), HCL_SIZEOF(hcl_oop_t)); |  | ||||||
| 	heap->limit = heap->base + size; |  | ||||||
|  |  | ||||||
| 	HCL_ASSERT (hcl, heap->ptr >= heap->base); |  | ||||||
| 	HCL_ASSERT (hcl, heap->limit >= heap->base );  |  | ||||||
| 	HCL_ASSERT (hcl, heap->limit - heap->base == size); |  | ||||||
|  |  | ||||||
| 	/* if size is too small, heap->ptr may go past heap->limit even at  | 	if (size <= 0) | ||||||
| 	 * this moment depending on the alignment of heap->base. subsequent | 	{ | ||||||
| 	 * calls to subhcl_allocheapmem() are bound to fail. Make sure to | 		/* use the existing memory allocator */ | ||||||
| 	 * pass a heap size large enough */ | 		heap->xmmgr = *hcl_getmmgr(hcl); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 	{ | ||||||
|  | 		/* create a new memory allocator over the allocated heap */ | ||||||
|  | 		heap->xma = hcl_xma_open(hcl_getmmgr(hcl), 0, heap->base, heap->size); | ||||||
|  | 		if (HCL_UNLIKELY(!heap->xma)) | ||||||
|  | 		{ | ||||||
|  | 			hcl->vmprim.free_heap (hcl, heap); | ||||||
|  | 			hcl_seterrbfmt (hcl, HCL_ESYSMEM, "unable to allocate xma"); | ||||||
|  | 			return HCL_NULL; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		heap->xmmgr.alloc = xma_alloc; | ||||||
|  | 		heap->xmmgr.realloc = xma_realloc; | ||||||
|  | 		heap->xmmgr.free = xma_free; | ||||||
|  | 		heap->xmmgr.ctx = heap->xma; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return heap; | 	return heap; | ||||||
| } | } | ||||||
|  |  | ||||||
| void hcl_killheap (hcl_t* hcl, hcl_heap_t* heap) | void hcl_killheap (hcl_t* hcl, hcl_heap_t* heap) | ||||||
| { | { | ||||||
|  | 	if (heap->xma) hcl_xma_close (heap->xma); | ||||||
| 	hcl->vmprim.free_heap (hcl, heap); | 	hcl->vmprim.free_heap (hcl, heap); | ||||||
| } | } | ||||||
|  |  | ||||||
| void* hcl_allocheapmem (hcl_t* hcl, hcl_heap_t* heap, hcl_oow_t size) | void* hcl_callocheapmem (hcl_t* hcl, hcl_heap_t* heap, hcl_oow_t size) | ||||||
| { | { | ||||||
| 	hcl_uint8_t* ptr; | 	void* ptr; | ||||||
|  |  | ||||||
| 	/* check the heap size limit */ | 	ptr = HCL_MMGR_ALLOC(&heap->xmmgr, size); | ||||||
| 	if (heap->ptr >= heap->limit || heap->limit - heap->ptr < size) | 	if (HCL_UNLIKELY(!ptr))  | ||||||
| 	{ | 	{ | ||||||
|  | 		HCL_DEBUG2 (hcl, "Cannot callocate %zd bytes from heap - ptr %p\n", size, heap); | ||||||
| 		hcl_seterrnum (hcl, HCL_EOOMEM); | 		hcl_seterrnum (hcl, HCL_EOOMEM); | ||||||
| 		return HCL_NULL; |  | ||||||
| 	} | 	} | ||||||
|  | 	else | ||||||
| 	/* allocation is as simple as moving the heap pointer */ | 	{ | ||||||
| 	ptr = heap->ptr; | 		HCL_MEMSET (ptr, 0, size); | ||||||
| 	heap->ptr += size; | 	} | ||||||
|  |  | ||||||
| 	return ptr; | 	return ptr; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void* hcl_callocheapmem_noerr (hcl_t* hcl, hcl_heap_t* heap, hcl_oow_t size) | ||||||
|  | { | ||||||
|  | 	void* ptr; | ||||||
|  | 	ptr = HCL_MMGR_ALLOC(&heap->xmmgr, size); | ||||||
|  | 	if (HCL_LIKELY(ptr)) HCL_MEMSET (ptr, 0, size); | ||||||
|  | 	return ptr; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void hcl_freeheapmem (hcl_t* hcl, hcl_heap_t* heap, void* ptr) | ||||||
|  | { | ||||||
|  | 	HCL_MMGR_FREE (&heap->xmmgr, ptr); | ||||||
|  | } | ||||||
|  | |||||||
| @ -127,17 +127,17 @@ hcl_oop_t hcl_addnums (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_oop_t v; | 		hcl_oop_t v; | ||||||
| 		hcl_ooi_t scale; | 		hcl_ooi_t scale; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
|  |  | ||||||
| 		scale = equalize_scale(hcl, &x, &y); | 		scale = equalize_scale(hcl, &x, &y); | ||||||
| 		if (scale <= -1)  | 		if (scale <= -1)  | ||||||
| 		{ | 		{ | ||||||
| 			hcl_poptmps (hcl, 2); | 			hcl_popvolats (hcl, 2); | ||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		v = hcl_addints(hcl, ((hcl_oop_fpdec_t)x)->value, ((hcl_oop_fpdec_t)y)->value); | 		v = hcl_addints(hcl, ((hcl_oop_fpdec_t)x)->value, ((hcl_oop_fpdec_t)y)->value); | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!v) return HCL_NULL; | 		if (!v) return HCL_NULL; | ||||||
|  |  | ||||||
| 		return hcl_makefpdec(hcl, v, scale); | 		return hcl_makefpdec(hcl, v, scale); | ||||||
| @ -156,17 +156,17 @@ hcl_oop_t hcl_subnums (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
| 		hcl_oop_t v; | 		hcl_oop_t v; | ||||||
| 		hcl_ooi_t scale; | 		hcl_ooi_t scale; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
|  |  | ||||||
| 		scale = equalize_scale(hcl, &x, &y); | 		scale = equalize_scale(hcl, &x, &y); | ||||||
| 		if (scale <= -1)  | 		if (scale <= -1)  | ||||||
| 		{ | 		{ | ||||||
| 			hcl_poptmps (hcl, 2); | 			hcl_popvolats (hcl, 2); | ||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		v = hcl_subints(hcl, ((hcl_oop_fpdec_t)x)->value, ((hcl_oop_fpdec_t)y)->value); | 		v = hcl_subints(hcl, ((hcl_oop_fpdec_t)x)->value, ((hcl_oop_fpdec_t)y)->value); | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		if (!v) return HCL_NULL; | 		if (!v) return HCL_NULL; | ||||||
|  |  | ||||||
| 		return hcl_makefpdec(hcl, v, scale); | 		return hcl_makefpdec(hcl, v, scale); | ||||||
| @ -269,19 +269,19 @@ hcl_oop_t hcl_divnums (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y) | |||||||
|  |  | ||||||
| 	nv = xv; | 	nv = xv; | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &yv); | 	hcl_pushvolat (hcl, &yv); | ||||||
| 	for (i = 0; i < ys; i++) | 	for (i = 0; i < ys; i++) | ||||||
| 	{ | 	{ | ||||||
| 		nv = hcl_mulints(hcl, nv, HCL_SMOOI_TO_OOP(10)); | 		nv = hcl_mulints(hcl, nv, HCL_SMOOI_TO_OOP(10)); | ||||||
| 		if (!nv)  | 		if (!nv)  | ||||||
| 		{ | 		{ | ||||||
| 			hcl_poptmp (hcl); | 			hcl_popvolat (hcl); | ||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	nv = hcl_divints(hcl, nv, yv, 0, HCL_NULL); | 	nv = hcl_divints(hcl, nv, yv, 0, HCL_NULL); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!nv) return HCL_NULL; | 	if (!nv) return HCL_NULL; | ||||||
|  |  | ||||||
| 	return hcl_makefpdec(hcl, nv, xs); | 	return hcl_makefpdec(hcl, nv, xs); | ||||||
| @ -299,17 +299,17 @@ static hcl_oop_t comp_nums (hcl_t* hcl, hcl_oop_t x, hcl_oop_t y, hcl_oop_t (*co | |||||||
| 		hcl_oop_t v; | 		hcl_oop_t v; | ||||||
| 		hcl_ooi_t scale; | 		hcl_ooi_t scale; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &x); | 		hcl_pushvolat (hcl, &x); | ||||||
| 		hcl_pushtmp (hcl, &y); | 		hcl_pushvolat (hcl, &y); | ||||||
|  |  | ||||||
| 		scale = equalize_scale(hcl, &x, &y); | 		scale = equalize_scale(hcl, &x, &y); | ||||||
| 		if (scale <= -1)  | 		if (scale <= -1)  | ||||||
| 		{ | 		{ | ||||||
| 			hcl_poptmps (hcl, 2); | 			hcl_popvolats (hcl, 2); | ||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
| 		v = comper(hcl, ((hcl_oop_fpdec_t)x)->value, ((hcl_oop_fpdec_t)y)->value); | 		v = comper(hcl, ((hcl_oop_fpdec_t)x)->value, ((hcl_oop_fpdec_t)y)->value); | ||||||
| 		hcl_poptmps (hcl, 2); | 		hcl_popvolats (hcl, 2); | ||||||
| 		return v; | 		return v; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @ -362,7 +362,7 @@ hcl_oop_t hcl_sqrtnum (hcl_t* hcl, hcl_oop_t x) | |||||||
| 			v = hcl_mulints(hcl, v, HCL_SMOOI_TO_OOP(10)); | 			v = hcl_mulints(hcl, v, HCL_SMOOI_TO_OOP(10)); | ||||||
| 			if (!v) | 			if (!v) | ||||||
| 			{ | 			{ | ||||||
| 				hcl_poptmp (hcl); | 				hcl_popvolat (hcl); | ||||||
| 				return HCL_NULL; | 				return HCL_NULL; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
							
								
								
									
										109
									
								
								hcl/lib/obj.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								hcl/lib/obj.c
									
									
									
									
									
								
							| @ -26,29 +26,88 @@ | |||||||
|  |  | ||||||
| #include "hcl-prv.h" | #include "hcl-prv.h" | ||||||
|  |  | ||||||
| void* hcl_allocbytes (hcl_t* hcl, hcl_oow_t size) |  | ||||||
| { |  | ||||||
| 	hcl_uint8_t* ptr; |  | ||||||
|  |  | ||||||
| #if defined(HCL_BUILD_DEBUG) | #if defined(HCL_PROFILE_VM) | ||||||
| 	if ((hcl->option.trait & HCL_TRAIT_DEBUG_GC) && !(hcl->option.trait & HCL_TRAIT_NOGC)) hcl_gc (hcl); | #include <sys/time.h> | ||||||
|  | #include <sys/resource.h> /* getrusage */ | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| 	ptr = (hcl_uint8_t*)hcl_allocheapmem(hcl, hcl->curheap, size); | void* hcl_allocbytes (hcl_t* hcl, hcl_oow_t size) | ||||||
| 	if (!ptr && hcl->errnum == HCL_EOOMEM && !(hcl->option.trait & HCL_TRAIT_NOGC)) | { | ||||||
|  | 	hcl_gchdr_t* gch; | ||||||
|  | 	hcl_oow_t allocsize; | ||||||
|  | 	int gc_called = 0; | ||||||
|  |  | ||||||
|  | #if defined(HCL_BUILD_DEBUG) | ||||||
|  | 	if ((hcl->option.trait & HCL_TRAIT_DEBUG_GC) && !(hcl->option.trait & HCL_TRAIT_NOGC)) hcl_gc (hcl, 1); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	struct rusage ru; | ||||||
|  | 	hcl_ntime_t rut; | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_INIT_NTIME (&rut,  ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | 	allocsize = HCL_SIZEOF(*gch) + size; | ||||||
|  |  | ||||||
|  | 	if (hcl->gci.bsz >= hcl->gci.threshold)  | ||||||
| 	{ | 	{ | ||||||
| 		hcl_gc (hcl); | 		hcl_gc (hcl, 0); | ||||||
| 		HCL_LOG4 (hcl, HCL_LOG_GC | HCL_LOG_INFO, | 		hcl->gci.threshold = hcl->gci.bsz + 100000; /* TODO: change this fomula */ | ||||||
| 			"GC completed - current heap ptr %p limit %p size %zd free %zd\n",  | 		gc_called = 1; | ||||||
| 			hcl->curheap->ptr, hcl->curheap->limit, |  | ||||||
| 			(hcl_oow_t)(hcl->curheap->limit - hcl->curheap->base), |  | ||||||
| 			(hcl_oow_t)(hcl->curheap->limit - hcl->curheap->ptr) |  | ||||||
| 		); |  | ||||||
| 		ptr = (hcl_uint8_t*)hcl_allocheapmem (hcl, hcl->curheap, size); |  | ||||||
| /* TODO: grow heap if ptr is still null. */ |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return ptr; | 	if (hcl->gci.lazy_sweep) hcl_gc_ms_sweep_lazy (hcl, allocsize); | ||||||
|  |  | ||||||
|  | 	gch = (hcl_gchdr_t*)hcl_callocheapmem_noerr(hcl, hcl->heap, allocsize);  | ||||||
|  | 	if (!gch) | ||||||
|  | 	{ | ||||||
|  | 		if (HCL_UNLIKELY(hcl->option.trait & HCL_TRAIT_NOGC)) goto calloc_heapmem_fail; | ||||||
|  | 		if (gc_called) goto sweep_the_rest; | ||||||
|  |  | ||||||
|  | 		hcl_gc (hcl, 0); | ||||||
|  | 		if (hcl->gci.lazy_sweep) hcl_gc_ms_sweep_lazy (hcl, allocsize); | ||||||
|  |  | ||||||
|  | 		gch = (hcl_gchdr_t*)hcl_callocheapmem_noerr(hcl, hcl->heap, allocsize);  | ||||||
|  | 		if (HCL_UNLIKELY(!gch))  | ||||||
|  | 		{ | ||||||
|  | 		sweep_the_rest: | ||||||
|  | 			if (hcl->gci.lazy_sweep) | ||||||
|  | 			{ | ||||||
|  | 				hcl_gc_ms_sweep_lazy (hcl, HCL_TYPE_MAX(hcl_oow_t)); /* sweep the rest */ | ||||||
|  | 				gch = (hcl_gchdr_t*)hcl_callocheapmem(hcl, hcl->heap, allocsize);  | ||||||
|  | 				if (HCL_UNLIKELY(!gch)) return HCL_NULL; | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 			{ | ||||||
|  | 			calloc_heapmem_fail: | ||||||
|  | 				hcl_seterrnum (hcl, HCL_EOOMEM); | ||||||
|  | 				return HCL_NULL; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if (hcl->gci.lazy_sweep && hcl->gci.ls.curr == hcl->gci.b)  | ||||||
|  | 	{ | ||||||
|  | 		/* if the lazy sweeping point is at the beginning of the allocation block, | ||||||
|  | 		 * hcl->gc.ls.prev must get updated */ | ||||||
|  | 		HCL_ASSERT (hcl, hcl->gci.ls.prev == HCL_NULL); | ||||||
|  | 		hcl->gci.ls.prev = gch; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	gch->next = hcl->gci.b; | ||||||
|  | 	hcl->gci.b = gch; | ||||||
|  | 	hcl->gci.bsz += size; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #if defined(HCL_PROFILE_VM) | ||||||
|  | 	getrusage(RUSAGE_SELF, &ru); | ||||||
|  | 	HCL_SUB_NTIME_SNS (&rut, &rut, ru.ru_utime.tv_sec, HCL_USEC_TO_NSEC(ru.ru_utime.tv_usec)); | ||||||
|  | 	HCL_SUB_NTIME (&hcl->gci.stat.alloc, &hcl->gci.stat.alloc, &rut); /* do subtraction because rut is negative */ | ||||||
|  | #endif | ||||||
|  | 	return (hcl_uint8_t*)(gch + 1); | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| static HCL_INLINE hcl_oop_t alloc_oop_array (hcl_t* hcl, int brand, hcl_oow_t size, int ngc) | static HCL_INLINE hcl_oop_t alloc_oop_array (hcl_t* hcl, int brand, hcl_oow_t size, int ngc) | ||||||
| @ -149,7 +208,7 @@ static HCL_INLINE hcl_oop_t alloc_numeric_array (hcl_t* hcl, int brand, const vo | |||||||
| 		hdr = (hcl_oop_t)hcl_callocmem(hcl, HCL_SIZEOF(hcl_obj_t) + nbytes_aligned); | 		hdr = (hcl_oop_t)hcl_callocmem(hcl, HCL_SIZEOF(hcl_obj_t) + nbytes_aligned); | ||||||
| 	else | 	else | ||||||
| 		hdr = (hcl_oop_t)hcl_allocbytes(hcl, HCL_SIZEOF(hcl_obj_t) + nbytes_aligned); | 		hdr = (hcl_oop_t)hcl_allocbytes(hcl, HCL_SIZEOF(hcl_obj_t) + nbytes_aligned); | ||||||
| 	if (!hdr) return HCL_NULL; | 	if (HCL_UNLIKELY(!hdr)) return HCL_NULL; | ||||||
|  |  | ||||||
| 	hdr->_flags = HCL_OBJ_MAKE_FLAGS(type, unit, extra, 0, 0, ngc, 0, 0); | 	hdr->_flags = HCL_OBJ_MAKE_FLAGS(type, unit, extra, 0, 0, ngc, 0, 0); | ||||||
| 	hdr->_size = len; | 	hdr->_size = len; | ||||||
| @ -235,8 +294,8 @@ hcl_oop_t hcl_makecons (hcl_t* hcl, hcl_oop_t car, hcl_oop_t cdr) | |||||||
| { | { | ||||||
| 	hcl_oop_cons_t cons; | 	hcl_oop_cons_t cons; | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, &car); | 	hcl_pushvolat (hcl, &car); | ||||||
| 	hcl_pushtmp (hcl, &cdr); | 	hcl_pushvolat (hcl, &cdr); | ||||||
|  |  | ||||||
| 	cons = (hcl_oop_cons_t)hcl_allocoopobj(hcl, HCL_BRAND_CONS, 2); | 	cons = (hcl_oop_cons_t)hcl_allocoopobj(hcl, HCL_BRAND_CONS, 2); | ||||||
| 	if (cons) | 	if (cons) | ||||||
| @ -245,7 +304,7 @@ hcl_oop_t hcl_makecons (hcl_t* hcl, hcl_oop_t car, hcl_oop_t cdr) | |||||||
| 		cons->cdr = cdr; | 		cons->cdr = cdr; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_poptmps (hcl, 2); | 	hcl_popvolats (hcl, 2); | ||||||
|  |  | ||||||
| 	return (hcl_oop_t)cons; | 	return (hcl_oop_t)cons; | ||||||
| } | } | ||||||
| @ -281,9 +340,9 @@ hcl_oop_t hcl_makefpdec (hcl_t* hcl, hcl_oop_t value, hcl_ooi_t scale) | |||||||
| 		return HCL_NULL; | 		return HCL_NULL; | ||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	hcl_pushtmp (hcl, &value); | 	hcl_pushvolat (hcl, &value); | ||||||
| 	f = (hcl_oop_fpdec_t)hcl_allocoopobj (hcl, HCL_BRAND_FPDEC, HCL_FPDEC_NAMED_INSTVARS); | 	f = (hcl_oop_fpdec_t)hcl_allocoopobj (hcl, HCL_BRAND_FPDEC, HCL_FPDEC_NAMED_INSTVARS); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
|  |  | ||||||
| 	if (!f) return HCL_NULL; | 	if (!f) return HCL_NULL; | ||||||
|  |  | ||||||
| @ -313,7 +372,7 @@ hcl_oop_t hcl_remakengcbytearray (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t newsize) | |||||||
|  |  | ||||||
| 	HCL_ASSERT (hcl, !obj || (HCL_OOP_IS_POINTER(obj) && HCL_OBJ_GET_FLAGS_NGC(obj))); | 	HCL_ASSERT (hcl, !obj || (HCL_OOP_IS_POINTER(obj) && HCL_OBJ_GET_FLAGS_NGC(obj))); | ||||||
|  |  | ||||||
| 	/* no hcl_pushtmp() is needed because 'obj' is a non-GC object. */ | 	/* no hcl_pushvolat() is needed because 'obj' is a non-GC object. */ | ||||||
| 	/* TODO: improve this by using realloc */ | 	/* TODO: improve this by using realloc */ | ||||||
|  |  | ||||||
| 	tmp = hcl_makengcbytearray (hcl, HCL_NULL, newsize); | 	tmp = hcl_makengcbytearray (hcl, HCL_NULL, newsize); | ||||||
| @ -341,7 +400,7 @@ hcl_oop_t hcl_remakengcarray (hcl_t* hcl, hcl_oop_t obj, hcl_oow_t newsize) | |||||||
|  |  | ||||||
| 	HCL_ASSERT (hcl, !obj || (HCL_OOP_IS_POINTER(obj) && HCL_OBJ_GET_FLAGS_NGC(obj))); | 	HCL_ASSERT (hcl, !obj || (HCL_OOP_IS_POINTER(obj) && HCL_OBJ_GET_FLAGS_NGC(obj))); | ||||||
|  |  | ||||||
| 	/* no hcl_pushtmp() is needed because 'obj' is a non-GC object. */ | 	/* no hcl_pushvolat() is needed because 'obj' is a non-GC object. */ | ||||||
| 	/* TODO: improve this by using realloc */ | 	/* TODO: improve this by using realloc */ | ||||||
|  |  | ||||||
| 	tmp = hcl_makengcarray (hcl, newsize); | 	tmp = hcl_makengcarray (hcl, newsize); | ||||||
|  | |||||||
| @ -219,7 +219,7 @@ static hcl_pfrc_t pf_sprintf (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) | |||||||
|  |  | ||||||
| static hcl_pfrc_t pf_gc (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) | static hcl_pfrc_t pf_gc (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) | ||||||
| { | { | ||||||
| 	hcl_gc (hcl); | 	hcl_gc (hcl, 1); | ||||||
| 	HCL_STACK_SETRET (hcl, nargs, hcl->_nil); | 	HCL_STACK_SETRET (hcl, nargs, hcl->_nil); | ||||||
| 	return HCL_PF_SUCCESS; | 	return HCL_PF_SUCCESS; | ||||||
| } | } | ||||||
| @ -850,17 +850,17 @@ int hcl_addbuiltinprims (hcl_t* hcl) | |||||||
| 	for (i = 0; i < HCL_COUNTOF(builtin_prims); i++) | 	for (i = 0; i < HCL_COUNTOF(builtin_prims); i++) | ||||||
| 	{ | 	{ | ||||||
| 		prim = hcl_makeprim(hcl, builtin_prims[i].impl, builtin_prims[i].minargs, builtin_prims[i].maxargs, HCL_NULL); | 		prim = hcl_makeprim(hcl, builtin_prims[i].impl, builtin_prims[i].minargs, builtin_prims[i].maxargs, HCL_NULL); | ||||||
| 		if (!prim) return -1; | 		if (HCL_UNLIKELY(!prim)) return -1; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &prim); | 		hcl_pushvolat (hcl, &prim); | ||||||
| 		name = hcl_makesymbol(hcl, builtin_prims[i].name, builtin_prims[i].namelen); | 		name = hcl_makesymbol(hcl, builtin_prims[i].name, builtin_prims[i].namelen); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!name) return -1; | 		if (HCL_UNLIKELY(!name)) return -1; | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &name); | 		hcl_pushvolat (hcl, &name); | ||||||
| 		cons = hcl_putatsysdic(hcl, name, prim); | 		cons = hcl_putatsysdic(hcl, name, prim); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!cons) return -1; | 		if (HCL_UNLIKELY(!cons)) return -1; | ||||||
|  |  | ||||||
| 		/* turn on the kernel bit in the symbol associated with a primitive  | 		/* turn on the kernel bit in the symbol associated with a primitive  | ||||||
| 		 * function. 'set' prevents this symbol from being used as a variable | 		 * function. 'set' prevents this symbol from being used as a variable | ||||||
|  | |||||||
| @ -1479,9 +1479,9 @@ static HCL_INLINE hcl_oop_t leave_list (hcl_t* hcl, int* flagv, int* oldflagv) | |||||||
| 			count++; | 			count++; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, &head); | 		hcl_pushvolat (hcl, &head); | ||||||
| 		arr = (hcl_oop_oop_t)hcl_makearray(hcl, count, 0); | 		arr = (hcl_oop_oop_t)hcl_makearray(hcl, count, 0); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!arr) return HCL_NULL; | 		if (!arr) return HCL_NULL; | ||||||
|  |  | ||||||
| 		ptr = head; | 		ptr = head; | ||||||
| @ -1692,9 +1692,9 @@ static hcl_oop_t chain_to_list (hcl_t* hcl, hcl_oop_t obj) | |||||||
| 			return HCL_NULL; | 			return HCL_NULL; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		hcl_pushtmp (hcl, (hcl_oop_t*)&rsa); | 		hcl_pushvolat (hcl, (hcl_oop_t*)&rsa); | ||||||
| 		cons = hcl_makecons(hcl, obj, hcl->_nil); | 		cons = hcl_makecons(hcl, obj, hcl->_nil); | ||||||
| 		hcl_poptmp (hcl); | 		hcl_popvolat (hcl); | ||||||
| 		if (!cons) return HCL_NULL; | 		if (!cons) return HCL_NULL; | ||||||
|  |  | ||||||
| 		if (HCL_IS_NIL(hcl, rsa->slot[0])) | 		if (HCL_IS_NIL(hcl, rsa->slot[0])) | ||||||
| @ -2094,7 +2094,7 @@ static int read_object (hcl_t* hcl) | |||||||
| 						return -1; | 						return -1; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					hcl_pushtmp (hcl, &obj); | 					hcl_pushvolat (hcl, &obj); | ||||||
| 					switch (pfbase->type) | 					switch (pfbase->type) | ||||||
| 					{ | 					{ | ||||||
| 						case HCL_PFBASE_FUNC: | 						case HCL_PFBASE_FUNC: | ||||||
| @ -2115,17 +2115,17 @@ static int read_object (hcl_t* hcl) | |||||||
| 							break; | 							break; | ||||||
|  |  | ||||||
| 						default: | 						default: | ||||||
| 							hcl_poptmp (hcl); | 							hcl_popvolat (hcl); | ||||||
| 							hcl_seterrbfmt (hcl, HCL_EINVAL, "invalid pfbase type - %d\n", pfbase->type); | 							hcl_seterrbfmt (hcl, HCL_EINVAL, "invalid pfbase type - %d\n", pfbase->type); | ||||||
| 							return -1; | 							return -1; | ||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 					if (!val || !hcl_putatsysdic(hcl, obj, val)) | 					if (!val || !hcl_putatsysdic(hcl, obj, val)) | ||||||
| 					{ | 					{ | ||||||
| 						hcl_poptmp (hcl); | 						hcl_popvolat (hcl); | ||||||
| 						return -1; | 						return -1; | ||||||
| 					} | 					} | ||||||
| 					hcl_poptmp (hcl); | 					hcl_popvolat (hcl); | ||||||
|  |  | ||||||
| 					/* make this dotted symbol special that it can't get changed | 					/* make this dotted symbol special that it can't get changed | ||||||
| 					 * to a different value */ | 					 * to a different value */ | ||||||
|  | |||||||
| @ -60,9 +60,9 @@ static hcl_oop_oop_t expand_bucket (hcl_t* hcl, hcl_oop_oop_t oldbuc) | |||||||
| 		newsz = oldsz + inc; | 		newsz = oldsz + inc; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	hcl_pushtmp (hcl, (hcl_oop_t*)&oldbuc); | 	hcl_pushvolat (hcl, (hcl_oop_t*)&oldbuc); | ||||||
| 	newbuc = (hcl_oop_oop_t)hcl_makearray(hcl, newsz, 0); | 	newbuc = (hcl_oop_oop_t)hcl_makearray(hcl, newsz, 0); | ||||||
| 	hcl_poptmp (hcl); | 	hcl_popvolat (hcl); | ||||||
| 	if (!newbuc) return HCL_NULL; | 	if (!newbuc) return HCL_NULL; | ||||||
|  |  | ||||||
| 	while (oldsz > 0) | 	while (oldsz > 0) | ||||||
|  | |||||||
| @ -108,7 +108,6 @@ static hcl_pfrc_t pf_sys_random (hcl_t* hcl, hcl_mod_t* mod, hcl_ooi_t nargs) | |||||||
|  |  | ||||||
| static hcl_pfinfo_t pfinfos[] = | static hcl_pfinfo_t pfinfos[] = | ||||||
| { | { | ||||||
| 	/*{ { 'V','A','R','\0' },                  { HCL_PFBASE_VAR,  HCL_NULL,           0,  0 } },*/ |  | ||||||
| 	{ { 'r','a','n','d','o','m','\0' },      { HCL_PFBASE_FUNC,  pf_sys_random,       0,  0 } }, | 	{ { 'r','a','n','d','o','m','\0' },      { HCL_PFBASE_FUNC,  pf_sys_random,       0,  0 } }, | ||||||
| 	{ { 's','r','a','n','d','o','m','\0' },  { HCL_PFBASE_FUNC,  pf_sys_srandom,      1,  1 } }, | 	{ { 's','r','a','n','d','o','m','\0' },  { HCL_PFBASE_FUNC,  pf_sys_srandom,      1,  1 } }, | ||||||
| 	{ { 's','t','i','m','e','\0' },          { HCL_PFBASE_FUNC,  pf_sys_stime,        1,  1 } }, | 	{ { 's','t','i','m','e','\0' },          { HCL_PFBASE_FUNC,  pf_sys_stime,        1,  1 } }, | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user