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 grow_refs_hash(void)
18 int new_hash_size
= (refs_hash_size
+ 1000) * 3 / 2;
19 struct object_refs
**new_hash
;
21 new_hash
= calloc(new_hash_size
, sizeof(struct object_refs
*));
22 for (i
= 0; i
< refs_hash_size
; i
++) {
24 struct object_refs
*ref
= refs_hash
[i
];
27 j
= hash_obj(ref
->base
, new_hash_size
);
32 refs_hash_size
= new_hash_size
;
35 static void insert_ref_hash(struct object_refs
*ref
)
37 int j
= hash_obj(ref
->base
, refs_hash_size
);
39 while (refs_hash
[j
]) {
41 if (j
>= refs_hash_size
)
47 static void add_object_refs(struct object
*obj
, struct object_refs
*ref
)
49 int nr
= nr_object_refs
+ 1;
51 if (nr
> refs_hash_size
* 2 / 3)
58 struct object_refs
*lookup_object_refs(struct object
*obj
)
60 int j
= hash_obj(obj
, refs_hash_size
);
61 struct object_refs
*ref
;
63 while ((ref
= refs_hash
[j
]) != NULL
) {
67 if (j
>= refs_hash_size
)
73 struct object_refs
*alloc_object_refs(unsigned count
)
75 struct object_refs
*refs
;
76 size_t size
= sizeof(*refs
) + count
*sizeof(struct object
*);
78 refs
= xcalloc(1, size
);
83 static int compare_object_pointers(const void *a
, const void *b
)
85 const struct object
* const *pa
= a
;
86 const struct object
* const *pb
= b
;
95 void set_object_refs(struct object
*obj
, struct object_refs
*refs
)
99 /* Do not install empty list of references */
100 if (refs
->count
< 1) {
105 /* Sort the list and filter out duplicates */
106 qsort(refs
->ref
, refs
->count
, sizeof(refs
->ref
[0]),
107 compare_object_pointers
);
108 for (i
= j
= 1; i
< refs
->count
; i
++) {
109 if (refs
->ref
[i
] != refs
->ref
[i
- 1])
110 refs
->ref
[j
++] = refs
->ref
[i
];
112 if (j
< refs
->count
) {
113 /* Duplicates were found - reallocate list */
114 size_t size
= sizeof(*refs
) + j
*sizeof(struct object
*);
116 refs
= xrealloc(refs
, size
);
119 for (i
= 0; i
< refs
->count
; i
++)
120 refs
->ref
[i
]->used
= 1;
121 add_object_refs(obj
, refs
);
124 void mark_reachable(struct object
*obj
, unsigned int mask
)
126 const struct object_refs
*refs
;
128 if (!track_object_refs
)
129 die("cannot do reachability with object refs turned off");
130 /* If we've been here already, don't bother */
131 if (obj
->flags
& mask
)
134 refs
= lookup_object_refs(obj
);
137 for (i
= 0; i
< refs
->count
; i
++)
138 mark_reachable(refs
->ref
[i
], mask
);