Skip to content

Commit fd9b1ba

Browse files
pcloudsgitster
authored andcommitted
pack-objects: turn type and in_pack_type to bitfields
An extra field type_valid is added to carry the equivalent of OBJ_BAD in the original "type" field. in_pack_type always contains a valid type so we only need 3 bits for it. A note about accepting OBJ_NONE as "valid" type. The function read_object_list_from_stdin() can pass this value [1] and it eventually calls create_object_entry() where current code skip setting "type" field if the incoming type is zero. This does not have any bad side effects because "type" field should be memset()'d anyway. But since we also need to set type_valid now, skipping oe_set_type() leaves type_valid zero/false, which will make oe_type() return OBJ_BAD, not OBJ_NONE anymore. Apparently we do care about OBJ_NONE in prepare_pack(). This switch from OBJ_NONE to OBJ_BAD may trigger fatal: unable to get type of object ... Accepting OBJ_NONE [2] does sound wrong, but this is how it is has been for a very long time and I haven't time to dig in further. [1] See 5c49c11 (pack-objects: better check_object() performances - 2007-04-16) [2] 21666f1 (convert object type handling from a string to a number - 2007-02-26) Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8d6ccce commit fd9b1ba

File tree

5 files changed

+58
-30
lines changed

5 files changed

+58
-30
lines changed

