Convert revwalk to use git_pool This removes the custom paged allocator from revwalk and replaces it with a `git_pool`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
diff --git a/src/pool.c b/src/pool.c
index 2e64bde..8f5c7e7 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -29,11 +29,8 @@ int git_pool_init(
else if (item_size == 3)
item_size = 4;
- if (!items_per_page) {
- uint32_t page_bytes =
- git_pool__system_page_size() - sizeof(git_pool_page);
- items_per_page = page_bytes / item_size;
- }
+ if (!items_per_page)
+ items_per_page = git_pool__suggest_items_per_page(item_size);
if (item_size * items_per_page < GIT_POOL_MIN_PAGESZ)
items_per_page = (GIT_POOL_MIN_PAGESZ + item_size - 1) / item_size;
@@ -288,3 +285,10 @@ uint32_t git_pool__system_page_size(void)
return size;
}
+uint32_t git_pool__suggest_items_per_page(uint32_t item_size)
+{
+ uint32_t page_bytes =
+ git_pool__system_page_size() - sizeof(git_pool_page);
+ return page_bytes / item_size;
+}
+
diff --git a/src/pool.h b/src/pool.h
index a925890..54a2861 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -120,4 +120,6 @@ extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr);
extern uint32_t git_pool__system_page_size(void);
+extern uint32_t git_pool__suggest_items_per_page(uint32_t item_size);
+
#endif
diff --git a/src/revwalk.c b/src/revwalk.c
index a625760..557966b 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -10,6 +10,7 @@
#include "odb.h"
#include "hashtable.h"
#include "pqueue.h"
+#include "pool.h"
#include "git2/revwalk.h"
#include "git2/merge.h"
@@ -46,6 +47,7 @@ struct git_revwalk {
git_odb *odb;
git_hashtable *commits;
+ git_pool commit_pool;
commit_list *iterator_topo;
commit_list *iterator_rand;
@@ -55,9 +57,6 @@ struct git_revwalk {
int (*get_next)(commit_object **, git_revwalk *);
int (*enqueue)(git_revwalk *, commit_object *);
- git_vector memory_alloc;
- size_t chunk_size;
-
unsigned walking:1;
unsigned int sorting;
@@ -133,42 +132,23 @@ static uint32_t object_table_hash(const void *key, int hash_id)
return r;
}
-#define COMMITS_PER_CHUNK 128
-#define CHUNK_STEP 64
-#define PARENTS_PER_COMMIT ((CHUNK_STEP - sizeof(commit_object)) / sizeof(commit_object *))
-
-static int alloc_chunk(git_revwalk *walk)
-{
- void *chunk;
-
- chunk = git__calloc(COMMITS_PER_CHUNK, CHUNK_STEP);
- GITERR_CHECK_ALLOC(chunk);
-
- walk->chunk_size = 0;
- return git_vector_insert(&walk->memory_alloc, chunk);
-}
+#define PARENTS_PER_COMMIT 2
+#define COMMIT_ALLOC \
+ (sizeof(commit_object) + PARENTS_PER_COMMIT * sizeof(commit_object *))
static commit_object *alloc_commit(git_revwalk *walk)
{
- unsigned char *chunk;
-
- if (walk->chunk_size == COMMITS_PER_CHUNK)
- if (alloc_chunk(walk) < 0)
- return NULL;
-
- chunk = git_vector_get(&walk->memory_alloc, walk->memory_alloc.length - 1);
- chunk += (walk->chunk_size * CHUNK_STEP);
- walk->chunk_size++;
-
- return (commit_object *)chunk;
+ return (commit_object *)git_pool_malloc(&walk->commit_pool, COMMIT_ALLOC);
}
-static commit_object **alloc_parents(commit_object *commit, size_t n_parents)
+static commit_object **alloc_parents(
+ git_revwalk *walk, commit_object *commit, size_t n_parents)
{
if (n_parents <= PARENTS_PER_COMMIT)
- return (commit_object **)((unsigned char *)commit + sizeof(commit_object));
+ return (commit_object **)((char *)commit + sizeof(commit_object));
- return git__malloc(n_parents * sizeof(commit_object *));
+ return (commit_object **)git_pool_malloc(
+ &walk->commit_pool, n_parents * sizeof(commit_object *));
}
@@ -185,10 +165,8 @@ static commit_object *commit_lookup(git_revwalk *walk, const git_oid *oid)
git_oid_cpy(&commit->oid, oid);
- if (git_hashtable_insert(walk->commits, &commit->oid, commit) < 0) {
- git__free(commit);
+ if (git_hashtable_insert(walk->commits, &commit->oid, commit) < 0)
return NULL;
- }
return commit;
}
@@ -212,7 +190,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
buffer += parent_len;
}
- commit->parents = alloc_parents(commit, parents);
+ commit->parents = alloc_parents(walk, commit, parents);
GITERR_CHECK_ALLOC(commit->parents);
buffer = parents_start;
@@ -756,9 +734,9 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
GITERR_CHECK_ALLOC(walk->commits);
if (git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp) < 0 ||
- git_vector_init(&walk->memory_alloc, 8, NULL) < 0 ||
git_vector_init(&walk->twos, 4, NULL) < 0 ||
- alloc_chunk(walk) < 0)
+ git_pool_init(&walk->commit_pool, 1,
+ git_pool__suggest_items_per_page(COMMIT_ALLOC) * COMMIT_ALLOC) < 0)
return -1;
walk->get_next = &revwalk_next_unsorted;
@@ -777,30 +755,15 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
void git_revwalk_free(git_revwalk *walk)
{
- unsigned int i;
- commit_object *commit;
-
if (walk == NULL)
return;
git_revwalk_reset(walk);
git_odb_free(walk->odb);
- /* if the parent has more than PARENTS_PER_COMMIT parents,
- * we had to allocate a separate array for those parents.
- * make sure it's being free'd */
- GIT_HASHTABLE_FOREACH_VALUE(walk->commits, commit, {
- if (commit->out_degree > PARENTS_PER_COMMIT)
- git__free(commit->parents);
- });
-
git_hashtable_free(walk->commits);
+ git_pool_clear(&walk->commit_pool);
git_pqueue_free(&walk->iterator_time);
-
- for (i = 0; i < walk->memory_alloc.length; ++i)
- git__free(git_vector_get(&walk->memory_alloc, i));
-
- git_vector_free(&walk->memory_alloc);
git_vector_free(&walk->twos);
git__free(walk);
}