[m-rev.] for review: arrays and the debugger
Zoltan Somogyi
zs at cs.mu.OZ.AU
Thu Jun 21 19:03:50 AEST 2001
On 19-Jun-2001, Mark Brown <dougl at cs.mu.OZ.AU> wrote:
> > +** this task. The reason for having those specialized variants is that
> > +** executing the full task can be extremely time consuming, especially when
> > +** large arrays are involved. (Simply allocating and filling in an array of
> > +** a million typeinfos can cause a system to start paging.) Therefore we
> > try to
> > +** make sure that in every circumstance we perform the minimum work
> > possible.
>
> It would be better if you mentioned the circumstances in question (that is,
> mention each of the callers of these functions).
Which combinations of features actually needed and what the functions
implementing them are concerns for std_util.m, not this file. They are already
documented in std_util.m, and this file contains a pointer to that
documentation, so mentioning those callers would not be much help but would
incur a double maintenance burden.
However, I acted on your other suggestions. Here is the relative diff.
I intend to commit it after a final bootcheck.
Zoltan.
--- /home/zs/mer/ws41/runtime/mercury_ml_expand_body.h Tue Jun 12 22:16:44 2001
+++ runtime/mercury_ml_expand_body.h Thu Jun 21 18:47:13 2001
@@ -8,10 +8,10 @@
** mercury_ml_expand_body.h
**
** This file is included several times in library/std_util.m. Each inclusion
-** defines a function that the body of several variants of the old ML_expand
-** function, which, given a data word and its type_info, returned its functor,
-** arity, argument vector and a type_info vector describing its arguments.
-** One variants still does all that. The others perform different subsets of
+** defines the body of one of several variants of the old ML_expand function,
+** which, given a data word and its type_info, returned its functor, arity,
+** argument vector and a type_info vector describing its arguments.
+** One variant still does all that. The others perform different subsets of
** this task. The reason for having those specialized variants is that
** executing the full task can be extremely time consuming, especially when
** large arrays are involved. (Simply allocating and filling in an array of
--- /home/zs/mer/ws41/library/std_util.m Tue Jun 12 17:02:39 2001
+++ library/std_util.m Thu Jun 21 18:54:48 2001
@@ -495,11 +495,12 @@
%-----------------------------------------------------------------------------%
- % functor, argument and deconstruct take any type (including univ),
- % and return representation information for that type.
+ % functor, argument and deconstruct and their variants take any type
+ % (including univ), and return representation information for that type.
+ %
+ % The string representation of the functor that these predicates
+ % return is:
%
- % The string representation of the functor that `functor' and
- % `deconstruct' return is:
% - for user defined types, the functor that is given
% in the type definition. For lists, this
% means the functors ./2 and []/0 are used, even if
@@ -510,11 +511,22 @@
% base 10 number, positive floating point numbers have
% no sign.
% - for strings, the string, inside double quotation marks
- % - for characters, the character inside single
- % quotation marks
- % - for predicates and functions, the string
- % <<predicate>>
+ % - for characters, the character inside single quotation marks
+ % - for predicates and functions, the string <<predicate>>
% - for tuples, the string {}
+ % - for arrays, the string <<array>>
+ %
+ % The arity that these predicates return is:
+ %
+ % - for user defined types, the arity of the functor.
+ % - for integers, zero.
+ % - for floats, zero.
+ % - for strings, zero.
+ % - for characters, zero.
+ % - for predicates and functions, zero; we do not return the
+ % number of arguments expected by the predicate or function.
+ % - for tuples, the number of elements in the tuple.
+ % - for arrays, the number of elements in the array.
% functor(Data, Functor, Arity)
%
@@ -564,12 +576,22 @@
% representation, i.e. one for which there is a user-defined
% equality predicate.)
%
+ % The cost of calling deconstruct depends greatly on how many arguments
+ % Data has. If Data is an array, then each element of the array is
+ % considered one of its arguments. Therefore calling deconstruct
+ % on large arrays can take a very large amount of memory and a very
+ % long time. If you call deconstruct in a situation in which you may
+ % pass it a large array, you should probably use limited_deconstruct
+ % instead.
+ %
:- pred deconstruct(T::in, string::out, int::out, list(univ)::out) is det.
% limited_deconstruct(Data, MaxArity, Functor, Arity, Arguments)
%
% limited_deconstruct works like deconstruct, but if the arity of T is
- % greater than MaxArity, limited_deconstruct fails.
+ % greater than MaxArity, limited_deconstruct fails. This is useful in
+ % avoiding bad performance in cases where Data may be a large array.
+ %
:- pred limited_deconstruct(T::in, int::in, string::out,
int::out, list(univ)::out) is semidet.
@@ -2890,8 +2912,71 @@
extern bool ML_named_arg_num(MR_TypeInfo type_info, MR_Word *term_ptr,
const char *arg_name, int *arg_num_ptr);
+/*
+** The following macros factor out the common parts of the various
+** deconstruction predicates.
+*/
+
+ /*
+ ** Check for attempts to deconstruct a non-canonical type.
+ ** Such deconstructions must be cc_multi, which is why we treat
+ ** violations of this as runtime errors in det deconstruction
+ ** predicates.
+ ** (There ought to be cc_multi versions of those predicates.)
+ */
+#define ML_abort_if_type_is_noncanonical(ei, predname) \
+ do { \
+ if ((ei).non_canonical_type) { \
+ MR_fatal_error(""called "" predname "" for a type "" \
+ ""with a user-defined equality predicate""); \
+ } \
+ } while (0)
+
#endif
+#define ML_deconstruct_get_functor(ei, functor_field, var) \
+ do { \
+ MR_make_aligned_string(MR_LVALUE_CAST(MR_ConstString, var), \
+ (ei).functor_field); \
+ } while (0)
+
+#define ML_deconstruct_get_arity(ei, var) \
+ do { \
+ var = (ei).arity; \
+ } while (0)
+
+#define ML_deconstruct_get_arg_list(ei, args_field, var) \
+ do { \
+ int i; \
+ \
+ var = MR_list_empty_msg(MR_PROC_LABEL); \
+ i = (ei).arity; \
+ \
+ while (--i >= 0) { \
+ MR_Word arg; \
+ \
+ /* Create an argument on the heap */ \
+ MR_new_univ_on_hp(arg, \
+ (ei).args_field.arg_type_infos[i], \
+ (ei).args_field.arg_values[i + \
+ (ei).args_field.num_extra_args]); \
+ \
+ /* Join the argument to the front of the list */ \
+ var = MR_list_cons_msg(arg, var, MR_PROC_LABEL); \
+ } \
+ } while (0)
+
+ /*
+ ** Free any arg_type_infos allocated by the ML_expand variant.
+ ** Should be called after we have used them for the last time.
+ */
+#define ML_deconstruct_free_allocated_arg_type_infos(ei, args_field)\
+ do { \
+ if ((ei).args_field.can_free_arg_type_infos) { \
+ MR_GC_free((ei).args_field.arg_type_infos); \
+ } \
+ } while (0)
+
").
:- pragma foreign_code("C", "
@@ -2960,19 +3045,7 @@
ML_Expand_Chosen_Arg_Only_Info expand_info;
ML_expand_chosen_arg_only(type_info, term_ptr, arg_index, &expand_info);
-
- /*
- ** Check for attempts to deconstruct a non-canonical type:
- ** such deconstructions must be cc_multi, and since
- ** arg/2 is det, we must treat violations of this
- ** as runtime errors.
- ** (There ought to be a cc_multi version of arg/2
- ** that allows this.)
- */
- if (expand_info.non_canonical_type) {
- MR_fatal_error(""called argument/2 for a type with a ""
- ""user-defined equality predicate"");
- }
+ ML_abort_if_type_is_noncanonical(expand_info, ""argument/2"");
/* Check range */
if (expand_info.chosen_index_exists) {
@@ -3109,24 +3182,9 @@
ML_expand_functor_only(type_info, &Term, &expand_info);
MR_restore_transient_registers();
- /*
- ** Check for attempts to deconstruct a non-canonical type:
- ** such deconstructions must be cc_multi, and since
- ** functor/2 is det, we must treat violations of this
- ** as runtime errors.
- ** (There ought to be a cc_multi version of functor/2
- ** that allows this.)
- */
- if (expand_info.non_canonical_type) {
- MR_fatal_error(""called functor/2 for a type with a ""
- ""user-defined equality predicate"");
- }
-
- /* Copy functor onto the heap */
- MR_make_aligned_string(MR_LVALUE_CAST(MR_ConstString, Functor),
- expand_info.functor_only);
-
- Arity = expand_info.arity;
+ ML_abort_if_type_is_noncanonical(expand_info, ""functor/3"");
+ ML_deconstruct_get_functor(expand_info, functor_only, Functor);
+ ML_deconstruct_get_arity(expand_info, Arity);
}").
/*
@@ -3243,9 +3301,6 @@
{
ML_Expand_Functor_Args_Info expand_info;
MR_TypeInfo type_info;
- MR_Word Argument;
- MR_Word tmp;
- int i;
type_info = (MR_TypeInfo) TypeInfo_for_T;
@@ -3253,49 +3308,11 @@
ML_expand_functor_args(type_info, &Term, &expand_info);
MR_restore_transient_registers();
- /*
- ** Check for attempts to deconstruct a non-canonical type:
- ** such deconstructions must be cc_multi, and since
- ** deconstruct/4 is det, we must treat violations of this
- ** as runtime errors.
- ** (There ought to be a cc_multi version of deconstruct/4
- ** that allows this.)
- */
- if (expand_info.non_canonical_type) {
- MR_fatal_error(""called deconstruct/4 for a type with a ""
- ""user-defined equality predicate"");
- }
-
- /* Get functor */
- MR_make_aligned_string(MR_LVALUE_CAST(MR_ConstString, Functor),
- expand_info.functor);
-
- /* Get arity */
- Arity = expand_info.arity;
-
- /* Build argument list */
- Arguments = MR_list_empty_msg(MR_PROC_LABEL);
- i = expand_info.arity;
-
- while (--i >= 0) {
-
- /* Create an argument on the heap */
- MR_new_univ_on_hp(Argument,
- expand_info.args.arg_type_infos[i],
- expand_info.args.arg_values[i + expand_info.args.num_extra_args]);
-
- /* Join the argument to the front of the list */
- Arguments = MR_list_cons_msg(Argument, Arguments, MR_PROC_LABEL);
- }
-
- /*
- ** Free the allocated arg_type_infos, since we just copied
- ** all its arguments onto the heap.
- */
-
- if (expand_info.args.can_free_arg_type_infos) {
- MR_GC_free(expand_info.args.arg_type_infos);
- }
+ ML_abort_if_type_is_noncanonical(expand_info, ""deconstruct/4"");
+ ML_deconstruct_get_functor(expand_info, functor, Functor);
+ ML_deconstruct_get_arity(expand_info, Arity);
+ ML_deconstruct_get_arg_list(expand_info, args, Arguments);
+ ML_deconstruct_free_allocated_arg_type_infos(expand_info, args);
}").
:- pragma foreign_proc("C",
@@ -3304,9 +3321,6 @@
{
ML_Expand_Functor_Args_Limit_Info expand_info;
MR_TypeInfo type_info;
- MR_Word Argument;
- MR_Word tmp;
- int i;
type_info = (MR_TypeInfo) TypeInfo_for_T;
@@ -3314,72 +3328,35 @@
ML_expand_functor_args_limit(type_info, &Term, MaxArity, &expand_info);
MR_restore_transient_registers();
- /*
- ** Check for attempts to deconstruct a non-canonical type:
- ** such deconstructions must be cc_multi, and since
- ** deconstruct/4 is det, we must treat violations of this
- ** as runtime errors.
- ** (There ought to be a cc_multi version of deconstruct/4
- ** that allows this.)
- */
- if (expand_info.non_canonical_type) {
- MR_fatal_error(""called deconstruct/4 for a type with a ""
- ""user-defined equality predicate"");
- }
+ ML_abort_if_type_is_noncanonical(expand_info, ""limited_deconstruct/5"");
if (expand_info.limit_reached) {
SUCCESS_INDICATOR = FALSE;
} else {
SUCCESS_INDICATOR = TRUE;
- /* Get functor */
- MR_make_aligned_string(MR_LVALUE_CAST(MR_ConstString, Functor),
- expand_info.functor);
-
- /* Get arity */
- Arity = expand_info.arity;
-
- /* Build argument list */
- Arguments = MR_list_empty_msg(MR_PROC_LABEL);
- i = expand_info.arity;
-
- while (--i >= 0) {
-
- /* Create an argument on the heap */
- MR_new_univ_on_hp(Argument,
- expand_info.args.arg_type_infos[i],
- expand_info.args.arg_values[i + expand_info.args.num_extra_args]);
-
- /* Join the argument to the front of the list */
- Arguments = MR_list_cons_msg(Argument, Arguments, MR_PROC_LABEL);
- }
-
- /*
- ** Free the allocated arg_type_infos, since we just copied
- ** all its arguments onto the heap.
- */
-
- if (expand_info.args.can_free_arg_type_infos) {
- MR_GC_free(expand_info.args.arg_type_infos);
- }
+ ML_deconstruct_get_functor(expand_info, functor, Functor);
+ ML_deconstruct_get_arity(expand_info, Arity);
+ ML_deconstruct_get_arg_list(expand_info, args, Arguments);
+ ML_deconstruct_free_allocated_arg_type_infos(expand_info, args);
}
}").
:- pragma foreign_proc("MC++",
deconstruct(_Term::in, _Functor::out, _Arity::out,
- _Arguments::out), will_not_call_mercury, "
+ _Arguments::out),
+ [will_not_call_mercury], "
{
mercury::runtime::Errors::SORRY(""foreign code for this function"");
-}
-").
+}").
:- pragma foreign_proc("MC++",
- limited_deconstruct(_Term::in, _MaxArity::in, _Functor::out, _Arity::out,
- _Arguments::out), will_not_call_mercury, "
+ limited_deconstruct(_Term::in, _MaxArity::in, _Functor::out,
+ _Arity::out, _Arguments::out),
+ [will_not_call_mercury], "
{
mercury::runtime::Errors::SORRY(""foreign code for this function"");
-}
-").
+}").
get_functor_info(Univ, FunctorInfo) :-
( univ_to_type(Univ, Int) ->
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list