diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2009-03-19 23:31:36 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2009-03-19 23:31:36 (GMT) |
commit | e6e54e79e2d7333a81f91a9525ed518f9d96a0cd (patch) | |
tree | 72f27d85c68739eb5710cc682cb2fd79c500452f /generic/tclNamesp.c | |
parent | e77ab61acdd95f64d2222c71c72f2b2db1a39f65 (diff) | |
download | tcl-e6e54e79e2d7333a81f91a9525ed518f9d96a0cd.zip tcl-e6e54e79e2d7333a81f91a9525ed518f9d96a0cd.tar.gz tcl-e6e54e79e2d7333a81f91a9525ed518f9d96a0cd.tar.bz2 |
* generic/tcl.h:
* generic/tclInt.h:
* generic/tclBasic.c:
* generic/tclExecute.c:
* generic/tclNamesp.c (Tcl_PopCallFrame): Rewritten tailcall
implementation, ::unsupported::atProcExit is (temporarily?)
gone. The new approach is much simpler, and also closer to being
correct. This commit fixes [Bug 2649975] and [Bug 2695587].
* tests/coroutine.test: Moved the tests to their own files,
* tests/tailcall.test: removed the unsupported.test. Added
* tests/unsupported.test: tests for the fixed bugs.
Diffstat (limited to 'generic/tclNamesp.c')
-rw-r--r-- | generic/tclNamesp.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c index 20b28eb..8caf7db 100644 --- a/generic/tclNamesp.c +++ b/generic/tclNamesp.c @@ -23,10 +23,11 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclNamesp.c,v 1.189 2009/02/10 22:50:07 nijtmans Exp $ + * RCS: @(#) $Id: tclNamesp.c,v 1.190 2009/03/19 23:31:37 msofer Exp $ */ #include "tclInt.h" +#include "tclCompile.h" /* just for NRCommand */ /* * Thread-local storage used to avoid having a global lock on data that is not @@ -428,7 +429,8 @@ Tcl_PushCallFrame( framePtr->compiledLocals = NULL; framePtr->clientData = NULL; framePtr->localCachePtr = NULL; - + framePtr->tailcallPtr = NULL; + /* * Push the new call frame onto the interpreter's stack of procedure call * frames making it the current frame. @@ -454,6 +456,7 @@ Tcl_PushCallFrame( * Modifies the call stack of the interpreter. Resets various fields of * the popped call frame. If a namespace has been deleted and has no more * activations on the call stack, the namespace is destroyed. + * Schedules a tailcall if one is present. * *---------------------------------------------------------------------- */ @@ -505,6 +508,30 @@ Tcl_PopCallFrame( Tcl_DeleteNamespace((Tcl_Namespace *) nsPtr); } framePtr->nsPtr = NULL; + + if (framePtr->tailcallPtr) { + /* + * Find the splicing spot: right before the NRCommand of the thing being + * tailcalled. Note that we skip NRCommands marked in data[1] (used by + * command redirectors) + */ + + TEOV_callback *tailcallPtr, *runPtr; + + for (runPtr = TOP_CB(interp); runPtr; runPtr = runPtr->nextPtr) { + if (((runPtr->procPtr) == NRCommand) && !runPtr->data[1]) { + break; + } + } + if (!runPtr) { + Tcl_Panic("Tailcall cannot find the right splicing spot: should not happen!"); + } + + tailcallPtr = framePtr->tailcallPtr; + + tailcallPtr->nextPtr = runPtr->nextPtr; + runPtr->nextPtr = tailcallPtr; + } } /* |