From 4fde4e10b29d4779189b81cf9c8a050593514aa3 Mon Sep 17 00:00:00 2001 From: Richard Brooksby Date: Sat, 1 Sep 2012 11:40:43 +0100 Subject: [PATCH] Compiling with a static checking level by default, doubling the speed of the cool variety. Copied from Perforce Change: 179157 ServerID: perforce.ravenbrook.com --- mps/code/check.h | 44 +++++++++++++++++++++++++++++--------------- mps/code/config.h | 24 ++++++++++++------------ mps/code/mpm.c | 6 ++++-- 3 files changed, 45 insertions(+), 29 deletions(-) diff --git a/mps/code/check.h b/mps/code/check.h index c43dcc1c3d2..63afefad564 100644 --- a/mps/code/check.h +++ b/mps/code/check.h @@ -68,12 +68,25 @@ * static variable CheckLevel controls the frequency and detail of * consistency checking on structures. * - * FIXME: This should be initialised from an environment variable and have - * an interface in mps.h. + * By default, CHECKLEVEL is defined to a static value in config.h, though + * it can be overridden on the compiler command line, e.g. + * cc -DCHECKLEVEL=CheckLevelSHALLOW ... + * + * However, if CHECKLEVEL_DYNAMIC is defined we use a variable to control + * the level of checking. The run-time overhead for this is quite high + * (observed double run-time on amcss when the variable is set to SHALLOW). + * CHECKLEVEL_DYNAMIC should be set to the initial level for the variable, + * which is in mpm.c. + * + * In general, it's better to adjust the check level by defining CHECKLEVEL + * but this is intended to meet the case where a run-time adjustable + * checking level is required -- where recompilation or relinking is + * undesirable or impossible. + * + * FIXME: Should also allow the check level variable to come from an + * environment variable. */ -extern unsigned CheckLevel; - enum { CheckLevelMINIMAL = 0, /* local sig check only */ CheckLevelSHALLOW = 1, /* local invariants, */ @@ -83,6 +96,12 @@ enum { /* and recursive down full type checks */ }; +#ifdef CHECKLEVEL_DYNAMIC +extern unsigned CheckLevel; +#undef CHECKLEVEL +#define CHECKLEVEL CheckLevel +#endif + /* AVER, AVERT -- MPM assertions * @@ -117,13 +136,13 @@ enum { #define AVER_CRITICAL(cond) \ BEGIN \ - if (CheckLevel != CheckLevelMINIMAL) \ + if (CHECKLEVEL != CheckLevelMINIMAL) \ ASSERT(cond, #cond); \ END #define AVERT_CRITICAL(type, val) \ BEGIN \ - if (CheckLevel != CheckLevelMINIMAL) \ + if (CHECKLEVEL != CheckLevelMINIMAL) \ ASSERT(type ## Check(val), "TypeCheck " #type ": " #val); \ END @@ -166,7 +185,7 @@ enum { /* CHECKS -- Check Signature * - * (if CheckLevel == CheckLevelMINIMAL, this is all we check) + * (if CHECKLEVEL == CheckLevelMINIMAL, this is all we check) */ #if defined(AVER_AND_CHECK_NONE) @@ -196,7 +215,7 @@ enum { * - check "up" values which are its "parents" with CHECKU. * * These various checks will be compiled out or compiled to be controlled - * by CheckLevel. + * by CHECKLEVEL. * * For example: * @@ -215,21 +234,16 @@ enum { * children which are Segments, etc. * * The important thing is to have a partial order on types so that recursive - * checking will terminate. When CheckLevel is set to DEEP, checking will + * checking will terminate. When CHECKLEVEL is set to DEEP, checking will * recurse into check methods for children, but will only do a shallow * signature check on parents, avoiding infinite regression. - * - * FIXME: Switching on every CHECK line doesn't compile very well, because - * the compiler can't tell that CheckLevel won't change between function - * calls and can't lift out the test. Is there a better arrangement, - * perhaps by reading CheckLevel into a local variable? */ #if defined(AVER_AND_CHECK_ALL) #define CHECK_BY_LEVEL(minimal, shallow, deep) \ BEGIN \ - switch (CheckLevel) { \ + switch (CHECKLEVEL) { \ case CheckLevelDEEP: deep; break; \ case CheckLevelSHALLOW: shallow; break; \ default: NOTREACHED; /* fall through */ \ diff --git a/mps/code/config.h b/mps/code/config.h index 86b3a22b610..15c30b6e5e0 100644 --- a/mps/code/config.h +++ b/mps/code/config.h @@ -35,7 +35,6 @@ #if defined(CONFIG_VAR_WE) /* White-hot variety */ /* no asserts */ -/* ... so CHECKLEVEL_INITIAL is irrelevant */ /* no statistic meters */ /* no telemetry log events */ @@ -49,7 +48,9 @@ #elif defined(CONFIG_VAR_HE) /* Hot variety */ #define CONFIG_ASSERT -#define CHECKLEVEL_INITIAL CheckLevelMINIMAL +#ifndef CHECKLEVEL +#define CHECKLEVEL CheckLevelMINIMAL +#endif /* no statistic meters */ /* no telemetry log events */ @@ -63,7 +64,9 @@ #elif defined(CONFIG_VAR_DI) /* Diagnostic variety */ #define CONFIG_ASSERT -#define CHECKLEVEL_INITIAL CheckLevelMINIMAL +#ifndef CHECKLEVEL +#define CHECKLEVEL CheckLevelMINIMAL +#endif #define CONFIG_STATS /* For diagnostics, choose a DIAG_WITH_... output method. * (We need to choose because the DIAG output system is under @@ -85,8 +88,10 @@ #elif defined(CONFIG_VAR_CI) /* Cool variety */ #define CONFIG_ASSERT #define CONFIG_ASSERT_ALL -/* ... let PRODUCT determine CHECKLEVEL_INITIAL */ #define CONFIG_STATS +#ifndef CHECKLEVEL +#define CHECKLEVEL CheckLevelSHALLOW +#endif /* no telemetry log events */ @@ -100,7 +105,9 @@ #elif defined(CONFIG_VAR_TI) /* Telemetry, Internal; variety.ti */ #define CONFIG_ASSERT #define CONFIG_ASSERT_ALL -/* ... let PRODUCT determine CHECKLEVEL_INITIAL */ +#ifndef CHECKLEVEL +#define CHECKLEVEL CheckLevelSHALLOW +#endif #define CONFIG_STATS #define CONFIG_LOG @@ -400,13 +407,6 @@ */ #define ARENA_SIZE ((Size)1<<30) -/* if CHECKLEVEL_INITIAL hasn't been defined already (e.g. by a variety, or - * in a makefile), take the value from the product. */ - -#ifndef CHECKLEVEL_INITIAL -#define CHECKLEVEL_INITIAL PROD_CHECKLEVEL_INITIAL -#endif - /* Dongle configuration */ diff --git a/mps/code/mpm.c b/mps/code/mpm.c index 4f9af3f888c..f287f2cf964 100644 --- a/mps/code/mpm.c +++ b/mps/code/mpm.c @@ -23,10 +23,12 @@ SRCID(mpm, "$Id$"); /* CheckLevel -- Control check level * - * This controls the behaviour of Check methods (see impl.h.check). + * This controls the behaviour of Check methods (see check.h). */ -unsigned CheckLevel = CHECKLEVEL_INITIAL; +#ifdef CHECKLEVEL_DYNAMIC +unsigned CheckLevel = CHECKLEVEL_DYNAMIC; +#endif /* MPMCheck -- test MPM assumptions */