4 int track_object_refs
= 0;
6 static unsigned int refs_hash_size
, nr_object_refs
;
7 static struct object_refs
**refs_hash
;
9 static unsigned int hash_obj(struct object
*obj
, unsigned int n
)
11 unsigned int hash
= *(unsigned int *)obj
->sha1
;
15 static void insert_ref_hash(struct object_refs
*ref
, struct object_refs
**hash
, unsigned int size
)
17 int j
= hash_obj(ref
->base
, size
);
27 static void grow_refs_hash(void)
30 int new_hash_size
= (refs_hash_size
+ 1000) * 3 / 2;
31 struct object_refs
**new_hash
;
33 new_hash
= xcalloc(new_hash_size
, sizeof(struct object_refs
*));
34 for (i
= 0; i
< refs_hash_size
; i
++) {
35 struct object_refs
*ref
= refs_hash
[i
];
38 insert_ref_hash(ref
, new_hash
, new_hash_size
);
42 refs_hash_size
= new_hash_size
;
45 static void add_object_refs(struct object
*obj
, struct object_refs
*ref
)
47 int nr
= nr_object_refs
+ 1;
49 if (nr
> refs_hash_size
* 2 / 3)
52 insert_ref_hash(ref
, refs_hash
, refs_hash_size
);
56 struct object_refs
*lookup_object_refs(struct object
*obj
)
58 struct object_refs
*ref
;
61 /* nothing to lookup */
64 j
= hash_obj(obj
, refs_hash_size
);
65 while ((ref
= refs_hash
[j
]) != NULL
) {
69 if (j
>= refs_hash_size
)
75 struct object_refs
*alloc_object_refs(unsigned count
)
77 struct object_refs
*refs
;
78 size_t size
= sizeof(*refs
) + count
*sizeof(struct object
*);
80 refs
= xcalloc(1, size
);
85 static int compare_object_pointers(const void *a
, const void *b
)
87 const struct object
* const *pa
= a
;
88 const struct object
* const *pb
= b
;
97 void set_object_refs(struct object
*obj
, struct object_refs
*refs
)
101 /* Do not install empty list of references */
102 if (refs
->count
< 1) {
107 /* Sort the list and filter out duplicates */
108 qsort(refs
->ref
, refs
->count
, sizeof(refs
->ref
[0]),
109 compare_object_pointers
);
110 for (i
= j
= 1; i
< refs
->count
; i
++) {
111 if (refs
->ref
[i
] != refs
->ref
[i
- 1])
112 refs
->ref
[j
++] = refs
->ref
[i
];
114 if (j
< refs
->count
) {
115 /* Duplicates were found - reallocate list */
116 size_t size
= sizeof(*refs
) + j
*sizeof(struct object
*);
118 refs
= xrealloc(refs
, size
);
121 for (i
= 0; i
< refs
->count
; i
++)
122 refs
->ref
[i
]->used
= 1;
123 add_object_refs(obj
, refs
);
126 void mark_reachable(struct object
*obj
, unsigned int mask
)
128 const struct object_refs
*refs
;
130 if (!track_object_refs
)
131 die("cannot do reachability with object refs turned off");
132 /* If we've been here already, don't bother */
133 if (obj
->flags
& mask
)
136 refs
= lookup_object_refs(obj
);
139 for (i
= 0; i
< refs
->count
; i
++)
140 mark_reachable(refs
->ref
[i
], mask
);