* src/vm/jit/replace.c (replace_sanity_check_read_write): New function.
authorEdwin Steiner <edwin.steiner@gmx.net>
Wed, 20 Feb 2008 20:30:03 +0000 (21:30 +0100)
committerEdwin Steiner <edwin.steiner@gmx.net>
Wed, 20 Feb 2008 20:30:03 +0000 (21:30 +0100)
Perform some basic sanity checks of the md_replacement_* implementations.
(replace_me_wrapper): Call above function in debugging mode.

src/vm/jit/replace.c

index 8ff72e1fe8779cfe296bef508555fc93dda4d9a6..1149d45afa788b6cbf8cc9217dc6c22d252a47f5 100644 (file)
@@ -113,6 +113,7 @@ typedef u8 stackslot_t;
 #if !defined(NDEBUG)
 static void java_value_print(s4 type, replace_val_t value);
 static void replace_stackframeinfo_println(stackframeinfo_t *sfi);
+static void replace_sanity_check_read_write(void *context);
 #endif
 
 #if !defined(NDEBUG)
@@ -2901,6 +2902,10 @@ bool replace_me_wrapper(u1 *pc, void *context)
 
        if ((rp != NULL) && (rp->pc == pc) && (rp->flags & RPLPOINT_FLAG_ACTIVE)) {
 
+#if !defined(NDEBUG)
+               replace_sanity_check_read_write(context);
+#endif
+
                /* set codeinfo pointer in execution state */
 
                es.code = code;
@@ -3562,6 +3567,97 @@ static void replace_stackframeinfo_println(stackframeinfo_t *sfi)
 }
 #endif
 
+
+/* replace_sanity_check_read_write *********************************************
+
+   Perform some sanity checks for the md_replace_executionstate_read
+   and md_replace_executionstate_write functions.
+
+*******************************************************************************/
+
+#if !defined(NDEBUG)
+static void replace_sanity_check_read_write(void *context)
+{
+    /* estimate a minimum for the context size */
+
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+#define MINIMUM_CONTEXT_SIZE  (SIZEOF_VOID_P    * ADR_REG_CNT \
+                                      + sizeof(double) * FLT_REG_CNT \
+                                                          + sizeof(int)    * INT_REG_CNT)
+#else
+#define MINIMUM_CONTEXT_SIZE  (SIZEOF_VOID_P    * INT_REG_CNT \
+                                      + sizeof(double) * FLT_REG_CNT)
+#endif
+
+       executionstate_t es1;
+       executionstate_t es2;
+       executionstate_t es3;
+       unsigned int i;
+       unsigned char reference[MINIMUM_CONTEXT_SIZE];
+
+       /* keep a copy of (a prefix of) the context for reference */
+
+       memcpy(&reference, context, MINIMUM_CONTEXT_SIZE);
+
+       /* different poisons */
+
+       memset(&es1, 0xc9, sizeof(executionstate_t));
+       memset(&es2, 0xb5, sizeof(executionstate_t));
+       memset(&es3, 0x6f, sizeof(executionstate_t));
+
+       md_replace_executionstate_read(&es1, context);
+
+       /* verify that item-by-item copying preserves the state */
+
+       es2.pc = es1.pc;
+       es2.sp = es1.sp;
+       es2.pv = es1.pv;
+       es2.code = es1.code;
+       for (i = 0; i < INT_REG_CNT; ++i)
+               es2.intregs[i] = es1.intregs[i];
+       for (i = 0; i < FLT_REG_CNT; ++i)
+               es2.fltregs[i] = es1.fltregs[i];
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       for (i = 0; i < ADR_REG_CNT; ++i)
+               es2.adrregs[i] = es1.adrregs[i];
+#endif
+
+       /* write it back - this should not change the context */
+       /* We cannot check that completely, unfortunately, as we don't know */
+       /* the size of the (OS-dependent) context. */
+
+       md_replace_executionstate_write(&es2, context);
+
+       /* Read it again, Sam! */
+
+       md_replace_executionstate_read(&es3, context);
+
+       /* Compare. Note: Because of the NAN madness, we cannot compare
+        * doubles using '=='. */
+
+       assert(es3.pc == es1.pc);
+       assert(es3.sp == es1.sp);
+       assert(es3.pv == es1.pv);
+       for (i = 0; i < INT_REG_CNT; ++i)
+               assert(es3.intregs[i] == es1.intregs[i]);
+       for (i = 0; i < FLT_REG_CNT; ++i)
+               assert(memcmp(es3.fltregs+i, es1.fltregs+i, sizeof(double)) == 0);
+#if defined(HAS_ADDRESS_REGISTER_FILE)
+       for (i = 0; i < ADR_REG_CNT; ++i)
+               assert(es3.adrregs[i] == es1.adrregs[i]);
+#endif
+
+       /* "code" is not set by the md_* functions */
+
+       assert(es3.code != es1.code);
+
+       /* assert that we have not messed up the context */
+
+       assert(memcmp(&reference, context, MINIMUM_CONTEXT_SIZE) == 0);
+}
+#endif
+
+
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where