v2 is mostly refinements with a big change: commit-slab.h is restructured to allow sharing commit slabs. Other changes are - rename struct source_slab to revision_sources - keep revision_sources_* functinons (and one static variable) to revision.c instead of duplicating them whenver revision.h is included. - reduce elemtype in commit_seen in sequencer.c from 4 bytes to 1. - avoid dereferencing _peek in sequencer.c Interdiff diff --git a/builtin/fast-export.c b/builtin/fast-export.c index 092e29583e..b08e5ea0e3 100644 --- a/builtin/fast-export.c +++ b/builtin/fast-export.c @@ -39,7 +39,7 @@ static struct string_list extra_refs = STRING_LIST_INIT_NODUP; static struct refspec *refspecs; static int refspecs_nr; static int anonymize; -static struct source_slab source_slab; +static struct revision_sources revision_sources; static int parse_opt_signed_tag_mode(const struct option *opt, const char *arg, int unset) @@ -592,7 +592,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev, if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode)) export_blob(&diff_queued_diff.queue[i]->two->oid); - refname = *source_slab_peek(&source_slab, commit); + refname = *revision_sources_peek(&revision_sources, commit); if (anonymize) { refname = anonymize_refname(refname); anonymize_ident_line(&committer, &committer_end); @@ -864,11 +864,11 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info) * This ref will not be updated through a commit, lets make * sure it gets properly updated eventually. */ - if (*source_slab_at(&source_slab, commit) || + if (*revision_sources_at(&revision_sources, commit) || commit->object.flags & SHOWN) string_list_append(&extra_refs, full_name)->util = commit; - if (!*source_slab_at(&source_slab, commit)) - *source_slab_at(&source_slab, commit) = full_name; + if (!*revision_sources_at(&revision_sources, commit)) + *revision_sources_at(&revision_sources, commit) = full_name; } } @@ -1032,9 +1032,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); init_revisions(&revs, prefix); - init_source_slab(&source_slab); + init_revision_sources(&revision_sources); revs.topo_order = 1; - revs.source_slab = &source_slab; + revs.sources = &revision_sources; revs.rewrite_parents = 1; argc = parse_options(argc, argv, prefix, options, fast_export_usage, PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN); diff --git a/builtin/log.c b/builtin/log.c index b771d27164..967fbc5caa 100644 --- a/builtin/log.c +++ b/builtin/log.c @@ -149,7 +149,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP; struct decoration_filter decoration_filter = {&decorate_refs_include, &decorate_refs_exclude}; - static struct source_slab source_slab; + static struct revision_sources revision_sources; const struct option builtin_log_options[] = { OPT__QUIET(&quiet, N_("suppress diff output")), @@ -197,8 +197,8 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix, rev->always_show_header = 0; if (source) { - init_source_slab(&source_slab); - rev->source_slab = &source_slab; + init_revision_sources(&revision_sources); + rev->sources = &revision_sources; } if (mailmap) { diff --git a/commit-slab-hdr.h b/commit-slab-hdr.h new file mode 100644 index 0000000000..adc7b46c83 --- /dev/null +++ b/commit-slab-hdr.h @@ -0,0 +1,43 @@ +#ifndef COMMIT_SLAB_HDR_H +#define COMMIT_SLAB_HDR_H + +/* allocate ~512kB at once, allowing for malloc overhead */ +#ifndef COMMIT_SLAB_SIZE +#define COMMIT_SLAB_SIZE (512*1024-32) +#endif + +#define declare_commit_slab(slabname, elemtype) \ + \ +struct slabname { \ + unsigned slab_size; \ + unsigned stride; \ + unsigned slab_count; \ + elemtype **slab; \ +} + +/* + * Statically initialize a commit slab named "var". Note that this + * evaluates "stride" multiple times! Example: + * + * struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees); + * + */ +#define COMMIT_SLAB_INIT(stride, var) { \ + COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \ + (stride), 0, NULL \ +} + +#define declare_commit_slab_prototypes(slabname, elemtype) \ + \ +void init_ ##slabname## _with_stride(struct slabname *s, unsigned stride); \ +void init_ ##slabname(struct slabname *s); \ +void clear_ ##slabname(struct slabname *s); \ +elemtype *slabname## _at_peek(struct slabname *s, const struct commit *c, int add_if_missing); \ +elemtype *slabname## _at(struct slabname *s, const struct commit *c); \ +elemtype *slabname## _peek(struct slabname *s, const struct commit *c) + +#define define_shared_commit_slab(slabname, elemtype) \ + declare_commit_slab(slabname, elemtype); \ + declare_commit_slab_prototypes(slabname, elemtype) + +#endif /* COMMIT_SLAB_HDR_H */ diff --git a/commit-slab-impl.h b/commit-slab-impl.h new file mode 100644 index 0000000000..19a88d7d8f --- /dev/null +++ b/commit-slab-impl.h @@ -0,0 +1,97 @@ +#ifndef COMMIT_SLAB_IMPL_H +#define COMMIT_SLAB_IMPL_H + +#define MAYBE_UNUSED __attribute__((__unused__)) + +#define implement_static_commit_slab(slabname, elemtype) \ + implement_commit_slab(slabname, elemtype, static MAYBE_UNUSED) + +#define implement_shared_commit_slab(slabname, elemtype) \ + implement_commit_slab(slabname, elemtype, ) + +#define implement_commit_slab(slabname, elemtype, scope) \ + \ +static int stat_ ##slabname## realloc; \ + \ +scope void init_ ##slabname## _with_stride(struct slabname *s, \ + unsigned stride) \ +{ \ + unsigned int elem_size; \ + if (!stride) \ + stride = 1; \ + s->stride = stride; \ + elem_size = sizeof(elemtype) * stride; \ + s->slab_size = COMMIT_SLAB_SIZE / elem_size; \ + s->slab_count = 0; \ + s->slab = NULL; \ +} \ + \ +scope void init_ ##slabname(struct slabname *s) \ +{ \ + init_ ##slabname## _with_stride(s, 1); \ +} \ + \ +scope void clear_ ##slabname(struct slabname *s) \ +{ \ + unsigned int i; \ + for (i = 0; i < s->slab_count; i++) \ + free(s->slab[i]); \ + s->slab_count = 0; \ + FREE_AND_NULL(s->slab); \ +} \ + \ +scope elemtype *slabname## _at_peek(struct slabname *s, \ + const struct commit *c, \ + int add_if_missing) \ +{ \ + unsigned int nth_slab, nth_slot; \ + \ + nth_slab = c->index / s->slab_size; \ + nth_slot = c->index % s->slab_size; \ + \ + if (s->slab_count <= nth_slab) { \ + unsigned int i; \ + if (!add_if_missing) \ + return NULL; \ + REALLOC_ARRAY(s->slab, nth_slab + 1); \ + stat_ ##slabname## realloc++; \ + for (i = s->slab_count; i <= nth_slab; i++) \ + s->slab[i] = NULL; \ + s->slab_count = nth_slab + 1; \ + } \ + if (!s->slab[nth_slab]) { \ + if (!add_if_missing) \ + return NULL; \ + s->slab[nth_slab] = xcalloc(s->slab_size, \ + sizeof(**s->slab) * s->stride); \ + } \ + return &s->slab[nth_slab][nth_slot * s->stride]; \ +} \ + \ +scope elemtype *slabname## _at(struct slabname *s, \ + const struct commit *c) \ +{ \ + return slabname##_at_peek(s, c, 1); \ +} \ + \ +scope elemtype *slabname## _peek(struct slabname *s, \ + const struct commit *c) \ +{ \ + return slabname##_at_peek(s, c, 0); \ +} \ + \ +struct slabname + +/* + * Note that this redundant forward declaration is required + * to allow a terminating semicolon, which makes instantiations look + * like function declarations. I.e., the expansion of + * + * implement_commit_slab(indegree, int); + * + * ends in 'struct indegree;'. This would otherwise + * be a syntax error according (at least) to ISO C. It's hard to + * catch because GCC silently parses it by default. + */ + +#endif /* COMMIT_SLAB_IMPL_H */ diff --git a/commit-slab.h b/commit-slab.h index dcaab8ca04..dc029acc66 100644 --- a/commit-slab.h +++ b/commit-slab.h @@ -1,6 +1,9 @@ #ifndef COMMIT_SLAB_H #define COMMIT_SLAB_H +#include "commit-slab-hdr.h" +#include "commit-slab-impl.h" + /* * define_commit_slab(slabname, elemtype) creates boilerplate code to define * a new struct (struct slabname) that is used to associate a piece of data @@ -41,114 +44,8 @@ * leaking memory. */ -/* allocate ~512kB at once, allowing for malloc overhead */ -#ifndef COMMIT_SLAB_SIZE -#define COMMIT_SLAB_SIZE (512*1024-32) -#endif - -#define MAYBE_UNUSED __attribute__((__unused__)) - -#define define_commit_slab(slabname, elemtype) \ - \ -struct slabname { \ - unsigned slab_size; \ - unsigned stride; \ - unsigned slab_count; \ - elemtype **slab; \ -}; \ -static int stat_ ##slabname## realloc; \ - \ -static MAYBE_UNUSED void init_ ##slabname## _with_stride(struct slabname *s, \ - unsigned stride) \ -{ \ - unsigned int elem_size; \ - if (!stride) \ - stride = 1; \ - s->stride = stride; \ - elem_size = sizeof(elemtype) * stride; \ - s->slab_size = COMMIT_SLAB_SIZE / elem_size; \ - s->slab_count = 0; \ - s->slab = NULL; \ -} \ - \ -static MAYBE_UNUSED void init_ ##slabname(struct slabname *s) \ -{ \ - init_ ##slabname## _with_stride(s, 1); \ -} \ - \ -static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \ -{ \ - unsigned int i; \ - for (i = 0; i < s->slab_count; i++) \ - free(s->slab[i]); \ - s->slab_count = 0; \ - FREE_AND_NULL(s->slab); \ -} \ - \ -static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s, \ - const struct commit *c, \ - int add_if_missing) \ -{ \ - unsigned int nth_slab, nth_slot; \ - \ - nth_slab = c->index / s->slab_size; \ - nth_slot = c->index % s->slab_size; \ - \ - if (s->slab_count <= nth_slab) { \ - unsigned int i; \ - if (!add_if_missing) \ - return NULL; \ - REALLOC_ARRAY(s->slab, nth_slab + 1); \ - stat_ ##slabname## realloc++; \ - for (i = s->slab_count; i <= nth_slab; i++) \ - s->slab[i] = NULL; \ - s->slab_count = nth_slab + 1; \ - } \ - if (!s->slab[nth_slab]) { \ - if (!add_if_missing) \ - return NULL; \ - s->slab[nth_slab] = xcalloc(s->slab_size, \ - sizeof(**s->slab) * s->stride); \ - } \ - return &s->slab[nth_slab][nth_slot * s->stride]; \ -} \ - \ -static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \ - const struct commit *c) \ -{ \ - return slabname##_at_peek(s, c, 1); \ -} \ - \ -static MAYBE_UNUSED elemtype *slabname## _peek(struct slabname *s, \ - const struct commit *c) \ -{ \ - return slabname##_at_peek(s, c, 0); \ -} \ - \ -struct slabname - -/* - * Note that this redundant forward declaration is required - * to allow a terminating semicolon, which makes instantiations look - * like function declarations. I.e., the expansion of - * - * define_commit_slab(indegree, int); - * - * ends in 'struct indegree;'. This would otherwise - * be a syntax error according (at least) to ISO C. It's hard to - * catch because GCC silently parses it by default. - */ - -/* - * Statically initialize a commit slab named "var". Note that this - * evaluates "stride" multiple times! Example: - * - * struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees); - * - */ -#define COMMIT_SLAB_INIT(stride, var) { \ - COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \ - (stride), 0, NULL \ -} +#define define_commit_slab(slabname, elemtype) \ + declare_commit_slab(slabname, elemtype); \ + implement_static_commit_slab(slabname, elemtype) #endif /* COMMIT_SLAB_H */ diff --git a/log-tree.c b/log-tree.c index d36a945fc4..0b41ee3235 100644 --- a/log-tree.c +++ b/log-tree.c @@ -295,8 +295,8 @@ void show_decorations(struct rev_info *opt, struct commit *commit) { struct strbuf sb = STRBUF_INIT; - if (opt->source_slab) { - char **slot = source_slab_peek(opt->source_slab, commit); + if (opt->sources) { + char **slot = revision_sources_peek(opt->sources, commit); if (slot && *slot) fprintf(opt->diffopt.file, "\t%s", *slot); diff --git a/revision.c b/revision.c index 41b56f789d..be8fe7d67b 100644 --- a/revision.c +++ b/revision.c @@ -29,6 +29,8 @@ volatile show_early_output_fn_t show_early_output; static const char *term_bad; static const char *term_good; +implement_shared_commit_slab(revision_sources, char *); + void show_object_with_name(FILE *out, struct object *obj, const char *name) { const char *p; @@ -262,8 +264,8 @@ static struct commit *handle_commit(struct rev_info *revs, mark_parents_uninteresting(commit); revs->limited = 1; } - if (revs->source_slab) { - char **slot = source_slab_at(revs->source_slab, commit); + if (revs->sources) { + char **slot = revision_sources_at(revs->sources, commit); if (!*slot) *slot = xstrdup(name); @@ -819,11 +821,11 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, } return -1; } - if (revs->source_slab) { - char **slot = source_slab_at(revs->source_slab, p); + if (revs->sources) { + char **slot = revision_sources_at(revs->sources, p); if (!*slot) - *slot = *source_slab_at(revs->source_slab, commit); + *slot = *revision_sources_at(revs->sources, commit); } p->object.flags |= left_flag; if (!(p->object.flags & SEEN)) { diff --git a/revision.h b/revision.h index 72404e2599..f3dc5f9740 100644 --- a/revision.h +++ b/revision.h @@ -6,7 +6,7 @@ #include "notes.h" #include "pretty.h" #include "diff.h" -#include "commit-slab.h" +#include "commit-slab-hdr.h" /* Remember to update object flag allocation in object.h */ #define SEEN (1u<<0) @@ -30,7 +30,7 @@ struct rev_info; struct log_info; struct string_list; struct saved_parents; -define_commit_slab(source_slab, char *); +define_shared_commit_slab(revision_sources, char *); struct rev_cmdline_info { unsigned int nr; @@ -226,7 +226,7 @@ struct rev_info { struct commit_list *previous_parents; const char *break_bar; - struct source_slab *source_slab; + struct revision_sources *sources; }; extern int ref_excluded(struct string_list *, const char *path); diff --git a/sequencer.c b/sequencer.c index 1a0a6916e3..dd4993fd99 100644 --- a/sequencer.c +++ b/sequencer.c @@ -3161,7 +3161,7 @@ static enum check_level get_missing_commit_check_level(void) return CHECK_IGNORE; } -define_commit_slab(commit_seen, int); +define_commit_slab(commit_seen, uint8_t); /* * Check if the user dropped some commits by mistake * Behaviour determined by rebase.missingCommitsCheck. @@ -3453,7 +3453,7 @@ int rearrange_squash(void) lookup_commit_reference_by_name(p)) && *commit_todo_item_at(&commit_todo, commit2)) /* found by commit name */ - i2 = *commit_todo_item_peek(&commit_todo, commit2) + i2 = *commit_todo_item_at(&commit_todo, commit2) - todo_list.items; else { /* copy can be a prefix of the commit subject */ diff --git a/shallow.c b/shallow.c index 6ea411b0d2..daf60a9391 100644 --- a/shallow.c +++ b/shallow.c @@ -75,6 +75,10 @@ int is_repository_shallow(void) return is_shallow; } +/* + * TODO: use "int" elemtype instead of "int *" when/if commit-slab + * supports a "valid" flag. + */ define_commit_slab(commit_depth, int *); struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag) Nguyễn Thái Ngọc Duy (14): commit-slab.h: code split commit-slab: support shared commit-slab blame: use commit-slab for blame suspects instead of commit->util describe: use commit-slab for commit names instead of commit->util shallow.c: use commit-slab for commit depth instead of commit->util sequencer.c: use commit-slab to mark seen commits sequencer.c: use commit-slab to associate todo items to commits revision.c: use commit-slab for show_source bisect.c: use commit-slab for commit weight instead of commit->util name-rev: use commit-slab for rev-name instead of commit->util show-branch: use commit-slab for commit-name instead of commit->util log: use commit-slab in prepare_bases() instead of commit->util merge: use commit-slab in merge remote desc instead of commit->util commit.h: delete 'util' field in struct commit bisect.c | 12 +++-- blame.c | 42 +++++++++++---- blame.h | 2 + builtin/blame.c | 2 +- builtin/describe.c | 16 ++++-- builtin/fast-export.c | 14 +++-- builtin/log.c | 17 +++++-- builtin/merge.c | 25 ++++----- builtin/name-rev.c | 23 +++++++-- builtin/show-branch.c | 39 +++++++++----- commit-slab-hdr.h | 43 ++++++++++++++++ commit-slab-impl.h | 97 +++++++++++++++++++++++++++++++++++ commit-slab.h | 115 +++--------------------------------------- commit.c | 12 ++++- commit.h | 8 ++- log-tree.c | 8 ++- merge-recursive.c | 8 +-- revision.c | 19 +++++-- revision.h | 5 +- sequencer.c | 24 ++++++--- shallow.c | 41 ++++++++++----- 21 files changed, 377 insertions(+), 195 deletions(-) create mode 100644 commit-slab-hdr.h create mode 100644 commit-slab-impl.h -- 2.17.0.705.g3525833791