builtin/pack-objects.c

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ static unsigned long write_no_reuse_object(struct hashfile *f, struct object_ent
266266
struct git_istream *st = NULL;
267267

268268
if (!usable_delta) {
269-
if (entry->type == OBJ_BLOB &&
269+
if (oe_type(entry) == OBJ_BLOB &&
270270
entry->size > big_file_threshold &&
271271
(st = open_istream(&entry->idx.oid, &type, &size, NULL)) != NULL)
272272
buf = NULL;
@@ -371,7 +371,7 @@ static off_t write_reuse_object(struct hashfile *f, struct object_entry *entry,
371371
struct pack_window *w_curs = NULL;
372372
struct revindex_entry *revidx;
373373
off_t offset;
374-
enum object_type type = entry->type;
374+
enum object_type type = oe_type(entry);
375375
off_t datalen;
376376
unsigned char header[MAX_PACK_OBJECT_HEADER],
377377
dheader[MAX_PACK_OBJECT_HEADER];
@@ -480,11 +480,12 @@ static off_t write_object(struct hashfile *f,
480480
to_reuse = 0; /* explicit */
481481
else if (!entry->in_pack)
482482
to_reuse = 0; /* can't reuse what we don't have */
483-
else if (entry->type == OBJ_REF_DELTA || entry->type == OBJ_OFS_DELTA)
483+
else if (oe_type(entry) == OBJ_REF_DELTA ||
484+
oe_type(entry) == OBJ_OFS_DELTA)
484485
/* check_object() decided it for us ... */
485486
to_reuse = usable_delta;
486487
/* ... but pack split may override that */
487-
else if (entry->type != entry->in_pack_type)
488+
else if (oe_type(entry) != entry->in_pack_type)
488489
to_reuse = 0; /* pack has delta which is unusable */
489490
else if (entry->delta)
490491
to_reuse = 0; /* we want to pack afresh */
@@ -705,8 +706,8 @@ static struct object_entry **compute_write_order(void)
705706
* And then all remaining commits and tags.
706707
*/
707708
for (i = last_untagged; i < to_pack.nr_objects; i++) {
708-
if (objects[i].type != OBJ_COMMIT &&
709-
objects[i].type != OBJ_TAG)
709+
if (oe_type(&objects[i]) != OBJ_COMMIT &&
710+
oe_type(&objects[i]) != OBJ_TAG)
710711
continue;
711712
add_to_write_order(wo, &wo_end, &objects[i]);
712713
}
@@ -715,7 +716,7 @@ static struct object_entry **compute_write_order(void)
715716
* And then all the trees.
716717
*/
717718
for (i = last_untagged; i < to_pack.nr_objects; i++) {
718-
if (objects[i].type != OBJ_TREE)
719+
if (oe_type(&objects[i]) != OBJ_TREE)
719720
continue;
720721
add_to_write_order(wo, &wo_end, &objects[i]);
721722
}
@@ -1066,8 +1067,7 @@ static void create_object_entry(const struct object_id *oid,
10661067

10671068
entry = packlist_alloc(&to_pack, oid->hash, index_pos);
10681069
entry->hash = hash;
1069-
if (type)
1070-
entry->type = type;
1070+
oe_set_type(entry, type);
10711071
if (exclude)
10721072
entry->preferred_base = 1;
10731073
else
@@ -1407,6 +1407,7 @@ static void check_object(struct object_entry *entry)
14071407
unsigned long avail;
14081408
off_t ofs;
14091409
unsigned char *buf, c;
1410+
enum object_type type;
14101411

14111412
buf = use_pack(p, &w_curs, entry->in_pack_offset, &avail);
14121413

@@ -1415,11 +1416,15 @@ static void check_object(struct object_entry *entry)
14151416
* since non-delta representations could still be reused.
14161417
*/
14171418
used = unpack_object_header_buffer(buf, avail,
1418-
&entry->in_pack_type,
1419+
&type,
14191420
&entry->size);
14201421
if (used == 0)
14211422
goto give_up;
14221423

1424+
if (type < 0)
1425+
BUG("invalid type %d", type);
1426+
entry->in_pack_type = type;
1427+
14231428
/*
14241429
* Determine if this is a delta and if so whether we can
14251430
* reuse it or not. Otherwise let's find out as cheaply as
@@ -1428,9 +1433,9 @@ static void check_object(struct object_entry *entry)
14281433
switch (entry->in_pack_type) {
14291434
default:
14301435
/* Not a delta hence we've already got all we need. */
1431-
entry->type = entry->in_pack_type;
1436+
oe_set_type(entry, entry->in_pack_type);
14321437
entry->in_pack_header_size = used;
1433-
if (entry->type < OBJ_COMMIT || entry->type > OBJ_BLOB)
1438+
if (oe_type(entry) < OBJ_COMMIT || oe_type(entry) > OBJ_BLOB)
14341439
goto give_up;
14351440
unuse_pack(&w_curs);
14361441
return;
@@ -1484,7 +1489,7 @@ static void check_object(struct object_entry *entry)
14841489
* deltify other objects against, in order to avoid
14851490
* circular deltas.
14861491
*/
1487-
entry->type = entry->in_pack_type;
1492+
oe_set_type(entry, entry->in_pack_type);
14881493
entry->delta = base_entry;
14891494
entry->delta_size = entry->size;
14901495
entry->delta_sibling = base_entry->delta_child;
@@ -1493,7 +1498,7 @@ static void check_object(struct object_entry *entry)
14931498
return;
14941499
}
14951500

1496-
if (entry->type) {
1501+
if (oe_type(entry)) {
14971502
/*
14981503
* This must be a delta and we already know what the
14991504
* final object type is. Let's extract the actual
@@ -1516,7 +1521,7 @@ static void check_object(struct object_entry *entry)
15161521
unuse_pack(&w_curs);
15171522
}
15181523

1519-
entry->type = oid_object_info(&entry->idx.oid, &entry->size);
1524+
oe_set_type(entry, oid_object_info(&entry->idx.oid, &entry->size));
15201525
/*
15211526
* The error condition is checked in prepare_pack(). This is
15221527
* to permit a missing preferred base object to be ignored
@@ -1559,6 +1564,7 @@ static void drop_reused_delta(struct object_entry *entry)
15591564
{
15601565
struct object_entry **p = &entry->delta->delta_child;
15611566
struct object_info oi = OBJECT_INFO_INIT;
1567+
enum object_type type;
15621568

15631569
while (*p) {
15641570
if (*p == entry)
@@ -1570,15 +1576,18 @@ static void drop_reused_delta(struct object_entry *entry)
15701576
entry->depth = 0;
15711577

15721578
oi.sizep = &entry->size;
1573-
oi.typep = &entry->type;
1579+
oi.typep = &type;
15741580
if (packed_object_info(entry->in_pack, entry->in_pack_offset, &oi) < 0) {
15751581
/*
15761582
* We failed to get the info from this pack for some reason;
15771583
* fall back to sha1_object_info, which may find another copy.
1578-
* And if that fails, the error will be recorded in entry->type
1584+
* And if that fails, the error will be recorded in oe_type(entry)
15791585
* and dealt with in prepare_pack().
15801586
*/
1581-
entry->type = oid_object_info(&entry->idx.oid, &entry->size);
1587+
oe_set_type(entry, oid_object_info(&entry->idx.oid,
1588+
&entry->size));
1589+
} else {
1590+
oe_set_type(entry, type);
15821591
}
15831592
}
15841593

@@ -1746,10 +1755,12 @@ static int type_size_sort(const void *_a, const void *_b)
17461755
{
17471756
const struct object_entry *a = *(struct object_entry **)_a;
17481757
const struct object_entry *b = *(struct object_entry **)_b;
1758+
enum object_type a_type = oe_type(a);
1759+
enum object_type b_type = oe_type(b);
17491760

1750-
if (a->type > b->type)
1761+
if (a_type > b_type)
17511762
return -1;
1752-
if (a->type < b->type)
1763+
if (a_type < b_type)
17531764
return 1;
17541765
if (a->hash > b->hash)
17551766
return -1;
@@ -1825,7 +1836,7 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
18251836
void *delta_buf;
18261837

18271838
/* Don't bother doing diffs between different types */
1828-
if (trg_entry->type != src_entry->type)
1839+
if (oe_type(trg_entry) != oe_type(src_entry))
18291840
return -1;
18301841

18311842
/*
@@ -2429,11 +2440,11 @@ static void prepare_pack(int window, int depth)
24292440

24302441
if (!entry->preferred_base) {
24312442
nr_deltas++;
2432-
if (entry->type < 0)
2443+
if (oe_type(entry) < 0)
24332444
die("unable to get type of object %s",
24342445
oid_to_hex(&entry->idx.oid));
24352446
} else {
2436-
if (entry->type < 0) {
2447+
if (oe_type(entry) < 0) {
24372448
/*
24382449
* This object is not found, but we
24392450
* don't have to include it anyway.
@@ -2542,7 +2553,7 @@ static void read_object_list_from_stdin(void)
25422553
die("expected object ID, got garbage:\n %s", line);
25432554

25442555
add_preferred_base_object(p + 1);
2545-
add_object_entry(&oid, 0, p + 1, 0);
2556+
add_object_entry(&oid, OBJ_NONE, p + 1, 0);
25462557
}
25472558
}
25482559

cache.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,8 @@ extern void free_name_hash(struct index_state *istate);
373373
#define read_blob_data_from_cache(path, sz) read_blob_data_from_index(&the_index, (path), (sz))
374374
#endif
375375

376+
#define TYPE_BITS 3
377+
376378
enum object_type {
377379
OBJ_BAD = -1,
378380
OBJ_NONE = 0,

object.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ struct object_array {
2525

2626
#define OBJECT_ARRAY_INIT { 0, 0, NULL }
2727

28-
#define TYPE_BITS 3
2928
/*
3029
* object flag allocation:
3130
* revision.h: 0---------10 26

pack-bitmap-write.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ void bitmap_writer_build_type_index(struct pack_idx_entry **index,
6464

6565
entry->in_pack_pos = i;
6666

67-
switch (entry->type) {
67+
switch (oe_type(entry)) {
6868
case OBJ_COMMIT:
6969
case OBJ_TREE:
7070
case OBJ_BLOB:
7171
case OBJ_TAG:
72-
real_type = entry->type;
72+
real_type = oe_type(entry);
7373
break;
7474

7575
default:
@@ -97,7 +97,7 @@ void bitmap_writer_build_type_index(struct pack_idx_entry **index,
9797
default:
9898
die("Missing type information for %s (%d/%d)",
9999
oid_to_hex(&entry->idx.oid), real_type,
100-
entry->type);
100+
oe_type(entry));
101101
}
102102
}
103103
}

pack-objects.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ struct object_entry {
5959
void *delta_data; /* cached delta (uncompressed) */
6060
unsigned long delta_size; /* delta data size (uncompressed) */
6161
unsigned long z_delta_size; /* delta data size (compressed) */
62-
enum object_type type;
63-
enum object_type in_pack_type; /* could be delta */
62+
unsigned type_:TYPE_BITS;
63+
unsigned in_pack_type:TYPE_BITS; /* could be delta */
64+
unsigned type_valid:1;
6465
uint32_t hash; /* name hint hash */
6566
unsigned int in_pack_pos;
6667
unsigned char in_pack_header_size;
@@ -123,4 +124,19 @@ static inline uint32_t pack_name_hash(const char *name)
123124
return hash;
124125
}
125126

127+
static inline enum object_type oe_type(const struct object_entry *e)
128+
{
129+
return e->type_valid ? e->type_ : OBJ_BAD;
130+
}
131+
132+
static inline void oe_set_type(struct object_entry *e,
133+
enum object_type type)
134+
{
135+
if (type >= OBJ_ANY)
136+
BUG("OBJ_ANY cannot be set in pack-objects code");
137+
138+
e->type_valid = type >= OBJ_NONE;
139+
e->type_ = (unsigned)type;
140+
}
141+
126142
#endif

0 commit comments

Comments
 (0)