@@ -1240,6 +1240,53 @@ JL_DLLEXPORT jl_value_t *jl_gc_internal_obj_base_ptr(void *p)
12401240 return NULL ;
12411241}
12421242
1243+ #define jl_p_gcpreserve_stack (jl_current_task->gcpreserve_stack)
1244+
1245+ // This macro currently uses malloc instead of alloca because this function will exit
1246+ // after pushing the roots into the gc_preserve_stack, which means that the preserve_begin function's
1247+ // stack frame will be destroyed (together with its alloca variables). When we support lowering this code
1248+ // inside the same function that is doing the preserve_begin/preserve_end calls we should be able to simple use allocas.
1249+ // Note also that we use a separate stack for gc preserve roots to avoid the possibility of calling free
1250+ // on a stack that has been allocated with alloca instead of malloc, which could happen depending on the order in which
1251+ // JL_GC_POP() and jl_gc_preserve_end_hook() occurs.
1252+
1253+ #define JL_GC_PUSHARGS_PRESERVE_ROOT_OBJS (rts_var ,n ) \
1254+ rts_var = ((jl_value_t**)malloc(((n)+2)*sizeof(jl_value_t*)))+2; \
1255+ ((void**)rts_var)[-2] = (void*)JL_GC_ENCODE_PUSHARGS(n); \
1256+ ((void**)rts_var)[-1] = jl_p_gcpreserve_stack; \
1257+ memset((void*)rts_var, 0, (n)*sizeof(jl_value_t*)); \
1258+ jl_p_gcpreserve_stack = (jl_gcframe_t*)&(((void**)rts_var)[-2]); \
1259+
1260+ #define JL_GC_POP_PRESERVE_ROOT_OBJS () \
1261+ jl_gcframe_t *curr = jl_p_gcpreserve_stack; \
1262+ if(curr) { \
1263+ (jl_p_gcpreserve_stack = jl_p_gcpreserve_stack->prev); \
1264+ free(curr); \
1265+ }
1266+
1267+ // Add each argument as a tpin root object.
1268+ // However, we cannot use JL_GC_PUSH and JL_GC_POP since the slots should live
1269+ // beyond this function. Instead, we maintain a tpin stack by mallocing/freeing
1270+ // the frames for each of the preserve regions we encounter
1271+ JL_DLLEXPORT void jl_gc_preserve_begin_hook (int n , ...) JL_NOTSAFEPOINT
1272+ {
1273+ jl_value_t * * frame ;
1274+ JL_GC_PUSHARGS_PRESERVE_ROOT_OBJS (frame , n );
1275+ if (n == 0 ) return ;
1276+
1277+ va_list args ;
1278+ va_start (args , n );
1279+ for (int i = 0 ; i < n ; i ++ ) {
1280+ frame [i ] = va_arg (args , jl_value_t * );
1281+ }
1282+ va_end (args );
1283+ }
1284+
1285+ JL_DLLEXPORT void jl_gc_preserve_end_hook (void ) JL_NOTSAFEPOINT
1286+ {
1287+ JL_GC_POP_PRESERVE_ROOT_OBJS ();
1288+ }
1289+
12431290#ifdef __cplusplus
12441291}
12451292#endif
0 commit comments