diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2004-12-15 20:44:17 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2004-12-15 20:44:17 (GMT) |
commit | 96a4475c4aa4e7f173d328e2a6f37770ae35f497 (patch) | |
tree | 03db1466c686ac3541167c4b12439b026a69750f /generic/tclExecute.c | |
parent | e3284f29c46d7eb7bdc8b89b1094f1024310bfc7 (diff) | |
download | tcl-96a4475c4aa4e7f173d328e2a6f37770ae35f497.zip tcl-96a4475c4aa4e7f173d328e2a6f37770ae35f497.tar.gz tcl-96a4475c4aa4e7f173d328e2a6f37770ae35f497.tar.bz2 |
* generic/tclTest.c: Added two new functions to allocate memory
from the execution stack (TclStackAlloc, TclStackFree). Added
functions TclPushStackFrame and TclPopStackFrame that do the work
of Tcl_PushCallFrame and Tcl_PopCallFrame, but using frames
allocated in the execution stack - i.e., heap instead of
C-stack. The core uses these two new functions exclusively; the
old ones remain for backwards compat, as at least two popular
extensions (itcl, xotcl) are known to use them.
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r-- | generic/tclExecute.c | 83 |
1 files changed, 82 insertions, 1 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 99cf90a..afbb4aa 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclExecute.c,v 1.167 2004/11/12 19:16:50 dgp Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.168 2004/12/15 20:44:36 msofer Exp $ */ #include "tclInt.h" @@ -659,6 +659,87 @@ GrowEvaluationStack(eePtr) /* *-------------------------------------------------------------- * + * TclStackAlloc -- + * + * Allocate memory from the execution stack; it has to be returned later + * with a call to TclStackFree + * + * Results: + * A pointer to the first byte allocated, or panics if the allocation did + * not succeed. + * + * Side effects: + * The execution stack may be grown. + * + *-------------------------------------------------------------- + */ + +char * +TclStackAlloc(interp, numBytes) + Tcl_Interp *interp; + int numBytes; +{ + Interp *iPtr = (Interp *) interp; + ExecEnv *eePtr = iPtr->execEnvPtr; + int numWords; + Tcl_Obj **tosPtr = eePtr->tosPtr; + char **stackRefCountPtr; + + /* + * Add two words to store + * - a pointer to the used execution stack + * - the number of words reserved + * These will be used later by TclStackFree. + */ + + numWords = (numBytes + 3*sizeof(void *) - 1)/sizeof(void *); + + while ((tosPtr + numWords) > eePtr->endPtr) { + GrowEvaluationStack(eePtr); + tosPtr = eePtr->tosPtr; + } + + /* + * Increase the stack's reference count, to make sure it is not freed + * prematurely. + */ + + stackRefCountPtr = (char **) (eePtr->stackPtr-1); + ++*stackRefCountPtr; + + /* + * Reserve the space in the exec stack, and store the data for freeing. + */ + + eePtr->tosPtr += numWords; + *(eePtr->tosPtr-1) = (Tcl_Obj *) stackRefCountPtr; + *(eePtr->tosPtr) = (Tcl_Obj *) numWords; + + return (char *) (tosPtr+1); +} + +void +TclStackFree(interp) + Tcl_Interp *interp; +{ + Interp *iPtr = (Interp *) interp; + ExecEnv *eePtr = iPtr->execEnvPtr; + char **stackRefCountPtr; + + + stackRefCountPtr = (char **) *(eePtr->tosPtr-1); + eePtr->tosPtr -= (int) *(eePtr->tosPtr); + + --*stackRefCountPtr; + if (*stackRefCountPtr == (char *) 0) { + ckfree((VOID *) stackRefCountPtr); + } +} + + +/* + *-------------------------------------------------------------- + * * Tcl_ExprObj -- * * Evaluate an expression in a Tcl_Obj. |