Updates from 0.2.1 into 0.2.1-inu-1.5
This commit is contained in:
		
							
								
								
									
										190
									
								
								gc/finalize.c
									
									
									
									
									
								
							
							
						
						
									
										190
									
								
								gc/finalize.c
									
									
									
									
									
								
							| @@ -14,8 +14,7 @@ | ||||
|  */ | ||||
| /* Boehm, February 1, 1996 1:19 pm PST */ | ||||
| # define I_HIDE_POINTERS | ||||
| # include "gc_priv.h" | ||||
| # include "gc_mark.h" | ||||
| # include "private/gc_pmark.h" | ||||
|  | ||||
| # ifdef FINALIZE_ON_DEMAND | ||||
|     int GC_finalize_on_demand = 1; | ||||
| @@ -86,13 +85,13 @@ static signed_word log_fo_table_size = -1; | ||||
|  | ||||
| word GC_fo_entries = 0; | ||||
|  | ||||
| # ifdef SRC_M3 | ||||
| void GC_push_finalizer_structures() | ||||
| void GC_push_finalizer_structures GC_PROTO((void)) | ||||
| { | ||||
|     GC_push_all((ptr_t)(&dl_head), (ptr_t)(&dl_head) + sizeof(word)); | ||||
|     GC_push_all((ptr_t)(&fo_head), (ptr_t)(&fo_head) + sizeof(word)); | ||||
|     GC_push_all((ptr_t)(&GC_finalize_now), | ||||
| 		(ptr_t)(&GC_finalize_now) + sizeof(word)); | ||||
| } | ||||
| # endif | ||||
|  | ||||
| /* Double the size of a hash table. *size_ptr is the log of its current	*/ | ||||
| /* size.  May be a noop.						*/ | ||||
| @@ -110,7 +109,7 @@ signed_word * log_size_ptr; | ||||
|     word old_size = ((log_old_size == -1)? 0: (1 << log_old_size)); | ||||
|     register word new_size = 1 << log_new_size; | ||||
|     struct hash_chain_entry **new_table = (struct hash_chain_entry **) | ||||
|     	GC_generic_malloc_inner_ignore_off_page( | ||||
|     	GC_INTERNAL_MALLOC_IGNORE_OFF_PAGE( | ||||
|     		(size_t)new_size * sizeof(struct hash_chain_entry *), NORMAL); | ||||
|      | ||||
|     if (new_table == 0) { | ||||
| @@ -179,9 +178,11 @@ signed_word * log_size_ptr; | ||||
| #	endif | ||||
|     	GC_grow_table((struct hash_chain_entry ***)(&dl_head), | ||||
|     		      &log_dl_table_size); | ||||
| #	ifdef PRINTSTATS | ||||
| #	ifdef CONDPRINT | ||||
| 	  if (GC_print_stats) { | ||||
| 	    GC_printf1("Grew dl table to %lu entries\n", | ||||
| 	    		(unsigned long)(1 << log_dl_table_size)); | ||||
| 	  } | ||||
| #	endif | ||||
| #	ifndef THREADS | ||||
| 	    ENABLE_SIGNALS(); | ||||
| @@ -199,22 +200,29 @@ signed_word * log_size_ptr; | ||||
|             return(1); | ||||
|         } | ||||
|     } | ||||
| #   ifdef THREADS | ||||
|       new_dl = (struct disappearing_link *) | ||||
|     	GC_generic_malloc_inner(sizeof(struct disappearing_link),NORMAL); | ||||
| #   else | ||||
|       new_dl = (struct disappearing_link *) | ||||
| 	GC_malloc(sizeof(struct disappearing_link)); | ||||
| #   endif | ||||
|     if (new_dl != 0) { | ||||
|         new_dl -> dl_hidden_obj = HIDE_POINTER(obj); | ||||
|         new_dl -> dl_hidden_link = HIDE_POINTER(link); | ||||
|         dl_set_next(new_dl, dl_head[index]); | ||||
|         dl_head[index] = new_dl; | ||||
|         GC_dl_entries++; | ||||
|     } else { | ||||
|         GC_finalization_failures++; | ||||
|     new_dl = (struct disappearing_link *) | ||||
|     	GC_INTERNAL_MALLOC(sizeof(struct disappearing_link),NORMAL); | ||||
|     if (0 == new_dl) { | ||||
| #     ifdef THREADS | ||||
| 	UNLOCK(); | ||||
|     	ENABLE_SIGNALS(); | ||||
| #     endif | ||||
|       new_dl == GC_oom_fn(sizeof(struct disappearing_link)); | ||||
|       if (0 == new_dl) { | ||||
| 	GC_finalization_failures++; | ||||
| 	return(0); | ||||
|       } | ||||
|       /* It's not likely we'll make it here, but ... */ | ||||
| #     ifdef THREADS | ||||
|         DISABLE_SIGNALS(); | ||||
| 	LOCK(); | ||||
| #     endif | ||||
|     } | ||||
|     new_dl -> dl_hidden_obj = HIDE_POINTER(obj); | ||||
|     new_dl -> dl_hidden_link = HIDE_POINTER(link); | ||||
|     dl_set_next(new_dl, dl_head[index]); | ||||
|     dl_head[index] = new_dl; | ||||
|     GC_dl_entries++; | ||||
| #   ifdef THREADS | ||||
|         UNLOCK(); | ||||
|         ENABLE_SIGNALS(); | ||||
| @@ -248,7 +256,11 @@ signed_word * log_size_ptr; | ||||
|             GC_dl_entries--; | ||||
|             UNLOCK(); | ||||
|     	    ENABLE_SIGNALS(); | ||||
|             GC_free((GC_PTR)curr_dl); | ||||
| #	    ifdef DBG_HDRS_ALL | ||||
| 	      dl_set_next(curr_dl, 0); | ||||
| #	    else | ||||
|               GC_free((GC_PTR)curr_dl); | ||||
| #	    endif | ||||
|             return(1); | ||||
|         } | ||||
|         prev_dl = curr_dl; | ||||
| @@ -283,7 +295,7 @@ ptr_t p; | ||||
|     ptr_t scan_limit; | ||||
|     ptr_t target_limit = p + WORDS_TO_BYTES(hhdr -> hb_sz) - 1; | ||||
|      | ||||
|     if ((descr & DS_TAGS) == DS_LENGTH) { | ||||
|     if ((descr & GC_DS_TAGS) == GC_DS_LENGTH) { | ||||
|        scan_limit = p + descr - sizeof(word); | ||||
|     } else { | ||||
|        scan_limit = target_limit + 1 - sizeof(word); | ||||
| @@ -324,6 +336,7 @@ finalization_mark_proc * mp; | ||||
|     struct finalizable_object * curr_fo, * prev_fo; | ||||
|     int index; | ||||
|     struct finalizable_object *new_fo; | ||||
|     hdr *hhdr; | ||||
|     DCL_LOCK_STATE; | ||||
|  | ||||
| #   ifdef THREADS | ||||
| @@ -337,9 +350,11 @@ finalization_mark_proc * mp; | ||||
| #	endif | ||||
|     	GC_grow_table((struct hash_chain_entry ***)(&fo_head), | ||||
|     		      &log_fo_table_size); | ||||
| #	ifdef PRINTSTATS | ||||
| #	ifdef CONDPRINT | ||||
| 	  if (GC_print_stats) { | ||||
| 	    GC_printf1("Grew fo table to %lu entries\n", | ||||
| 	    		(unsigned long)(1 << log_fo_table_size)); | ||||
| 	  } | ||||
| #	endif | ||||
| #	ifndef THREADS | ||||
| 	    ENABLE_SIGNALS(); | ||||
| @@ -369,7 +384,7 @@ finalization_mark_proc * mp; | ||||
|                   /* May not happen if we get a signal.  But a high	*/ | ||||
|                   /* estimate will only make the table larger than	*/ | ||||
|                   /* necessary.						*/ | ||||
| #		ifndef THREADS | ||||
| #		if !defined(THREADS) && !defined(DBG_HDRS_ALL) | ||||
|                   GC_free((GC_PTR)curr_fo); | ||||
| #		endif | ||||
|             } else { | ||||
| @@ -402,25 +417,41 @@ finalization_mark_proc * mp; | ||||
| #	endif | ||||
|         return; | ||||
|     } | ||||
| #   ifdef THREADS | ||||
|       new_fo = (struct finalizable_object *) | ||||
|     	GC_generic_malloc_inner(sizeof(struct finalizable_object),NORMAL); | ||||
| #   else | ||||
|       new_fo = (struct finalizable_object *) | ||||
| 	GC_malloc(sizeof(struct finalizable_object)); | ||||
| #   endif | ||||
|     if (new_fo != 0) { | ||||
|         new_fo -> fo_hidden_base = (word)HIDE_POINTER(base); | ||||
| 	new_fo -> fo_fn = fn; | ||||
| 	new_fo -> fo_client_data = (ptr_t)cd; | ||||
| 	new_fo -> fo_object_size = GC_size(base); | ||||
| 	new_fo -> fo_mark_proc = mp; | ||||
| 	fo_set_next(new_fo, fo_head[index]); | ||||
| 	GC_fo_entries++; | ||||
| 	fo_head[index] = new_fo; | ||||
|     } else { | ||||
|      	GC_finalization_failures++; | ||||
|     GET_HDR(base, hhdr); | ||||
|     if (0 == hhdr) { | ||||
|       /* We won't collect it, hence finalizer wouldn't be run. */ | ||||
| #     ifdef THREADS | ||||
|           UNLOCK(); | ||||
|     	  ENABLE_SIGNALS(); | ||||
| #     endif | ||||
|       return; | ||||
|     } | ||||
|     new_fo = (struct finalizable_object *) | ||||
|     	GC_INTERNAL_MALLOC(sizeof(struct finalizable_object),NORMAL); | ||||
|     if (0 == new_fo) { | ||||
| #     ifdef THREADS | ||||
| 	UNLOCK(); | ||||
|     	ENABLE_SIGNALS(); | ||||
| #     endif | ||||
|       new_fo == GC_oom_fn(sizeof(struct finalizable_object)); | ||||
|       if (0 == new_fo) { | ||||
| 	GC_finalization_failures++; | ||||
| 	return; | ||||
|       } | ||||
|       /* It's not likely we'll make it here, but ... */ | ||||
| #     ifdef THREADS | ||||
|         DISABLE_SIGNALS(); | ||||
| 	LOCK(); | ||||
| #     endif | ||||
|     } | ||||
|     new_fo -> fo_hidden_base = (word)HIDE_POINTER(base); | ||||
|     new_fo -> fo_fn = fn; | ||||
|     new_fo -> fo_client_data = (ptr_t)cd; | ||||
|     new_fo -> fo_object_size = hhdr -> hb_sz; | ||||
|     new_fo -> fo_mark_proc = mp; | ||||
|     fo_set_next(new_fo, fo_head[index]); | ||||
|     GC_fo_entries++; | ||||
|     fo_head[index] = new_fo; | ||||
| #   ifdef THREADS | ||||
|         UNLOCK(); | ||||
|     	ENABLE_SIGNALS(); | ||||
| @@ -478,6 +509,34 @@ finalization_mark_proc * mp; | ||||
|     				ocd, GC_null_finalize_mark_proc); | ||||
| } | ||||
|  | ||||
| #ifndef NO_DEBUGGING | ||||
| void GC_dump_finalization() | ||||
| { | ||||
|     struct disappearing_link * curr_dl; | ||||
|     struct finalizable_object * curr_fo; | ||||
|     ptr_t real_ptr, real_link; | ||||
|     int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << log_dl_table_size); | ||||
|     int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << log_fo_table_size); | ||||
|     int i; | ||||
|  | ||||
|     GC_printf0("Disappearing links:\n"); | ||||
|     for (i = 0; i < dl_size; i++) { | ||||
|       for (curr_dl = dl_head[i]; curr_dl != 0; curr_dl = dl_next(curr_dl)) { | ||||
|         real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj); | ||||
|         real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link); | ||||
|         GC_printf2("Object: 0x%lx, Link:0x%lx\n", real_ptr, real_link); | ||||
|       } | ||||
|     } | ||||
|     GC_printf0("Finalizers:\n"); | ||||
|     for (i = 0; i < fo_size; i++) { | ||||
|       for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) { | ||||
|         real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base); | ||||
|         GC_printf1("Finalizable object: 0x%lx\n", real_ptr); | ||||
|       } | ||||
|     } | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* Called with world stopped.  Cause disappearing links to disappear,	*/ | ||||
| /* and invoke finalizers.						*/ | ||||
| void GC_finalize() | ||||
| @@ -515,9 +574,7 @@ void GC_finalize() | ||||
|     } | ||||
|   /* Mark all objects reachable via chains of 1 or more pointers	*/ | ||||
|   /* from finalizable objects.						*/ | ||||
| #   ifdef PRINTSTATS | ||||
|         if (GC_mark_state != MS_NONE) ABORT("Bad mark state"); | ||||
| #   endif | ||||
|     GC_ASSERT(GC_mark_state == MS_NONE); | ||||
|     for (i = 0; i < fo_size; i++) { | ||||
|       for (curr_fo = fo_head[i]; curr_fo != 0; curr_fo = fo_next(curr_fo)) { | ||||
|         real_ptr = (ptr_t)REVEAL_POINTER(curr_fo -> fo_hidden_base); | ||||
| @@ -560,11 +617,7 @@ void GC_finalize() | ||||
|               GC_words_finalized += | ||||
|                  	ALIGNED_WORDS(curr_fo -> fo_object_size) | ||||
|               		+ ALIGNED_WORDS(sizeof(struct finalizable_object)); | ||||
| #	    ifdef PRINTSTATS | ||||
|               if (!GC_is_marked((ptr_t)curr_fo)) { | ||||
|                 ABORT("GC_finalize: found accessible unmarked object\n"); | ||||
|               } | ||||
| #	    endif | ||||
| 	    GC_ASSERT(GC_is_marked(GC_base((ptr_t)curr_fo))); | ||||
|             curr_fo = next_fo; | ||||
|         } else { | ||||
|             prev_fo = curr_fo; | ||||
| @@ -619,7 +672,7 @@ void GC_finalize() | ||||
| void GC_enqueue_all_finalizers() | ||||
| { | ||||
|     struct finalizable_object * curr_fo, * prev_fo, * next_fo; | ||||
|     ptr_t real_ptr, real_link; | ||||
|     ptr_t real_ptr; | ||||
|     register int i; | ||||
|     int fo_size; | ||||
|      | ||||
| @@ -694,6 +747,14 @@ GC_API void GC_finalize_all() | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* Returns true if it is worth calling GC_invoke_finalizers. (Useful if	*/ | ||||
| /* finalizers can only be called from some kind of `safe state' and	*/ | ||||
| /* getting into that safe state is expensive.)				*/ | ||||
| int GC_should_invoke_finalizers GC_PROTO((void)) | ||||
| { | ||||
|     return GC_finalize_now != 0; | ||||
| } | ||||
|  | ||||
| /* Invoke finalizers for all objects that are ready to be finalized.	*/ | ||||
| /* Should be called without allocation lock.				*/ | ||||
| int GC_invoke_finalizers() | ||||
| @@ -731,6 +792,25 @@ int GC_invoke_finalizers() | ||||
|     return count; | ||||
| } | ||||
|  | ||||
| void (* GC_finalizer_notifier)() = (void (*) GC_PROTO((void)))0; | ||||
|  | ||||
| static GC_word last_finalizer_notification = 0; | ||||
|  | ||||
| void GC_notify_or_invoke_finalizers GC_PROTO((void)) | ||||
| { | ||||
|     if (GC_finalize_now == 0) return; | ||||
|     if (!GC_finalize_on_demand) { | ||||
| 	(void) GC_invoke_finalizers(); | ||||
| 	GC_ASSERT(GC_finalize_now == 0); | ||||
| 	return; | ||||
|     } | ||||
|     if (GC_finalizer_notifier != (void (*) GC_PROTO((void)))0 | ||||
| 	&& last_finalizer_notification != GC_gc_no) { | ||||
| 	last_finalizer_notification = GC_gc_no; | ||||
| 	GC_finalizer_notifier(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| # ifdef __STDC__ | ||||
|     GC_PTR GC_call_with_alloc_lock(GC_fn_type fn, | ||||
|     					 GC_PTR client_data) | ||||
| @@ -750,7 +830,9 @@ int GC_invoke_finalizers() | ||||
| #   endif | ||||
|     result = (*fn)(client_data); | ||||
| #   ifdef THREADS | ||||
|       UNSET_LOCK_HOLDER(); | ||||
| #     ifndef GC_ASSERTIONS | ||||
|         UNSET_LOCK_HOLDER(); | ||||
| #     endif /* o.w. UNLOCK() does it implicitly */ | ||||
|       UNLOCK(); | ||||
|       ENABLE_SIGNALS(); | ||||
| #   endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user