diff options
author | Xavier Leroy <xavier.leroy@inria.fr> | 2013-06-01 07:43:45 +0000 |
---|---|---|
committer | Xavier Leroy <xavier.leroy@inria.fr> | 2013-06-01 07:43:45 +0000 |
commit | 1b72ae5896ae5a9c4f5cd79f1d289e3de19c9954 (patch) | |
tree | b725ba7fa1926d1646c1bed7c349d58fdfeb2006 /byterun/memory.c | |
parent | 87508f1d4b13203eddd8366e4ce26f39c1da07f3 (diff) |
More efficient implementation of caml_modify().
Performance improvement in caml_initialize().
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@13723 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
Diffstat (limited to 'byterun/memory.c')
-rw-r--r-- | byterun/memory.c | 54 |
1 files changed, 50 insertions, 4 deletions
diff --git a/byterun/memory.c b/byterun/memory.c index 6f86e3e9a..775146207 100644 --- a/byterun/memory.c +++ b/byterun/memory.c @@ -502,10 +502,11 @@ CAMLexport void caml_adjust_gc_speed (mlsize_t res, mlsize_t max) */ /* [caml_initialize] never calls the GC, so you may call it while a block is unfinished (i.e. just after a call to [caml_alloc_shr].) */ -void caml_initialize (value *fp, value val) +CAMLexport void caml_initialize (value *fp, value val) { + CAMLassert(Is_in_heap(fp)); *fp = val; - if (Is_block (val) && Is_young (val) && Is_in_heap (fp)){ + if (Is_block (val) && Is_young (val)) { if (caml_ref_table.ptr >= caml_ref_table.limit){ caml_realloc_ref_table (&caml_ref_table); } @@ -517,9 +518,54 @@ void caml_initialize (value *fp, value val) unless you are sure the value being overwritten is not a shared block and the value being written is not a young block. */ /* [caml_modify] never calls the GC. */ -void caml_modify (value *fp, value val) +/* [caml_modify] can also be used to do assignment on data structures that are + in the minor heap instead of in the major heap. In this case, it + is a bit slower than simple assignment. + In particular, you can use [caml_modify] when you don't know whether the + block being changed is in the minor heap or the major heap. +*/ + +CAMLexport void caml_modify (value *fp, value val) { - Modify (fp, val); + /* The write barrier implemented by [caml_modify] checks for the + following two conditions and takes appropriate action: + 1- a pointer from the major heap to the minor heap is created + --> add [fp] to the remembered set + 2- a pointer from the major heap to the major heap is overwritten, + while the GC is in the marking phase + --> call [caml_darken] on the overwritten pointer so that the + major GC treats it as an additional root. + */ + value old; + + if (Is_young(fp)) { + /* The modified object resides in the minor heap. + Conditions 1 and 2 cannot occur. */ + *fp = val; + } else { + /* The modified object resides in the major heap. */ + CAMLassert(Is_in_heap(fp)); + old = *fp; + *fp = val; + if (Is_block(old)) { + /* If [old] is a pointer within the minor heap, we already + have a major->minor pointer and [fp] is already in the + remembered set. Conditions 1 and 2 cannot occur. */ + if (Is_young(old)) return; + /* Here, [old] can be a pointer within the major heap. + Check for condition 2. */ + if (caml_gc_phase == Phase_mark) caml_darken(old, NULL); + } + /* Check for condition 1. */ + if (Is_block(val) && Is_young(val)) { + /* Add [fp] to remembered set */ + if (caml_ref_table.ptr >= caml_ref_table.limit){ + CAMLassert (caml_ref_table.ptr == caml_ref_table.limit); + caml_realloc_ref_table (&caml_ref_table); + } + *caml_ref_table.ptr++ = fp; + } + } } CAMLexport void * caml_stat_alloc (asize_t sz) |