diff options
author | Ivan Maidanski <ivmai@mail.ru> | 2023-04-26 08:31:36 +0300 |
---|---|---|
committer | Ivan Maidanski <ivmai@mail.ru> | 2023-04-26 17:31:05 +0300 |
commit | 3e93d05a20d0da777765078836c69cc60472187d (patch) | |
tree | 664b505dddb55d778dc2046804172a0a8cb6e3c8 | |
parent | 223ce4fdf375a59dc963dc57dd900cb7f37bc8d0 (diff) | |
download | bdwgc-3e93d05a20d0da777765078836c69cc60472187d.tar.gz |
Decouple descriptor compute from object alloc in calloc_explicitly_typed
(refactoring)
This is a preparation for providing ability to the client to compute
(and allocate) the internal descriptor of GC_calloc_explicitly_typed
once (for the given object layout and elements count) and perform
the typed allocation multiple times.
* typd_mlc.c (GC_calloc_typed_descr_s): New struct type.
* typd_mlc.c (GC_calloc_prepare_explicitly_typed,
GC_calloc_do_explicitly_typed): New static function (move part of code
from GC_calloc_explicitly_typed); use GC_calloc_typed_descr_s to pass
leaf, simple_d, complex_d, alloc_lb, descr_type values between two
functions; set and use alloc_lb instead of updating lb local variable.
* typd_mlc.c (GC_calloc_explicitly_typed): Use
GC_calloc_prepare_explicitly_typed and GC_calloc_do_explicitly_typed.
* typd_mlc.c (GC_array_mark_proc): Update comment.
-rw-r--r-- | typd_mlc.c | 106 |
1 files changed, 70 insertions, 36 deletions
@@ -469,53 +469,77 @@ STATIC int GC_make_array_descriptor(size_t nelements, size_t size, return LEAF; } -GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_explicitly_typed(size_t n, - size_t lb, GC_descr d) -{ - void *op; - size_t nwords; - GC_descr simple_d; - complex_descriptor *complex_d; - int descr_type; - struct LeafDescriptor leaf; +struct GC_calloc_typed_descr_s { + struct LeafDescriptor leaf; + GC_descr simple_d; + complex_descriptor *complex_d; + size_t alloc_lb; + int descr_type; +}; +STATIC void GC_calloc_prepare_explicitly_typed( + struct GC_calloc_typed_descr_s *pctd, + size_t n, size_t lb, GC_descr d) +{ GC_STATIC_ASSERT(sizeof(struct LeafDescriptor) % sizeof(word) == 0); GC_ASSERT(GC_explicit_typing_initialized); if (EXPECT(0 == lb || 0 == n, FALSE)) lb = n = 1; if (EXPECT((lb | n) > GC_SQRT_SIZE_MAX, FALSE) /* fast initial check */ - && n > GC_SIZE_MAX / lb) - return (*GC_get_oom_fn())(GC_SIZE_MAX); /* n*lb overflow */ - - descr_type = GC_make_array_descriptor((word)n, (word)lb, d, - &simple_d, &complex_d, &leaf); - lb *= n; - switch(descr_type) { - case NO_MEM: - return (*GC_get_oom_fn())(lb); - case SIMPLE: - return GC_malloc_explicitly_typed(lb, simple_d); - case LEAF: - lb = SIZET_SAT_ADD(lb, + && n > GC_SIZE_MAX / lb) { + pctd -> alloc_lb = GC_SIZE_MAX; /* n*lb overflow */ + pctd -> descr_type = NO_MEM; + /* The rest of the fields are unset. */ + return; + } + + pctd -> descr_type = GC_make_array_descriptor((word)n, (word)lb, d, + &(pctd -> simple_d), &(pctd -> complex_d), + &(pctd -> leaf)); + switch (pctd -> descr_type) { + case NO_MEM: + case SIMPLE: + pctd -> alloc_lb = lb * n; + break; + case LEAF: + pctd -> alloc_lb = SIZET_SAT_ADD(lb * n, sizeof(struct LeafDescriptor) + TYPD_EXTRA_BYTES); - break; - case COMPLEX: - lb = SIZET_SAT_ADD(lb, TYPD_EXTRA_BYTES); - break; + break; + case COMPLEX: + pctd -> alloc_lb = SIZET_SAT_ADD(lb * n, TYPD_EXTRA_BYTES); + break; + } +} + +STATIC GC_ATTR_MALLOC void * GC_calloc_do_explicitly_typed( + const struct GC_calloc_typed_descr_s *pctd) +{ + void *op; + size_t nwords; + + switch (pctd -> descr_type) { + case NO_MEM: + return (*GC_get_oom_fn())(pctd -> alloc_lb); + case SIMPLE: + return GC_malloc_explicitly_typed(pctd -> alloc_lb, pctd -> simple_d); + case LEAF: + case COMPLEX: + break; } - op = GC_malloc_kind(lb, GC_array_kind); + op = GC_malloc_kind(pctd -> alloc_lb, GC_array_kind); if (EXPECT(NULL == op, FALSE)) - return NULL; + return NULL; + nwords = GRANULES_TO_WORDS(BYTES_TO_GRANULES(GC_size(op))); - if (descr_type == LEAF) { + if (pctd -> descr_type == LEAF) { /* Set up the descriptor inside the object itself. */ struct LeafDescriptor *lp = (struct LeafDescriptor *)((word *)op + nwords - (BYTES_TO_WORDS(sizeof(struct LeafDescriptor)) + 1)); lp -> ld_tag = LEAF_TAG; - lp -> ld_size = leaf.ld_size; - lp -> ld_nelements = leaf.ld_nelements; - lp -> ld_descriptor = leaf.ld_descriptor; + lp -> ld_size = pctd -> leaf.ld_size; + lp -> ld_nelements = pctd -> leaf.ld_nelements; + lp -> ld_descriptor = pctd -> leaf.ld_descriptor; /* Hold the allocation lock while writing the descriptor word */ /* to the object to ensure that the descriptor contents are seen */ /* by GC_array_mark_proc as expected. */ @@ -530,11 +554,11 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_explicitly_typed(size_t n, } else { # ifndef GC_NO_FINALIZATION LOCK(); - ((word *)op)[nwords - 1] = (word)complex_d; + ((word *)op)[nwords - 1] = (word)(pctd -> complex_d); UNLOCK(); GC_dirty((word *)op + nwords - 1); - REACHABLE_AFTER_DIRTY(complex_d); + REACHABLE_AFTER_DIRTY(pctd -> complex_d); /* Make sure the descriptor is cleared once there is any danger */ /* it may have been collected. */ @@ -543,12 +567,22 @@ GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_explicitly_typed(size_t n, # endif { /* Couldn't register it due to lack of memory. Punt. */ - return (*GC_get_oom_fn())(lb); + return (*GC_get_oom_fn())(pctd -> alloc_lb); } } return op; } +GC_API GC_ATTR_MALLOC void * GC_CALL GC_calloc_explicitly_typed(size_t n, + size_t lb, + GC_descr d) +{ + struct GC_calloc_typed_descr_s ctd; + + GC_calloc_prepare_explicitly_typed(&ctd, n, lb, d); + return GC_calloc_do_explicitly_typed(&ctd); +} + /* Return the size of the object described by complex_d. It would be */ /* faster to store this directly, or to compute it as part of */ /* GC_push_complex_descriptor, but hopefully it does not matter. */ @@ -631,7 +665,7 @@ static complex_descriptor *get_complex_descr(word *addr, size_t nwords) return (complex_descriptor *)addr[nwords - 1]; } -/* Used by GC_calloc_explicitly_typed via GC_array_kind. */ +/* Used by GC_calloc_do_explicitly_typed via GC_array_kind. */ STATIC mse *GC_array_mark_proc(word *addr, mse *mark_stack_ptr, mse *mark_stack_limit, word env) { |