diff options
Diffstat (limited to 'SCM/continue.c')
-rw-r--r-- | SCM/continue.c | 242 |
1 files changed, 0 insertions, 242 deletions
diff --git a/SCM/continue.c b/SCM/continue.c deleted file mode 100644 index 1f8c6de..0000000 --- a/SCM/continue.c +++ /dev/null @@ -1,242 +0,0 @@ -/* "continue.c" Scheme Continuations for C. - * Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1997 Free Software Foundation, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this program. If not, see - * <http://www.gnu.org/licenses/>. - */ - -/* Author: Aubrey Jaffer */ - -/* "setjump.h" contains definitions for the `other' field (type - CONTINUATION_OTHER) the struct Continuation. "setjump.h" must - #include "continue.h". CONTINUATION_OTHER defaults to `long' */ - -#define IN_CONTINUE_C -#ifdef USE_CONTINUE_H -# include "continue.h" -#else -# include "setjump.h" -#endif - -/* For platforms with short integers, we use thrown_value instead of - the value returned from setjump so that any (long) value can be - returned. */ - -#ifdef SHORT_INT -long thrown_value; -#endif - -/* stack_size() returns the number of units of size STACKITEM which - fit between @var{start} and the current top of stack. No check is - done in this routine to ensure that @var{start} is actually in the - current stack segment. */ - -long stack_size(start) - STACKITEM *start; -{ - STACKITEM stack; -#ifdef STACK_GROWS_UP - return &stack - start; -#else - return start - &stack; -#endif /* def STACK_GROWS_UP */ -} - -/* make_root_continuation() allocates (malloc) storage for a - CONTINUATION near the current extent of stack. This newly - allocated CONTINUATION is returned if successful, 0 if not. After - make_root_continuation() returns, the calling routine still needs - to `setjump(new_continuation->jmpbuf)' in order to complete the - capture of this continuation. */ - -#ifndef __ia64__ -CONTINUATION *make_root_continuation(stack_base) - STACKITEM *stack_base; -{ - CONTINUATION *cont; - cont = (CONTINUATION *)malloc(sizeof(CONTINUATION)); - if (!cont) return 0; - cont->length = 0; - cont->stkbse = stack_base; - cont->parent = cont; - return cont; -} - -/* make_continuation() allocates storage for the current continuation, - copying (or encapsulating) the stack state from parent_cont->stkbse - to the current top of stack. The newly allocated CONTINUATION is - returned if successful, 0 if not. After make_continuation() - returns, the calling routine still needs to - `setjump(new_continuation->jmpbuf)' in order to complete the capture - of this continuation. */ - -/* Note: allocating local (stack) storage for the CONTINUATION would - not work; Think about it. */ - -CONTINUATION *make_continuation(parent_cont) - CONTINUATION *parent_cont; -{ - CONTINUATION *cont; -# ifdef CHEAP_CONTINUATIONS - cont = (CONTINUATION *)malloc(sizeof(CONTINUATION)); - if (!cont) return 0; - cont->length = 0; - cont->stkbse = parent_cont->stkbse; -# else - long j; - register STACKITEM *src, *dst; - FLUSH_REGISTER_WINDOWS; - j = stack_size(parent_cont->stkbse); - cont = (CONTINUATION *)malloc((sizeof(CONTINUATION) + j*sizeof(STACKITEM))); - if (!cont) return 0; - cont->length = j; - cont->stkbse = parent_cont->stkbse; - src = cont->stkbse; -# ifdef STACK_GROWS_UP - src += parent_cont->length; -# else - src -= parent_cont->length + cont->length; -# endif/* ndef STACK_GROWS_UP */ - dst = (STACKITEM *)(cont + 1); - for (j = cont->length; 0 <= --j; ) *dst++ = *src++; -# endif /* ndef CHEAP_CONTINUATIONS */ - cont->parent = parent_cont; - return cont; -} -#endif - -/* free_continuation() is trivial, but who knows what the future - holds. */ - -void free_continuation(cont) - CONTINUATION *cont; -{ - free(cont); -} - -/* Final routine involved in throw()ing to a continuation. After - ensuring that there is sufficient room on the stack for the saved - continuation, dynthrow() copies the continuation onto the stack and - longjump()s into it. The routine does not return. */ - -/* If you use conservative GC and your Sparc(SUN-4) heap is growing - out of control: - - You are experiencing a GC problem peculiar to the Sparc. The - problem is that SCM doesn't know how to clear register windows. - Every location which is not reused still gets marked at GC time. - This causes lots of stuff which should be collected to not be. - This will be a problem with any *conservative* GC until we find - what instruction will clear the register windows. This problem is - exacerbated by using lots of make-CONTINUATION. - - Possibly adding the following before the thrown_value = val; line - might help to clear out unused stack above the continuation (a - small part of the problem). - -#ifdef sparc - bzero((void *)&a, sizeof(STACKITEM) * - (((STACKITEM *)&a) - (dst - cont->length))) -#endif - - Let me know if you try it. */ - -/* SCM_GROWTH is how many `long's to grow the stack by when we need room. */ -#define SCM_GROWTH 100 - -#ifndef __ia64__ -void dynthrow(a) - long *a; -{ - register CONTINUATION *cont = (CONTINUATION *)(a[0]); - long val = a[1]; -# ifndef CHEAP_CONTINUATIONS - register long j; - register STACKITEM *src, *dst = cont->stkbse; -# ifdef STACK_GROWS_UP -# ifndef hpux - if (a[2] && (a - ((long *)a[3]) < SCM_GROWTH)) - puts("grow_throw: check if long growth[]; being optimized out"); -# endif - /* if (a[2]) fprintf(stderr, " ct = %ld, dist = %ld\n", a[2], (((long *)a[3]) - a)); */ - if (PTR_GE(dst + (cont->length), (STACKITEM *)&a)) grow_throw(a); -# else -# ifndef hpux - if (a[2] && (((long *)a[3]) - a < SCM_GROWTH)) - puts("grow_throw: check if long growth[]; being optimized out"); -# endif - /* if (a[2]) fprintf(stderr, " ct = %ld, dist = %ld\n", a[2], (((long *)a[3]) - a)); */ - dst -= cont->length; - if (PTR_LE(dst, (STACKITEM *)&a)) grow_throw(a); -# endif/* def STACK_GROWS_UP */ - FLUSH_REGISTER_WINDOWS; - src = (STACKITEM *)(cont + 1); - for (j = cont->length;0 <= --j;) *dst++ = *src++; -# endif /* ndef CHEAP_CONTINUATIONS */ -# ifdef SHORT_INT - thrown_value = val; - longjump(cont->jmpbuf, 1); -# else - longjump(cont->jmpbuf, val); -# endif -} - -/* grow_throw() grows the stack by SCM_GROWTH long words. If the - "sizeof growth" assignment is not sufficient to restrain your - overly optimistic compiler, the stack will grow by much less and - grow_throw() and dynthrow() will waste time calling each other. To - fix this you will have to compile grow_throw() in a separate file - so the compiler won't be able to guess that the growth array isn't - all used. */ - -# ifndef CHEAP_CONTINUATIONS -void grow_throw(a) /* Grow the stack so that there is room */ - long *a; /* to copy in the continuation. Then */ -{ /* retry the throw. */ - long growth[SCM_GROWTH]; - growth[0] = a[0]; - growth[1] = a[1]; - growth[2] = a[2] + 1; - growth[3] = (long) a; - growth[SCM_GROWTH-1] = sizeof growth; - dynthrow(growth); -} -# endif /* ndef CHEAP_CONTINUATIONS */ -#endif - -/* throw_to_continuation() restores the stack in effect when - @var{cont} was made and resumes @var{cont}'s processor state. If - the stack cannot be resotred because @var{cont} and @var{root_cont} - do not have the same stkbase, @code{throw_to_continuation() - returns. */ - -/* Note: If 2 or more @var{cont}s share a parent continuation and if - the values of stack allocated variables in that parent continuation - are changed, the results are unspecified. This is because the - parent continuation may or may not be reloaded, depending on what - other throws have intervened. */ - -void throw_to_continuation(cont, val, root_cont) - CONTINUATION *cont; - long val; - CONTINUATION *root_cont; -{ - long a[3]; - a[0] = (long)cont; - a[1] = val; - a[2] = 0; - if (cont->stkbse != root_cont->stkbse) - return; /* Stale continuation */ - dynthrow(a); -} |