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
= calloc(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 int j
= hash_obj(obj
, refs_hash_size
);
59 struct object_refs
*ref
;
61 while ((ref
= refs_hash
[j
]) != NULL
) {
65 if (j
>= refs_hash_size
)
71 struct object_refs
*alloc_object_refs(unsigned count
)
73 struct object_refs
*refs
;
74 size_t size
= sizeof(*refs
) + count
*sizeof(struct object
*);
76 refs
= xcalloc(1, size
);
81 static int compare_object_pointers(const void *a
, const void *b
)
83 const struct object
* const *pa
= a
;
84 const struct object
* const *pb
= b
;
93 void set_object_refs(struct object
*obj
, struct object_refs
*refs
)
97 /* Do not install empty list of references */
98 if (refs
->count
< 1) {
103 /* Sort the list and filter out duplicates */
104 qsort(refs
->ref
, refs
->count
, sizeof(refs
->ref
[0]),
105 compare_object_pointers
);
106 for (i
= j
= 1; i
< refs
->count
; i
++) {
107 if (refs
->ref
[i
] != refs
->ref
[i
- 1])
108 refs
->ref
[j
++] = refs
->ref
[i
];
110 if (j
< refs
->count
) {
111 /* Duplicates were found - reallocate list */
112 size_t size
= sizeof(*refs
) + j
*sizeof(struct object
*);
114 refs
= xrealloc(refs
, size
);
117 for (i
= 0; i
< refs
->count
; i
++)
118 refs
->ref
[i
]->used
= 1;
119 add_object_refs(obj
, refs
);
122 void mark_reachable(struct object
*obj
, unsigned int mask
)
124 const struct object_refs
*refs
;
126 if (!track_object_refs
)
127 die("cannot do reachability with object refs turned off");
128 /* nothing to lookup */
131 /* If we've been here already, don't bother */
132 if (obj
->flags
& mask
)
135 refs
= lookup_object_refs(obj
);
138 for (i
= 0; i
< refs
->count
; i
++)
139 mark_reachable(refs
->ref
[i
], mask
);