diff options
author | Jonathan Chambers <joncham@gmail.com> | 2019-02-11 23:55:47 +0300 |
---|---|---|
committer | Jonathan Chambers <joncham@gmail.com> | 2019-02-21 22:15:37 +0300 |
commit | eaafcc146b9e033c24c592689afa8a6f3242d659 (patch) | |
tree | 1878cea2463ad2bc27286225055223d8067aa6ef | |
parent | cd2c41ba19df1eb52ee1d7c41cc9d27fea053947 (diff) |
Add GC_gcj_vector_malloc to support marking complex (value types with reference fields) arrays.
-rw-r--r-- | gcj_mlc.c | 89 | ||||
-rw-r--r-- | include/gc_gcj.h | 6 |
2 files changed, 95 insertions, 0 deletions
@@ -46,13 +46,24 @@ #endif GC_bool GC_gcj_malloc_initialized = FALSE; +#ifdef GC_ASSERTIONS + GC_INNER /* variable is also used in thread_local_alloc.c */ +#else + STATIC +#endif +GC_bool GC_gcj_vector_initialized = FALSE; + int GC_gcj_kind = 0; /* Object kind for objects with descriptors */ /* in "vtable". */ int GC_gcj_debug_kind = 0; /* The kind of objects that is always marked */ /* with a mark proc call. */ +int GC_gcj_vector_kind = 0; /* Object kind for objects with descriptors */ + /* in "vtable". */ + GC_INNER ptr_t * GC_gcjobjfreelist = NULL; +GC_INNER ptr_t * GC_gcjvecfreelist = NULL; STATIC struct GC_ms_entry * GC_gcj_fake_mark_proc(word * addr GC_ATTR_UNUSED, struct GC_ms_entry *mark_stack_ptr, @@ -121,6 +132,36 @@ GC_API void GC_CALL GC_init_gcj_malloc(int mp_index, UNLOCK(); } +/* Caller does not hold allocation lock. */ +GC_API void GC_CALL GC_init_gcj_vector (int mp_index, + void * /* really GC_mark_proc */mp) +{ + DCL_LOCK_STATE; + + if (mp == 0) /* In case GC_DS_PROC is unused. */ + ABORT ("GC_init_gcj_vector: bad index"); + + GC_init (); /* In case it's not already done. */ + LOCK (); + if (GC_gcj_vector_initialized) { + UNLOCK (); + return; + } + GC_gcj_vector_initialized = TRUE; + + GC_ASSERT (GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */ + GC_mark_procs[mp_index ] = (GC_mark_proc)(word)mp; + if ((unsigned)mp_index >= GC_n_mark_procs) + ABORT ("GC_init_gcj_vector: bad index"); + GC_gcjvecfreelist = (ptr_t *)GC_new_free_list_inner (); + GC_gcj_vector_kind = GC_new_kind_inner (GC_gcjvecfreelist, + GC_MAKE_PROC (mp_index, + 0), + FALSE, TRUE); + + UNLOCK (); +} + #define GENERAL_MALLOC_INNER(lb,k) \ GC_clear_stack(GC_generic_malloc_inner(lb, k)) @@ -197,6 +238,54 @@ static void maybe_finalize(void) GC_dirty(op); return((void *) op); } + +#ifdef THREAD_LOCAL_ALLOC +#error No THREAD_LOCAL_ALLOC support for GC_gcj_vector_malloc +#else + GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_vector_malloc (size_t lb, + void * ptr_to_struct_containing_descr) +#endif + { + ptr_t op; + DCL_LOCK_STATE; + + GC_DBG_COLLECT_AT_MALLOC (lb); + if (SMALL_OBJ (lb)) { + word lg; + + LOCK (); + lg = GC_size_map[lb]; + op = GC_gcjvecfreelist[lg]; + if (EXPECT (0 == op, FALSE)) { + maybe_finalize (); + op = (ptr_t)GENERAL_MALLOC_INNER ((word)lb, GC_gcj_vector_kind); + if (0 == op) { + GC_oom_func oom_fn = GC_oom_fn; + UNLOCK (); + return((*oom_fn)(lb)); + } + } + else { + GC_gcjvecfreelist[lg] = (ptr_t)obj_link (op); + GC_bytes_allocd += GRANULES_TO_BYTES ((word)lg); + } + GC_ASSERT (((void **)op)[1] == 0); + } + else { + LOCK (); + maybe_finalize (); + op = (ptr_t)GENERAL_MALLOC_INNER ((word)lb, GC_gcj_vector_kind); + if (0 == op) { + GC_oom_func oom_fn = GC_oom_fn; + UNLOCK (); + return((*oom_fn)(lb)); + } + } + *(void **)op = ptr_to_struct_containing_descr; + UNLOCK (); + GC_dirty (op); + return((void *)op); + } #endif /* Similar to GC_gcj_malloc, but add debug info. This is allocated */ diff --git a/include/gc_gcj.h b/include/gc_gcj.h index 476db221..deca0fee 100644 --- a/include/gc_gcj.h +++ b/include/gc_gcj.h @@ -68,6 +68,8 @@ /* (GC_GCJ_RESERVED_MARK_PROC_INDEX in gc_mark.h) is an obvious choice. */ GC_API void GC_CALL GC_init_gcj_malloc(int /* mp_index */, void * /* really mark_proc */ /* mp */); +GC_API void GC_CALL GC_init_gcj_vector (int /* mp_index */, + void * /* really mark_proc */ /* mp */); /* Allocate an object, clear it, and store the pointer to the */ /* type structure (vtable in gcj). */ @@ -89,6 +91,10 @@ GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL GC_gcj_malloc_ignore_off_page(size_t /* lb */, void * /* ptr_to_struct_containing_descr */); +GC_API GC_ATTR_MALLOC void * GC_CALL + GC_gcj_vector_malloc(size_t /* lb */, + void * /* ptr_to_struct_containing_descr */); + /* The kind numbers of normal and debug gcj objects. */ /* Useful only for debug support, we hope. */ GC_API int GC_gcj_kind; |