📄 gc_priv.h
字号:
# ifdef GATHERSTATS# define GC_composite_in_use GC_arrays._composite_in_use# define GC_atomic_in_use GC_arrays._atomic_in_use# endif# ifdef MERGE_SIZES# define GC_size_map GC_arrays._size_map# endif# define beginGC_arrays ((ptr_t)(&GC_arrays))# define endGC_arrays (((ptr_t)(&GC_arrays)) + (sizeof GC_arrays))#define USED_HEAP_SIZE (GC_heapsize - GC_large_free_bytes)/* Object kinds: */# define MAXOBJKINDS 16extern struct obj_kind { ptr_t *ok_freelist; /* Array of free listheaders for this kind of object */ /* Point either to GC_arrays or to storage allocated */ /* with GC_scratch_alloc. */ struct hblk **ok_reclaim_list; /* List headers for lists of blocks waiting to be */ /* swept. */ word ok_descriptor; /* Descriptor template for objects in this */ /* block. */ GC_bool ok_relocate_descr; /* Add object size in bytes to descriptor */ /* template to obtain descriptor. Otherwise */ /* template is used as is. */ GC_bool ok_init; /* Clear objects before putting them on the free list. */} GC_obj_kinds[MAXOBJKINDS];# define beginGC_obj_kinds ((ptr_t)(&GC_obj_kinds))# define endGC_obj_kinds (beginGC_obj_kinds + (sizeof GC_obj_kinds))/* Variables that used to be in GC_arrays, but need to be accessed by *//* inline allocation code. If they were in GC_arrays, the inlined *//* allocation code would include GC_arrays offsets (as it did), which *//* introduce maintenance problems. */#ifdef SEPARATE_GLOBALS word GC_words_allocd; /* Number of words allocated during this collection cycle */ ptr_t GC_objfreelist[MAXOBJSZ+1]; /* free list for NORMAL objects */# define beginGC_objfreelist ((ptr_t)(&GC_objfreelist))# define endGC_objfreelist (beginGC_objfreelist + sizeof(GC_objfreelist)) ptr_t GC_aobjfreelist[MAXOBJSZ+1]; /* free list for atomic (PTRFREE) objs */# define beginGC_aobjfreelist ((ptr_t)(&GC_aobjfreelist))# define endGC_aobjfreelist (beginGC_aobjfreelist + sizeof(GC_aobjfreelist))#endif/* Predefined kinds: */# define PTRFREE 0# define NORMAL 1# define UNCOLLECTABLE 2# ifdef ATOMIC_UNCOLLECTABLE# define AUNCOLLECTABLE 3# define STUBBORN 4# define IS_UNCOLLECTABLE(k) (((k) & ~1) == UNCOLLECTABLE)# else# define STUBBORN 3# define IS_UNCOLLECTABLE(k) ((k) == UNCOLLECTABLE)# endifextern int GC_n_kinds;GC_API word GC_fo_entries;extern word GC_n_heap_sects; /* Number of separately added heap */ /* sections. */extern word GC_page_size;# if defined(MSWIN32) || defined(MSWINCE) struct _SYSTEM_INFO; extern struct _SYSTEM_INFO GC_sysinfo; extern word GC_n_heap_bases; /* See GC_heap_bases. */# endifextern word GC_total_stack_black_listed; /* Number of bytes on stack blacklist. */extern word GC_black_list_spacing; /* Average number of bytes between blacklisted */ /* blocks. Approximate. */ /* Counts only blocks that are */ /* "stack-blacklisted", i.e. that are */ /* problematic in the interior of an object. */extern map_entry_type * GC_invalid_map; /* Pointer to the nowhere valid hblk map */ /* Blocks pointing to this map are free. */extern struct hblk * GC_hblkfreelist[]; /* List of completely empty heap blocks */ /* Linked through hb_next field of */ /* header structure associated with */ /* block. */extern GC_bool GC_is_initialized; /* GC_init() has been run. */extern GC_bool GC_objects_are_marked; /* There are marked objects in */ /* the heap. */#ifndef SMALL_CONFIG extern GC_bool GC_incremental; /* Using incremental/generational collection. */#else# define GC_incremental FALSE /* Hopefully allow optimizer to remove some code. */#endifextern GC_bool GC_dirty_maintained; /* Dirty bits are being maintained, */ /* either for incremental collection, */ /* or to limit the root set. */extern word GC_root_size; /* Total size of registered root sections */extern GC_bool GC_debugging_started; /* GC_debug_malloc has been called. */ extern long GC_large_alloc_warn_interval; /* Interval between unsuppressed warnings. */extern long GC_large_alloc_warn_suppressed; /* Number of warnings suppressed so far. *//* Operations */# ifndef abs# define abs(x) ((x) < 0? (-(x)) : (x))# endif/* Marks are in a reserved area in *//* each heap block. Each word has one mark bit associated *//* with it. Only those corresponding to the beginning of an *//* object are used. *//* Set mark bit correctly, even if mark bits may be concurrently *//* accessed. */#ifdef PARALLEL_MARK# define OR_WORD(addr, bits) \ { word old; \ do { \ old = *((volatile word *)addr); \ } while (!GC_compare_and_exchange((addr), old, old | (bits))); \ }# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ { word old; \ word my_bits = (bits); \ do { \ old = *((volatile word *)addr); \ if (old & my_bits) goto exit_label; \ } while (!GC_compare_and_exchange((addr), old, old | my_bits)); \ }#else# define OR_WORD(addr, bits) *(addr) |= (bits)# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \ { \ word old = *(addr); \ word my_bits = (bits); \ if (old & my_bits) goto exit_label; \ *(addr) = (old | my_bits); \ }#endif/* Mark bit operations *//* * Retrieve, set, clear the mark bit corresponding * to the nth word in a given heap block. * * (Recall that bit n corresponds to object beginning at word n * relative to the beginning of the block, including unused words) */#ifdef USE_MARK_BYTES# define mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n) >> 1])# define set_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 1# define clear_mark_bit_from_hdr(hhdr,n) ((hhdr)->hb_marks[(n)>>1]) = 0#else /* !USE_MARK_BYTES */# define mark_bit_from_hdr(hhdr,n) (((hhdr)->hb_marks[divWORDSZ(n)] \ >> (modWORDSZ(n))) & (word)1)# define set_mark_bit_from_hdr(hhdr,n) \ OR_WORD((hhdr)->hb_marks+divWORDSZ(n), \ (word)1 << modWORDSZ(n))# define clear_mark_bit_from_hdr(hhdr,n) (hhdr)->hb_marks[divWORDSZ(n)] \ &= ~((word)1 << modWORDSZ(n))#endif /* !USE_MARK_BYTES *//* Important internal collector routines */ptr_t GC_approx_sp GC_PROTO((void)); GC_bool GC_should_collect GC_PROTO((void)); void GC_apply_to_all_blocks GC_PROTO(( \ void (*fn) GC_PROTO((struct hblk *h, word client_data)), \ word client_data)); /* Invoke fn(hbp, client_data) for each */ /* allocated heap block. */struct hblk * GC_next_used_block GC_PROTO((struct hblk * h)); /* Return first in-use block >= h */struct hblk * GC_prev_block GC_PROTO((struct hblk * h)); /* Return last block <= h. Returned block */ /* is managed by GC, but may or may not be in */ /* use. */void GC_mark_init GC_PROTO((void));void GC_clear_marks GC_PROTO((void)); /* Clear mark bits for all heap objects. */void GC_invalidate_mark_state GC_PROTO((void)); /* Tell the marker that marked */ /* objects may point to unmarked */ /* ones, and roots may point to */ /* unmarked objects. */ /* Reset mark stack. */GC_bool GC_mark_stack_empty GC_PROTO((void));GC_bool GC_mark_some GC_PROTO((ptr_t cold_gc_frame)); /* Perform about one pages worth of marking */ /* work of whatever kind is needed. Returns */ /* quickly if no collection is in progress. */ /* Return TRUE if mark phase finished. */void GC_initiate_gc GC_PROTO((void)); /* initiate collection. */ /* If the mark state is invalid, this */ /* becomes full colleection. Otherwise */ /* it's partial. */void GC_push_all GC_PROTO((ptr_t bottom, ptr_t top)); /* Push everything in a range */ /* onto mark stack. */void GC_push_selected GC_PROTO(( \ ptr_t bottom, \ ptr_t top, \ int (*dirty_fn) GC_PROTO((struct hblk *h)), \ void (*push_fn) GC_PROTO((ptr_t bottom, ptr_t top)) )); /* Push all pages h in [b,t) s.t. */ /* select_fn(h) != 0 onto mark stack. */#ifndef SMALL_CONFIG void GC_push_conditional GC_PROTO((ptr_t b, ptr_t t, GC_bool all));#else# define GC_push_conditional(b, t, all) GC_push_all(b, t)#endif /* Do either of the above, depending */ /* on the third arg. */void GC_push_all_stack GC_PROTO((ptr_t b, ptr_t t)); /* As above, but consider */ /* interior pointers as valid */void GC_push_all_eager GC_PROTO((ptr_t b, ptr_t t)); /* Same as GC_push_all_stack, but */ /* ensures that stack is scanned */ /* immediately, not just scheduled */ /* for scanning. */#ifndef THREADS void GC_push_all_stack_partially_eager GC_PROTO(( \ ptr_t bottom, ptr_t top, ptr_t cold_gc_frame )); /* Similar to GC_push_all_eager, but only the */ /* part hotter than cold_gc_frame is scanned */ /* immediately. Needed to ensure that callee- */ /* save registers are not missed. */#else /* In the threads case, we push part of the current thread stack */ /* with GC_push_all_eager when we push the registers. This gets the */ /* callee-save registers that may disappear. The remainder of the */ /* stacks are scheduled for scanning in *GC_push_other_roots, which */ /* is thread-package-specific. */#endifvoid GC_push_current_stack GC_PROTO((ptr_t cold_gc_frame)); /* Push enough of the current stack eagerly to */ /* ensure that callee-save registers saved in */ /* GC frames are scanned. */ /* In the non-threads case, schedule entire */ /* stack for scanning. */void GC_push_roots GC_PROTO((GC_bool all, ptr_t cold_gc_frame)); /* Push all or dirty roots. */extern void (*GC_push_other_roots) GC_PROTO((void)); /* Push system or application specific roots */ /* onto the mark stack. In some environments */ /* (e.g. threads environments) this is */ /* predfined to be non-zero. A client supplied */ /* replacement should also call the original */ /* function. */extern void GC_push_gc_structures GC_PROTO((void)); /* Push GC internal roots. These are normally */ /* included in the static data segment, and */ /* Thus implicitly pushed. But we must do this */ /* explicitly if normal root processing is */ /* disabled. Calls the following: */ extern void GC_push_finalizer_structures GC_PROTO((void)); extern void GC_push_stubborn_structures GC_PROTO((void));# ifdef THREADS extern void GC_push_thread_structures GC_PROTO((void));# endifextern void (*GC_start_call_back) GC_PROTO((void)); /* Called at start of full collections. */ /* Not called if 0. Called with allocation */ /* lock held. */ /* 0 by default. */# if defined(USE_GENERIC_PUSH_REGS) void GC_generic_push_regs GC_PROTO((ptr_t cold_gc_frame));# else void GC_push_regs GC_PROTO((void));# endif /* Push register contents onto mark stack. */ /* If NURSERY is defined, the default push */ /* action can be overridden with GC_push_proc */# ifdef NURSERY extern void (*GC_push_proc)(ptr_t);# endif# if defined(MSWIN32) || defined(MSWINCE) void __cdecl GC_push_one GC_PROTO((word p));# else void GC_push_one GC_PROTO((word p)); /* If p points to an object, mark it */ /* and push contents on the mark stack */ /* Pointer recognition test always */ /* accepts interior pointers, i.e. this */ /* is appropriate for pointers found on */ /* stack. */# endif# if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS) void GC_mark_and_push_stack GC_PROTO((word p, ptr_t source)); /* Ditto, omits plausibility test */# else void GC_mark_and_push_stack GC_PROTO((word p));# endifvoid GC_push_marked GC_PROTO((struct hblk * h, hdr * hhdr)); /* Push contents of all marked objects in h onto */ /* mark stack. */#ifdef SMALL_CONFIG# define GC_push_next_marked_dirty(h) GC_push_next_marked(h)#else struct hblk * GC_push_next_marked_dirty GC_PROTO((struct hblk * h)); /* Invoke GC_push_marked on next dirty block above h. */ /* Return a pointer just past the end of this block. */#endif /* !SMALL_CONFIG */struct hblk * GC_push_next_marked GC_PROTO((struct hblk * h)); /* Ditto, but also mark from clean pages. */struct hblk * GC_push_next_marked_uncollectable GC_PROTO((struct hblk * h)); /* Ditto, but mark only from uncollectable pages. */GC_bool GC_stopped_mark GC_PROTO((GC_stop_func stop_func)); /* Stop world and mark from all roots */ /* and rescuers. */void GC_clear_hdr_marks GC_PROTO((hdr * hhdr)); /* Clear the mark bits in a header */void GC_set_hdr_marks GC_PROTO((hdr * hhdr)); /* Set the mark bits in a header */void GC_set_fl_marks GC_PROTO((ptr_t p)); /* Set all mark bits associated with */ /* a free list. */void GC_add_roots_inner GC_PROTO((char * b, char * e, GC_bool tmp));GC_bool GC_is_static_root GC_PROTO((ptr_t p)); /* Is the address p in one of the registered static */ /* root sections? */# if defined(MSWIN32) || defined(_WIN32_WCE_EMULATION)GC_bool GC_is_tmp_root GC_PROTO((ptr_t p)); /* Is the address p in one of the temporary static */ /* root sections? */# endifvoid GC_register_dynamic_libraries GC_PROTO((void)); /* Add dynamic library data sections to the root set. */GC_bool GC_register_main_static_data GC_PROTO((void)); /* We need to register the main data segment. Returns */ /* TRUE unless this is done implicitly as part of */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -