Path: csiph.com!xmission!news.snarked.org!border2.nntp.dca1.giganews.com!nntp.giganews.com!news.iecc.com!.POSTED.news.iecc.com!nerds-end From: Kaz Kylheku <217-679-0842@kylheku.com> Newsgroups: comp.compilers Subject: Re: Add nested-function support in a language the based on a stack-machine Date: Tue, 6 Mar 2018 18:17:47 +0000 (UTC) Organization: Aioe.org NNTP Server Lines: 47 Sender: news@iecc.com Approved: comp.compilers@iecc.com Message-ID: <18-03-028@comp.compilers> References: <18-02-009@comp.compilers> <18-03-002@comp.compilers> <18-03-012@comp.compilers> <18-03-020@comp.compilers> <18-03-024@comp.compilers> Injection-Info: gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="40224"; mail-complaints-to="abuse@iecc.com" Keywords: code, Lisp Posted-Date: 06 Mar 2018 13:23:51 EST X-submission-address: compilers@iecc.com X-moderator-address: compilers-request@iecc.com X-FAQ-and-archives: http://compilers.iecc.com Xref: csiph.com comp.compilers:1980 On 2018-03-06, John Levine wrote: >>>>>This is because displays were found to be more costly for Algol-like >>>>>languages ... >>> >>>>> IIRC the additional cost is in updating the display on calls >>>>>and returns. > > I get the impression that displays describe two different things. > > One is a static array that has one entry for each level of lexical > scoping. In a routine declared N levels (zero based) down, its prolog > saves the Nth entry in the display and replaces it with a pointer to > the current stack frame, and the epilog restores it. It can assume > that higher level routines have correctly set entries 0:N-1. That > seems pretty efficient. Assuming the saved pointer is at a known > location in each stack frame you can do a longjmp and unwind stacks > without too much pain. > > The other is the same array, but with a copy of the current display in > each routine's stack frame. This is slower at call time but probably > faster to use on machines like S/360 without direct addressing > since the display on the stack is addressable from the frame pointer, > but static data needs to load a pointer from a constant pool. A > longjmp doesn't need anything special since stacked displays go away > when the stack frames go away. This is precisely what I happen to be working on at the moment: a virtual machine for a Lisp dialect in which I plan to have displays copied into the local stack frame. I expect it to be a performance advantage that there is nothing special to do when the stack frame goes away. If we had to take some unconditional action, we would have to set up a catch frame. That means doing a setjmp-like operation that saves a whole vector of stuff similar to a jmp_buf. Not just machine registers, but the signal mask (or a virtualized representation of it, for efficiency), and other stuff. This vector is larger than a display display containing a significant number of environment levels! If the scope binds dynamically scoped variables, those have to be undone. However, that requires no special action. The dynamic environment is a chain rooted at a global pointer called dyn_env. Long ago, I made the simplifying design decision to include this dyn_env pointer in the jmp_buf-like context that is saved at every catch frame, and so there is no need for a scope to set up a handler for the sake of restoring dynamically scoped bindings. The normal return case has to restore dyn_env, which is simple.