5 int track_object_refs
= 0;
7 static struct decoration ref_decorate
;
9 struct object_refs
*lookup_object_refs(struct object
*base
)
11 return lookup_decoration(&ref_decorate
, base
);
14 static void add_object_refs(struct object
*obj
, struct object_refs
*refs
)
16 if (add_decoration(&ref_decorate
, obj
, refs
))
17 die("object %s tried to add refs twice!", sha1_to_hex(obj
->sha1
));
20 struct object_refs
*alloc_object_refs(unsigned count
)
22 struct object_refs
*refs
;
23 size_t size
= sizeof(*refs
) + count
*sizeof(struct object
*);
25 refs
= xcalloc(1, size
);
30 static int compare_object_pointers(const void *a
, const void *b
)
32 const struct object
* const *pa
= a
;
33 const struct object
* const *pb
= b
;
42 void set_object_refs(struct object
*obj
, struct object_refs
*refs
)
46 /* Do not install empty list of references */
47 if (refs
->count
< 1) {
52 /* Sort the list and filter out duplicates */
53 qsort(refs
->ref
, refs
->count
, sizeof(refs
->ref
[0]),
54 compare_object_pointers
);
55 for (i
= j
= 1; i
< refs
->count
; i
++) {
56 if (refs
->ref
[i
] != refs
->ref
[i
- 1])
57 refs
->ref
[j
++] = refs
->ref
[i
];
59 if (j
< refs
->count
) {
60 /* Duplicates were found - reallocate list */
61 size_t size
= sizeof(*refs
) + j
*sizeof(struct object
*);
63 refs
= xrealloc(refs
, size
);
66 for (i
= 0; i
< refs
->count
; i
++)
67 refs
->ref
[i
]->used
= 1;
68 add_object_refs(obj
, refs
);
71 void mark_reachable(struct object
*obj
, unsigned int mask
)
73 const struct object_refs
*refs
;
75 if (!track_object_refs
)
76 die("cannot do reachability with object refs turned off");
77 /* If we've been here already, don't bother */
78 if (obj
->flags
& mask
)
81 refs
= lookup_object_refs(obj
);
84 for (i
= 0; i
< refs
->count
; i
++)
85 mark_reachable(refs
->ref
[i
], mask
);