[m-rev.] for review: Store less-than-word-sized values in LSBs of box.

Peter Wang novalazy at gmail.com
Thu Jun 6 16:53:43 AEST 2019


runtime/mercury_heap.h:
    Store less-than-word-sized values in least significant bits of a
    box. This makes no any difference on little endian machines.
    On big endian machines, affects the value printed out
    when the box is printed generically.

diff --git a/runtime/mercury_heap.h b/runtime/mercury_heap.h
index 6837af28f..7cd437326 100644
--- a/runtime/mercury_heap.h
+++ b/runtime/mercury_heap.h
@@ -480,14 +480,21 @@
 // Copy a value of type T from `value' to `box', boxing it if necessary
 // (i.e. if type T won't fit in type MR_Box).
 
+#ifdef MR_BIG_ENDIAN
+  #define MR_IF_BIG_ENDIAN(x)   do { x } while (0)
+#else
+  #define MR_IF_BIG_ENDIAN(x)   do { } while (0)
+#endif
+
 #define MR_MAYBE_BOX_FOREIGN_TYPE(T, value, box)                            \
         do {                                                                \
             MR_CHECK_EXPR_TYPE((value), T);                                 \
             MR_CHECK_EXPR_TYPE((box), MR_Box);                              \
-            if (sizeof(T) == sizeof(MR_Box)) {                              \
+            long extra_bytes = (long) sizeof(T) - (long) sizeof(MR_Box);    \
+            if (extra_bytes == 0L) {                                        \
                 (box) = * (MR_Box *) &(value);                              \
-            } else if (sizeof(T) > sizeof(MR_Box)) {                        \
-                MR_Word     box_word;                                       \
+            } else if (extra_bytes > 0L) {                                  \
+                MR_Word box_word;                                           \
                 size_t size_in_words =                                      \
                     (sizeof(T) + sizeof(MR_Word) - 1) / sizeof(MR_Word);    \
                 /*                                                          \
@@ -506,19 +513,14 @@
                 MR_profmem_record_allocation(size_in_words, NULL,           \
                     "foreign type: " MR_STRINGIFY(T));                      \
             } else {                                                        \
-                /*                                                          \
-                ** We can't take the address of `box' here,                 \
-                ** since it might be a global register.                     \
-                ** Hence we need to use a temporary copy.                   \
-                */                                                          \
-                MR_Box box_copy;                                            \
-                if (sizeof(T) < sizeof(MR_Box)) {                           \
-                    /*                                                      \
-                    ** Make sure we don't leave any part of it uninitialized. \
-                    */                                                      \
-                    box_copy = 0;                                           \
-                }                                                           \
+                MR_Box box_copy = 0;                                        \
                 MR_memcpy(&box_copy, &(value), sizeof(T));                  \
+                /* Store value in least significant bits. */                \
+                MR_IF_BIG_ENDIAN(                                           \
+                    MR_Word box_word = (MR_Word) box_copy;                  \
+                    box_word >>= -(extra_bytes * CHAR_BIT);                 \
+                    box_copy = (MR_Box) box_word;                           \
+                );                                                          \
                 (box) = box_copy;                                           \
             }                                                               \
         } while (0)
@@ -530,20 +532,24 @@
         do {                                                                \
             MR_CHECK_EXPR_TYPE((value), T);                                 \
             MR_CHECK_EXPR_TYPE((box), MR_Box);                              \
-            if (sizeof(T) > sizeof(MR_Word)) {                              \
-                MR_assign_structure((value), * (T *) (box));                \
-            } else {                                                        \
+            long extra_bytes = (long) sizeof(T) - (long) sizeof(MR_Box);    \
+            if (extra_bytes == 0L) {                                        \
                 /*                                                          \
                 ** We can't take the address of `box' here,                 \
                 ** since it might be a global register.                     \
-                ** Hence we need to use a temporary copy.                   \
                 */                                                          \
                 MR_Box box_copy = (box);                                    \
-                if (sizeof(T) == sizeof(MR_Box)) {                          \
-                    (value) = * (T *) &box_copy;                            \
-                } else {                                                    \
-                    MR_memcpy(&(value), &box_copy, sizeof(T));              \
-                }                                                           \
+                (value) = * (T *) &box_copy;                                \
+            } else if (extra_bytes > 0L) {                                  \
+                MR_assign_structure((value), * (T *) (box));                \
+            } else {                                                        \
+                MR_Box box_copy = (box);                                    \
+                MR_IF_BIG_ENDIAN(                                           \
+                    MR_Word box_word = (MR_Word) box_copy;                  \
+                    box_word <<= -(extra_bytes * CHAR_BIT);                 \
+                    box_copy = (MR_Box) box_word;                           \
+                );                                                          \
+                MR_memcpy(&(value), &box_copy, sizeof(T));                  \
             }                                                               \
         } while (0)
 
-- 
2.21.0



More information about the reviews mailing list