for review: deep copy cleanup.

Tyson Dowd trd at cs.mu.OZ.AU
Tue Jun 2 14:16:57 AEST 1998


Hi,

Here's a cleanup of deep copy.  This should make it easier to add
other functions that need to do similar things. 

===================================================================


Estimated hours taken: 4

Cleanup deep copy.

runtime/mercury_deep_copy.c:
	Use MR_categorize_data, and switch on the result.
	
	This makes the control flow much simpler -- each case only needs
	to worry about copying the data.
	We can also use fallthru to exploit duplicated code.

	Remove get_base_type_layout_entry, it isn't very useful.

runtime/mercury_type_info.c:
runtime/mercury_type_info.h:
	Define MR_categorize_data and the enum MR_DataRepresentation.

	MR_categorize_data can be used by any function that needs to
	manipulate data.



Index: runtime/mercury_deep_copy.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_deep_copy.c,v
retrieving revision 1.6
diff -u -t -r1.6 mercury_deep_copy.c
--- mercury_deep_copy.c	1998/05/15 07:09:13	1.6
+++ mercury_deep_copy.c	1998/06/01 07:43:22
@@ -17,7 +17,6 @@
 /*
 ** Prototypes.
 */
-static Word get_base_type_layout_entry(Word data, Word *type_info);
 static Word deep_copy_arg(Word data, Word *type_info, Word *arg_type_info,
         Word *lower_limit, Word *upper_limit);
 static Word * deep_copy_type_info(Word *type_info,
@@ -37,205 +36,39 @@
 Word 
 deep_copy(Word data, Word *type_info, Word *lower_limit, Word *upper_limit)
 {
+    Word *base_type_info, *base_type_layout, *base_type_functors;
+    Word functors_indicator;
     Word layout_entry, *entry_value, *data_value;
-    int data_tag, entry_tag; 
-
-    int arity, i;
-    Word *argument_vector, *type_info_vector;
-
+    enum MR_DataRepresentation data_rep;
+    int data_tag; 
     Word new_data;
-
         
     data_tag = tag(data);
     data_value = (Word *) body(data, data_tag);
-
-    layout_entry = get_base_type_layout_entry(data_tag, type_info);
-
-    entry_tag = tag(layout_entry);
-    entry_value = (Word *) body(layout_entry, entry_tag);
-
-    switch(entry_tag) {
-
-        case TYPELAYOUT_CONST_TAG: /* and TYPELAYOUT_COMP_CONST_TAG */
-
-            /* Some builtins need special treatment */
-            if ((Word) entry_value <= TYPELAYOUT_MAX_VARINT) {
-                int builtin_type = unmkbody(entry_value);
-
-                switch(builtin_type) {
-
-                    case TYPELAYOUT_UNASSIGNED_VALUE:
-                        fatal_error("Attempt to use an UNASSIGNED tag "
-                            "in deep_copy");
-                        break;
-
-                    case TYPELAYOUT_UNUSED_VALUE:
-                        fatal_error("Attempt to use an UNUSED tag "
-                            "in deep_copy");
-                        break;
-
-                    case TYPELAYOUT_STRING_VALUE:
-                        if (in_range(data_value)) {
-                            incr_saved_hp_atomic(new_data, 
-                                (strlen((String) data_value) + sizeof(Word)) 
-                                / sizeof(Word));
-                            strcpy((String) new_data, (String) data_value);
-                        } else {
-                            new_data = data;
-                        }
-                        break;
 
-                    case TYPELAYOUT_FLOAT_VALUE:
-                        #ifdef BOXED_FLOAT
-                            if (in_range(data_value)) {
-                                /*
-                                ** force a deep copy by converting to float
-                                ** and back
-                                */
-                                new_data = float_to_word(word_to_float(data));
-                            } else {
-                                new_data = data;
-                            }
-                        #else
-                            new_data = data;
-                        #endif
-                        break;
-
-                    case TYPELAYOUT_INT_VALUE:
-                        new_data = data;
-                        break;
-
-                    case TYPELAYOUT_CHARACTER_VALUE:
-                        new_data = data;
-                        break;
-
-                    case TYPELAYOUT_UNIV_VALUE: 
-                            /* if the univ is stored in range, copy it */ 
-                        if (in_range(data_value)) {
-                            Word *new_data_ptr;
-
-                                /* allocate space for a univ */
-                            incr_saved_hp(new_data, 2);
-                            new_data_ptr = (Word *) new_data;
-                            new_data_ptr[UNIV_OFFSET_FOR_TYPEINFO] = 
-                                (Word) deep_copy_type_info( (Word *)
-                                    data_value[UNIV_OFFSET_FOR_TYPEINFO],
-                                    lower_limit, upper_limit);
-                            new_data_ptr[UNIV_OFFSET_FOR_DATA] = deep_copy(
-                                data_value[UNIV_OFFSET_FOR_DATA], 
-                                (Word *) data_value[UNIV_OFFSET_FOR_TYPEINFO],
-                                lower_limit, upper_limit);
-                        } else {
-                            new_data = data;
-                        }
-                        break;
-
-                    case TYPELAYOUT_PREDICATE_VALUE:
-                    {
-                        /*
-                        ** predicate closures store the number of curried
-                        ** arguments as their first argument, the
-                        ** Code * as their second, and then the
-                        ** arguments
-                        **
-                        ** Their type-infos have a pointer to
-                        ** base_type_info for pred/0, arity, and then
-                        ** argument typeinfos.
-                        **/
-                        if (in_range(data_value)) {
-                            int args;
-                            Word *new_closure;
-
-                            /* get number of curried arguments */
-                            args = data_value[0];
-
-                            /* create new closure */
-                            incr_saved_hp(LVALUE_CAST(Word, new_closure),
-                                args + 2);
-
-                            /* copy number of arguments */
-                            new_closure[0] = args;
-
-                            /* copy pointer to code for closure */
-                            new_closure[1] = data_value[1];
-
-                            /* copy arguments */
-                            for (i = 0; i < args; i++) {
-                                new_closure[i + 2] = deep_copy(
-                                    data_value[i + 2],
-                                    (Word *) type_info[i +
-                                        TYPEINFO_OFFSET_FOR_PRED_ARGS],
-                                    lower_limit, upper_limit);
-                            }
-                            new_data = (Word) new_closure;
-                        } else {
-                            new_data = data;
-                        }
-                        break;
-                    }
-
-                    case TYPELAYOUT_VOID_VALUE:
-                        fatal_error("Attempt to use a VOID tag in deep_copy");
-                        break;
-
-                    case TYPELAYOUT_ARRAY_VALUE:
-                        if (in_range(data_value)) {
-                            MR_ArrayType *new_array;
-                            MR_ArrayType *old_array;
-                            Integer array_size;
-
-                            old_array = (MR_ArrayType *) data_value;
-                            array_size = old_array->size;
-                            new_array = MR_make_array(array_size);
-                            new_array->size = array_size;
-                            for (i = 0; i < array_size; i++) {
-                                new_array->elements[i] = deep_copy_arg(
-                                        old_array->elements[i], type_info, 
-                                        (Word *) 1, lower_limit, upper_limit);
-                            }
-                            new_data = (Word) new_array;
-                        } else {
-                            new_data = data;
-                        }
-                        break;
-
-                    case TYPELAYOUT_TYPEINFO_VALUE:
-                        new_data = (Word) deep_copy_type_info(data_value,
-                            lower_limit, upper_limit);
-                        break;
-
-                    case TYPELAYOUT_C_POINTER_VALUE:
-                        if (in_range(data_value)) {
-                            /*
-                            ** This error occurs if we try to deep_copy() a
-                            ** `c_pointer' type that points to memory allocated
-                            ** on the Mercury heap.
-                            */
-                            fatal_error("Attempt to use a C_POINTER tag "
-                                    "in deep_copy");
-                        } else {
-                            new_data = data;
-                        }
-                        break;
-
-                    default:
-                        fatal_error("Invalid tag value in deep_copy");
-                        break;
-                }
-            } else {
-                    /* a constant or enumeration */
-                new_data = data;        /* just a copy of the actual item */
-            }
-            break;
-
-        case TYPELAYOUT_SIMPLE_TAG: 
-
+    base_type_info = MR_TYPEINFO_GET_BASE_TYPEINFO(type_info);
+    base_type_layout = MR_BASE_TYPEINFO_GET_TYPELAYOUT(base_type_info);
+    layout_entry = base_type_layout[data_tag];
+
+    base_type_functors = MR_BASE_TYPEINFO_GET_TYPEFUNCTORS(base_type_info);
+    functors_indicator = MR_TYPEFUNCTORS_INDICATOR(base_type_functors);
+
+    entry_value = (Word *) strip_tag(layout_entry);
+
+    data_rep = MR_categorize_data(functors_indicator, layout_entry);
+
+    switch(data_rep) {
+        case MR_DATAREP_ENUM:                   /* fallthru */
+        case MR_DATAREP_COMPLICATED_CONST:
+            new_data = data;    /* just a copy of the actual item */
+        break;
+
+        case MR_DATAREP_SIMPLE: {
+            int arity, i;
+            Word *argument_vector, *type_info_vector;
             argument_vector = data_value;
 
-                /*
-                ** If the argument vector is in range, copy the
-                ** arguments.
-                */
+                /* If the argument vector is in range, copy the arguments */
             if (in_range(argument_vector)) {
                 arity = entry_value[TYPELAYOUT_SIMPLE_ARITY_OFFSET];
                 type_info_vector = entry_value + TYPELAYOUT_SIMPLE_ARGS_OFFSET;
@@ -245,10 +78,9 @@
 
                     /* copy arguments */
                 for (i = 0; i < arity; i++) {
-                    field(0, new_data, i) =
-                        deep_copy_arg(argument_vector[i],
-                                type_info, (Word *) type_info_vector[i],
-                                lower_limit, upper_limit);
+                    field(0, new_data, i) = deep_copy_arg(argument_vector[i],
+                        type_info, (Word *) type_info_vector[i], lower_limit,
+                        upper_limit);
                 }
                     /* tag this pointer */
                 new_data = (Word) mkword(data_tag, new_data);
@@ -256,29 +88,26 @@
                 new_data = data;
             }
             break;
+        }
 
-        case TYPELAYOUT_COMPLICATED_TAG:
-        {
+        case MR_DATAREP_COMPLICATED: {
             Word secondary_tag;
             Word *new_entry;
+            Word *argument_vector, *type_info_vector;
+            int arity, i;
 
                 /*
-                ** if the vector containing the secondary
-                ** tags and the arguments is in range, 
-                ** copy it.
+                ** if the vector containing the secondary tags and the
+                ** arguments is in range, copy it.
                 */
             if (in_range(data_value)) {
                 secondary_tag = *data_value;
                 argument_vector = data_value + 1;
                 new_entry = (Word *) entry_value[secondary_tag +1];
                 arity = new_entry[TYPELAYOUT_SIMPLE_ARITY_OFFSET];
-                type_info_vector = new_entry + 
-                    TYPELAYOUT_SIMPLE_ARGS_OFFSET;
+                type_info_vector = new_entry + TYPELAYOUT_SIMPLE_ARGS_OFFSET;
 
-                /*
-                ** allocate space for new args, and 
-                ** secondary tag 
-                */
+                    /* allocate space for new args, and secondary tag */
                 incr_saved_hp(new_data, arity + 1);
 
                     /* copy secondary tag */
@@ -286,57 +115,190 @@
 
                     /* copy arguments */
                 for (i = 0; i < arity; i++) {
-                    field(0, new_data, i + 1) = 
-                        deep_copy_arg(argument_vector[i],
-                                type_info, (Word *) type_info_vector[i],
-                                lower_limit, upper_limit);
+                    field(0, new_data, i + 1) = deep_copy_arg(
+                        argument_vector[i], type_info,
+                        (Word *) type_info_vector[i], lower_limit,
+                        upper_limit);
                 }
 
-                /* tag this pointer */
+                    /* tag this pointer */
                 new_data = (Word) mkword(data_tag, new_data);
             } else {
                 new_data = data;
             }
-            break;
         }
+            break;
+
+        case MR_DATAREP_NOTAG:
+            new_data = deep_copy_arg(data, type_info, 
+                    (Word *) *MR_TYPELAYOUT_NO_TAG_VECTOR_ARGS(entry_value),
+                    lower_limit, upper_limit);
+            break;
+
+        case MR_DATAREP_EQUIV: 
+            new_data = deep_copy_arg(data, type_info, 
+                    (Word *) MR_TYPELAYOUT_EQUIV_TYPE((Word *) entry_value),
+                    lower_limit, upper_limit);
+            break;
+
+        case MR_DATAREP_EQUIV_VAR:
+            new_data = deep_copy(data, (Word *) type_info[(Word) entry_value],
+                    lower_limit, upper_limit);
+            break;
+
+        case MR_DATAREP_INT:
+            new_data = data;
+            break;
+
+        case MR_DATAREP_CHAR:
+            new_data = data;
+            break;
+
+        case MR_DATAREP_FLOAT:
+                        #ifdef BOXED_FLOAT
+                if (in_range(data_value)) {
+                        /*
+                        ** force a deep copy by converting to float
+                        ** and back
+                        */
+                    new_data = float_to_word(word_to_float(data));
+                } else {
+                    new_data = data;
+                            }
+            #else
+                new_data = data;
+            #endif
+            break;
 
-        case TYPELAYOUT_EQUIV_TAG: /* and TYPELAYOUT_NO_TAG */
-            /* note: we treat no_tag types just like equivalences */
+        case MR_DATAREP_STRING:
+            if (in_range(data_value)) {
+                incr_saved_hp_atomic(new_data, 
+                    (strlen((String) data_value) + sizeof(Word)) 
+                                / sizeof(Word));
+                strcpy((String) new_data, (String) data_value);
+            } else {
+                new_data = data;
+            }
+            break;
+
+        case MR_DATAREP_PRED: {
+                /*
+                ** predicate closures store the number of curried
+                ** arguments as their first argument, the
+                ** Code * as their second, and then the
+                ** arguments
+                **
+                ** Their type-infos have a pointer to
+                ** base_type_info for pred/0, arity, and then
+                ** argument typeinfos.
+                **/
+            if (in_range(data_value)) {
+                int args, i;
+                Word *new_closure;
+
+                    /* get number of curried arguments */
+                args = data_value[0];
+
+                    /* create new closure */
+                incr_saved_hp(LVALUE_CAST(Word, new_closure), args + 2);
+
+                    /* copy number of arguments */
+                new_closure[0] = args;
+
+                    /* copy pointer to code for closure */
+                new_closure[1] = data_value[1];
 
-            if ((Word) entry_value < TYPELAYOUT_MAX_VARINT) {
-                new_data = deep_copy(data,
-                    (Word *) type_info[(Word) entry_value],
+                    /* copy arguments */
+                for (i = 0; i < args; i++) {
+                    new_closure[i + 2] = deep_copy(data_value[i + 2],
+                        (Word *) type_info[i + TYPEINFO_OFFSET_FOR_PRED_ARGS],
+                        lower_limit, upper_limit);
+                }
+            new_data = (Word) new_closure;
+            } else {
+                new_data = data;
+            }
+        }
+            break;
+        
+        case MR_DATAREP_UNIV: 
+                /* if the univ is stored in range, copy it */ 
+            if (in_range(data_value)) {
+                Word *new_data_ptr;
+
+                    /* allocate space for a univ */
+                incr_saved_hp(new_data, 2);
+                new_data_ptr = (Word *) new_data;
+                new_data_ptr[UNIV_OFFSET_FOR_TYPEINFO] = 
+                    (Word) deep_copy_type_info( (Word *)
+                    data_value[UNIV_OFFSET_FOR_TYPEINFO],
+                    lower_limit, upper_limit);
+                new_data_ptr[UNIV_OFFSET_FOR_DATA] = deep_copy(
+                    data_value[UNIV_OFFSET_FOR_DATA], 
+                    (Word *) data_value[UNIV_OFFSET_FOR_TYPEINFO],
                     lower_limit, upper_limit);
             } else {
-                /*
-                ** offset 0 is no-tag indicator
-                ** offset 1 is the pseudo-typeinfo
-                ** (as per comments in base_type_layout.m)
-                ** XXX should avoid use of hard-coded offset `1' here
-                */
-                new_data = deep_copy_arg(data,
-                                type_info, (Word *) entry_value[1],
-                                lower_limit, upper_limit);
+                new_data = data;
             }
             break;
 
-        default:
-            fatal_error("Unknown layout tag in deep copy");
+        case MR_DATAREP_VOID:
+            fatal_error("Cannot deep copy a void type");
             break;
+
+        case MR_DATAREP_ARRAY: {
+            int i;
+
+            if (in_range(data_value)) {
+                MR_ArrayType *new_array;
+                MR_ArrayType *old_array;
+                Integer array_size;
+
+                old_array = (MR_ArrayType *) data_value;
+                array_size = old_array->size;
+                new_array = MR_make_array(array_size);
+                new_array->size = array_size;
+                for (i = 0; i < array_size; i++) {
+                    new_array->elements[i] = deep_copy_arg(
+                        old_array->elements[i], type_info, 
+                        (Word *) 1, lower_limit, upper_limit);
+                }
+                new_data = (Word) new_array;
+            } else {
+                new_data = data;
+            }
+            break;
+        }
+
+        case MR_DATAREP_TYPEINFO:
+            new_data = (Word) deep_copy_type_info(data_value,
+                lower_limit, upper_limit);
+            break;
+
+        case MR_DATAREP_C_POINTER:
+            if (in_range(data_value)) {
+                /*
+                ** This error occurs if we try to deep_copy() a
+                ** `c_pointer' type that points to memory allocated
+                ** on the Mercury heap.
+                */
+                fatal_error("Cannot copy a c_pointer type");
+            } else {
+                new_data = data;
+            }
+            break;
+            
+        case MR_DATAREP_UNKNOWN:
+            fatal_error("Unknown layout type in deep copy");
+            break;
+
+        default:
+            fatal_error("Unknown layout type in deep copy");
+        break;
     }
 
     return new_data;
 } /* end deep_copy() */
-
-
-Word 
-get_base_type_layout_entry(Word data_tag, Word *type_info)
-{
-        Word *base_type_info, *base_type_layout;
-        base_type_info = MR_TYPEINFO_GET_BASE_TYPEINFO(type_info);
-        base_type_layout = MR_BASE_TYPEINFO_GET_TYPELAYOUT(base_type_info);
-        return base_type_layout[data_tag];
-}
 
 /*
 ** deep_copy_arg is like deep_copy() except that it takes a
Index: runtime/mercury_type_info.c
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_type_info.c,v
retrieving revision 1.6
diff -u -t -r1.6 mercury_type_info.c
--- mercury_type_info.c	1998/05/25 21:46:41	1.6
+++ mercury_type_info.c	1998/06/01 07:28:44
@@ -542,6 +542,74 @@
 
 /*---------------------------------------------------------------------------*/
 
+enum MR_DataRepresentation
+MR_categorize_data(Word functors_indicator, Word layout_entry)
+{
+        switch(functors_indicator) { 
+                case MR_TYPEFUNCTORS_ENUM: 
+                        return MR_DATAREP_ENUM;
+                        break;
+                case MR_TYPEFUNCTORS_DU: 
+                        switch (tag(layout_entry)) {
+                                case TYPELAYOUT_SIMPLE_TAG:
+                                        return MR_DATAREP_SIMPLE;
+                                case TYPELAYOUT_COMPLICATED_TAG:
+                                        return MR_DATAREP_COMPLICATED;
+                                case TYPELAYOUT_CONST_TAG:
+                                        return MR_DATAREP_COMPLICATED_CONST;
+                                default:
+                                        return MR_DATAREP_UNKNOWN;
+                        }
+                case MR_TYPEFUNCTORS_NO_TAG:
+                        return MR_DATAREP_NOTAG;
+                case MR_TYPEFUNCTORS_EQUIV:
+                        if (TYPEINFO_IS_VARIABLE(strip_tag(layout_entry))) {
+                                return MR_DATAREP_EQUIV_VAR;
+                        } else {
+                                return MR_DATAREP_EQUIV;
+                        }
+                case MR_TYPEFUNCTORS_SPECIAL:
+                {
+                        int builtin_type = unmkbody(strip_tag(layout_entry));
+
+                        switch (builtin_type) {
+                                case TYPELAYOUT_UNASSIGNED_VALUE:
+                                        return MR_DATAREP_UNKNOWN;
+                                case TYPELAYOUT_UNUSED_VALUE:
+                                        return MR_DATAREP_UNKNOWN;
+                                case TYPELAYOUT_STRING_VALUE:
+                                        return MR_DATAREP_STRING;
+                                case TYPELAYOUT_FLOAT_VALUE:
+                                        return MR_DATAREP_FLOAT;
+                                case TYPELAYOUT_INT_VALUE:
+                                        return MR_DATAREP_INT;
+                                case TYPELAYOUT_CHARACTER_VALUE:
+                                        return MR_DATAREP_CHAR;
+                                case TYPELAYOUT_PREDICATE_VALUE:
+                                        return MR_DATAREP_PRED;
+                                case TYPELAYOUT_VOID_VALUE:
+                                        return MR_DATAREP_VOID;
+                                case TYPELAYOUT_ARRAY_VALUE:
+                                        return MR_DATAREP_ARRAY;
+                                case TYPELAYOUT_TYPEINFO_VALUE:
+                                        return MR_DATAREP_TYPEINFO;
+                                case TYPELAYOUT_C_POINTER_VALUE:
+                                        return MR_DATAREP_C_POINTER;
+                                default: 
+                                        return MR_DATAREP_UNKNOWN;
+                        }
+                }
+                case MR_TYPEFUNCTORS_UNIV:
+                        return MR_DATAREP_UNIV;
+                default:
+                        return MR_DATAREP_UNKNOWN;
+        }
+}
+
+
+
+/*---------------------------------------------------------------------------*/
+
 void mercury_sys_init_type_info(void); /* suppress gcc warning */
 void mercury_sys_init_type_info(void) {
         mercury__builtin_unify_pred_module();
Index: runtime/mercury_type_info.h
===================================================================
RCS file: /home/staff/zs/imp/mercury/runtime/mercury_type_info.h,v
retrieving revision 1.7
diff -u -t -r1.7 mercury_type_info.h
--- mercury_type_info.h	1998/05/25 21:46:42	1.7
+++ mercury_type_info.h	1998/06/01 07:34:17
@@ -799,6 +799,50 @@
         MR_MemoryList *allocated);
 void MR_deallocate(MR_MemoryList allocated_memory_cells);
 
+/*---------------------------------------------------------------------------*/
+
+/*
+** defintions and functions for categorizing data representations.
+*/
+
+
+/*
+** These have been ordered so that the most similar cases are next
+** to each other, so a switch on this type can exploit fallthrough
+** to cut down on code duplication.
+*/
+enum MR_DataRepresentation {
+        MR_DATAREP_ENUM,
+        MR_DATAREP_COMPLICATED_CONST,
+        MR_DATAREP_SIMPLE,
+        MR_DATAREP_COMPLICATED,
+        MR_DATAREP_NOTAG,
+        MR_DATAREP_EQUIV,
+        MR_DATAREP_EQUIV_VAR,
+        MR_DATAREP_INT,
+        MR_DATAREP_CHAR,
+        MR_DATAREP_FLOAT,
+        MR_DATAREP_STRING,
+        MR_DATAREP_PRED,
+        MR_DATAREP_UNIV,
+        MR_DATAREP_VOID,
+        MR_DATAREP_ARRAY,
+        MR_DATAREP_TYPEINFO,
+        MR_DATAREP_C_POINTER,
+        MR_DATAREP_UNKNOWN
+};
+
+/*
+** Return the data representation used by the data with the given
+** functors_indicator and layout_entry.
+**
+** functors_indicator is part of the base_type_functors data structure.
+** layout_entry is the base_type_layout entry corresponding to the
+** primary tag of the data.
+**
+*/
+enum MR_DataRepresentation MR_categorize_data(Word functors_indicator,
+                Word layout_entry);
 
 /*---------------------------------------------------------------------------*/
 #endif /* not MERCURY_TYPEINFO_H */


-- 
       Tyson Dowd           # There isn't any reason why Linux can't be
                            # implemented as an enterprise computing solution.
     trd at cs.mu.oz.au        # Find out what you've been missing while you've
http://www.cs.mu.oz.au/~trd # been rebooting Windows NT. -- InfoWorld, 1998.



More information about the developers mailing list