[m-dev.] For review: Add implementation of reference types (global heap)
Fergus Henderson
fjh at cs.mu.OZ.AU
Wed Jun 10 03:42:32 AEST 1998
On 09-Jun-1998, Warwick Harvey <wharvey at cs.monash.edu.au> wrote:
> Here's the updated diffs, as requested...
> +Word
> +MR_make_permanent(Word term, Word *type_info)
> +{
> + return MR_make_long_lived(term, type_info, NULL);
> +}
It would be more efficient to define this as a macro in the header file.
Same applies for MR_make_long_lived() in the CONSERVATIVE_GC case.
You can take that as an optional suggestion ;-)
> +#define swap(val1, val2, type) \
> + do { \
> + type swap_tmp; \
> + swap_tmp = (val1); \
> + (val1) = (val2); \
> + (val2) = swap_tmp; \
> + } while (0)
Since this macro is not function-like (its first two arguments
are by reference and the last is a type), I suggest s/swap/SWAP/.
Also it's easier to read if you line up all the backslashes.
> +++ mercury_deep_copy.h 1998/06/09 06:48:37
> @@ -63,4 +63,32 @@
> Word deep_copy(Word data, Word *type_info, Word *lower_limit,
> Word *upper_limit);
>
> +/* MR_make_permanent:
> +**
Should be
/*
** ...
**
not
/* ...
**
> +/* MR_make_long_lived:
> +**
Ditto.
> extras/references/nb_reference.m
...
> :- implementation.
>
> % This type is not really used. I'd rather define this as c_pointer, but
> % there's a bug in the Mercury compiler that makes that not work.
> :- type nb_reference(T) ---> nb_reference(c_pointer).
The first sentence in that comment is a bit misleading.
I suggest you replace it with "This type is implemented in C."
Regarding the second sentence,
It's true that there is a bug in the Mercury compiler that makes
:- type nb_reference(T) == c_pointer.
not work. However, the definition using == is actually less useful
than the one above, IMHO, since the one above gives you more informative
output from type_of/1, io__write/3, etc.
Thus I suggest you delete the second sentence.
> :- pragma inline(new_nb_reference/2).
> :- pragma c_code(new_nb_reference(X::in, Ref::out), will_not_call_mercury, "
> incr_hp(Ref, 1);
> save_transient_registers();
> *(Word *)Ref = MR_make_long_lived(X, (Word *) TypeInfo_for_T,
> (Word *) Ref);
> restore_transient_registers();
> ").
>
> :- pragma inline(value/2).
> :- pragma c_code(value(Ref::in, X::out), will_not_call_mercury, "
> X = *(Word *) Ref;
> ").
>
> :- pragma inline(update/2).
> :- pragma c_code(update(Ref::in, X::in), will_not_call_mercury, "
> save_transient_registers();
> *(Word *)Ref = MR_make_long_lived(X, (Word *) TypeInfo_for_T,
> (Word *) Ref);
> restore_transient_registers();
> ").
If you were concerned about efficiency, you could wrap `#ifndef
CONSERVATIVE_GC ... #endif' around those calls to
save_transient_registers() and restore_transient_registers().
> extras/references/reference.m
...
> :- implementation.
>
> % This type is not really used. I'd rather define this as c_pointer, but
> % there's a bug in the Mercury compiler that makes that not work.
> :- type reference(T) ---> reference(c_pointer).
Same comment as above.
> :- pragma inline(new_reference/2).
> :- pragma c_code(new_reference(X::in, Ref::out), will_not_call_mercury, "
> incr_hp(Ref, (sizeof(Reference) + sizeof(Word) - 1) / sizeof(Word));
> ((RefPtr)Ref)->value = (void *)X;
> ((RefPtr)Ref)->id = MR_current_choicepoint_id();
> ").
>
> :- pragma inline(value/2).
> :- pragma c_code(value(Ref::in, X::out), will_not_call_mercury, "
> X = (Word) ((RefPtr)Ref)->value;
> ").
Our convention is to put a space after type casts:
s/(RefPtr)/(RefPtr) /g
s/(void *)/(void *) /
> :- pragma c_code(update(Ref::in, X::in), will_not_call_mercury, "
> RefPtr ref = (RefPtr) Ref;
> if (ref->id != MR_current_choicepoint_id()) {
> MR_trail_current_value((Word*)(&ref->value));
> MR_trail_current_value((Word*)(&ref->id));
> ref->id = MR_current_choicepoint_id();
> }
> ref->value = (void *)X;
> ").
Ditto here.
> typedef struct {
> Word *var;
> Word insideval;
> Word outsideval;
> } *ScopeHandle;
>
> void ME_enter_scope_failing(ScopeHandle handle, MR_untrail_reason reason);
> void ME_exit_scope_failing(ScopeHandle handle, MR_untrail_reason reason);
The ScopeHandle type should get a `ME_' prefix too, lest it clash
with a type defined in some other header file.
(There is some argument for prefixing even struct members, lest
they clash with macro names, but I think that the inconvenience
of the longer names probably outweighs the advantage in that case.
Defining lower-case non-function-like macros has always been considered
bad style in C, so if the user does that, and it causes a clash, then
I think it is not unreasonable for us to say that it's up to the user
to fix it.)
> #ifdef ME_DEBUG_SCOPE
> #define show_handle(msg, handle) \
> printf(""%s <%5d, in: %5d, out: %5d\n"", msg, *(int *)handle->var, \
> (int) handle->insideval, (int) handle->outsideval)
> #define untrail_msg(msg) \
> printf(msg)
> #else
> #define show_handle(msg, handle)
> #define untrail_msg(msg)
> #endif
These macros should get a ME_ prefix too.
Also, the uses of the macro parameters should be parenthesized.
And our convention is that stuff inside #ifdef should be intended two spaces:
#ifdef ME_DEBUG_SCOPE
#define ME_show_handle(msg, handle) \
printf(""%s <%5d, in: %5d, out: %5d\n"", (msg), \
*(int *)(handle)->var, \
(int) (handle)->insideval, \
(int) (handle)->outsideval)
#define ME_untrail_msg(msg) \
printf(msg)
#else
#define ME_show_handle(msg, handle)
#define ME_untrail_msg(msg)
#endif
I think these changes should be straightforward, but just to confirm,
can you please send one more diff when you've dealt with them?
I'd prefer a relative diff (i.e. make a backup copy of your current
version of the files before you modify them and diff against that)
this time.
Thanks again,
Fergus.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3 | -- the last words of T. S. Garp.
More information about the developers
mailing list