|
12 | 12 | val is_main: t -> bool |
13 | 13 | val is_unique: t -> bool |
14 | 14 |
|
15 | | - (** Overapproximates whether the first TID can be involved in the creation fo the second TID*) |
16 | | - val may_create: t -> t -> bool |
| 15 | + (** Overapproximates whether the first TID can be involved in the creation of the second TID*) |
| 16 | + val may_be_ancestor: t -> t -> bool |
17 | 17 |
|
18 | | - (** Is the first TID a must parent of the second thread. Always false if the first TID is not unique *) |
19 | | - val is_must_parent: t -> t -> bool |
| 18 | + (** Is the first TID a must ancestor of the second thread. Always false if the first TID is not unique *) |
| 19 | + val must_be_ancestor: t -> t -> bool |
20 | 20 | end |
21 | 21 |
|
22 | 22 | module type Stateless = |
|
87 | 87 | | _ -> false |
88 | 88 |
|
89 | 89 | let is_unique = is_main |
90 | | - let may_create _ _ = true |
91 | | - let is_must_parent _ _ = false |
| 90 | + let may_be_ancestor _ _ = true |
| 91 | + let must_be_ancestor _ _ = false |
92 | 92 | end |
93 | 93 |
|
94 | 94 |
|
@@ -140,18 +140,34 @@ struct |
140 | 140 | let is_unique (_, s) = |
141 | 141 | S.is_empty s |
142 | 142 |
|
143 | | - let is_must_parent (p,s) (p',s') = |
144 | | - if not (S.is_empty s) then |
| 143 | + let must_be_ancestor ((p, s) as t) ((p', s') as t') = |
| 144 | + if not (is_unique t) then |
145 | 145 | false |
146 | | - else if P.equal p' p && S.is_empty s' then (* s is already empty *) |
147 | | - (* We do not consider a thread its own parent *) |
148 | | - false |
149 | | - else |
150 | | - let cdef_ancestor = P.common_suffix p p' in |
151 | | - P.equal p cdef_ancestor |
| 146 | + else if is_unique t' && P.equal p p' then (* t is already unique, so no need to compare sets *) |
| 147 | + false (* thread is not its own parent *) |
| 148 | + else ( (* t is already unique, so no need to check sets *) |
| 149 | + match GobList.remove_common_prefix Base.equal (List.rev p) (List.rev p') with (* prefixes are stored reversed *) |
| 150 | + | [], _ -> true (* p is prefix of p' *) |
| 151 | + | _ :: _, _ -> false |
| 152 | + ) |
152 | 153 |
|
153 | | - let may_create (p,s) (p',s') = |
154 | | - S.subset (S.union (S.of_list p) s) (S.union (S.of_list p') s') |
| 154 | + let may_be_ancestor ((p, s) as t) ((p', s') as t') = |
| 155 | + if is_unique t' then |
| 156 | + must_be_ancestor t t' (* unique must be created by something unique (that's a prefix) *) |
| 157 | + else ( (* t' is already non-unique (but doesn't matter) *) |
| 158 | + match GobList.remove_common_prefix Base.equal (List.rev p) (List.rev p') with (* prefixes are stored reversed *) |
| 159 | + | [], dp when is_unique t -> (* p is prefix of p' *) |
| 160 | + (* dp = elements added to prefix (reversed, but doesn't matter) *) |
| 161 | + true (* all elements are contained: p is prefix of p' and s is empty (due to uniqueness) *) |
| 162 | + | dp', [] -> (* p' is prefix of p *) |
| 163 | + (* dp' = elements removed from prefix (reversed, but doesn't matter) *) |
| 164 | + S.subset (S.of_list dp') s' && (* removed elements become part of set, must be contained, because compose can only add them *) |
| 165 | + S.subset s s' (* set elements must be contained, because compose can only add them *) |
| 166 | + | [], _ :: _ -> (* p is strict prefix of p' and t is non-unique *) |
| 167 | + false (* composing to non-unique cannot lengthen prefix *) |
| 168 | + | _ :: _, _ :: _ -> (* prefixes are incompatible *) |
| 169 | + false (* composing cannot fix incompatibility there *) |
| 170 | + ) |
155 | 171 |
|
156 | 172 | let compose ((p, s) as current) ni = |
157 | 173 | if BatList.mem_cmp Base.compare ni p then ( |
@@ -242,8 +258,8 @@ struct |
242 | 258 |
|
243 | 259 | let is_main = unop H.is_main P.is_main |
244 | 260 | let is_unique = unop H.is_unique P.is_unique |
245 | | - let may_create = binop H.may_create P.may_create |
246 | | - let is_must_parent = binop H.is_must_parent P.is_must_parent |
| 261 | + let may_be_ancestor = binop H.may_be_ancestor P.may_be_ancestor |
| 262 | + let must_be_ancestor = binop H.must_be_ancestor P.must_be_ancestor |
247 | 263 |
|
248 | 264 | let created x d = |
249 | 265 | let lifth x' d' = |
@@ -339,14 +355,14 @@ struct |
339 | 355 | | Thread tid -> FlagConfiguredTID.is_unique tid |
340 | 356 | | UnknownThread -> false |
341 | 357 |
|
342 | | - let may_create t1 t2 = |
| 358 | + let may_be_ancestor t1 t2 = |
343 | 359 | match t1, t2 with |
344 | | - | Thread tid1, Thread tid2 -> FlagConfiguredTID.may_create tid1 tid2 |
| 360 | + | Thread tid1, Thread tid2 -> FlagConfiguredTID.may_be_ancestor tid1 tid2 |
345 | 361 | | _, _ -> true |
346 | 362 |
|
347 | | - let is_must_parent t1 t2 = |
| 363 | + let must_be_ancestor t1 t2 = |
348 | 364 | match t1, t2 with |
349 | | - | Thread tid1, Thread tid2 -> FlagConfiguredTID.is_must_parent tid1 tid2 |
| 365 | + | Thread tid1, Thread tid2 -> FlagConfiguredTID.must_be_ancestor tid1 tid2 |
350 | 366 | | _, _ -> false |
351 | 367 |
|
352 | 368 | module D = FlagConfiguredTID.D |
|
0 commit comments