Hacker News new | past | comments | ask | show | jobs | submit login
Ask HN: How does Common Lisp implement hot-reloading?
5 points by register on Oct 21, 2018 | hide | past | favorite | 4 comments
I have always wondered how Common Lisp implements hot-reloading on live functions in multithreaded contexts.

A typical approach used in other languages or debuggers is either to use a dispatch table or to have some NOP bytes at the beginning of every function that could be rewritten into a jmp to the new function definition. In the first case the code incurs a performance penalty for every invocation. In the latter there is no performance hit however the call stack must be kept completely unchanged. This doesn't seem to match the experience one achieves with SBCL on Linux where calls don't seem to be slowed down and one can recompile just some forms in the middle of the stack. It seems that in some way the CL compiler could update also the call stack. The only other language that reaches the same level of interactivity is Smalltalk for which however I know only about of single-threaded implementations. How is CL different from other languages with respect to this? Where can I find more technical details about how hot-reloading is implemented in CL?

Cheers




A function is an object. When we redefine a global function, we're simply replacing the symbol's function binding to point to a new function object. That can be an atomic operation: a word-sized cell is overwritten.

If one or more threads are executing the old function, then they continue to do that. That object is referenced by those threads and so doesn't become garbage until the last thread stops executing it. Newly issued calls to that function go to the new one through the newly established binding.

ANSI CL allows functions that are in the source file (actually compilation unit) to use more efficient calling; they don't have to go through the global symbol function binding. The idea is that compilation units are replaced at once, rather than individual functions. Call optimizing behavior can be overridden for individual functions by declaim-ing them notinline.


Ok so this means that calls accross compilation units always incur an indirection, right? Also I don't get how swapping the whole compilation unit can be achieved atomically. A compilation unit might be composed by several functions. Where can I find more? I have tried to look in the literature but haven't found anything that reaches this level of detail.


do you understand lisp symbols? read up on it and try to understand how they are represented internally, that's the key.


A very similar question was asked a few weeks ago in another Ask HN. See my answer there https://news.ycombinator.com/item?id=18111600




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: