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