mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-09 19:02:18 +00:00
Estimated hours taken: 80 Branches: main Improvements for bitmap.m, to make it useable as a general container for binary data. library/bitmap.m: runtime/mercury_bitmap.c: runtime/mercury_bitmap.h: Specialize the representation of bitmaps to an array of unsigned bytes defined as a foreign type. This is better than building on top of array(int) because it: - is better for interfacing with foreign code - has a more sensible machine-independent comparison order (same as array(bool)) - avoids storing the size twice - has more efficient copying, unification, comparison and tabling (although we should probably specialize the handling of array(int) and isomorphic types as well) - uses GC_MALLOC_ATOMIC to avoid problems with bit patterns that look like pointers (although we should do that for array(int) as well) XXX The code for the Java and IL backends is untested. Building the library in grade Java with Sun JDK 1.6 failed (but at least passed error checking), and I don't have access to a copy of MSVS.NET. The foreign code that needs to be tested is trivial. Add fields `bit', `bits' and `byte' to get/set a single bit, multiple bits (from an int) or an 8 bit byte. Add functions for converting bitmaps to hex strings and back, for use by stream.string_writer.write and deconstruct.functor/4. bitmap.intersect was buggy in the case where the input bitmaps had a different size. Given that bitmaps are implemented with a fixed domain (lookups out of range throw an exception), it makes more sense to throw an exception in that case anyway, so all of the set operations do that now. The difference operation actually performed xor. Fix it and add an xor function. library/version_bitmap.m: This hasn't been fully updated to be the same as bitmap.m. The payoff would be much less because foreign code can't really do anything with version_bitmaps. Add a `bit' field. Deprecate the `get/2' function in favour of the `bit' field. Fix the union, difference, intersection and xor functions as for bitmap.m. Fix comparison of version_arrays so that it uses the same method as array.m: compare size then elements in order. The old code found version_arrays to be equal if one was a suffix of the other. library/char.m: Add predicates for converting between hex digits and integers. library/io.m: library/stream.string_writer.m: library/term.m: Read and write bitmaps. runtime/mercury_type_info.h: runtime/mercury_deep_copy_body.h: runtime/mercury_mcpp.h: runtime/mercury_table_type_body.h: runtime/mercury_tabling_macros.h: runtime/mercury_unify_compare_body.h: runtime/mercury_construct.c: runtime/mercury_deconstruct.c: runtime/mercury_term_size.c: runtime/mercury_string.h: library/construct.m: library/deconstruct.m compiler/prog_type.m: compiler/mlds_to_gcc.m: compiler/rtti.m: Add a MR_TypeCtorRep for bitmaps, and handle it in the library and runtinme. library/Mercury.options: Compile bitmap.m with `--no-warn-insts-without-matching-type'. runtime/mercury_type_info.h: Bump MR_RTTI_VERSION. NEWS: Document the changes. tests/hard_coded/Mmakefile: tests/hard_coded/bitmap_test.m: tests/hard_coded/bitmap_simple.m: tests/hard_coded/bitmap_tester.m: tests/hard_coded/bitmap_test.exp: tests/tabling/Mmakefile: tests/tabling/expand_bitmap.m: tests/tabling/expand_bitmap.exp: tests/hard_coded/version_array_test.m: tests/hard_coded/version_array_test.exp: Test cases.
712 lines
23 KiB
C
712 lines
23 KiB
C
/*
|
|
** vim:ts=4 sw=4 expandtab
|
|
*/
|
|
/*
|
|
** Copyright (C) 2003-2005, 2007 The University of Melbourne.
|
|
** This file may only be copied under the terms of the GNU Library General
|
|
** Public License - see the file COPYING.LIB in the Mercury distribution.
|
|
*/
|
|
|
|
/*
|
|
** mercury_term_size.c
|
|
**
|
|
** This module defines a function for measuring the sizes of terms.
|
|
*/
|
|
|
|
#include "mercury_imp.h"
|
|
#include <stdio.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
#ifdef MR_RECORD_TERM_SIZES
|
|
|
|
MR_ComplexityCounter MR_complexity_word_counter = 0;
|
|
MR_ComplexityCounter MR_complexity_cell_counter = 0;
|
|
MR_ComplexityCounter MR_complexity_tick_counter = 0;
|
|
|
|
static void MR_write_complexity_proc(MR_ComplexityProc *proc);
|
|
static void MR_complexity_output_args_desc(FILE *fp,
|
|
MR_ComplexityProc *proc);
|
|
|
|
MR_Unsigned
|
|
MR_term_size(MR_TypeInfo type_info, MR_Word term)
|
|
{
|
|
MR_TypeCtorInfo type_ctor_info;
|
|
MR_DuTypeLayout du_type_layout;
|
|
const MR_DuPtagLayout *ptag_layout;
|
|
int ptag;
|
|
int sectag;
|
|
int arity;
|
|
int size;
|
|
|
|
try_again:
|
|
type_ctor_info = MR_TYPEINFO_GET_TYPE_CTOR_INFO(type_info);
|
|
|
|
if (! MR_type_ctor_has_valid_rep(type_ctor_info)) {
|
|
MR_fatal_error("MR_term_size: term of unknown representation");
|
|
}
|
|
|
|
switch (MR_type_ctor_rep(type_ctor_info)) {
|
|
case MR_TYPECTOR_REP_RESERVED_ADDR:
|
|
case MR_TYPECTOR_REP_RESERVED_ADDR_USEREQ:
|
|
/* XXX the code to handle these cases hasn't been written yet */
|
|
MR_fatal_error("MR_term_size: RESERVED_ADDR");
|
|
|
|
case MR_TYPECTOR_REP_DU:
|
|
case MR_TYPECTOR_REP_DU_USEREQ:
|
|
du_type_layout = MR_type_ctor_layout(type_ctor_info).MR_layout_du;
|
|
ptag = MR_tag(term);
|
|
ptag_layout = &du_type_layout[ptag];
|
|
|
|
switch (ptag_layout->MR_sectag_locn) {
|
|
case MR_SECTAG_NONE:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (ptag_layout->MR_sectag_alternatives[0]->
|
|
MR_du_functor_orig_arity <= 0)
|
|
{
|
|
MR_fatal_error("MR_term_size: zero arity ptag none");
|
|
}
|
|
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: du sectag none %p -> %d\n",
|
|
(void *) term,
|
|
(int) MR_field(MR_mktag(ptag), term, -1));
|
|
printf("type %s.%s/%d, functor %s\n",
|
|
type_ctor_info->MR_type_ctor_module_name,
|
|
type_ctor_info->MR_type_ctor_name,
|
|
type_ctor_info->MR_type_ctor_arity,
|
|
ptag_layout->MR_sectag_alternatives[0]->
|
|
MR_du_functor_name);
|
|
}
|
|
#endif
|
|
return MR_field(MR_mktag(ptag), term, -1);
|
|
|
|
case MR_SECTAG_LOCAL:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: du sectag local %p\n",
|
|
(void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_SECTAG_REMOTE:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
sectag = MR_field(MR_mktag(ptag), term, 0);
|
|
|
|
if (ptag_layout->MR_sectag_alternatives[sectag]->
|
|
MR_du_functor_orig_arity <= 0)
|
|
{
|
|
MR_fatal_error("MR_term_size: zero arity ptag remote");
|
|
}
|
|
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: du sectag remote %p -> %d\n",
|
|
(void *) term,
|
|
(int) MR_field(MR_mktag(ptag), term, -1));
|
|
printf("type %s.%s/%d, functor %s\n",
|
|
type_ctor_info->MR_type_ctor_module_name,
|
|
type_ctor_info->MR_type_ctor_name,
|
|
type_ctor_info->MR_type_ctor_arity,
|
|
ptag_layout->MR_sectag_alternatives[sectag]->
|
|
MR_du_functor_name);
|
|
}
|
|
#endif
|
|
return MR_field(MR_mktag(ptag), term, -1);
|
|
|
|
case MR_SECTAG_VARIABLE:
|
|
MR_fatal_error("MR_term_size: VARIABLE");
|
|
|
|
default:
|
|
fprintf(stderr, "sectag_locn: %d\n",
|
|
(int) ptag_layout->MR_sectag_locn);
|
|
MR_fatal_error("MR_term_size: sectag_locn");
|
|
}
|
|
|
|
case MR_TYPECTOR_REP_EQUIV:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: equiv %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
type_info = MR_create_type_info(
|
|
MR_TYPEINFO_GET_FIXED_ARITY_ARG_VECTOR(type_info),
|
|
MR_type_ctor_layout(type_ctor_info).MR_layout_equiv);
|
|
goto try_again;
|
|
|
|
case MR_TYPECTOR_REP_EQUIV_GROUND:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: equiv ground %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
type_info = MR_pseudo_type_info_is_ground(
|
|
MR_type_ctor_layout(type_ctor_info).MR_layout_equiv);
|
|
goto try_again;
|
|
|
|
case MR_TYPECTOR_REP_NOTAG:
|
|
case MR_TYPECTOR_REP_NOTAG_USEREQ:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: notag (usereq) %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
MR_save_transient_hp();
|
|
type_info = MR_create_type_info(
|
|
MR_TYPEINFO_GET_FIXED_ARITY_ARG_VECTOR(type_info),
|
|
MR_type_ctor_layout(type_ctor_info).MR_layout_notag->
|
|
MR_notag_functor_arg_type);
|
|
MR_restore_transient_hp();
|
|
goto try_again;
|
|
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND:
|
|
case MR_TYPECTOR_REP_NOTAG_GROUND_USEREQ:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: notag ground (usereq) %p\n",
|
|
(void *) term);
|
|
}
|
|
#endif
|
|
type_info = MR_pseudo_type_info_is_ground(
|
|
MR_type_ctor_layout(type_ctor_info).MR_layout_notag
|
|
->MR_notag_functor_arg_type);
|
|
goto try_again;
|
|
|
|
case MR_TYPECTOR_REP_TUPLE:
|
|
arity = MR_TYPEINFO_GET_VAR_ARITY_ARITY(type_info);
|
|
if (arity == 0) {
|
|
/* term may be a NULL pointer, so don't follow it */
|
|
size = 0;
|
|
} else {
|
|
size = MR_field(MR_mktag(0), term, -1);
|
|
}
|
|
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: tuple %p -> %d\n",
|
|
(void *) term, size);
|
|
}
|
|
#endif
|
|
return size;
|
|
|
|
case MR_TYPECTOR_REP_PRED:
|
|
case MR_TYPECTOR_REP_FUNC:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: pred/func %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
/* currently we don't collect stats on closure sizes */
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_ARRAY:
|
|
/* currently we don't collect stats on array sizes */
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: array %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_BITMAP:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: bitmap %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_ENUM:
|
|
case MR_TYPECTOR_REP_ENUM_USEREQ:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: enum (usereq) %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_INT:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: int %p %ld\n",
|
|
(void *) term, (long) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_CHAR:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: char %p %c\n",
|
|
(void *) term, (char) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_FLOAT:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: float %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_STRING:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: string %p '%s'\n",
|
|
(void *) term, (char *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_SUCCIP:
|
|
case MR_TYPECTOR_REP_HP:
|
|
case MR_TYPECTOR_REP_CURFR:
|
|
case MR_TYPECTOR_REP_MAXFR:
|
|
case MR_TYPECTOR_REP_REDOFR:
|
|
case MR_TYPECTOR_REP_REDOIP:
|
|
case MR_TYPECTOR_REP_TRAIL_PTR:
|
|
case MR_TYPECTOR_REP_TICKET:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: impl artifact type %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_TYPEINFO:
|
|
case MR_TYPECTOR_REP_TYPECLASSINFO:
|
|
case MR_TYPECTOR_REP_TYPECTORINFO:
|
|
case MR_TYPECTOR_REP_BASETYPECLASSINFO:
|
|
case MR_TYPECTOR_REP_TYPEDESC:
|
|
case MR_TYPECTOR_REP_TYPECTORDESC:
|
|
case MR_TYPECTOR_REP_PSEUDOTYPEDESC:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: type_info etc %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_SUBGOAL:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: subgoal %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_C_POINTER:
|
|
case MR_TYPECTOR_REP_STABLE_C_POINTER:
|
|
case MR_TYPECTOR_REP_FOREIGN:
|
|
case MR_TYPECTOR_REP_STABLE_FOREIGN:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: c_pointer/foreign %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 0;
|
|
|
|
case MR_TYPECTOR_REP_REFERENCE:
|
|
#ifdef MR_DEBUG_TERM_SIZES
|
|
if (MR_heapdebug && MR_lld_print_enabled) {
|
|
printf("MR_term_size: reference %p\n", (void *) term);
|
|
}
|
|
#endif
|
|
return 1;
|
|
|
|
case MR_TYPECTOR_REP_VOID:
|
|
MR_fatal_error("MR_term_size: VOID");
|
|
|
|
case MR_TYPECTOR_REP_UNKNOWN:
|
|
MR_fatal_error("MR_term_size: UNKNOWN");
|
|
|
|
default:
|
|
fprintf(stderr, "default rep: %d\n",
|
|
(int) MR_type_ctor_rep(type_ctor_info));
|
|
MR_fatal_error("MR_term_size: default");
|
|
}
|
|
|
|
MR_fatal_error("MR_term_size: unexpected fallthrough");
|
|
}
|
|
|
|
void
|
|
MR_write_complexity_procs(void)
|
|
{
|
|
int proc_num;
|
|
MR_ComplexityProc *proc;
|
|
|
|
for (proc_num = 0; proc_num < MR_num_complexity_procs; proc_num++) {
|
|
proc = &MR_complexity_procs[proc_num];
|
|
if (proc->MR_clp_num_profiled_args >= 0) {
|
|
MR_write_complexity_proc(proc);
|
|
}
|
|
}
|
|
}
|
|
|
|
#define MR_COMPLEXITY_ARGS_DIR "ComplexityArgs"
|
|
#define MR_COMPLEXITY_DATA_DIR "ComplexityData"
|
|
|
|
static MR_bool MR_have_created_complexity_dirs = MR_FALSE;
|
|
static MR_bool MR_have_printed_complexity_dirs_error = MR_FALSE;
|
|
|
|
static void
|
|
MR_write_complexity_proc(MR_ComplexityProc *proc)
|
|
{
|
|
char *full_proc_name;
|
|
int full_proc_name_len;
|
|
FILE *fp;
|
|
char *args_filename;
|
|
char *data_filename;
|
|
const char *data_filemode;
|
|
struct stat statbuf;
|
|
char *slash;
|
|
MR_ComplexityMetrics *metrics;
|
|
int num_profiled_args;
|
|
int *sizes;
|
|
int num_slots;
|
|
MR_ComplexityPastSlots *past_slots;
|
|
char *cmd_buf;
|
|
|
|
full_proc_name_len = strlen(proc->MR_clp_full_proc_name);
|
|
full_proc_name = MR_malloc(100 + full_proc_name_len);
|
|
strcpy(full_proc_name, proc->MR_clp_full_proc_name);
|
|
|
|
/*
|
|
** We can't have slash characters in the filenames we construct from
|
|
** full_proc_name.
|
|
*/
|
|
while ((slash = strchr(full_proc_name, '/')) != NULL) {
|
|
*slash = ':';
|
|
}
|
|
|
|
cmd_buf = MR_malloc(100 + 2 * full_proc_name_len);
|
|
/* will be big enough */
|
|
|
|
if (! MR_have_created_complexity_dirs) {
|
|
sprintf(cmd_buf, "mkdir -p %s %s",
|
|
MR_COMPLEXITY_ARGS_DIR, MR_COMPLEXITY_DATA_DIR);
|
|
if (system(cmd_buf) != 0) {
|
|
if (! MR_have_printed_complexity_dirs_error) {
|
|
fprintf(stderr, "%s: cannot create %s and %s: %s\n",
|
|
MR_progname, MR_COMPLEXITY_ARGS_DIR,
|
|
MR_COMPLEXITY_DATA_DIR, strerror(errno));
|
|
/* there is no point in aborting */
|
|
MR_have_printed_complexity_dirs_error = MR_TRUE;
|
|
return;
|
|
}
|
|
}
|
|
MR_have_created_complexity_dirs = MR_TRUE;
|
|
}
|
|
|
|
args_filename = MR_malloc(100 + full_proc_name_len);
|
|
/* will be big enough */
|
|
sprintf(args_filename, "%s/%s", MR_COMPLEXITY_ARGS_DIR, full_proc_name);
|
|
|
|
if (stat(args_filename, &statbuf) != 0) {
|
|
/* args_filename does not exist */
|
|
fp = fopen(args_filename, "w");
|
|
if (fp == NULL) {
|
|
fprintf(stderr, "%s: cannot open %s: %s\n",
|
|
MR_progname, args_filename, strerror(errno));
|
|
/* there is no point in aborting */
|
|
return;
|
|
}
|
|
|
|
MR_complexity_output_args_desc(fp, proc);
|
|
fclose(fp);
|
|
data_filemode = "w";
|
|
} else {
|
|
/* args_filename does exist */
|
|
char *tmp_filename;
|
|
|
|
tmp_filename = MR_malloc(100 + full_proc_name_len);
|
|
sprintf(tmp_filename, "%s/%s.tmp",
|
|
MR_COMPLEXITY_ARGS_DIR, full_proc_name);
|
|
fp = fopen(tmp_filename, "w");
|
|
if (fp == NULL) {
|
|
fprintf(stderr, "%s: cannot open %s: %s\n",
|
|
MR_progname, tmp_filename, strerror(errno));
|
|
/* there is no point in aborting */
|
|
return;
|
|
}
|
|
|
|
MR_complexity_output_args_desc(fp, proc);
|
|
fclose(fp);
|
|
|
|
sprintf(cmd_buf, "cmp -s %s %s", args_filename, tmp_filename);
|
|
if (system(cmd_buf) == 0) {
|
|
/* the files are identical */
|
|
(void) unlink(tmp_filename);
|
|
data_filemode = "a";
|
|
} else {
|
|
/* the files are different */
|
|
rename(tmp_filename, args_filename);
|
|
data_filemode = "w";
|
|
}
|
|
}
|
|
|
|
data_filename = MR_malloc(100 + full_proc_name_len);
|
|
sprintf(data_filename, "%s/%s", MR_COMPLEXITY_DATA_DIR, full_proc_name);
|
|
|
|
fp = fopen(data_filename, data_filemode);
|
|
if (fp == NULL) {
|
|
fprintf(stderr, "%s: cannot open %s: %s\n",
|
|
MR_progname, data_filename, strerror(errno));
|
|
/* there is no point in aborting */
|
|
return;
|
|
}
|
|
|
|
num_profiled_args = proc->MR_clp_num_profiled_args;
|
|
|
|
metrics = proc->MR_clp_metrics;
|
|
sizes = proc->MR_clp_sizes;
|
|
num_slots = proc->MR_clp_next_slot_num;
|
|
past_slots = proc->MR_clp_past_slots;
|
|
|
|
do {
|
|
int slot, arg;
|
|
|
|
for (slot = num_slots - 1; slot >= 0; slot--) {
|
|
fprintf(fp, "%d %d %d",
|
|
metrics[slot].MR_clpm_num_words,
|
|
metrics[slot].MR_clpm_num_cells,
|
|
metrics[slot].MR_clpm_num_ticks);
|
|
|
|
for (arg = 0; arg < num_profiled_args; arg++) {
|
|
fprintf(fp, " %d", sizes[slot * num_profiled_args + arg]);
|
|
}
|
|
|
|
fprintf(fp, "\n");
|
|
}
|
|
|
|
if (past_slots == NULL) {
|
|
break;
|
|
}
|
|
|
|
metrics = past_slots->MR_clpps_metrics;
|
|
sizes = past_slots->MR_clpps_sizes;
|
|
num_slots = MR_COMPLEXITY_SLOTS_PER_CHUNK;
|
|
past_slots = past_slots->MR_clpps_previous;
|
|
} while (MR_TRUE);
|
|
|
|
(void) fclose(fp);
|
|
}
|
|
|
|
static void
|
|
MR_complexity_output_args_desc(FILE *fp, MR_ComplexityProc *proc)
|
|
{
|
|
int arg;
|
|
int num_args;
|
|
MR_ComplexityArgInfo *arg_infos;
|
|
|
|
arg_infos = proc->MR_clp_arg_infos;
|
|
num_args = proc->MR_clp_num_args;
|
|
|
|
for (arg = 0; arg < num_args; arg++) {
|
|
if (arg_infos[arg].MR_clpai_maybe_name != NULL) {
|
|
fprintf(fp, "%s ", arg_infos[arg].MR_clpai_maybe_name);
|
|
} else {
|
|
fprintf(fp, "_ ");
|
|
}
|
|
|
|
switch (arg_infos[arg].MR_clpai_kind) {
|
|
case MR_COMPLEXITY_INPUT_VAR_SIZE:
|
|
fprintf(fp, "profiled_input\n");
|
|
break;
|
|
case MR_COMPLEXITY_INPUT_FIX_SIZE:
|
|
fprintf(fp, "unprofiled_input\n");
|
|
break;
|
|
case MR_COMPLEXITY_OUTPUT:
|
|
fprintf(fp, "output\n");
|
|
break;
|
|
default:
|
|
fprintf(fp, "unknown\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
MR_init_complexity_proc(int proc_num, const char *fullname,
|
|
int num_profiled_args, int num_args, MR_ComplexityArgInfo *arg_infos)
|
|
{
|
|
MR_ComplexityProc *proc;
|
|
|
|
if (MR_complexity_procs == NULL) {
|
|
fprintf(stderr, "%s: executable wasn't fully prepared "
|
|
"for complexity experiment\n", MR_progname);
|
|
exit(1);
|
|
}
|
|
|
|
proc = &MR_complexity_procs[proc_num];
|
|
if (! MR_streq(fullname, proc->MR_clp_full_proc_name)) {
|
|
fprintf(stderr, "%s: proc_num %d is %s: expected %s\n",
|
|
MR_progname, proc_num, proc->MR_clp_full_proc_name, fullname);
|
|
exit(1);
|
|
}
|
|
|
|
if (proc->MR_clp_num_profiled_args >= 0) {
|
|
fprintf(stderr, "%s: proc_num %d: duplicate initialization\n",
|
|
MR_progname, proc_num);
|
|
exit(1);
|
|
}
|
|
|
|
if (num_profiled_args < 0) {
|
|
fprintf(stderr, "%s: proc_num %d: bad num_profiled_args\n",
|
|
MR_progname, proc_num);
|
|
exit(1);
|
|
}
|
|
|
|
proc->MR_clp_num_profiled_args = num_profiled_args;
|
|
proc->MR_clp_num_args = num_args;
|
|
proc->MR_clp_arg_infos = arg_infos;
|
|
|
|
proc->MR_clp_metrics = MR_NEW_ARRAY(MR_ComplexityMetrics,
|
|
MR_COMPLEXITY_SLOTS_PER_CHUNK);
|
|
proc->MR_clp_sizes = MR_NEW_ARRAY(int,
|
|
MR_COMPLEXITY_SLOTS_PER_CHUNK * num_profiled_args);
|
|
}
|
|
|
|
void
|
|
MR_check_complexity_init(void)
|
|
{
|
|
int proc_num;
|
|
MR_bool printed_heading;
|
|
MR_ComplexityProc *proc;
|
|
|
|
printed_heading = MR_FALSE;
|
|
for (proc_num = 0; proc_num < MR_num_complexity_procs; proc_num++) {
|
|
proc = &MR_complexity_procs[proc_num];
|
|
|
|
if (proc->MR_clp_num_profiled_args < 0) {
|
|
if (! printed_heading) {
|
|
fprintf(stderr, "%s: the following procedures are "
|
|
"not available for complexity experiment:\n",
|
|
MR_progname);
|
|
printed_heading = MR_TRUE;
|
|
}
|
|
|
|
fprintf(stderr, "%s\n", proc->MR_clp_full_proc_name);
|
|
}
|
|
}
|
|
|
|
if (printed_heading) {
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
MR_ComplexityIsActive
|
|
MR_complexity_is_active_func(int num_procs, int proc_num, const char *name,
|
|
int num_profiled_inputs)
|
|
{
|
|
MR_ComplexityProc *proc;
|
|
|
|
if (num_procs != MR_num_complexity_procs || MR_complexity_procs == NULL) {
|
|
fprintf(stderr, "%s: executable wasn't fully prepared "
|
|
"for complexity experiment\n", MR_progname);
|
|
exit(1);
|
|
}
|
|
|
|
if (proc_num >= num_procs) {
|
|
fprintf(stderr, "%s: proc_num %d >= num_procs %d\n",
|
|
MR_progname, proc_num, num_procs);
|
|
exit(1);
|
|
}
|
|
|
|
proc = &MR_complexity_procs[proc_num];
|
|
if (! MR_streq(name, proc->MR_clp_full_proc_name)) {
|
|
fprintf(stderr, "%s: proc_num %d is %s: expected %s\n",
|
|
MR_progname, proc_num, proc->MR_clp_full_proc_name, name);
|
|
exit(1);
|
|
}
|
|
|
|
if (proc->MR_clp_num_profiled_args != num_profiled_inputs) {
|
|
fprintf(stderr, "%s: proc_num %d: bad num_profiled_inputs\n",
|
|
MR_progname, proc_num);
|
|
exit(1);
|
|
}
|
|
|
|
return proc->MR_clp_is_active;
|
|
}
|
|
|
|
int
|
|
MR_complexity_call_func(int procnum)
|
|
{
|
|
MR_ComplexityProc *proc;
|
|
MR_ComplexityMetrics *metrics;
|
|
int slot;
|
|
|
|
proc = &MR_complexity_procs[procnum];
|
|
slot = proc->MR_clp_next_slot_num;
|
|
if (slot < MR_COMPLEXITY_SLOTS_PER_CHUNK) {
|
|
proc->MR_clp_next_slot_num++;
|
|
} else {
|
|
MR_ComplexityPastSlots *past_slots;
|
|
|
|
past_slots = MR_NEW(MR_ComplexityPastSlots);
|
|
past_slots->MR_clpps_metrics = proc->MR_clp_metrics;
|
|
past_slots->MR_clpps_sizes = proc->MR_clp_sizes;
|
|
past_slots->MR_clpps_previous = proc->MR_clp_past_slots;
|
|
proc->MR_clp_past_slots = past_slots;
|
|
|
|
proc->MR_clp_metrics = MR_NEW_ARRAY(MR_ComplexityMetrics,
|
|
MR_COMPLEXITY_SLOTS_PER_CHUNK);
|
|
proc->MR_clp_sizes = MR_NEW_ARRAY(int,
|
|
MR_COMPLEXITY_SLOTS_PER_CHUNK * proc->MR_clp_num_profiled_args);
|
|
proc->MR_clp_next_slot_num = 1;
|
|
slot = 0;
|
|
}
|
|
metrics = &proc->MR_clp_metrics[slot];
|
|
metrics->MR_clpm_num_words -= MR_complexity_word_counter;
|
|
metrics->MR_clpm_num_cells -= MR_complexity_cell_counter;
|
|
metrics->MR_clpm_num_ticks -= MR_complexity_tick_counter;
|
|
proc->MR_clp_is_active = MR_COMPLEXITY_IS_ACTIVE;
|
|
|
|
return slot;
|
|
}
|
|
|
|
void
|
|
MR_complexity_fill_size_slot(MR_ComplexityProc *proc, int slot,
|
|
int num_profiled_args, int argnum, int size)
|
|
{
|
|
MR_ComplexityCounter *sizes;
|
|
|
|
sizes = proc->MR_clp_sizes;
|
|
sizes[(slot * proc->MR_clp_num_profiled_args) + argnum] = size;
|
|
}
|
|
|
|
void
|
|
MR_complexity_leave_func(int procnum, int slot)
|
|
{
|
|
MR_ComplexityProc *proc;
|
|
MR_ComplexityMetrics *metrics;
|
|
|
|
proc = &MR_complexity_procs[procnum];
|
|
metrics = &proc->MR_clp_metrics[slot];
|
|
metrics->MR_clpm_num_words += MR_complexity_word_counter;
|
|
metrics->MR_clpm_num_cells += MR_complexity_cell_counter;
|
|
metrics->MR_clpm_num_ticks += MR_complexity_tick_counter;
|
|
proc->MR_clp_is_active = MR_COMPLEXITY_IS_INACTIVE;
|
|
}
|
|
|
|
void
|
|
MR_complexity_redo_func(int procnum, int slot)
|
|
{
|
|
MR_ComplexityProc *proc;
|
|
MR_ComplexityMetrics *metrics;
|
|
|
|
proc = &MR_complexity_procs[procnum];
|
|
metrics = &proc->MR_clp_metrics[slot];
|
|
metrics->MR_clpm_num_words -= MR_complexity_word_counter;
|
|
metrics->MR_clpm_num_cells -= MR_complexity_cell_counter;
|
|
metrics->MR_clpm_num_ticks -= MR_complexity_tick_counter;
|
|
proc->MR_clp_is_active = MR_COMPLEXITY_IS_ACTIVE;
|
|
}
|
|
|
|
#endif /* MR_RECORD_TERM_SIZES */
|