summaryrefslogtreecommitdiff
path: root/gcc/ggc-page.c
diff options
context:
space:
mode:
authorZack Weinberg <zack@gcc.gnu.org>2002-08-22 19:17:04 +0000
committerZack Weinberg <zack@gcc.gnu.org>2002-08-22 19:17:04 +0000
commit8537ed688c3994e0fc923f6b34c456ff6ccd2626 (patch)
treebd0a076c9450bb1886ff2d1bc5edfa5af79c6cff /gcc/ggc-page.c
parent8567c70f72df23a2ceb3c26ac7a058a6b6aa4054 (diff)
downloadgcc-8537ed688c3994e0fc923f6b34c456ff6ccd2626.tar.gz
ggc-page.c: Avoid division in ggc_set_mark.
* ggc-page.c: Avoid division in ggc_set_mark. (DIV_MULT, DIV_SHIFT, OFFSET_TO_BIT, inverse_table, compute_inverse): New. (ggc_set_mark, ggc_marked_p): Use OFFSET_TO_BIT. (init_ggc): Initialize inverse_table. From-SVN: r56512
Diffstat (limited to 'gcc/ggc-page.c')
-rw-r--r--gcc/ggc-page.c59
1 files changed, 55 insertions, 4 deletions
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 9a5644a3232..af3af1ab0bb 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -158,6 +158,15 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* The size of an object on a page of the indicated ORDER. */
#define OBJECT_SIZE(ORDER) object_size_table[ORDER]
+/* For speed, we avoid doing a general integer divide to locate the
+ offset in the allocation bitmap, by precalculating numbers M, S
+ such that (O * M) >> S == O / Z (modulo 2^32), for any offset O
+ within the page which is evenly divisible by the object size Z. */
+#define DIV_MULT(ORDER) inverse_table[ORDER].mult
+#define DIV_SHIFT(ORDER) inverse_table[ORDER].shift
+#define OFFSET_TO_BIT(OFFSET, ORDER) \
+ (((OFFSET) * DIV_MULT (ORDER)) >> DIV_SHIFT (ORDER))
+
/* The number of extra orders, not corresponding to power-of-two sized
objects. */
@@ -209,6 +218,17 @@ static unsigned objects_per_page_table[NUM_ORDERS];
static size_t object_size_table[NUM_ORDERS];
+/* The Ith entry is a pair of numbers (mult, shift) such that
+ ((k * mult) >> shift) mod 2^32 == (k / OBJECT_SIZE(I)) mod 2^32,
+ for all k evenly divisible by OBJECT_SIZE(I). */
+
+static struct
+{
+ unsigned int mult;
+ unsigned int shift;
+}
+inverse_table[NUM_ORDERS];
+
/* A page_entry records the status of an allocation page. This
structure is dynamically sized to fit the bitmap in_use_p. */
typedef struct page_entry
@@ -377,6 +397,7 @@ static void release_pages PARAMS ((void));
static void clear_marks PARAMS ((void));
static void sweep_pages PARAMS ((void));
static void ggc_recalculate_in_use_p PARAMS ((page_entry *));
+static void compute_inverse PARAMS ((unsigned));
#ifdef GGC_POISON
static void poison_pages PARAMS ((void));
@@ -988,7 +1009,7 @@ ggc_set_mark (p)
/* Calculate the index of the object on the page; this is its bit
position in the in_use_p bitmap. */
- bit = (((const char *) p) - entry->page) / OBJECT_SIZE (entry->order);
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
word = bit / HOST_BITS_PER_LONG;
mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
@@ -1028,7 +1049,7 @@ ggc_marked_p (p)
/* Calculate the index of the object on the page; this is its bit
position in the in_use_p bitmap. */
- bit = (((const char *) p) - entry->page) / OBJECT_SIZE (entry->order);
+ bit = OFFSET_TO_BIT (((const char *) p) - entry->page, entry->order);
word = bit / HOST_BITS_PER_LONG;
mask = (unsigned long) 1 << (bit % HOST_BITS_PER_LONG);
@@ -1045,8 +1066,37 @@ ggc_get_size (p)
return OBJECT_SIZE (pe->order);
}
-/* Initialize the ggc-mmap allocator. */
+/* Subroutine of init_ggc which computes the pair of numbers used to
+ perform division by OBJECT_SIZE (order) and fills in inverse_table[].
+
+ This algorithm is taken from Granlund and Montgomery's paper
+ "Division by Invariant Integers using Multiplication"
+ (Proc. SIGPLAN PLDI, 1994), section 9 (Exact division by
+ constants). */
+
+static void
+compute_inverse (order)
+ unsigned order;
+{
+ unsigned size, inv, e;
+
+ size = OBJECT_SIZE (order);
+ e = 0;
+ while (size % 2 == 0)
+ {
+ e++;
+ size >>= 1;
+ }
+ inv = size;
+ while (inv * size != 1)
+ inv = inv * (2 - inv*size);
+
+ DIV_MULT (order) = inv;
+ DIV_SHIFT (order) = e;
+}
+
+/* Initialize the ggc-mmap allocator. */
void
init_ggc ()
{
@@ -1109,12 +1159,13 @@ init_ggc ()
object_size_table[order] = s;
}
- /* Initialize the objects-per-page table. */
+ /* Initialize the objects-per-page and inverse tables. */
for (order = 0; order < NUM_ORDERS; ++order)
{
objects_per_page_table[order] = G.pagesize / OBJECT_SIZE (order);
if (objects_per_page_table[order] == 0)
objects_per_page_table[order] = 1;
+ compute_inverse (order);
}
/* Reset the size_lookup array to put appropriately sized objects in