Version française
Home     About     Download     Resources     Contact us    
Browse thread
Modify macro and caml_initialize function
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Basile Starynkevitch <basile@s...>
Subject: Re: [Caml-list] Modify macro and caml_initialize function
On Sun, 5 Dec 2010 17:02:37 +0100
"CUOQ Pascal" <Pascal.CUOQ@cea.fr> wrote:

> ygrek wrote:
> 
> > BTW, while we are on this topic, why the following is not in upstream yet?
> >
> > http://eigenclass.org/R2/writings/optimizing-caml_modify
> >
> > Looks like a clear win-win without drawbacks (increased code size shouldn't be significant
> > cause Modify is only used in a couple of places). What do you think?
> 
> This is very interesting. Thanks for pointing it out.


Sorry to be nitpicking, but...

IIRC, there might be some rare occasions where the Modify macro could
be called several times in a C routine. And then you've got several
caml_modify_maybe_add_to_ref_table labels in the same C routine.

With GCC, you could use a local __label__
http://gcc.gnu.org/onlinedocs/gcc/Local-Labels.html but if you want to
be portable to non GCC compilers, you'll need a Modify macro which
generates a unique label (perhaps using __LINE__ for that purpose).

I am thinking of something like [UNTESTED CODE]

#define Modify(fp, val) Modify_at(fp, val, __LINE__)

#define Modify_at(fp, val, lin) do{                                         \
  value in_heap = 0;                                                        \
  value _old_ = *(fp);                                                      \
  *(fp) = (val);                                                            \
  if (caml_gc_phase == Phase_mark) {                                        \
    if (Is_in_heap (fp)) {                                                  \
      caml_darken (_old_, NULL);                                            \
      in_heap = 1;                                                          \
      goto caml_modify_maybe_add_to_ref_table##Lin;                         \
    }                                                                       \
  } else {                                                                  \
      caml_modify_maybe_add_to_ref_table##Lin:                              \
      if (Is_block (val) && Is_young (val)                                  \
          && ! (Is_block (_old_) && Is_young (_old_)) &&                    \
          (in_heap || Is_in_heap (fp)) ){                                   \
        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);                                       \
      }                                                                     \
  }                                                                         \
}while(0)

Cheers.
-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***