11#include "mmtk_julia.h"
22#include "mmtk.h"
3+ #include "mmtk_julia_types.h"
34#include <stdbool.h>
45#include <stddef.h>
56#include "gc.h"
@@ -233,239 +234,51 @@ int* get_jl_gc_have_pending_finalizers(void) {
233234 return (int * )& jl_gc_have_pending_finalizers ;
234235}
235236
236- // add the initial root set to mmtk roots
237- static void queue_roots (void )
238- {
239- // modules
240- mmtk_add_object_to_mmtk_roots (jl_main_module );
241-
242- // invisible builtin values
243- if (jl_an_empty_vec_any != NULL )
244- mmtk_add_object_to_mmtk_roots (jl_an_empty_vec_any );
245- if (jl_module_init_order != NULL )
246- mmtk_add_object_to_mmtk_roots (jl_module_init_order );
247- for (size_t i = 0 ; i < jl_current_modules .size ; i += 2 ) {
248- if (jl_current_modules .table [i + 1 ] != HT_NOTFOUND ) {
249- mmtk_add_object_to_mmtk_roots (jl_current_modules .table [i ]);
250- }
251- }
252- mmtk_add_object_to_mmtk_roots (jl_anytuple_type_type );
253- for (size_t i = 0 ; i < N_CALL_CACHE ; i ++ ) {
254- jl_typemap_entry_t * v = jl_atomic_load_relaxed (& call_cache [i ]);
255- if (v != NULL )
256- mmtk_add_object_to_mmtk_roots (v );
257- }
258- if (jl_all_methods != NULL )
259- mmtk_add_object_to_mmtk_roots (jl_all_methods );
260-
261- if (_jl_debug_method_invalidation != NULL )
262- mmtk_add_object_to_mmtk_roots (_jl_debug_method_invalidation );
263- // if (jl_build_ids != NULL)
264- // add_object_to_mmtk_roots(jl_build_ids);
265-
266- // constants
267- mmtk_add_object_to_mmtk_roots (jl_emptytuple_type );
268- if (cmpswap_names != NULL )
269- mmtk_add_object_to_mmtk_roots (cmpswap_names );
270- mmtk_add_object_to_mmtk_roots (jl_global_roots_table );
271-
272- }
273-
274- // Handle the case where the stack is only partially copied.
275- static inline uintptr_t mmtk_gc_get_stack_addr (void * _addr , uintptr_t offset ,
276- uintptr_t lb , uintptr_t ub )
277- {
278- uintptr_t addr = (uintptr_t )_addr ;
279- if (addr >= lb && addr < ub )
280- return addr + offset ;
281- return addr ;
282- }
283-
284- static inline uintptr_t mmtk_gc_read_stack (void * _addr , uintptr_t offset ,
285- uintptr_t lb , uintptr_t ub )
286- {
287- uintptr_t real_addr = mmtk_gc_get_stack_addr (_addr , offset , lb , ub );
288- return * (uintptr_t * )real_addr ;
289- }
290-
291- void scan_gcstack (jl_task_t * ta , void * closure , ProcessEdgeFn process_edge )
292- {
293- void * stkbuf = ta -> stkbuf ;
294- #ifdef COPY_STACKS
295- if (stkbuf && ta -> copy_stack && mmtk_object_is_managed_by_mmtk (ta -> stkbuf )) {
296- // printf("-copystack: %p\n", &ta->stkbuf);fflush(stdout);
297- process_edge (closure , & ta -> stkbuf );
298- }
299- #endif
300- jl_gcframe_t * s = ta -> gcstack ;
301- size_t nroots ;
302- uintptr_t offset = 0 ;
303- uintptr_t lb = 0 ;
304- uintptr_t ub = (uintptr_t )-1 ;
305- #ifdef COPY_STACKS
306- if (stkbuf && ta -> copy_stack && ta -> ptls == NULL ) {
307- assert (ta -> tid >= 0 );
308- jl_ptls_t ptls2 = jl_all_tls_states [ta -> tid ];
309- ub = (uintptr_t )ptls2 -> stackbase ;
310- lb = ub - ta -> copy_stack ;
311- offset = (uintptr_t )stkbuf - lb ;
312- }
313- #endif
314- if (s ) { // gc_mark_stack()
315- nroots = mmtk_gc_read_stack (& s -> nroots , offset , lb , ub );
316- assert (nroots <= UINT32_MAX );
317-
318- uint32_t nr = nroots >> 2 ;
319-
320- while (1 ) {
321- jl_value_t * * * rts = (jl_value_t * * * )(((void * * )s ) + 2 );
322- for (uint32_t i = 0 ; i < nr ; i ++ ) {
323- if (nroots & 1 ) {
324- void * * slot = (void * * )mmtk_gc_read_stack (& rts [i ], offset , lb , ub );
325- uintptr_t real_addr = mmtk_gc_get_stack_addr (slot , offset , lb , ub );
326- // printf("-nroots&1 i = %d/%d: %p\n", i, nr, real_addr);fflush(stdout);
327- process_edge (closure , (void * )real_addr );
328- }
329- else {
330- uintptr_t real_addr = mmtk_gc_get_stack_addr (& rts [i ], offset , lb , ub );
331- // printf("-nroots i = %d/%d: %p\n", i, nr, real_addr);fflush(stdout);
332- process_edge (closure , (void * )real_addr );
333- }
334- }
335-
336- jl_gcframe_t * sprev = (jl_gcframe_t * )mmtk_gc_read_stack (& s -> prev , offset , lb , ub );
337- if (sprev == NULL )
338- break ;
339-
340- s = sprev ;
341- uintptr_t new_nroots = mmtk_gc_read_stack (& s -> nroots , offset , lb , ub );
342- assert (new_nroots <= UINT32_MAX );
343- nroots = (uint32_t )new_nroots ;
344- nr = nroots >> 2 ;
345- continue ;
346- }
347- }
348- if (ta -> excstack ) { // inlining label `excstack` from mark_loop
349- // if it is not managed by MMTk, nothing needs to be done because the object does not need to be scanned
350- if (mmtk_object_is_managed_by_mmtk (ta -> excstack )) {
351- // printf("-excstack: %p\n", &ta->excstack);fflush(stdout);
352- process_edge (closure , & ta -> excstack );
353- }
354- jl_excstack_t * excstack = ta -> excstack ;
355- size_t itr = ta -> excstack -> top ;
356- size_t bt_index = 0 ;
357- size_t jlval_index = 0 ;
358- while (itr > 0 ) {
359- size_t bt_size = jl_excstack_bt_size (excstack , itr );
360- jl_bt_element_t * bt_data = jl_excstack_bt_data (excstack , itr );
361- for (; bt_index < bt_size ; bt_index += jl_bt_entry_size (bt_data + bt_index )) {
362- jl_bt_element_t * bt_entry = bt_data + bt_index ;
363- if (jl_bt_is_native (bt_entry ))
364- continue ;
365- // Found an extended backtrace entry: iterate over any
366- // GC-managed values inside.
367- size_t njlvals = jl_bt_num_jlvals (bt_entry );
368- while (jlval_index < njlvals ) {
369- jl_value_t * * new_obj_edge = & bt_entry [2 + jlval_index ].jlvalue ;
370- jlval_index += 1 ;
371- process_edge (closure , new_obj_edge );
372- }
373- jlval_index = 0 ;
374- }
375-
376- jl_bt_element_t * stack_raw = (jl_bt_element_t * )(excstack + 1 );
377- jl_value_t * * stack_obj_edge = & stack_raw [itr - 1 ].jlvalue ;
237+ static void add_node_to_roots_buffer (RootsWorkClosure * closure , RootsWorkBuffer * buf , size_t * buf_len , void * root ) {
238+ if (root == NULL )
239+ return ;
378240
379- itr = jl_excstack_next (excstack , itr );
380- bt_index = 0 ;
381- jlval_index = 0 ;
382- process_edge (closure , stack_obj_edge );
383- }
241+ buf -> ptr [* buf_len ] = root ;
242+ * buf_len += 1 ;
243+ if (* buf_len >= buf -> cap ) {
244+ RootsWorkBuffer new_buf = (closure -> report_nodes_func )(buf -> ptr , * buf_len , buf -> cap , closure -> data , true);
245+ * buf = new_buf ;
246+ * buf_len = 0 ;
384247 }
385248}
386249
387- void root_scan_task ( jl_ptls_t ptls , jl_task_t * task )
250+ void scan_vm_specific_roots ( RootsWorkClosure * closure )
388251{
389- // This is never accessed so just leave it NULL.
390- void * c = NULL ;
252+ // Create a new buf
253+ RootsWorkBuffer buf = (closure -> report_nodes_func )((void * * )0 , 0 , 0 , closure -> data , true);
254+ size_t len = 0 ;
391255
392- // Scan the stack
393- scan_gcstack (task , c , mmtk_process_root_edges );
394- // And add the task itself
395- mmtk_add_object_to_mmtk_roots (task );
396- }
256+ // add module
257+ add_node_to_roots_buffer (closure , & buf , & len , jl_main_module );
397258
398- static void jl_gc_queue_bt_buf_mmtk (jl_ptls_t ptls2 )
399- {
400- jl_bt_element_t * bt_data = ptls2 -> bt_data ;
401- jl_value_t * bt_entry_value ;
402- size_t bt_size = ptls2 -> bt_size ;
403- for (size_t i = 0 ; i < bt_size ; i += jl_bt_entry_size (bt_data + i )) {
404- jl_bt_element_t * bt_entry = bt_data + i ;
405- if (jl_bt_is_native (bt_entry ))
406- continue ;
407- size_t njlvals = jl_bt_num_jlvals (bt_entry );
408- for (size_t j = 0 ; j < njlvals ; j ++ ) {
409- bt_entry_value = jl_bt_entry_jlvalue (bt_entry , j );
410- mmtk_add_object_to_mmtk_roots (bt_entry_value );
259+ // buildin values
260+ add_node_to_roots_buffer (closure , & buf , & len , jl_an_empty_vec_any );
261+ add_node_to_roots_buffer (closure , & buf , & len , jl_module_init_order );
262+ for (size_t i = 0 ; i < jl_current_modules .size ; i += 2 ) {
263+ if (jl_current_modules .table [i + 1 ] != HT_NOTFOUND ) {
264+ add_node_to_roots_buffer (closure , & buf , & len , jl_current_modules .table [i ]);
411265 }
412266 }
413- }
414-
415- static void jl_gc_queue_thread_local_mmtk (jl_ptls_t ptls2 )
416- {
417- jl_task_t * task ;
418- task = ptls2 -> root_task ;
419- if (task != NULL ) {
420- root_scan_task (ptls2 , task );
421- }
422-
423- task = jl_atomic_load_relaxed (& ptls2 -> current_task );
424- if (task != NULL ) {
425- root_scan_task (ptls2 , task );
426- }
427-
428- task = ptls2 -> next_task ;
429- if (task != NULL ) {
430- root_scan_task (ptls2 , task );
431- }
432-
433- task = ptls2 -> previous_task ;
434- if (task != NULL ) {
435- root_scan_task (ptls2 , task );
436- }
437-
438- if (ptls2 -> previous_exception ) {
439- mmtk_add_object_to_mmtk_roots (ptls2 -> previous_exception );
440- }
441- }
442-
443- static void jl_gc_queue_remset_mmtk (jl_ptls_t ptls2 )
444- {
445- size_t len = ptls2 -> heap .last_remset -> len ;
446- void * * items = ptls2 -> heap .last_remset -> items ;
447- for (size_t i = 0 ; i < len ; i ++ ) {
448- mmtk_add_object_to_mmtk_roots (items [i ]);
267+ add_node_to_roots_buffer (closure , & buf , & len , jl_anytuple_type_type );
268+ for (size_t i = 0 ; i < N_CALL_CACHE ; i ++ ) {
269+ jl_typemap_entry_t * v = jl_atomic_load_relaxed (& call_cache [i ]);
270+ add_node_to_roots_buffer (closure , & buf , & len , v );
449271 }
450- }
272+ add_node_to_roots_buffer (closure , & buf , & len , jl_all_methods );
273+ add_node_to_roots_buffer (closure , & buf , & len , _jl_debug_method_invalidation );
451274
452- void calculate_roots (void * ptls_raw )
453- {
454- for (int t_i = 0 ; t_i < gc_n_threads ; t_i ++ )
455- gc_premark (gc_all_tls_states [t_i ]);
456-
457- for (int t_i = 0 ; t_i < gc_n_threads ; t_i ++ ) {
458- jl_ptls_t ptls2 = gc_all_tls_states [t_i ];
459- // 2.1. mark every thread local root
460- jl_gc_queue_thread_local_mmtk (ptls2 );
461- // 2.2. mark any managed objects in the backtrace buffer
462- jl_gc_queue_bt_buf_mmtk (ptls2 );
463- // 2.3. mark any managed objects in the backtrace buffer
464- // TODO: treat these as roots for gc_heap_snapshot_record
465- jl_gc_queue_remset_mmtk (ptls2 );
466- }
275+ // constants
276+ add_node_to_roots_buffer (closure , & buf , & len , jl_emptytuple_type );
277+ add_node_to_roots_buffer (closure , & buf , & len , cmpswap_names );
278+ add_node_to_roots_buffer (closure , & buf , & len , jl_global_roots_table );
467279
468- queue_roots ();
280+ // Push the result of the work.
281+ (closure -> report_nodes_func )(buf .ptr , len , buf .cap , closure -> data , false);
469282}
470283
471284JL_DLLEXPORT void scan_julia_exc_obj (void * obj_raw , void * closure , ProcessEdgeFn process_edge ) {
@@ -523,14 +336,70 @@ void update_gc_time(uint64_t inc) {
523336 gc_num .total_time += inc ;
524337}
525338
339+ #define assert_size (ty_a , ty_b ) \
340+ if(sizeof(ty_a) != sizeof(ty_b)) {\
341+ printf("%s size = %ld, %s size = %ld. Need to update our type definition.\n", #ty_a, sizeof(ty_a), #ty_b, sizeof(ty_b));\
342+ exit(1); \
343+ }
344+
345+ #define PRINT_STRUCT_SIZE false
346+ #define print_sizeof (type ) (PRINT_STRUCT_SIZE ? (printf("C " #type " = %zu bytes\n", sizeof(type)), sizeof(type)) : sizeof(type))
347+
526348uintptr_t get_abi_structs_checksum_c (void ) {
527- return sizeof (MMTkMutatorContext );
349+ assert_size (struct mmtk__jl_taggedvalue_bits , struct _jl_taggedvalue_bits );
350+ assert_size (mmtk_jl_taggedvalue_t , jl_taggedvalue_t );
351+ assert_size (mmtk_jl_array_flags_t , jl_array_flags_t );
352+ assert_size (mmtk_jl_datatype_layout_t , jl_datatype_layout_t );
353+ assert_size (mmtk_jl_typename_t , jl_typename_t );
354+ assert_size (mmtk_jl_svec_t , jl_svec_t );
355+ assert_size (mmtk_jl_datatype_t , jl_datatype_t );
356+ assert_size (mmtk_jl_array_t , jl_array_t );
357+ assert_size (mmtk_jl_sym_t , jl_sym_t );
358+ assert_size (mmtk_jl_binding_t , jl_binding_t );
359+ assert_size (mmtk_htable_t , htable_t );
360+ assert_size (mmtk_arraylist_t , arraylist_t );
361+ assert_size (mmtk_jl_uuid_t , jl_uuid_t );
362+ assert_size (mmtk_jl_mutex_t , jl_mutex_t );
363+ assert_size (mmtk_jl_module_t , jl_module_t );
364+ assert_size (mmtk_jl_excstack_t , jl_excstack_t );
365+ assert_size (mmtk_jl_bt_element_t , jl_bt_element_t );
366+ assert_size (mmtk_jl_stack_context_t , jl_stack_context_t );
367+ assert_size (mmtk_jl_ucontext_t , jl_ucontext_t );
368+ assert_size (struct mmtk__jl_gcframe_t , struct _jl_gcframe_t );
369+ assert_size (mmtk_jl_task_t , jl_task_t );
370+ assert_size (mmtk_jl_weakref_t , jl_weakref_t );
371+
372+ return print_sizeof (MMTkMutatorContext )
373+ ^ print_sizeof (struct mmtk__jl_taggedvalue_bits )
374+ ^ print_sizeof (mmtk_jl_taggedvalue_t )
375+ ^ print_sizeof (mmtk_jl_array_flags_t )
376+ ^ print_sizeof (mmtk_jl_datatype_layout_t )
377+ ^ print_sizeof (mmtk_jl_typename_t )
378+ ^ print_sizeof (mmtk_jl_svec_t )
379+ ^ print_sizeof (mmtk_jl_datatype_t )
380+ ^ print_sizeof (mmtk_jl_array_t )
381+ ^ print_sizeof (mmtk_jl_sym_t )
382+ ^ print_sizeof (mmtk_jl_binding_t )
383+ ^ print_sizeof (mmtk_htable_t )
384+ ^ print_sizeof (mmtk_arraylist_t )
385+ ^ print_sizeof (mmtk_jl_uuid_t )
386+ ^ print_sizeof (mmtk_jl_mutex_t )
387+ ^ print_sizeof (mmtk_jl_module_t )
388+ ^ print_sizeof (mmtk_jl_excstack_t )
389+ ^ print_sizeof (mmtk_jl_bt_element_t )
390+ ^ print_sizeof (mmtk_jl_stack_context_t )
391+ ^ print_sizeof (mmtk_jl_ucontext_t )
392+ ^ print_sizeof (struct mmtk__jl_gcframe_t )
393+ ^ print_sizeof (mmtk_jl_task_t )
394+ ^ print_sizeof (mmtk_jl_weakref_t )
395+ ^ print_sizeof (mmtk_jl_tls_states_t )
396+ ^ print_sizeof (mmtk_jl_thread_heap_t )
397+ ^ print_sizeof (mmtk_jl_thread_gc_num_t );
528398}
529399
530400Julia_Upcalls mmtk_upcalls = (Julia_Upcalls ) {
531401 .scan_julia_exc_obj = scan_julia_exc_obj ,
532402 .get_stackbase = get_stackbase ,
533- .calculate_roots = calculate_roots ,
534403 // .run_finalizer_function = run_finalizer_function,
535404 .get_jl_last_err = get_jl_last_err ,
536405 .set_jl_last_err = set_jl_last_err ,
@@ -551,4 +420,5 @@ Julia_Upcalls mmtk_upcalls = (Julia_Upcalls) {
551420 .get_marked_finalizers_list = get_marked_finalizers_list ,
552421 .arraylist_grow = (void (* )(void * , long unsigned int ))arraylist_grow ,
553422 .get_jl_gc_have_pending_finalizers = get_jl_gc_have_pending_finalizers ,
423+ .scan_vm_specific_roots = scan_vm_specific_roots ,
554424};
0 commit comments