Re: GC safety and return values Michael Sperber 27 Dec 2003 16:10 UTC
>>>>> "Tom" == Tom Lord <xxxxxx@emf.net> writes: Tom> jimb is correct. Right. I misunderstood him. Thanks for the clarifying example! Tom> Consider the code: Tom> scheme_value x; Tom> [...] Tom> GCPRO(&x); Tom> [...] Tom> z = SCHEME_CONS (x, y); /* XXX */ Tom> during execution of the the statement marked "XXX", the sequence Tom> over time of operations may be: Tom> thread 1: thread 2: Tom> | Tom> reg1 = x; - t Tom> reg2 = y; - i Tom> - trigger GC m Tom> call SCHEME_CONS - e Tom> (on return, - | Tom> reg1 holds new pair) - V Tom> - trigger GC Tom> z = reg1 - Tom> At the first GC, a stop-and-copy GC will want to modify the values Tom> stored in x and y, but it won't find reg1 and reg2. Tom> At the second GC, a stop-and-copy GC will want to modify the value Tom> about to be stored in z, but it won't find reg1. Tom> That is one reason why it isn't sufficient to make sure that protected Tom> scheme values are always stored in GCPROtected locations -- you must Tom> also make sure that, other than in the internals of the FFI Tom> implementation, they are not stored anywhere else. Tom> You can make that guarantee by not passing or returning those values Tom> directly at all -- but instead passing and returning "handles" for Tom> those values. Tom> Jimb and I have each shown a technique (so now you have two available) Tom> for always passing and returning handles: in jimb's approach, handles Tom> are separately allocated objects; in my approach, handles are the Tom> addresses of GCPROtected values. So you have either: Tom> scheme_value_handle x = 0; Tom> scheme_value_handle y = 0; Tom> scheme_value_handle z = 0; Tom> [....] Tom> z = SCHEME_CONS (this_call, x, y); Tom> /* caller frees any handles allocated above. */ Tom> or: Tom> struct my_frame Tom> { Tom> scheme_value x; Tom> scheme_value y; Tom> scheme_value z; Tom> } f; Tom> GCPRO_FRAME (f); Tom> [...] Tom> SCHEME_CONS (&f.z, this_instance, &f.x, &f.y); Tom> /* eventual GCUNPRO_FRAME needed */ Tom> (As I said elsewhere, I think that there are some performance and, Tom> more importantly, GC-precision advantages to the second approach.) Tom> Either approach also has advantages for single-threaded systems simply Tom> because they both make it harder to make certain kinds of mistakes Tom> that will lead to subtle and difficult-to-reproduce GC bugs. Tom> -t -- Cheers =8-} Mike Friede, Völkerverständigung und überhaupt blabla