[m-dev.] for review: use type_ctor_rep for unify, index and compare

Fergus Henderson fjh at cs.mu.OZ.AU
Thu Sep 30 18:15:26 AEST 1999


On 30-Sep-1999, Zoltan Somogyi <zs at cs.mu.OZ.AU> wrote:
> 
> Change the way unify, index and compare work. Instead of always calling the
> type-specific unification, index and comparison procedures, do a dispatch
> on the type_ctor_rep instead, and call the type-specific routine only
> if necessary. Also, specialize the common cases of type_ctors of arity
> 0, 1 and 2. This gives us a speedup of about 3 or 4 percent.
> Later we should be able to use the RTTI info to avoid calling the type-specific
> routines at all, except for types with user-defined equality.

... and hence also avoid generating them, which will give us a major
reduction in code size and compilation time.  Great stuff.

> runtime/mercury_ho_call.c:
> 	Make the change described above, while keeping the old code around
> 	but #ifdef'd out.
> 
> 	The index routine now (properly) prints an error for enumerated types;
> 	previously, the compiler-generated predicate would usually (depending
> 	on compilation options) ignore the error.

I discussed this with Zoltan.  Currently index/1 is not used for
enumerated types.  However, it might well make sense to use it for
enumerated types in the future.  index/1 in general makes sense for
any discriminated union type.

For example, we might want to implement deep_copy or something similar
in Mercury, using std_util:deconstruct and std_util:construct.  To make
that work, we need a way of finding out the functor number to pass to
construct.  Currently the only way to do that is to call
std_util:functor to figure out the name of the functor, and to call
std_util:num_functors to figure out the number of functors in the type,
and to then call std_util:get_functor for each functor in the type,
until we find one for which the name returned from std_util:get_functor
matches the name that was returned from std_util:functor.
Clearly this is a rather round-about route.  It would be much nicer
if that could be done by just calling index/1.
Unfortunately that doesn't work yet, because index/1 numbers the functors
in declaration order, whereas std_util:construct and std_util:get_functor
number them in alphabetical order.  But hopefully we can eventually
make them all use declaration order in which case index/1 will become
useful.

Similarly, index/1 could be useful for some versions of io__write_binary,
or perhaps even for hashing, tries, and so forth.

For builtin types such as float, string, c_pointer, etc., index/1
does not make much sense.  The existing code for index/1 returns -1
in such cases, so that code which calls index/1 can handle the
generic case first, check the result for -1, and then if necessary
handle the special cases; this may be more efficient than checking
for the special cases first.  I think we should keep that behaviour,
rather than calling fatal_error() in those cases.

(On a related point, most of those calls to fatal_error() in compare
and unify should eventually be replaced by code that throws exceptions.)

> +		case MR_TYPECTOR_REP_ENUM:
> +			r1 = ((Unsigned) x == (Unsigned) y);
> +			proceed();
> +
> +		case MR_TYPECTOR_REP_INT:
> +		case MR_TYPECTOR_REP_CHAR:
> +			r1 = ((Integer) x == (Integer) y);
> +			proceed();

In other parts of the compiler, we treat enumerations as Mercury ints
(`Integer') rather than as unsigned.  So you might as well do so here.
I don't think it is worth the extra code size to cater for the case
where someone writes Mercury code that includes an enumeration with
more than 2^31 different alternatives.  Even 2^15 would be unlikely,
even for automatically-generated code.

>  	/* 
> -	** Macros for retreiving things from type_ctor_infos.
> +	** Macros for retrieving things from type_ctor_infos.
> +	**
> +	** XXX zs: these macros should be deleted; the code using them
> +	** would be clearer if it referred to TypeCtorInfo fields directly.
>  	*/
>  #define MR_TYPE_CTOR_INFO_GET_TYPE_CTOR_FUNCTORS(TypeCtorInfo)		\
>  	((TypeCtorInfo)->type_ctor_functors)

Actually there are advantages to having the extra layer of abstraction.
It makes it easier to change the representation of the TypeCtorInfo type
without modifying the code that uses it.  However, you're probably right
that the readability advantages of referring to the fields directly
outweighs the maintainability advantages of that extra layer of abstraction.
In this respect, C sucks ;-)

-- 
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.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list