Tcl Source Code

Check-in [955265f9a0]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:[0b874c344d] Fix for nested coroutines ability to stitch together multiple parts of the CmdFrame chain traversed by [info frame].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 955265f9a0d235b25cc61066745180ea3709fa96
User & Date: dgp 2013-12-18 18:23:20
Context
2013-12-19
14:35
Add TclRegisterLiteral() to internal stub table (from "mig-optimize" branch, looks like a good idea ... check-in: e6528e54af user: jan.nijtmans tags: trunk
12:21
merge trunk check-in: 7d7672c1eb user: jan.nijtmans tags: novem
2013-12-18
22:01
merge trunk check-in: c08920b226 user: mig tags: mig-optimize
18:23
[0b874c344d] Fix for nested coroutines ability to stitch together multiple parts of the CmdFrame cha... check-in: 955265f9a0 user: dgp tags: trunk
18:20
merge trunk Closed-Leaf check-in: c2729f6ccc user: dgp tags: bug-0b874c344d
16:06
Making the optimizer pluggable by extensions check-in: f1ad9cd44e user: mig tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclCmdIL.c.

1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

1153
1154
1155
1156
1157
1158


1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1182
1183

1184

1185
1186
1187
1188
1189
1190
1191
InfoFrameCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    int level, topLevel, code = TCL_OK;
    CmdFrame *runPtr, *framePtr;
    CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;


    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?number?");
	return TCL_ERROR;
    }



    topLevel = ((iPtr->cmdFramePtr == NULL)
	    ? 0
	    : iPtr->cmdFramePtr->level);

    if (corPtr) {
	/*
	 * A coroutine: must fix the level computations AND the cmdFrame chain,
	 * which is interrupted at the base.
	 */

	CmdFrame *lastPtr = NULL;

	runPtr = iPtr->cmdFramePtr;

	/* TODO - deal with overflow */
	topLevel += corPtr->caller.cmdFramePtr->level;

	while (runPtr) {
	    runPtr->level += corPtr->caller.cmdFramePtr->level;
	    lastPtr = runPtr;
	    runPtr = runPtr->nextPtr;
	}
	if (lastPtr) {
	    lastPtr->nextPtr = corPtr->caller.cmdFramePtr;
	} else {
	    iPtr->cmdFramePtr = corPtr->caller.cmdFramePtr;

	}

    }

    if (objc == 1) {
	/*
	 * Just "info frame".
	 */








|
|

>






>
>
|
<
|
|
|
<
|
<
<
|
|
|
|

<
|
>
|
|
<
|

|
<
<
<
>

>







1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

1163
1164
1165

1166


1167
1168
1169
1170
1171

1172
1173
1174
1175

1176
1177
1178



1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
InfoFrameCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    Interp *iPtr = (Interp *) interp;
    int level, code = TCL_OK;
    CmdFrame *framePtr, **cmdFramePtrPtr = &iPtr->cmdFramePtr;
    CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
    int topLevel = 0;

    if (objc > 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "?number?");
	return TCL_ERROR;
    }

    while (corPtr) {
	while (*cmdFramePtrPtr) {
	    topLevel++;

	    cmdFramePtrPtr = &((*cmdFramePtrPtr)->nextPtr);
	}
	if (corPtr->caller.cmdFramePtr) {

	    *cmdFramePtrPtr = corPtr->caller.cmdFramePtr;


	}
	corPtr = corPtr->callerEEPtr->corPtr;
    }
    topLevel += (*cmdFramePtrPtr)->level;


    if (topLevel != iPtr->cmdFramePtr->level) {
	framePtr = iPtr->cmdFramePtr;
	while (framePtr) {
	    framePtr->level = topLevel--;

	    framePtr = framePtr->nextPtr;
	}
	if (topLevel) {



	    Tcl_Panic("Broken frame level calculation");
	}
	topLevel = iPtr->cmdFramePtr->level;
    }

    if (objc == 1) {
	/*
	 * Just "info frame".
	 */

1227
1228
1229
1230
1231
1232
1233


1234

1235

1236
1237
1238
1239

1240
1241
1242
1243
1244
1245
1246

1247

1248
1249
1250
1251
1252
1253
1254
	    goto levelError;
	}
    }

    Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr));

  done:


    if (corPtr) {



	if (iPtr->cmdFramePtr == corPtr->caller.cmdFramePtr) {
	    iPtr->cmdFramePtr = NULL;
	} else {
	    runPtr = iPtr->cmdFramePtr;

	    while (runPtr->nextPtr != corPtr->caller.cmdFramePtr) {
	    	runPtr->level -= corPtr->caller.cmdFramePtr->level;
		runPtr = runPtr->nextPtr;
	    }
	    runPtr->level = 1;
	    runPtr->nextPtr = NULL;
	}



    }
    return code;
}

/*
 *----------------------------------------------------------------------
 *







>
>
|
>

>
|
|
|
|
>
|
|
|
|
|
|
|
>
|
>







1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
	    goto levelError;
	}
    }

    Tcl_SetObjResult(interp, TclInfoFrame(interp, framePtr));

  done:
    cmdFramePtrPtr = &iPtr->cmdFramePtr;
    corPtr = iPtr->execEnvPtr->corPtr;
    while (corPtr) {
	CmdFrame *endPtr = corPtr->caller.cmdFramePtr;

	if (endPtr) {
	    if (*cmdFramePtrPtr == endPtr) {
		*cmdFramePtrPtr = NULL;
	    } else {
		CmdFrame *runPtr = *cmdFramePtrPtr;

		while (runPtr->nextPtr != endPtr) {
		    runPtr->level -= endPtr->level;
		    runPtr = runPtr->nextPtr;
		}
		runPtr->level = 1;
		runPtr->nextPtr = NULL;
	    }
	    cmdFramePtrPtr = &corPtr->caller.cmdFramePtr;
	}
	corPtr = corPtr->callerEEPtr->corPtr;
    }
    return code;
}

/*
 *----------------------------------------------------------------------
 *

Changes to tests/coroutine.test.

338
339
340
341
342
343
344



345
346
347
348
349
350
351
    proc a {} stack
} -body {
    coroutine aa a
} -cleanup {
    rename stack {}
    rename a {}
} -result {}




test coroutine-4.1 {bug #2093188} -setup {
    proc foo {} {
	set v 1
	trace add variable v {write unset} bar
	yield
	set v 2







>
>
>







338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
    proc a {} stack
} -body {
    coroutine aa a
} -cleanup {
    rename stack {}
    rename a {}
} -result {}
test coroutine-3.7 {bug 0b874c344d} {
    dict get [coroutine X coroutine Y info frame 0] cmd
} {coroutine X coroutine Y info frame 0}

test coroutine-4.1 {bug #2093188} -setup {
    proc foo {} {
	set v 1
	trace add variable v {write unset} bar
	yield
	set v 2