📄 misc.c
字号:
r = (word)p; if (!GC_is_initialized) return 0; h = HBLKPTR(r); GET_BI(r, bi); candidate_hdr = HDR_FROM_BI(bi, r); if (candidate_hdr == 0) return(0); /* If it's a pointer to the middle of a large object, move it */ /* to the beginning. */ while (IS_FORWARDING_ADDR_OR_NIL(candidate_hdr)) { h = FORWARDED_ADDR(h,candidate_hdr); r = (word)h; candidate_hdr = HDR(h); } if (candidate_hdr -> hb_map == GC_invalid_map) return(0); /* Make sure r points to the beginning of the object */ r &= ~(WORDS_TO_BYTES(1) - 1); { register int offset = HBLKDISPL(r); register signed_word sz = candidate_hdr -> hb_sz; register signed_word map_entry; map_entry = MAP_ENTRY((candidate_hdr -> hb_map), offset); if (map_entry > CPP_MAX_OFFSET) { map_entry = (signed_word)(BYTES_TO_WORDS(offset)) % sz; } r -= WORDS_TO_BYTES(map_entry); limit = r + WORDS_TO_BYTES(sz); if (limit > (word)(h + 1) && sz <= BYTES_TO_WORDS(HBLKSIZE)) { return(0); } if ((word)p >= limit) return(0); } return((GC_PTR)r);}/* Return the size of an object, given a pointer to its base. *//* (For small obects this also happens to work from interior pointers, *//* but that shouldn't be relied upon.) */# ifdef __STDC__ size_t GC_size(GC_PTR p)# else size_t GC_size(p) GC_PTR p;# endif{ register int sz; register hdr * hhdr = HDR(p); sz = WORDS_TO_BYTES(hhdr -> hb_sz); return(sz);}size_t GC_get_heap_size GC_PROTO(()){ return ((size_t) GC_heapsize);}size_t GC_get_free_bytes GC_PROTO(()){ return ((size_t) GC_large_free_bytes);}size_t GC_get_bytes_since_gc GC_PROTO(()){ return ((size_t) WORDS_TO_BYTES(GC_words_allocd));}size_t GC_get_total_bytes GC_PROTO(()){ return ((size_t) WORDS_TO_BYTES(GC_words_allocd+GC_words_allocd_before_gc));}GC_bool GC_is_initialized = FALSE;void GC_init(){ DCL_LOCK_STATE; DISABLE_SIGNALS();#if defined(GC_WIN32_THREADS) && !defined(GC_PTHREADS) if (!GC_is_initialized) { BOOL (WINAPI *pfn) (LPCRITICAL_SECTION, DWORD) = NULL; HMODULE hK32 = GetModuleHandle("kernel32.dll"); if (hK32) (FARPROC) pfn = GetProcAddress(hK32, "InitializeCriticalSectionAndSpinCount"); if (pfn) pfn(&GC_allocate_ml, 4000); else InitializeCriticalSection (&GC_allocate_ml); }#endif /* MSWIN32 */ LOCK(); GC_init_inner(); UNLOCK(); ENABLE_SIGNALS();# if defined(PARALLEL_MARK) || defined(THREAD_LOCAL_ALLOC) /* Make sure marker threads and started and thread local */ /* allocation is initialized, in case we didn't get */ /* called from GC_init_parallel(); */ { extern void GC_init_parallel(void); GC_init_parallel(); }# endif /* PARALLEL_MARK || THREAD_LOCAL_ALLOC */# if defined(DYNAMIC_LOADING) && defined(DARWIN) { /* This must be called WITHOUT the allocation lock held and before any threads are created */ extern void GC_init_dyld(); GC_init_dyld(); }# endif}#if defined(MSWIN32) || defined(MSWINCE) CRITICAL_SECTION GC_write_cs;#endif#ifdef MSWIN32 extern void GC_init_win32 GC_PROTO((void));#endifextern void GC_setpagesize();#ifdef MSWIN32extern GC_bool GC_no_win32_dlls;#else# define GC_no_win32_dlls FALSE#endifvoid GC_exit_check GC_PROTO((void)){ GC_gcollect();}#ifdef SEARCH_FOR_DATA_START extern void GC_init_linux_data_start GC_PROTO((void));#endif#ifdef UNIX_LIKEextern void GC_set_and_save_fault_handler GC_PROTO((void (*handler)(int)));static void looping_handler(sig)int sig;{ GC_err_printf1("Caught signal %d: looping in handler\n", sig); for(;;);}static GC_bool installed_looping_handler = FALSE;static void maybe_install_looping_handler(){ /* Install looping handler before the write fault handler, so we */ /* handle write faults correctly. */ if (!installed_looping_handler && 0 != GETENV("GC_LOOP_ON_ABORT")) { GC_set_and_save_fault_handler(looping_handler); installed_looping_handler = TRUE; }}#else /* !UNIX_LIKE */# define maybe_install_looping_handler()#endifvoid GC_init_inner(){# if !defined(THREADS) && defined(GC_ASSERTIONS) word dummy;# endif word initial_heap_sz = (word)MINHINCR; if (GC_is_initialized) return;# ifdef PRINTSTATS GC_print_stats = 1;# endif# if defined(MSWIN32) || defined(MSWINCE) InitializeCriticalSection(&GC_write_cs);# endif if (0 != GETENV("GC_PRINT_STATS")) { GC_print_stats = 1; } # ifndef NO_DEBUGGING if (0 != GETENV("GC_DUMP_REGULARLY")) { GC_dump_regularly = 1; }# endif# ifdef KEEP_BACK_PTRS { char * backtraces_string = GETENV("GC_BACKTRACES"); if (0 != backtraces_string) { GC_backtraces = atol(backtraces_string); if (backtraces_string[0] == '\0') GC_backtraces = 1; } }# endif if (0 != GETENV("GC_FIND_LEAK")) { GC_find_leak = 1;# ifdef __STDC__ atexit(GC_exit_check);# endif } if (0 != GETENV("GC_ALL_INTERIOR_POINTERS")) { GC_all_interior_pointers = 1; } if (0 != GETENV("GC_DONT_GC")) { GC_dont_gc = 1; } if (0 != GETENV("GC_PRINT_BACK_HEIGHT")) { GC_print_back_height = 1; } if (0 != GETENV("GC_NO_BLACKLIST_WARNING")) { GC_large_alloc_warn_interval = LONG_MAX; } { char * time_limit_string = GETENV("GC_PAUSE_TIME_TARGET"); if (0 != time_limit_string) { long time_limit = atol(time_limit_string); if (time_limit < 5) { WARN("GC_PAUSE_TIME_TARGET environment variable value too small " "or bad syntax: Ignoring\n", 0); } else { GC_time_limit = time_limit; } } } { char * interval_string = GETENV("GC_LARGE_ALLOC_WARN_INTERVAL"); if (0 != interval_string) { long interval = atol(interval_string); if (interval <= 0) { WARN("GC_LARGE_ALLOC_WARN_INTERVAL environment variable has " "bad value: Ignoring\n", 0); } else { GC_large_alloc_warn_interval = interval; } } } maybe_install_looping_handler(); /* Adjust normal object descriptor for extra allocation. */ if (ALIGNMENT > GC_DS_TAGS && EXTRA_BYTES != 0) { GC_obj_kinds[NORMAL].ok_descriptor = ((word)(-ALIGNMENT) | GC_DS_LENGTH); } GC_setpagesize(); GC_exclude_static_roots(beginGC_arrays, endGC_arrays); GC_exclude_static_roots(beginGC_obj_kinds, endGC_obj_kinds);# ifdef SEPARATE_GLOBALS GC_exclude_static_roots(beginGC_objfreelist, endGC_objfreelist); GC_exclude_static_roots(beginGC_aobjfreelist, endGC_aobjfreelist);# endif# ifdef MSWIN32 GC_init_win32();# endif# if defined(SEARCH_FOR_DATA_START) GC_init_linux_data_start();# endif# if (defined(NETBSD) || defined(OPENBSD)) && defined(__ELF__) GC_init_netbsd_elf();# endif# if defined(GC_PTHREADS) || defined(GC_SOLARIS_THREADS) \ || defined(GC_WIN32_THREADS) GC_thr_init();# endif# ifdef GC_SOLARIS_THREADS /* We need dirty bits in order to find live stack sections. */ GC_dirty_init();# endif# if !defined(THREADS) || defined(GC_PTHREADS) || defined(GC_WIN32_THREADS) \ || defined(GC_SOLARIS_THREADS) if (GC_stackbottom == 0) { GC_stackbottom = GC_get_stack_base();# if (defined(LINUX) || defined(HPUX)) && defined(IA64) GC_register_stackbottom = GC_get_register_stack_base();# endif } else {# if (defined(LINUX) || defined(HPUX)) && defined(IA64) if (GC_register_stackbottom == 0) { WARN("GC_register_stackbottom should be set with GC_stackbottom", 0); /* The following may fail, since we may rely on */ /* alignment properties that may not hold with a user set */ /* GC_stackbottom. */ GC_register_stackbottom = GC_get_register_stack_base(); }# endif }# endif GC_STATIC_ASSERT(sizeof (ptr_t) == sizeof(word)); GC_STATIC_ASSERT(sizeof (signed_word) == sizeof(word)); GC_STATIC_ASSERT(sizeof (struct hblk) == HBLKSIZE);# ifndef THREADS# if defined(STACK_GROWS_UP) && defined(STACK_GROWS_DOWN) ABORT( "Only one of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");# endif# if !defined(STACK_GROWS_UP) && !defined(STACK_GROWS_DOWN) ABORT( "One of STACK_GROWS_UP and STACK_GROWS_DOWN should be defd\n");# endif# ifdef STACK_GROWS_DOWN GC_ASSERT((word)(&dummy) <= (word)GC_stackbottom);# else GC_ASSERT((word)(&dummy) >= (word)GC_stackbottom);# endif# endif# if !defined(_AUX_SOURCE) || defined(__GNUC__) GC_ASSERT((word)(-1) > (word)0); /* word should be unsigned */# endif GC_ASSERT((signed_word)(-1) < (signed_word)0); /* Add initial guess of root sets. Do this first, since sbrk(0) */ /* might be used. */ if (GC_REGISTER_MAIN_STATIC_DATA()) GC_register_data_segments(); GC_init_headers(); GC_bl_init(); GC_mark_init(); { char * sz_str = GETENV("GC_INITIAL_HEAP_SIZE"); if (sz_str != NULL) { initial_heap_sz = atoi(sz_str); if (initial_heap_sz <= MINHINCR * HBLKSIZE) { WARN("Bad initial heap size %s - ignoring it.\n", sz_str); } initial_heap_sz = divHBLKSZ(initial_heap_sz); } } { char * sz_str = GETENV("GC_MAXIMUM_HEAP_SIZE"); if (sz_str != NULL) { word max_heap_sz = (word)atol(sz_str); if (max_heap_sz < initial_heap_sz * HBLKSIZE) { WARN("Bad maximum heap size %s - ignoring it.\n", sz_str); } if (0 == GC_max_retries) GC_max_retries = 2; GC_set_max_heap_size(max_heap_sz); } } if (!GC_expand_hp_inner(initial_heap_sz)) { GC_err_printf0("Can't start up: not enough memory\n"); EXIT(); } /* Preallocate large object map. It's otherwise inconvenient to */ /* deal with failure. */ if (!GC_add_map_entry((word)0)) { GC_err_printf0("Can't start up: not enough memory\n"); EXIT(); } GC_register_displacement_inner(0L);# ifdef MERGE_SIZES GC_init_size_map();# endif# ifdef PCR if (PCR_IL_Lock(PCR_Bool_false, PCR_allSigsBlocked, PCR_waitForever) != PCR_ERes_okay) { ABORT("Can't lock load state\n"); } else if (PCR_IL_Unlock() != PCR_ERes_okay) { ABORT("Can't unlock load state\n"); } PCR_IL_Unlock(); GC_pcr_install();# endif# if !defined(SMALL_CONFIG) if (!GC_no_win32_dlls && 0 != GETENV("GC_ENABLE_INCREMENTAL")) { GC_ASSERT(!GC_incremental); GC_setpagesize();# ifndef GC_SOLARIS_THREADS GC_dirty_init();# endif GC_ASSERT(GC_words_allocd == 0) GC_incremental = TRUE; }# endif /* !SMALL_CONFIG */ COND_DUMP; /* Get black list set up and/or incremental GC started */ if (!GC_dont_precollect || GC_incremental) GC_gcollect_inner(); GC_is_initialized = TRUE;# ifdef STUBBORN_ALLOC GC_stubborn_init();# endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -