-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Doubly-linked lists for CFG layouts #1124
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The use of
Obj.magic 0
is slightly better than a dummy instruction. Just to confirm , the use of '0' here will result in a tagged (immediate) value stored in thevalue
field, right? is_dummy_node
will be fine with marshal/unmarshal because the self-loop is a "local" check, but we will end up with more than one "dummy" node in this scenario. I think it is possible in this scenario after a few add/remove operations to have an empty ist in which first and last are not the same or first.prev and last.prev not pointinng to the same node. I think it's fine and we don't rely on it anywhere at the moment. Maybe worth a comment?- The generic new doubly link list module doesn't need to live inside
Cfg
. It would be nice to split it out in a follow-up PR.cfg.ml
is getting too long.
I would really prefer if we could avoid using |
Both ? My point is that using |
I don't really agree that you should have to write a version without module Node : sig
type 'a t
module Neighbour : sig
type 'a node := 'a t
type 'a t
val is_dummy : 'a t -> bool
val get : 'a t -> 'a node
end
val prev : 'a t -> 'a Neighbour.t
val next : 'a t -> 'a Neighbour.t
val value : 'a t -> 'a
end = struct
type 'a t =
{ value : 'a;
mutable prev : Obj.t t;
mutable next : Obj.t t
}
let rec dummy_node =
{ value = Obj.repr 0; prev = dummy_node; next = dummy_node }
module Neighbour = struct
let is_dummy t = t == t.next
let get t =
if is_dummy t then raise Not_found
else (Obj.magic (t : Obj.t t) : 'a t)
type nonrec 'a t = Obj.t t
end
let prev t = t.prev
let next t = t.next
let value t = t.value
end |
I don't see why we need the |
That seems fine too. My objections were to the automatic rejection of using |
The types stored in this doubly-linked list are instructions and labels, which don't have an obvious dummy value. The previous version used id |
I still think that every use of unsafe functions from
|
Using an id of |
And for labels, you can create a first label at tolevel (for instance using |
I got confused and mistakenly pushed another version |
Additionally, except if I missed something, you never actually read/use the [1] in some cases it's useful/needed to require such a dummy value to be different (either physically or through a compare/equal function) from all other "normal" values, but in the cas of doubly linked list, I could not find a place in the code where that would be needed. |
My understanding is that we will: apply Leo's suggestion, |
sounds good to me. @Gbury would it be okay with you to continue this discussion on a separate PR? |
Did you run any benchs/tests to have some idea of the performance improvements regarding time and/or allocations (even rough percentages) ? Using |
So, I actually went ahead and modified the implementation of doubly-linked lists to not use |
@Gbury |
@gretay-js I don't see to what indirection you're referring to. #1145 uses an inline record for nodes, which means that the memory layout of a node with it is exactly the same as with this PR, with the only difference begin that pointers to the dummy node are replaced by a tagged integer( for the |
Indeed, I missed it! That's great, thank you. |
This pull request does two things:
instruction lists so that we can have doubly-linked
list of any type;