Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.2 9/18/84; site cornell.UUCP Path: utzoo!watmath!clyde!burl!ulysses!mhuxr!mhuxt!houxm!vax135!cornell!jqj@bullwinkle From: jqj@bullwinkle Newsgroups: net.emacs Subject: gnu design question Message-ID: <21@cornell.UUCP> Date: Mon, 30-Dec-85 07:21:23 EST Article-I.D.: cornell.21 Posted: Mon Dec 30 07:21:23 1985 Date-Received: Tue, 31-Dec-85 03:58:20 EST Sender: daemon@cornell.UUCP Organization: Cornell Univ. CS Dept. Lines: 80 From: jqj@bullwinkle (J Q Johnson) One of the design goals of C was to produce a language with very simple and efficient variable allocation. The result, with no nested procedures and only local and global variables (no uplevel references, no heap variables though you do have heap storage, no variable-dimensioned arrays) produces a language that can be implemented without a frame pointer. This is a desirable characteristic of the language, and implies that you should not expect all or even the typical implementation to use a frame pointer. Unfortunately, since the VAX CALLS/RET discipline uses a frame pointer, the alloca() routine exists. And since it exists on the VAX, it is used heavily by GNU emacs. However, its use conflicts with one of what I take to be GNU emacs's design goals -- portability. I would like to improve that portability if possible. My particular domain is porting GNU emacs to a Gould PN. I see several alternatives, and would like advice on which to pursue. Note that emacs uses alloca() in a very stylized way -- almost entirely to provide dynamically dimensioned arrays. One never sees code like: foo() { ... while (baz) { p->next = alloca(sizeof(p)+n); p = p->next; ... So alloca() would not have been necessary at all in an Algol-like language. My alternatives seem to be: 1/ implement a full alloca() for the Gould. This would not be hard but would be a gross assembler hack -- alloca()ed variables would actually be malloc()ed, but alloca() would push the ptr on a private stack and fudge the caller's return to free() then pop the private stack. setjmp{} would be extended to mark the private stack, and longjmp() would do a number of free()s. The only visible change to existing code would be redefining jmp.buf by changing the #include to reference a private setjmp.h. However, as I remarked above this would be a gross assembler hack, and nonportable. Also, it would be impossible to preserve the alloca() semantics during interrupts, and would limit you to a (small) fixed number of outstanding alloca()s based on the size of the private stack. 2/ recode entirely in C to eliminate the need for alloca() as such. This could be done in several ways. Perhaps the simplest would be to have alloca() allocate on the heap, saving the pointer on a private stack, and in alloca()'s caller record the private stack top in a local variable. Add a "mark()" routine at the beginning of each function that uses alloca() and a "release()" routine at each return: old: new: foo() { ... foo() { ... char *name=alloca(xxx); int alloclim = mymark(); ... char *name=myalloca(xxx); return baz; ... ... (myrelease(alloclim), return baz); } ... myrelease(alloclim); } Similarly, setjmp would be protected with a mark/release: old: new: if (setjmp(buf)) int alloclim; ... foo; if (alloclim = mymark(), setjmp(buf)) (myrelease(alloclim), foo); This scheme has the disadvantage of running slower if a true alloca() exists (unless all the code is conditionalized, which would be a maintenance headache). It also makes the code less clear, again increasing maintenance. But it has the advantage of being completely portable. 3/ Recode GNU emacs to do compile-time maximum-size array allocations instead of runtime bounds. This is typical C style but could increase (dramatically!) the size of the stack. Except in a few places where reasonable bounds are known in advance (e.g. dispnew.c), I think this would be a bad idea. 4/ Hack up the Gould C compiler to use a stack frame. And it's still non-portable. 5/ Do something else entirely. (e.g. use Hemlock?) 1/, 2/, or 3/ would each take, I estimate, less than a person-week to program and debug. 4/ would take several person-months for the average hacker.