{"thread":{"id":"4513","subject":"Shrink \"struct object\" a bit","startedAt":"2006-06-14T23:45:13Z","lastAt":"2006-06-17T19:13:48Z","messageCount":3,"participants":["Linus Torvalds","Philip Pokorny"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"21812","messageId":"Pine.LNX.4.64.0606141630570.5498@g5.osdl.org","threadId":"4513","inReplyTo":null,"subject":"Shrink \"struct object\" a bit","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-14T23:45:13Z","receivedAt":"2006-06-14T23:45:13Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\nThis shrinks \"struct object\" by a small amount, by getting rid of the \n\"struct type *\" pointer and replacing it with a 3-bit bitfield instead.\n\nIn addition, we merge the bitfields and the \"flags\" field, which \nincidentally should also remove a useless 4-byte padding from the object \nwhen in 64-bit mode.\n\nNow, our \"struct object\" is still too damn large, but it's now less \nobviously bloated, and of the remaining fields, only the \"util\" (which is \nnot used by most things) is clearly something that should be eventually \ndiscarded.\n\nThis shrinks the \"git-rev-list --all\" memory use by about 2.5% on the \nkernel archive (and, perhaps more importantly, on the larger mozilla \narchive). That may not sound like much, but I suspect it's more on a \n64-bit platform.\n\nThere are other remaining inefficiencies (the parent lists, for example, \nprobably have horrible malloc overhead), but this was pretty obvious.\n\nMost of the patch is just changing the comparison of the \"type\" pointer \nfrom one of the constant string pointers to the appropriate new TYPE_xxx \nsmall integer constant.\n\nSigned-off-by: Linus Torvalds <torvalds@osdl.org>\n---\n\nNOTE! This shrinks the number of branches that git-show-branch can show \nfurther. It's now 25 instead of 29 (because the three bits required for \nthe type field, and the previous two bits used for flags. I _think_ it \nshould have been 30 before, so we really lost 5 bits of the word but \nbecause of the off-by-one, we only lost four branches).\n\ndiff --git a/blob.c b/blob.c\nindex c1fdd86..85deccc 100644\n--- a/blob.c\n+++ b/blob.c\n@@ -10,14 +10,14 @@ struct blob *lookup_blob(const unsigned \n \tif (!obj) {\n \t\tstruct blob *ret = xcalloc(1, sizeof(struct blob));\n \t\tcreated_object(sha1, &ret->object);\n-\t\tret->object.type = blob_type;\n+\t\tret->object.type = TYPE_BLOB;\n \t\treturn ret;\n \t}\n \tif (!obj->type)\n-\t\tobj->type = blob_type;\n-\tif (obj->type != blob_type) {\n+\t\tobj->type = TYPE_BLOB;\n+\tif (obj->type != TYPE_BLOB) {\n \t\terror(\"Object %s is a %s, not a blob\", \n-\t\t      sha1_to_hex(sha1), obj->type);\n+\t\t      sha1_to_hex(sha1), typename(obj->type));\n \t\treturn NULL;\n \t}\n \treturn (struct blob *) obj;\ndiff --git a/builtin-diff.c b/builtin-diff.c\nindex 27451d5..6ac3d4b 100644\n--- a/builtin-diff.c\n+++ b/builtin-diff.c\n@@ -303,9 +303,9 @@ int cmd_diff(int argc, const char **argv\n \t\tobj = deref_tag(obj, NULL, 0);\n \t\tif (!obj)\n \t\t\tdie(\"invalid object '%s' given.\", name);\n-\t\tif (!strcmp(obj->type, commit_type))\n+\t\tif (obj->type == TYPE_COMMIT)\n \t\t\tobj = &((struct commit *)obj)->tree->object;\n-\t\tif (!strcmp(obj->type, tree_type)) {\n+\t\tif (obj->type == TYPE_TREE) {\n \t\t\tif (ARRAY_SIZE(ent) <= ents)\n \t\t\t\tdie(\"more than %d trees given: '%s'\",\n \t\t\t\t    (int) ARRAY_SIZE(ent), name);\n@@ -315,7 +315,7 @@ int cmd_diff(int argc, const char **argv\n \t\t\tents++;\n \t\t\tcontinue;\n \t\t}\n-\t\tif (!strcmp(obj->type, blob_type)) {\n+\t\tif (obj->type == TYPE_BLOB) {\n \t\t\tif (2 <= blobs)\n \t\t\t\tdie(\"more than two blobs given: '%s'\", name);\n \t\t\tmemcpy(blob[blobs].sha1, obj->sha1, 20);\ndiff --git a/builtin-grep.c b/builtin-grep.c\nindex 5fac570..9806499 100644\n--- a/builtin-grep.c\n+++ b/builtin-grep.c\n@@ -630,10 +630,9 @@ static int grep_tree(struct grep_opt *op\n static int grep_object(struct grep_opt *opt, const char **paths,\n \t\t       struct object *obj, const char *name)\n {\n-\tif (!strcmp(obj->type, blob_type))\n+\tif (obj->type == TYPE_BLOB)\n \t\treturn grep_sha1(opt, obj->sha1, name);\n-\tif (!strcmp(obj->type, commit_type) ||\n-\t    !strcmp(obj->type, tree_type)) {\n+\tif (obj->type == TYPE_COMMIT || obj->type == TYPE_TREE) {\n \t\tstruct tree_desc tree;\n \t\tvoid *data;\n \t\tint hit;\n@@ -646,7 +645,7 @@ static int grep_object(struct grep_opt *\n \t\tfree(data);\n \t\treturn hit;\n \t}\n-\tdie(\"unable to grep from object of type %s\", obj->type);\n+\tdie(\"unable to grep from object of type %s\", typename(obj->type));\n }\n \n static const char builtin_grep_usage[] =\ndiff --git a/builtin-rev-list.c b/builtin-rev-list.c\nindex e885624..2b298c4 100644\n--- a/builtin-rev-list.c\n+++ b/builtin-rev-list.c\n@@ -158,16 +158,16 @@ static void show_commit_list(struct rev_\n \t\tconst char *name = pending->name;\n \t\tif (obj->flags & (UNINTERESTING | SEEN))\n \t\t\tcontinue;\n-\t\tif (obj->type == tag_type) {\n+\t\tif (obj->type == TYPE_TAG) {\n \t\t\tobj->flags |= SEEN;\n \t\t\tp = add_object(obj, p, NULL, name);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (obj->type == tree_type) {\n+\t\tif (obj->type == TYPE_TREE) {\n \t\t\tp = process_tree((struct tree *)obj, p, NULL, name);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (obj->type == blob_type) {\n+\t\tif (obj->type == TYPE_BLOB) {\n \t\t\tp = process_blob((struct blob *)obj, p, NULL, name);\n \t\t\tcontinue;\n \t\t}\ndiff --git a/builtin-show-branch.c b/builtin-show-branch.c\nindex 2895140..cf9c071 100644\n--- a/builtin-show-branch.c\n+++ b/builtin-show-branch.c\n@@ -15,7 +15,7 @@ static const char **default_arg = NULL;\n #define UNINTERESTING\t01\n \n #define REV_SHIFT\t 2\n-#define MAX_REVS\t29 /* should not exceed bits_per_int - REV_SHIFT */\n+#define MAX_REVS\t(FLAG_BITS - REV_SHIFT) /* should not exceed bits_per_int - REV_SHIFT */\n \n static struct commit *interesting(struct commit_list *list)\n {\ndiff --git a/commit.c b/commit.c\nindex 94f470b..11fca55 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -56,10 +56,10 @@ static struct commit *check_commit(struc\n \t\t\t\t   const unsigned char *sha1,\n \t\t\t\t   int quiet)\n {\n-\tif (obj->type != commit_type) {\n+\tif (obj->type != TYPE_COMMIT) {\n \t\tif (!quiet)\n \t\t\terror(\"Object %s is a %s, not a commit\",\n-\t\t\t      sha1_to_hex(sha1), obj->type);\n+\t\t\t      sha1_to_hex(sha1), typename(obj->type));\n \t\treturn NULL;\n \t}\n \treturn (struct commit *) obj;\n@@ -86,11 +86,11 @@ struct commit *lookup_commit(const unsig\n \tif (!obj) {\n \t\tstruct commit *ret = xcalloc(1, sizeof(struct commit));\n \t\tcreated_object(sha1, &ret->object);\n-\t\tret->object.type = commit_type;\n+\t\tret->object.type = TYPE_COMMIT;\n \t\treturn ret;\n \t}\n \tif (!obj->type)\n-\t\tobj->type = commit_type;\n+\t\tobj->type = TYPE_COMMIT;\n \treturn check_commit(obj, sha1, 0);\n }\n \ndiff --git a/describe.c b/describe.c\nindex 8a9cd5d..aa3434a 100644\n--- a/describe.c\n+++ b/describe.c\n@@ -67,7 +67,7 @@ static int get_name(const char *path, co\n \t * Otherwise only annotated tags are used.\n \t */\n \tif (!strncmp(path, \"refs/tags/\", 10)) {\n-\t\tif (object->type == tag_type)\n+\t\tif (object->type == TYPE_TAG)\n \t\t\tprio = 2;\n \t\telse\n \t\t\tprio = 1;\ndiff --git a/fetch-pack.c b/fetch-pack.c\nindex 8daa93d..1d676bf 100644\n--- a/fetch-pack.c\n+++ b/fetch-pack.c\n@@ -40,7 +40,7 @@ static int rev_list_insert_ref(const cha\n {\n \tstruct object *o = deref_tag(parse_object(sha1), path, 0);\n \n-\tif (o && o->type == commit_type)\n+\tif (o && o->type == TYPE_COMMIT)\n \t\trev_list_push((struct commit *)o, SEEN);\n \n \treturn 0;\n@@ -235,14 +235,14 @@ static int mark_complete(const char *pat\n {\n \tstruct object *o = parse_object(sha1);\n \n-\twhile (o && o->type == tag_type) {\n+\twhile (o && o->type == TYPE_TAG) {\n \t\tstruct tag *t = (struct tag *) o;\n \t\tif (!t->tagged)\n \t\t\tbreak; /* broken repository */\n \t\to->flags |= COMPLETE;\n \t\to = parse_object(t->tagged->sha1);\n \t}\n-\tif (o && o->type == commit_type) {\n+\tif (o && o->type == TYPE_COMMIT) {\n \t\tstruct commit *commit = (struct commit *)o;\n \t\tcommit->object.flags |= COMPLETE;\n \t\tinsert_by_date(commit, &complete);\n@@ -336,7 +336,7 @@ static int everything_local(struct ref *\n \t\t * in sync with the other side at some time after\n \t\t * that (it is OK if we guess wrong here).\n \t\t */\n-\t\tif (o->type == commit_type) {\n+\t\tif (o->type == TYPE_COMMIT) {\n \t\t\tstruct commit *commit = (struct commit *)o;\n \t\t\tif (!cutoff || cutoff < commit->date)\n \t\t\t\tcutoff = commit->date;\n@@ -355,7 +355,7 @@ static int everything_local(struct ref *\n \t\tstruct object *o = deref_tag(lookup_object(ref->old_sha1),\n \t\t\t\t\t     NULL, 0);\n \n-\t\tif (!o || o->type != commit_type || !(o->flags & COMPLETE))\n+\t\tif (!o || o->type != TYPE_COMMIT || !(o->flags & COMPLETE))\n \t\t\tcontinue;\n \n \t\tif (!(o->flags & SEEN)) {\ndiff --git a/fetch.c b/fetch.c\nindex cf6c994..238032b 100644\n--- a/fetch.c\n+++ b/fetch.c\n@@ -118,27 +118,27 @@ static struct object_list **process_queu\n \n static int process_object(struct object *obj)\n {\n-\tif (obj->type == commit_type) {\n+\tif (obj->type == TYPE_COMMIT) {\n \t\tif (process_commit((struct commit *)obj))\n \t\t\treturn -1;\n \t\treturn 0;\n \t}\n-\tif (obj->type == tree_type) {\n+\tif (obj->type == TYPE_TREE) {\n \t\tif (process_tree((struct tree *)obj))\n \t\t\treturn -1;\n \t\treturn 0;\n \t}\n-\tif (obj->type == blob_type) {\n+\tif (obj->type == TYPE_BLOB) {\n \t\treturn 0;\n \t}\n-\tif (obj->type == tag_type) {\n+\tif (obj->type == TYPE_TAG) {\n \t\tif (process_tag((struct tag *)obj))\n \t\t\treturn -1;\n \t\treturn 0;\n \t}\n \treturn error(\"Unable to determine requirements \"\n \t\t     \"of type %s for %s\",\n-\t\t     obj->type, sha1_to_hex(obj->sha1));\n+\t\t     typename(obj->type), sha1_to_hex(obj->sha1));\n }\n \n static int process(struct object *obj)\n@@ -179,9 +179,7 @@ static int loop(void)\n \t\t */\n \t\tif (! (obj->flags & TO_SCAN)) {\n \t\t\tif (fetch(obj->sha1)) {\n-\t\t\t\treport_missing(obj->type\n-\t\t\t\t\t       ? obj->type\n-\t\t\t\t\t       : \"object\", obj->sha1);\n+\t\t\t\treport_missing(typename(obj->type), obj->sha1);\n \t\t\t\treturn -1;\n \t\t\t}\n \t\t}\ndiff --git a/fsck-objects.c b/fsck-objects.c\nindex 33ce366..99b419e 100644\n--- a/fsck-objects.c\n+++ b/fsck-objects.c\n@@ -34,7 +34,7 @@ static void objreport(struct object *obj\n                       const char *err, va_list params)\n {\n \tfprintf(stderr, \"%s in %s %s: \",\n-\t        severity, obj->type, sha1_to_hex(obj->sha1));\n+\t        severity, typename(obj->type), sha1_to_hex(obj->sha1));\n \tvfprintf(stderr, err, params);\n \tfputs(\"\\n\", stderr);\n }\n@@ -74,7 +74,7 @@ static void check_connectivity(void)\n \t\t\t\t; /* it is in pack */\n \t\t\telse\n \t\t\t\tprintf(\"missing %s %s\\n\",\n-\t\t\t\t       obj->type, sha1_to_hex(obj->sha1));\n+\t\t\t\t       typename(obj->type), sha1_to_hex(obj->sha1));\n \t\t\tcontinue;\n \t\t}\n \n@@ -87,20 +87,20 @@ static void check_connectivity(void)\n \t\t\t\t    (has_sha1_file(ref->sha1)))\n \t\t\t\t\tcontinue;\n \t\t\t\tprintf(\"broken link from %7s %s\\n\",\n-\t\t\t\t       obj->type, sha1_to_hex(obj->sha1));\n+\t\t\t\t       typename(obj->type), sha1_to_hex(obj->sha1));\n \t\t\t\tprintf(\"              to %7s %s\\n\",\n-\t\t\t\t       ref->type, sha1_to_hex(ref->sha1));\n+\t\t\t\t       typename(ref->type), sha1_to_hex(ref->sha1));\n \t\t\t}\n \t\t}\n \n \t\tif (show_unreachable && !(obj->flags & REACHABLE)) {\n \t\t\tprintf(\"unreachable %s %s\\n\",\n-\t\t\t       obj->type, sha1_to_hex(obj->sha1));\n+\t\t\t       typename(obj->type), sha1_to_hex(obj->sha1));\n \t\t\tcontinue;\n \t\t}\n \n \t\tif (!obj->used) {\n-\t\t\tprintf(\"dangling %s %s\\n\", obj->type, \n+\t\t\tprintf(\"dangling %s %s\\n\", typename(obj->type), \n \t\t\t       sha1_to_hex(obj->sha1));\n \t\t}\n \t}\n@@ -282,7 +282,7 @@ static int fsck_tag(struct tag *tag)\n \tif (!show_tags)\n \t\treturn 0;\n \n-\tprintf(\"tagged %s %s\", tagged->type, sha1_to_hex(tagged->sha1));\n+\tprintf(\"tagged %s %s\", typename(tagged->type), sha1_to_hex(tagged->sha1));\n \tprintf(\" (%s) in %s\\n\", tag->tag, sha1_to_hex(tag->object.sha1));\n \treturn 0;\n }\n@@ -295,16 +295,16 @@ static int fsck_sha1(unsigned char *sha1\n \tif (obj->flags & SEEN)\n \t\treturn 0;\n \tobj->flags |= SEEN;\n-\tif (obj->type == blob_type)\n+\tif (obj->type == TYPE_BLOB)\n \t\treturn 0;\n-\tif (obj->type == tree_type)\n+\tif (obj->type == TYPE_TREE)\n \t\treturn fsck_tree((struct tree *) obj);\n-\tif (obj->type == commit_type)\n+\tif (obj->type == TYPE_COMMIT)\n \t\treturn fsck_commit((struct commit *) obj);\n-\tif (obj->type == tag_type)\n+\tif (obj->type == TYPE_TAG)\n \t\treturn fsck_tag((struct tag *) obj);\n \t/* By now, parse_object() would've returned NULL instead. */\n-\treturn objerror(obj, \"unknown type '%s' (internal fsck error)\", obj->type);\n+\treturn objerror(obj, \"unknown type '%d' (internal fsck error)\", obj->type);\n }\n \n /*\n@@ -470,7 +470,7 @@ static int fsck_cache_tree(struct cache_\n \t\t}\n \t\tmark_reachable(obj, REACHABLE);\n \t\tobj->used = 1;\n-\t\tif (obj->type != tree_type)\n+\t\tif (obj->type != TYPE_TREE)\n \t\t\terr |= objerror(obj, \"non-tree in cache-tree\");\n \t}\n \tfor (i = 0; i < it->subtree_nr; i++)\ndiff --git a/http-push.c b/http-push.c\nindex b39b36b..599929e 100644\n--- a/http-push.c\n+++ b/http-push.c\n@@ -1773,16 +1773,16 @@ static int get_delta(struct rev_info *re\n \n \t\tif (obj->flags & (UNINTERESTING | SEEN))\n \t\t\tcontinue;\n-\t\tif (obj->type == tag_type) {\n+\t\tif (obj->type == TYPE_TAG) {\n \t\t\tobj->flags |= SEEN;\n \t\t\tp = add_object(obj, p, NULL, name);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (obj->type == tree_type) {\n+\t\tif (obj->type == TYPE_TREE) {\n \t\t\tp = process_tree((struct tree *)obj, p, NULL, name);\n \t\t\tcontinue;\n \t\t}\n-\t\tif (obj->type == blob_type) {\n+\t\tif (obj->type == TYPE_BLOB) {\n \t\t\tp = process_blob((struct blob *)obj, p, NULL, name);\n \t\t\tcontinue;\n \t\t}\n@@ -1949,12 +1949,12 @@ static int ref_newer(const unsigned char\n \t * old.  Otherwise we require --force.\n \t */\n \to = deref_tag(parse_object(old_sha1), NULL, 0);\n-\tif (!o || o->type != commit_type)\n+\tif (!o || o->type != TYPE_COMMIT)\n \t\treturn 0;\n \told = (struct commit *) o;\n \n \to = deref_tag(parse_object(new_sha1), NULL, 0);\n-\tif (!o || o->type != commit_type)\n+\tif (!o || o->type != TYPE_COMMIT)\n \t\treturn 0;\n \tnew = (struct commit *) o;\n \n@@ -2033,7 +2033,7 @@ static void add_remote_info_ref(struct r\n \tfwrite_buffer(ref_info, 1, len, buf);\n \tfree(ref_info);\n \n-\tif (o->type == tag_type) {\n+\tif (o->type == TYPE_TAG) {\n \t\to = deref_tag(o, ls->dentry_name, 0);\n \t\tif (o) {\n \t\t\tlen = strlen(ls->dentry_name) + 45;\ndiff --git a/name-rev.c b/name-rev.c\nindex bad8a53..1f0135f 100644\n--- a/name-rev.c\n+++ b/name-rev.c\n@@ -84,14 +84,14 @@ static int name_ref(const char *path, co\n \tif (tags_only && strncmp(path, \"refs/tags/\", 10))\n \t\treturn 0;\n \n-\twhile (o && o->type == tag_type) {\n+\twhile (o && o->type == TYPE_TAG) {\n \t\tstruct tag *t = (struct tag *) o;\n \t\tif (!t->tagged)\n \t\t\tbreak; /* broken repository */\n \t\to = parse_object(t->tagged->sha1);\n \t\tderef = 1;\n \t}\n-\tif (o && o->type == commit_type) {\n+\tif (o && o->type == TYPE_COMMIT) {\n \t\tstruct commit *commit = (struct commit *)o;\n \n \t\tif (!strncmp(path, \"refs/heads/\", 11))\n@@ -167,7 +167,7 @@ int main(int argc, char **argv)\n \t\t}\n \n \t\to = deref_tag(parse_object(sha1), *argv, 0);\n-\t\tif (!o || o->type != commit_type) {\n+\t\tif (!o || o->type != TYPE_COMMIT) {\n \t\t\tfprintf(stderr, \"Could not get commit for %s. Skipping.\\n\",\n \t\t\t\t\t*argv);\n \t\t\tcontinue;\ndiff --git a/object.c b/object.c\nindex 9adc874..0f70890 100644\n--- a/object.c\n+++ b/object.c\n@@ -9,6 +9,10 @@ struct object **objs;\n static int nr_objs;\n int obj_allocs;\n \n+const char *type_names[] = {\n+\t\"none\", \"blob\", \"tree\", \"commit\", \"bad\"\n+};\n+\n int track_object_refs = 0;\n \n static int hashtable_index(const unsigned char *sha1)\n@@ -50,7 +54,7 @@ void created_object(const unsigned char \n \n \tobj->parsed = 0;\n \tmemcpy(obj->sha1, sha1, 20);\n-\tobj->type = NULL;\n+\tobj->type = TYPE_NONE;\n \tobj->refs = NULL;\n \tobj->used = 0;\n \n@@ -179,7 +183,7 @@ struct object *lookup_unknown_object(con\n \tif (!obj) {\n \t\tunion any_object *ret = xcalloc(1, sizeof(*ret));\n \t\tcreated_object(sha1, &ret->object);\n-\t\tret->object.type = NULL;\n+\t\tret->object.type = TYPE_NONE;\n \t\treturn &ret->object;\n \t}\n \treturn obj;\ndiff --git a/object.h b/object.h\nindex e08afbd..a0762b6 100644\n--- a/object.h\n+++ b/object.h\n@@ -12,12 +12,22 @@ struct object_refs {\n \tstruct object *ref[FLEX_ARRAY]; /* more */\n };\n \n+#define TYPE_BITS   3\n+#define FLAG_BITS  27\n+\n+#define TYPE_NONE   0\n+#define TYPE_BLOB   1\n+#define TYPE_TREE   2\n+#define TYPE_COMMIT 3\n+#define TYPE_TAG    4\n+#define TYPE_BAD    5\n+\n struct object {\n \tunsigned parsed : 1;\n \tunsigned used : 1;\n-\tunsigned int flags;\n+\tunsigned type : TYPE_BITS;\n+\tunsigned flags : FLAG_BITS;\n \tunsigned char sha1[20];\n-\tconst char *type;\n \tstruct object_refs *refs;\n \tvoid *util;\n };\n@@ -25,6 +35,12 @@ struct object {\n extern int track_object_refs;\n extern int obj_allocs;\n extern struct object **objs;\n+extern const char *type_names[];\n+\n+static inline const char *typename(unsigned int type)\n+{\n+\treturn type_names[type > TYPE_TAG ? TYPE_BAD : type];\n+}\n \n /** Internal only **/\n struct object *lookup_object(const unsigned char *sha1);\ndiff --git a/revision.c b/revision.c\nindex 6a6952c..f4b8826 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -140,7 +140,7 @@ static struct commit *handle_commit(stru\n \t/*\n \t * Tag object? Look what it points to..\n \t */\n-\twhile (object->type == tag_type) {\n+\twhile (object->type == TYPE_TAG) {\n \t\tstruct tag *tag = (struct tag *) object;\n \t\tif (revs->tag_objects && !(flags & UNINTERESTING))\n \t\t\tadd_pending_object(revs, object, tag->tag);\n@@ -153,7 +153,7 @@ static struct commit *handle_commit(stru\n \t * Commit object? Just return it, we'll do all the complex\n \t * reachability crud.\n \t */\n-\tif (object->type == commit_type) {\n+\tif (object->type == TYPE_COMMIT) {\n \t\tstruct commit *commit = (struct commit *)object;\n \t\tif (parse_commit(commit) < 0)\n \t\t\tdie(\"unable to parse commit %s\", name);\n@@ -169,7 +169,7 @@ static struct commit *handle_commit(stru\n \t * Tree object? Either mark it uniniteresting, or add it\n \t * to the list of objects to look at later..\n \t */\n-\tif (object->type == tree_type) {\n+\tif (object->type == TYPE_TREE) {\n \t\tstruct tree *tree = (struct tree *)object;\n \t\tif (!revs->tree_objects)\n \t\t\treturn NULL;\n@@ -184,7 +184,7 @@ static struct commit *handle_commit(stru\n \t/*\n \t * Blob object? You know the drill by now..\n \t */\n-\tif (object->type == blob_type) {\n+\tif (object->type == TYPE_BLOB) {\n \t\tstruct blob *blob = (struct blob *)object;\n \t\tif (!revs->blob_objects)\n \t\t\treturn NULL;\n@@ -498,11 +498,11 @@ static int add_parents_only(struct rev_i\n \t\treturn 0;\n \twhile (1) {\n \t\tit = get_reference(revs, arg, sha1, 0);\n-\t\tif (strcmp(it->type, tag_type))\n+\t\tif (it->type != TYPE_TAG)\n \t\t\tbreak;\n \t\tmemcpy(sha1, ((struct tag*)it)->tagged->sha1, 20);\n \t}\n-\tif (strcmp(it->type, commit_type))\n+\tif (it->type != TYPE_COMMIT)\n \t\treturn 0;\n \tcommit = (struct commit *)it;\n \tfor (parents = commit->parents; parents; parents = parents->next) {\ndiff --git a/send-pack.c b/send-pack.c\nindex 409f188..af93b11 100644\n--- a/send-pack.c\n+++ b/send-pack.c\n@@ -151,12 +151,12 @@ static int ref_newer(const unsigned char\n \t * old.  Otherwise we require --force.\n \t */\n \to = deref_tag(parse_object(old_sha1), NULL, 0);\n-\tif (!o || o->type != commit_type)\n+\tif (!o || o->type != TYPE_COMMIT)\n \t\treturn 0;\n \told = (struct commit *) o;\n \n \to = deref_tag(parse_object(new_sha1), NULL, 0);\n-\tif (!o || o->type != commit_type)\n+\tif (!o || o->type != TYPE_COMMIT)\n \t\treturn 0;\n \tnew = (struct commit *) o;\n \ndiff --git a/server-info.c b/server-info.c\nindex 05bce7d..0eb5132 100644\n--- a/server-info.c\n+++ b/server-info.c\n@@ -12,7 +12,7 @@ static int add_info_ref(const char *path\n \tstruct object *o = parse_object(sha1);\n \n \tfprintf(info_ref_fp, \"%s\t%s\\n\", sha1_to_hex(sha1), path);\n-\tif (o->type == tag_type) {\n+\tif (o->type == TYPE_TAG) {\n \t\to = deref_tag(o, path, 0);\n \t\tif (o)\n \t\t\tfprintf(info_ref_fp, \"%s\t%s^{}\\n\",\ndiff --git a/sha1_name.c b/sha1_name.c\nindex fbbde1c..8463d4b 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -358,7 +358,7 @@ static int peel_onion(const char *name, \n {\n \tunsigned char outer[20];\n \tconst char *sp;\n-\tconst char *type_string = NULL;\n+\tunsigned int expected_type = 0;\n \tstruct object *o;\n \n \t/*\n@@ -382,13 +382,13 @@ static int peel_onion(const char *name, \n \n \tsp++; /* beginning of type name, or closing brace for empty */\n \tif (!strncmp(commit_type, sp, 6) && sp[6] == '}')\n-\t\ttype_string = commit_type;\n+\t\texpected_type = TYPE_COMMIT;\n \telse if (!strncmp(tree_type, sp, 4) && sp[4] == '}')\n-\t\ttype_string = tree_type;\n+\t\texpected_type = TYPE_TREE;\n \telse if (!strncmp(blob_type, sp, 4) && sp[4] == '}')\n-\t\ttype_string = blob_type;\n+\t\texpected_type = TYPE_BLOB;\n \telse if (sp[0] == '}')\n-\t\ttype_string = NULL;\n+\t\texpected_type = TYPE_NONE;\n \telse\n \t\treturn -1;\n \n@@ -398,7 +398,7 @@ static int peel_onion(const char *name, \n \to = parse_object(outer);\n \tif (!o)\n \t\treturn -1;\n-\tif (!type_string) {\n+\tif (!expected_type) {\n \t\to = deref_tag(o, name, sp - name - 2);\n \t\tif (!o || (!o->parsed && !parse_object(o->sha1)))\n \t\t\treturn -1;\n@@ -413,18 +413,18 @@ static int peel_onion(const char *name, \n \t\twhile (1) {\n \t\t\tif (!o || (!o->parsed && !parse_object(o->sha1)))\n \t\t\t\treturn -1;\n-\t\t\tif (o->type == type_string) {\n+\t\t\tif (o->type == expected_type) {\n \t\t\t\tmemcpy(sha1, o->sha1, 20);\n \t\t\t\treturn 0;\n \t\t\t}\n-\t\t\tif (o->type == tag_type)\n+\t\t\tif (o->type == TYPE_TAG)\n \t\t\t\to = ((struct tag*) o)->tagged;\n-\t\t\telse if (o->type == commit_type)\n+\t\t\telse if (o->type == TYPE_COMMIT)\n \t\t\t\to = &(((struct commit *) o)->tree->object);\n \t\t\telse\n \t\t\t\treturn error(\"%.*s: expected %s type, but the object dereferences to %s type\",\n-\t\t\t\t\t     len, name, type_string,\n-\t\t\t\t\t     o->type);\n+\t\t\t\t\t     len, name, typename(expected_type),\n+\t\t\t\t\t     typename(o->type));\n \t\t\tif (!o->parsed)\n \t\t\t\tparse_object(o->sha1);\n \t\t}\ndiff --git a/tag.c b/tag.c\nindex f390ee7..24ea6f6 100644\n--- a/tag.c\n+++ b/tag.c\n@@ -5,7 +5,7 @@ const char *tag_type = \"tag\";\n \n struct object *deref_tag(struct object *o, const char *warn, int warnlen)\n {\n-\twhile (o && o->type == tag_type)\n+\twhile (o && o->type == TYPE_TAG)\n \t\to = parse_object(((struct tag *)o)->tagged->sha1);\n \tif (!o && warn) {\n \t\tif (!warnlen)\n@@ -21,14 +21,14 @@ struct tag *lookup_tag(const unsigned ch\n         if (!obj) {\n                 struct tag *ret = xcalloc(1, sizeof(struct tag));\n                 created_object(sha1, &ret->object);\n-                ret->object.type = tag_type;\n+                ret->object.type = TYPE_TAG;\n                 return ret;\n         }\n \tif (!obj->type)\n-\t\tobj->type = tag_type;\n-        if (obj->type != tag_type) {\n+\t\tobj->type = TYPE_TAG;\n+        if (obj->type != TYPE_TAG) {\n                 error(\"Object %s is a %s, not a tree\", \n-                      sha1_to_hex(sha1), obj->type);\n+                      sha1_to_hex(sha1), typename(obj->type));\n                 return NULL;\n         }\n         return (struct tag *) obj;\ndiff --git a/tree.c b/tree.c\nindex 9bbe2da..9277715 100644\n--- a/tree.c\n+++ b/tree.c\n@@ -131,14 +131,14 @@ struct tree *lookup_tree(const unsigned \n \tif (!obj) {\n \t\tstruct tree *ret = xcalloc(1, sizeof(struct tree));\n \t\tcreated_object(sha1, &ret->object);\n-\t\tret->object.type = tree_type;\n+\t\tret->object.type = TYPE_TREE;\n \t\treturn ret;\n \t}\n \tif (!obj->type)\n-\t\tobj->type = tree_type;\n-\tif (obj->type != tree_type) {\n+\t\tobj->type = TYPE_TREE;\n+\tif (obj->type != TYPE_TREE) {\n \t\terror(\"Object %s is a %s, not a tree\", \n-\t\t      sha1_to_hex(sha1), obj->type);\n+\t\t      sha1_to_hex(sha1), typename(obj->type));\n \t\treturn NULL;\n \t}\n \treturn (struct tree *) obj;\n@@ -216,11 +216,11 @@ struct tree *parse_tree_indirect(const u\n \tdo {\n \t\tif (!obj)\n \t\t\treturn NULL;\n-\t\tif (obj->type == tree_type)\n+\t\tif (obj->type == TYPE_TREE)\n \t\t\treturn (struct tree *) obj;\n-\t\telse if (obj->type == commit_type)\n+\t\telse if (obj->type == TYPE_COMMIT)\n \t\t\tobj = &(((struct commit *) obj)->tree->object);\n-\t\telse if (obj->type == tag_type)\n+\t\telse if (obj->type == TYPE_TAG)\n \t\t\tobj = ((struct tag *) obj)->tagged;\n \t\telse\n \t\t\treturn NULL;\ndiff --git a/upload-pack.c b/upload-pack.c\nindex 47560c9..979e583 100644\n--- a/upload-pack.c\n+++ b/upload-pack.c\n@@ -105,7 +105,7 @@ static int got_sha1(char *hex, unsigned \n \t\t\to = parse_object(sha1);\n \t\tif (!o)\n \t\t\tdie(\"oops (%s)\", sha1_to_hex(sha1));\n-\t\tif (o->type == commit_type) {\n+\t\tif (o->type == TYPE_COMMIT) {\n \t\t\tstruct commit_list *parents;\n \t\t\tif (o->flags & THEY_HAVE)\n \t\t\t\treturn 0;\n@@ -234,7 +234,7 @@ static int send_ref(const char *refname,\n \t\to->flags |= OUR_REF;\n \t\tnr_our_refs++;\n \t}\n-\tif (o->type == tag_type) {\n+\tif (o->type == TYPE_TAG) {\n \t\to = deref_tag(o, refname, 0);\n \t\tpacket_write(1, \"%s %s^{}\\n\", sha1_to_hex(o->sha1), refname);\n \t}\n"},{"id":"21959","messageId":"44942176.1070107@mindspring.com","threadId":"4513","inReplyTo":"Pine.LNX.4.64.0606141630570.5498@g5.osdl.org","subject":"Re: Shrink \"struct object\" a bit","fromName":"Philip Pokorny","fromEmail":"ppokorny@mindspring.com","sentAt":"2006-06-17T15:36:22Z","receivedAt":"2006-06-17T15:36:22Z","isPatch":false,"sender":{"key":"ppokorny@mindspring.com","avatar":null},"body":"Linus Torvalds wrote:\n\n>This shrinks \"struct object\" by a small amount, by getting rid of the \n>\"struct type *\" pointer and replacing it with a 3-bit bitfield instead.\n>\n>@@ -179,9 +179,7 @@ static int loop(void)\n> \t\t */\n> \t\tif (! (obj->flags & TO_SCAN)) {\n> \t\t\tif (fetch(obj->sha1)) {\n>-\t\t\t\treport_missing(obj->type\n>-\t\t\t\t\t       ? obj->type\n>-\t\t\t\t\t       : \"object\", obj->sha1);\n>+\t\t\t\treport_missing(typename(obj->type), obj->sha1);\n> \t\t\t\treturn -1;\n> \t\t\t}\n> \t\t}\n>  \n>\n\n>diff --git a/object.c b/object.c\n>index 9adc874..0f70890 100644\n>--- a/object.c\n>+++ b/object.c\n>@@ -9,6 +9,10 @@ struct object **objs;\n> static int nr_objs;\n> int obj_allocs;\n> \n>+const char *type_names[] = {\n>+\t\"none\", \"blob\", \"tree\", \"commit\", \"bad\"\n>+};\n>+\n>  \n>\n\nA minor thing, but doesn't this mean the \"report_missing\" message would \nchange from:\n\n > Cannot obtain needed object ab12cdef1234567890abcd\n > while processing commit fedcbadeadbeefdeadbe\n\nto\n\n > Cannot obtain needed none ab12cdef1234567890abcd\n > while processing commit fedcbadeadbeefdeadbe\n\nin some cases? I'm not sure that it's possible for the type value to be \nunspecified at this point in the code, but it seemed like the output \nfrom report_missing would be confusing if this ever happened.\n\n:v)\n"},{"id":"21964","messageId":"Pine.LNX.4.64.0606171211580.5498@g5.osdl.org","threadId":"4513","inReplyTo":"44942176.1070107@mindspring.com","subject":"Re: Shrink \"struct object\" a bit","fromName":"Linus Torvalds","fromEmail":"torvalds@osdl.org","sentAt":"2006-06-17T19:13:48Z","receivedAt":"2006-06-17T19:13:48Z","isPatch":false,"sender":{"key":"torvalds@linux-foundation.org","avatar":"https://avatars.githubusercontent.com/u/1024025?v=4"},"body":"\n\nOn Sat, 17 Jun 2006, Philip Pokorny wrote:\n> \n> A minor thing, but doesn't this mean the \"report_missing\" message would change\n> from:\n> \n> > Cannot obtain needed object ab12cdef1234567890abcd\n> > while processing commit fedcbadeadbeefdeadbe\n> \n> to\n> \n> > Cannot obtain needed none ab12cdef1234567890abcd\n> > while processing commit fedcbadeadbeefdeadbe\n\nYeah. I guess you could either just keep the old conditional, or just \nchange the object type-name for the unspecified mode 0 to something like \n\"untyped object\" which would cause a much more readable errors.\n\n\t\tLinus\n"}]}