aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDavid Goldblatt <davidgoldblatt@fb.com>2017-12-19 17:30:50 -0800
committerDavid Goldblatt <davidtgoldblatt@gmail.com>2017-12-21 14:25:43 -0800
commit21f7c13d0b172dac6ea76236bbe0a2f3ee4bcb7b (patch)
tree0b57b8ba7a9946d599adc21070f58983ce59d1f3 /src
parent7f1b02e3fa9de7e0bb5e2562994b5ab3b82c0ec3 (diff)
downloadplatform_external_jemalloc_new-21f7c13d0b172dac6ea76236bbe0a2f3ee4bcb7b.tar.gz
platform_external_jemalloc_new-21f7c13d0b172dac6ea76236bbe0a2f3ee4bcb7b.tar.bz2
platform_external_jemalloc_new-21f7c13d0b172dac6ea76236bbe0a2f3ee4bcb7b.zip
Add the div module, which allows fast division by dynamic values.
Diffstat (limited to 'src')
-rw-r--r--src/div.c55
-rw-r--r--src/sz.c3
2 files changed, 57 insertions, 1 deletions
diff --git a/src/div.c b/src/div.c
new file mode 100644
index 00000000..808892a1
--- /dev/null
+++ b/src/div.c
@@ -0,0 +1,55 @@
+#include "jemalloc/internal/jemalloc_preamble.h"
+
+#include "jemalloc/internal/div.h"
+
+#include "jemalloc/internal/assert.h"
+
+/*
+ * Suppose we have n = q * d, all integers. We know n and d, and want q = n / d.
+ *
+ * For any k, we have (here, all division is exact; not C-style rounding):
+ * floor(ceil(2^k / d) * n / 2^k) = floor((2^k + r) / d * n / 2^k), where
+ * r = (-2^k) mod d.
+ *
+ * Expanding this out:
+ * ... = floor(2^k / d * n / 2^k + r / d * n / 2^k)
+ * = floor(n / d + (r / d) * (n / 2^k)).
+ *
+ * The fractional part of n / d is 0 (because of the assumption that d divides n
+ * exactly), so we have:
+ * ... = n / d + floor((r / d) * (n / 2^k))
+ *
+ * So that our initial expression is equal to the quantity we seek, so long as
+ * (r / d) * (n / 2^k) < 1.
+ *
+ * r is a remainder mod d, so r < d and r / d < 1 always. We can make
+ * n / 2 ^ k < 1 by setting k = 32. This gets us a value of magic that works.
+ */
+
+void
+div_init(div_info_t *div_info, size_t d) {
+ /* Nonsensical. */
+ assert(d != 0);
+ /*
+ * This would make the value of magic too high to fit into a uint32_t
+ * (we would want magic = 2^32 exactly). This would mess with code gen
+ * on 32-bit machines.
+ */
+ assert(d != 1);
+
+ uint64_t two_to_k = ((uint64_t)1 << 32);
+ uint32_t magic = (uint32_t)(two_to_k / d);
+
+ /*
+ * We want magic = ceil(2^k / d), but C gives us floor. We have to
+ * increment it unless the result was exact (i.e. unless d is a power of
+ * two).
+ */
+ if (two_to_k % d != 0) {
+ magic++;
+ }
+ div_info->magic = magic;
+#ifdef JEMALLOC_DEBUG
+ div_info->d = d;
+#endif
+}
diff --git a/src/sz.c b/src/sz.c
index 0986615f..9de77e45 100644
--- a/src/sz.c
+++ b/src/sz.c
@@ -26,7 +26,8 @@ const size_t sz_index2size_tab[NSIZES] = {
JEMALLOC_ALIGNED(CACHELINE)
const uint8_t sz_size2index_tab[] = {
#if LG_TINY_MIN == 0
-#warning "Dangerous LG_TINY_MIN"
+/* The div module doesn't support division by 1. */
+#error "Unsupported LG_TINY_MIN"
#define S2B_0(i) i,
#elif LG_TINY_MIN == 1
#warning "Dangerous LG_TINY_MIN"