freenode/#sicl - IRC Chatlog
Search
6:11:46
beach
Now, I have to be careful. That transformation will work now, because the dynamic environment is not managed by side effects. But the day I want to use side effects, I must change the way I determine when to pop the environment.
6:11:47
beach
Currently, the idea is to keep a stack of lexical variables holding dynamic environments, and when an instruction has a successor that is not in the same dynamic environment, I would emit a certain number of POPs. I must make sure that no POP is emitted when the top environment variable was assigned to.
6:14:30
beach
So I guess an entry in the stack would not be a single lexical variable, but a list of lexical variables. When a dynamic-environment variable is merely assigned to, I would then just add the output variable to the topmost entry.
6:21:32
beach
Bike: Is this where Clasp just doesn't care, and does not free the entries when they are unused?
6:22:29
Bike
clasp does not have dynamic environments or entries. the later phases of translation ignore the dynamic-environment hir data.
6:24:37
Bike
i don't know what you mean by the scare quotes... clasp uses call-with-variable-bound right now.
6:26:42
Bike
well we don't, right now. i haven't incorporated cleavir2 into clasp since you're still working on it.
6:29:42
Bike
to sum up, every function in the runtime, like the actual machine code, has an exception table nearby. the unwinder function consults the tables for each frame. the table has a map of instruction pointers to "landing pads", which are other instruction pointers in the same function. The unwinder looks up the landing pad for the return address associated with that frame, finds the landing pad, and jumps to it.
6:31:10
beach
So does that imply that Clasp must have a function invocation for each "entry" in the dynamic environment?
6:32:34
Bike
we additionally attach an integer code to each possible return point. like, if a function has two (block ...)s in it, one will be 0 and one will be 1, and the associated return-froms get that ID from the code generator and pass it to the unwinder.
6:33:26
Bike
it's the C++ "zero cost" system, except we've progressively warped it away from C++ since C++ has several aspects that are inconvenient
6:33:59
Bike
"zero cost" in the sense that entering a block is supposed to not incur any runtime cost
6:35:29
beach
Presumably you then give up some things, like checking whether an exit point has been "abandoned"?
6:36:25
Bike
yeah, I don't think we do that right now... honestly i'm still not sure I understand those rules entirely
6:37:22
beach
In fact, your current system may make it hard to implement UNWIND-PROTECT in the first place.
6:38:41
Bike
i have been thinking about it. the landing pad code is allowed to resume unwinding rather than just transferring control, which i think should be enough
6:42:20
Bike
mm, i think you're right that abandonment only matters with unwind-protect, since that's the only time you might initiate an unwind during another unwind
6:43:38
Bike
if i'm reading CLHS 5.2 right, if you try to exit to an abandoned exit point, it's undefined behavior rather than an error
6:44:07
Bike
so i don't think leaving it to unwind to the abandoned exit point anyway is too terrible
6:46:48
Bike
we identify which frame to return to using the frame base pointer (probably need an additional identifier like sicl will have too, but that's unrelated), so we can just check if the point the cleanup is trying to unwind to is deeper in the stack or not
7:07:06
beach
So I think you get away with not having an explicit dynamic environment because 1. You use call-with-variable-bound, and 2. You don't deallocate saved multiple values when they go out of scope.
7:09:37
Bike
i don't think clasp needs it to bind dynamic variables. We could just transform (let ((*foo* bar)) ...) into (let ((#:old (tl-symbol-value '*foo*))) (unwind-protect (progn (setf (tl-symbol-value '*foo*) bar) ...) (setf (tl-symbol-value '*foo*) #:old)))
7:17:01
Bike
which as you pointed out before means that a loop repeatedly reentering an m-v-prog1 might extend the frame indefinitely, though i'm not totally sure how the LLVM semantics work out there
9:32:43
heisig
beach: Thanks! There are still some issues that I plan to address today. Like the TODO entries in the examples section.
9:33:51
heisig
I am glad that ELS exists. Writing the paper made me improve many aspects of that library.
9:34:52
beach
I know what you mean. But ELS does take a lot of time. I am counting a few months per year.
9:56:47
beach
Anyway, lunch guests will arrive in the next 15 minutes or so. Then I'll be busy for several hours.
13:08:42
scymtym
yesterday i thought of a funny way of speeding up the "applicable methods must not change check" in CALL-NEXT-METHOD: https://github.com/scymtym/sbcl/blob/6ed3332f053b555e2f605b64456989d14b72f1bf/src/pcl/cnm.lisp#L26 . i thought people here might be interested. does this matter in practice? yes: https://techfak.de/~jmoringe/clim.flamegraph-medium-draw-rectangle-star.png
13:42:42
scymtym
the first link is an implementation sketch. the second shows a profile that illustrates the performance problem of the current approach (which basically calls COMPUTE-APPLICABLE-METHODS twice for each CALL-NEXT-METHOD call that "changes" the required arguments)
13:43:52
beach
I will study it later, because it looks important, but I am about to take a break now after a long morning which included cooking for my lunch guests and entertaining them.
13:52:01
Bike
i saw you post this in #sbcl before but i didn't actually get it... this seems pretty clever
13:52:50
Bike
i'm wondering if we couldn't speed it up in sicl using the call history, but i guess it could technically be possible to c-n-m with arguments that are different classes but have the same applciable methods
13:54:10
scymtym
i also feel like i am doing this the lazy way by defining a generic function instead of using a lower-level mechanism such as the PCL cache directly
13:58:19
scymtym
in any case, the slow path (that is some arguments being unEQL) seems to come up rarely. but when it does, it hurts a lot
14:01:01
Bike
when does that.... ohhh, twiddling with keys... i see. i wouldn't have even thought of that case
14:05:02
scymtym
pairwise EQL comparison of the required arguments was already there and is definitely the more important trick. i'm only trying to improve the slow-slow-slow path or something like that
14:23:50
Bike
well, in sicl we probably couldn't do anything much faster than a generic function call, so it would probably look like this anyway
14:35:07
Bike
i wonder, in the slow path is it more common to call with arguments that specailize the same? maybe that specifically could be sped up?
14:47:21
Bike
i guess you could have one checker per applicable method set and save a bit of dispatch, but that probably doesn't matter
14:51:37
scymtym
this is so rare that i want to make it as simple as possible rather than as fast as possible. the only cases hitting the slow path i have seen so far have been like (call-next-method (1+ x) (1+ y) …) or similar
14:54:06
Bike
i don't think clasp does any checking at all at the moment. i'll have to at least put in the slow path and the eql check
14:55:38
scymtym
oh, in SBCL, it is probably the slow*5 path instead of the slow*3 path since, in addition to the other preconditions, the check is only performed in safe code