|
From: | Peter Bex |
Subject: | [Chicken-hackers] [PATCH] Fix an off-by-one size calculation error in compiler |
Date: | Sat, 23 May 2015 16:15:14 +0200 |
User-agent: | Mutt/1.5.21 (2010-09-15) |
Hi all, While working on the numbers-integration branch, I stumbled across a bug that's been in CHICKEN for a while: when compiling something that involves a call to (list ...), it will generate a call to the inline allocating C function "C_a_i_list" with the calculated size of the number of items times three. Unfortunately, this is one word too short, as can be seen from the following definition from chicken.h: #define C_SIZEOF_LIST(n) ((n) * 3 + 1) Because it's "only" an off-by-one, it rarely causes issues (though it may explain a few mysterious bugs). A good example is the locative-stress-test: If you look at the generated C code, it will have generated code to allocate 90 words for storing a list of 10 items which are the result of conversion from the C "long" type. In the chicken-4 and master branches, this will look like this: /* k408 in loop in k475 in k383 in k303 in k300 in k297 in k294 */ static void C_ccall f_410(C_word c,C_word t0,C_word t1){ C_word tmp; C_word t2; C_word t3; C_word t4; C_word ab[70],*a=ab; C_check_for_interrupt; if(!C_stack_probe(&a)){ C_save_and_reclaim((void*)tr2,(void*)f_410,2,t0,t1);} t2=C_a_i_list(&a,10,C_long_to_num(&a,*((long *)C_data_pointer(((C_word*)t0)[2]))),C_long_to_num(&a,*((long *)C_d ata_pointer(((C_word*)t0)[3]))),C_long_to_num(&a,*((long *)C_data_pointer(((C_word*)t0)[4]))),C_long_to_num(&a,* ((long *)C_data_pointer(((C_word*)t0)[5]))),C_long_to_num(&a,*((long *)C_data_pointer(((C_word*)t0)[6]))),C_long _to_num(&a,*((long *)C_data_pointer(((C_word*)t0)[7]))),C_long_to_num(&a,*((long *)C_data_pointer(((C_word*)t0)[ 8]))),C_long_to_num(&a,*((long *)C_data_pointer(((C_word*)t0)[9]))),C_long_to_num(&a,*((long *)C_data_pointer((( C_word*)t0)[10]))),C_long_to_num(&a,*((long *)C_data_pointer(((C_word*)t0)[11])))); if(C_truep(C_i_equalp(t2,((C_word*)t0)[12]))){ t3=C_fixnum_difference(((C_word*)t0)[13],C_fix(1)); C_trace("locative-stress-test.scm:50: loop"); t4=((C_word*)((C_word*)t0)[14])[1]; f_400(t4,((C_word*)t0)[15],t3);} else{ C_trace("locative-stress-test.scm:49: error"); ((C_proc4)C_fast_retrieve_proc(*((C_word*)lf[3]+1)))(4,*((C_word*)lf[3]+1),((C_word*)t0)[15],lf[4],t2);}} If you check the &a's, you'll see it only passes it to C_stack_probe (which does not allocate), to C_a_i_list (which will use 31 words: 1 for the NIL at the end and 3 slots for each pair containing one number) and to the 10 calls to C_long_to_num (which use up 4 words each, as determined in the "long" part in estimate-foreign-result-size in support.scm). This gives us 31+40*1 = 71 words. As you can see, it misses one word. Usually this doesn't cause trouble, but it may trigger a bug when the stack is lined up *just* so. Attached are patches for the numbers-scratchspace, chicken-5 and master branches. Cheers, Peter
0001-Fix-size-calculation-for-generated-code-for-list-CHICKEN-5.patch
Description: Text Data
0001-Fix-size-calculation-for-generated-code-for-list-MASTER.patch
Description: Text Data
0001-Fix-size-calculation-for-generated-code-for-list-NUMBERS-INTEGRATION-SCRATCHSPACE.patch
Description: Text Data
signature.asc
Description: Digital signature
[Prev in Thread] | Current Thread | [Next in Thread] |