Check-in [40089e043b]
Not logged in

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

Overview
Comment:This is [Patch 3168398], Joe Mistachkin's optimisation of Tip #285
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 40089e043b001a989b0496c8e787e66264141512
User & Date: mig 2011-03-01 19:54:54.347
Context
2011-03-01
20:02
fix leaks in throw and unset compilers check-in: 0e18b9441c user: mig tags: trunk
19:54
This is [Patch 3168398], Joe Mistachkin's optimisation of Tip #285 check-in: 40089e043b user: mig tags: trunk
19:26
* generic/tclExecute.c (ExprObjCallback): fix object leak check-in: 41088210ac user: mig tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to ChangeLog.
1











2
3
4
5
6
7
8
2011-03-01  Miguel Sofer  <msofer@users.sf.net>












	* generic/tclExecute.c (ExprObjCallback): fix object leak

	* generic/tclExecute.c (TEBCresume): store local var array and
	constants in automatic vars to reduce indirection, slight perf
	increase 
	

>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2011-03-01  Miguel Sofer  <msofer@users.sf.net>

	* generic/tclBasic.c:       This is [Patch 3168398],
	* generic/tclCompCmdsSZ.c:  Joe Mistachkin's optimisation
	* generic/tclExecute.c:     of Tip #285
	* generic/tclInt.decls:
	* generic/tclInt.h:
	* generic/tclIntDecls.h:
	* generic/tclInterp.c:
	* generic/tclOODecls.h:
	* generic/tclStubInit.c:
	* win/makefile.vc:

	* generic/tclExecute.c (ExprObjCallback): fix object leak

	* generic/tclExecute.c (TEBCresume): store local var array and
	constants in automatic vars to reduce indirection, slight perf
	increase 
	
Changes to generic/tclBasic.c.
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258




3259


3260
3261
3262
3263
3264
3265
3266

    if (cancelInfo != NULL) {
	Tcl_MutexLock(&cancelLock);
	iPtr = (Interp *) cancelInfo->interp;

	if (iPtr != NULL) {
	    /*
	     * Setting this flag will cause the script in progress to be
	     * canceled as soon as possible. The core honors this flag at all
	     * the necessary places to ensure script cancellation is
	     * responsive. Extensions can check for this flag by calling
	     * Tcl_Canceled and checking if TCL_ERROR is returned or they can
	     * choose to ignore the script cancellation flag and the
	     * associated functionality altogether.
	     */

	    iPtr->flags |= CANCELED;

	    /*
	     * Currently, we only care about the TCL_CANCEL_UNWIND flag from
	     * Tcl_CancelEval. We do not want to simply combine all the flags
	     * from original Tcl_CancelEval call with the interp flags here
	     * just in case the caller passed flags that might cause behaviour
	     * unrelated to script cancellation.
	     */

	    if (cancelInfo->flags & TCL_CANCEL_UNWIND) {
		iPtr->flags |= TCL_CANCEL_UNWIND;




	    }



	    /*
	     * Create the result object now so that Tcl_Canceled can avoid
	     * locking the cancelLock mutex.
	     */

	    if (cancelInfo->result != NULL) {







|
|
|



|
<
<
<
<
<
|
|





|
|
>
>
>
>
|
>
>







3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244





3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267

    if (cancelInfo != NULL) {
	Tcl_MutexLock(&cancelLock);
	iPtr = (Interp *) cancelInfo->interp;

	if (iPtr != NULL) {
	    /*
	     * Setting the CANCELED flag will cause the script in progress to
	     * be canceled as soon as possible. The core honors this flag at
	     * all the necessary places to ensure script cancellation is
	     * responsive. Extensions can check for this flag by calling
	     * Tcl_Canceled and checking if TCL_ERROR is returned or they can
	     * choose to ignore the script cancellation flag and the
	     * associated functionality altogether. Currently, the only other





	     * flag we care about here is the TCL_CANCEL_UNWIND flag (from
	     * Tcl_CancelEval). We do not want to simply combine all the flags
	     * from original Tcl_CancelEval call with the interp flags here
	     * just in case the caller passed flags that might cause behaviour
	     * unrelated to script cancellation.
	     */

	    TclSetCancelFlags(iPtr, cancelInfo->flags | CANCELED);

	    /*
	     * Now, we must set the script cancellation flags on all the slave
	     * interpreters belonging to this one.
	     */

	    TclSetSlaveCancelFlags((Tcl_Interp *) iPtr,
		    cancelInfo->flags | CANCELED, 0);

	    /*
	     * Create the result object now so that Tcl_Canceled can avoid
	     * locking the cancelLock mutex.
	     */

	    if (cancelInfo->result != NULL) {
3781
3782
3783
3784
3785
3786
3787
3788








3789
3790
3791
3792
3793
3794
3795
	Tcl_AppendResult(interp,
		"attempt to call eval in deleted interpreter", NULL);
	Tcl_SetErrorCode(interp, "TCL", "IDELETE",
		"attempt to call eval in deleted interpreter", NULL);
	return TCL_ERROR;
    }

    if (iPtr->execEnvPtr->rewind ||








	    (TCL_OK != Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG))) {
	return TCL_ERROR;
    }

    /*
     * Check depth of nested calls to Tcl_Eval: if this gets too large, it's
     * probably because of an infinite loop somewhere.







|
>
>
>
>
>
>
>
>







3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
	Tcl_AppendResult(interp,
		"attempt to call eval in deleted interpreter", NULL);
	Tcl_SetErrorCode(interp, "TCL", "IDELETE",
		"attempt to call eval in deleted interpreter", NULL);
	return TCL_ERROR;
    }

    if (iPtr->execEnvPtr->rewind) {
	return TCL_ERROR;
    }

    /*
     * Make sure the script being evaluated (if any) has not been canceled.
     */

    if (TclCanceled(iPtr) &&
	    (TCL_OK != Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG))) {
	return TCL_ERROR;
    }

    /*
     * Check depth of nested calls to Tcl_Eval: if this gets too large, it's
     * probably because of an infinite loop somewhere.
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
    register Interp *iPtr = (Interp *) interp;

    if (iPtr == NULL) {
	return TCL_ERROR;
    }

    if (force || (iPtr->numLevels == 0)) {
	iPtr->flags &= (~(CANCELED | TCL_CANCEL_UNWIND));
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *







|







3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
    register Interp *iPtr = (Interp *) interp;

    if (iPtr == NULL) {
	return TCL_ERROR;
    }

    if (force || (iPtr->numLevels == 0)) {
	TclUnsetCancelFlags(iPtr);
    }
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
Tcl_Canceled(
    Tcl_Interp *interp,
    int flags)
{
    register Interp *iPtr = (Interp *) interp;

    /*
     * Traverse up the to the top-level interp, checking for the CANCELED flag
     * along the way. If any of the intervening interps have the CANCELED flag
     * set, the current script in progress is considered to be canceled and we
     * stop checking. Otherwise, if any interp has the DELETED flag set we
     * stop checking.
     */

    for (; iPtr!=NULL; iPtr = (Interp *) Tcl_GetMaster((Tcl_Interp *) iPtr)) {
	/*
	 * Has the current script in progress for this interpreter been
	 * canceled or is the stack being unwound due to the previous script
	 * cancellation?
	 */

	if ((iPtr->flags & CANCELED) || (iPtr->flags & TCL_CANCEL_UNWIND)) {
	    /*
	     * The CANCELED flag is a one-shot flag that is reset immediately
	     * upon being detected; however, if the TCL_CANCEL_UNWIND flag is
	     * set we will continue to report that the script in progress has
	     * been canceled thereby allowing the evaluation stack for the
	     * interp to be fully unwound.
	     */







<
<
<
<
<
<
<
<
<





|







3878
3879
3880
3881
3882
3883
3884









3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
Tcl_Canceled(
    Tcl_Interp *interp,
    int flags)
{
    register Interp *iPtr = (Interp *) interp;

    /*









	 * Has the current script in progress for this interpreter been
	 * canceled or is the stack being unwound due to the previous script
	 * cancellation?
	 */

    if (TclCanceled(iPtr)) {
	    /*
	     * The CANCELED flag is a one-shot flag that is reset immediately
	     * upon being detected; however, if the TCL_CANCEL_UNWIND flag is
	     * set we will continue to report that the script in progress has
	     * been canceled thereby allowing the evaluation stack for the
	     * interp to be fully unwound.
	     */
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
		 * Tcl core itself) that indicates further processing of the
		 * script or command in progress should halt gracefully and as
		 * soon as possible.
		 */

		return TCL_ERROR;
	    }
	} else {
	    /*
	     * FIXME: If this interpreter is being deleted we cannot continue
	     * to traverse up the interp chain due to an issue with
	     * Tcl_GetMaster (really the slave interp bookkeeping) that causes
	     * us to run off into a freed interp struct. Ideally, this check
	     * would not be necessary because Tcl_GetMaster would return NULL
	     * instead of a pointer to invalid (freed) memory.
	     */

	    if (iPtr->flags & DELETED) {
		break;
	    }
	}
    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------







<
<
<
<
<
<
<
<
<
<
<
<
<
<







3951
3952
3953
3954
3955
3956
3957














3958
3959
3960
3961
3962
3963
3964
		 * Tcl core itself) that indicates further processing of the
		 * script or command in progress should halt gracefully and as
		 * soon as possible.
		 */

		return TCL_ERROR;
	    }














    }

    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
     * Do not interrupt a series of cleanups with async or limit checks:
     * just check at the end?
     */

    if (TclAsyncReady(iPtr)) {
	result = Tcl_AsyncInvoke(interp, result);
    }
    if (result == TCL_OK) {
	result = Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG);
    }
    if (result == TCL_OK && TclLimitReady(iPtr->limit)) {
	result = Tcl_LimitCheck(interp);
    }

    return result;







|







4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
     * Do not interrupt a series of cleanups with async or limit checks:
     * just check at the end?
     */

    if (TclAsyncReady(iPtr)) {
	result = Tcl_AsyncInvoke(interp, result);
    }
    if ((result == TCL_OK) && TclCanceled(iPtr)) {
	result = Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG);
    }
    if (result == TCL_OK && TclLimitReady(iPtr->limit)) {
	result = Tcl_LimitCheck(interp);
    }

    return result;
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504

    /*
     * We are returning to level 0, so should process TclResetCancellation. As
     * numLevels has not *yet* been decreased, do not call it: do the thing
     * here directly.
     */

    iPtr->flags &= (~(CANCELED | TCL_CANCEL_UNWIND));
    return result;
}

static int
TEOV_Error(
    ClientData data[],
    Tcl_Interp *interp,







|







4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490

    /*
     * We are returning to level 0, so should process TclResetCancellation. As
     * numLevels has not *yet* been decreased, do not call it: do the thing
     * here directly.
     */

    TclUnsetCancelFlags(iPtr);
    return result;
}

static int
TEOV_Error(
    ClientData data[],
    Tcl_Interp *interp,
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
	}

	/*
	 * We are returning to level 0, so should call TclResetCancellation.
	 * Let us just unset the flags inline.
	 */

	iPtr->flags &= (~(CANCELED | TCL_CANCEL_UNWIND));
    }
    iPtr->evalFlags = 0;

    /*
     * Restore the callFrame if this was a TCL_EVAL_GLOBAL.
     */








|







6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
	}

	/*
	 * We are returning to level 0, so should call TclResetCancellation.
	 * Let us just unset the flags inline.
	 */

	TclUnsetCancelFlags(iPtr);
    }
    iPtr->evalFlags = 0;

    /*
     * Restore the callFrame if this was a TCL_EVAL_GLOBAL.
     */

Changes to generic/tclExecute.c.
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102

2103
2104
2105
2106
2107




2108
2109
2110
2111
2112
2113
2114
     * Globals: variables that store state, must remain valid at all times.
     */

    Tcl_Obj **tosPtr;	      /* Cached pointer to top of evaluation
			       * stack. */
    const unsigned char *pc;  /* The current program counter. */

#ifdef TCL_COMPILE_DEBUG
    traceInstructions = (tclTraceExec == 3);
#endif

    /*
     * Transfer variables - needed only between opcodes, but not while
     * executing an instruction.
     */

    int cleanup = 0;
    Tcl_Obj *objResultPtr;

    /*
     * Locals - variables that are used within opcodes or bounded sections of
     * the file (jumps between opcodes within a family).
     * NOTE: These are now mostly defined locally where needed.
     */

    Tcl_Obj *objPtr, *valuePtr, *value2Ptr, *part1Ptr, *part2Ptr, *tmpPtr;
    Tcl_Obj **objv;

    int opnd, objc, length, pcAdjustment;
    Var *varPtr, *arrayPtr;
#ifdef TCL_COMPILE_DEBUG
    char cmdNameBuf[21];
#endif





    NR_DATA_DIG();

#ifdef TCL_COMPILE_DEBUG
    if (!data[1] && (tclTraceExec >= 2)) {
	PrintByteCodeInfo(codePtr);
	fprintf(stdout, "  Starting stack top=%d\n", (int) CURR_DEPTH);







<
<
<
<
















>
|




>
>
>
>







2076
2077
2078
2079
2080
2081
2082




2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
     * Globals: variables that store state, must remain valid at all times.
     */

    Tcl_Obj **tosPtr;	      /* Cached pointer to top of evaluation
			       * stack. */
    const unsigned char *pc;  /* The current program counter. */





    /*
     * Transfer variables - needed only between opcodes, but not while
     * executing an instruction.
     */

    int cleanup = 0;
    Tcl_Obj *objResultPtr;

    /*
     * Locals - variables that are used within opcodes or bounded sections of
     * the file (jumps between opcodes within a family).
     * NOTE: These are now mostly defined locally where needed.
     */

    Tcl_Obj *objPtr, *valuePtr, *value2Ptr, *part1Ptr, *part2Ptr, *tmpPtr;
    Tcl_Obj **objv;
    int objc = 0;
    int opnd, length, pcAdjustment;
    Var *varPtr, *arrayPtr;
#ifdef TCL_COMPILE_DEBUG
    char cmdNameBuf[21];
#endif

#ifdef TCL_COMPILE_DEBUG
    traceInstructions = (tclTraceExec == 3);
#endif

    NR_DATA_DIG();

#ifdef TCL_COMPILE_DEBUG
    if (!data[1] && (tclTraceExec >= 2)) {
	PrintByteCodeInfo(codePtr);
	fprintf(stdout, "  Starting stack top=%d\n", (int) CURR_DEPTH);
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285

2286
2287
2288
2289
2290
2291
2292
	    result = Tcl_AsyncInvoke(interp, result);
	    if (result == TCL_ERROR) {
		CACHE_STACK_INFO();
		goto gotError;
	    }
	}


	if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
	    CACHE_STACK_INFO();
	    goto gotError;

	}

	if (TclLimitReady(iPtr->limit)) {
	    if (Tcl_LimitCheck(interp) == TCL_ERROR) {
		CACHE_STACK_INFO();
		goto gotError;
	    }







>
|
|
|
>







2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
	    result = Tcl_AsyncInvoke(interp, result);
	    if (result == TCL_ERROR) {
		CACHE_STACK_INFO();
		goto gotError;
	    }
	}

	if (TclCanceled(iPtr)) {
	    if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) {
		CACHE_STACK_INFO();
		goto gotError;
	    }
	}

	if (TclLimitReady(iPtr->limit)) {
	    if (Tcl_LimitCheck(interp) == TCL_ERROR) {
		CACHE_STACK_INFO();
		goto gotError;
	    }
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
	 * the TCL_CANCEL_UNWIND flag. Instead, it blows outwards until we
	 * either hit another interpreter (presumably where the script in
	 * progress has not been canceled) or we get to the top-level. We do
	 * NOT modify the interpreter result here because we know it will
	 * already be set prior to vectoring down to this point in the code.
	 */

	if (Tcl_Canceled(interp, 0) == TCL_ERROR) {
#ifdef TCL_COMPILE_DEBUG
	    if (traceInstructions) {
		fprintf(stdout, "   ... cancel with unwind, returning %s\n",
			StringForResultCode(result));
	    }
#endif
	    goto abnormalReturn;







|







6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
	 * the TCL_CANCEL_UNWIND flag. Instead, it blows outwards until we
	 * either hit another interpreter (presumably where the script in
	 * progress has not been canceled) or we get to the top-level. We do
	 * NOT modify the interpreter result here because we know it will
	 * already be set prior to vectoring down to this point in the code.
	 */

	if (TclCanceled(iPtr) && (Tcl_Canceled(interp, 0) == TCL_ERROR)) {
#ifdef TCL_COMPILE_DEBUG
	    if (traceInstructions) {
		fprintf(stdout, "   ... cancel with unwind, returning %s\n",
			StringForResultCode(result));
	    }
#endif
	    goto abnormalReturn;
Changes to generic/tclInt.decls.
997
998
999
1000
1001
1002
1003





1004
1005
1006
1007
1008
1009
1010
	    Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr)
}

declare 249 {
    char* TclDoubleDigits(double dv, int ndigits, int flags,
			  int* decpt, int* signum, char** endPtr)
}






##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tclIntPlat







>
>
>
>
>







997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
	    Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr)
}

declare 249 {
    char* TclDoubleDigits(double dv, int ndigits, int flags,
			  int* decpt, int* signum, char** endPtr)
}

# TIP #285: Script cancellation support.
declare 250 {
    void TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags, int force)
}

##############################################################################

# Define the platform specific internal Tcl interface. These functions are
# only available on the designated platform.

interface tclIntPlat
Changes to generic/tclInt.h.
2179
2180
2181
2182
2183
2184
2185
















2186
2187
2188
2189
2190
2191
2192
/*
 * Macros that use the TSD-ekeko.
 */

#define TclAsyncReady(iPtr) \
    *((iPtr)->asyncReadyPtr)

















/*
 * General list of interpreters. Doubly linked for easier removal of items
 * deep in the list.
 */

typedef struct InterpList {
    Interp *interpPtr;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
/*
 * Macros that use the TSD-ekeko.
 */

#define TclAsyncReady(iPtr) \
    *((iPtr)->asyncReadyPtr)

/*
 * Macros for script cancellation support (TIP #285).
 */

#define TclCanceled(iPtr) \
    (((iPtr)->flags & CANCELED) || ((iPtr)->flags & TCL_CANCEL_UNWIND))

#define TclSetCancelFlags(iPtr, cancelFlags)   \
    (iPtr)->flags |= CANCELED;                 \
    if ((cancelFlags) & TCL_CANCEL_UNWIND) {   \
        (iPtr)->flags |= TCL_CANCEL_UNWIND;    \
    }

#define TclUnsetCancelFlags(iPtr) \
    (iPtr)->flags &= (~(CANCELED | TCL_CANCEL_UNWIND))

/*
 * General list of interpreters. Doubly linked for easier removal of items
 * deep in the list.
 */

typedef struct InterpList {
    Interp *interpPtr;
Changes to generic/tclIntDecls.h.
596
597
598
599
600
601
602



603
604
605
606
607
608
609
/* 248 */
EXTERN int		TclCopyChannel(Tcl_Interp *interp,
				Tcl_Channel inChan, Tcl_Channel outChan,
				Tcl_WideInt toRead, Tcl_Obj *cmdPtr);
/* 249 */
EXTERN char*		TclDoubleDigits(double dv, int ndigits, int flags,
				int*decpt, int*signum, char**endPtr);




typedef struct TclIntStubs {
    int magic;
    const struct TclIntStubHooks *hooks;

    void (*reserved0)(void);
    void (*reserved1)(void);







>
>
>







596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
/* 248 */
EXTERN int		TclCopyChannel(Tcl_Interp *interp,
				Tcl_Channel inChan, Tcl_Channel outChan,
				Tcl_WideInt toRead, Tcl_Obj *cmdPtr);
/* 249 */
EXTERN char*		TclDoubleDigits(double dv, int ndigits, int flags,
				int*decpt, int*signum, char**endPtr);
/* 250 */
EXTERN void		TclSetSlaveCancelFlags(Tcl_Interp *interp, int flags,
				int force);

typedef struct TclIntStubs {
    int magic;
    const struct TclIntStubHooks *hooks;

    void (*reserved0)(void);
    void (*reserved1)(void);
851
852
853
854
855
856
857

858
859
860
861
862
863
864
    void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */
    Tcl_HashTable * (*tclGetNamespaceChildTable) (Tcl_Namespace *nsPtr); /* 244 */
    Tcl_HashTable * (*tclGetNamespaceCommandTable) (Tcl_Namespace *nsPtr); /* 245 */
    int (*tclInitRewriteEnsemble) (Tcl_Interp *interp, int numRemoved, int numInserted, Tcl_Obj *const *objv); /* 246 */
    void (*tclResetRewriteEnsemble) (Tcl_Interp *interp, int isRootEnsemble); /* 247 */
    int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 248 */
    char* (*tclDoubleDigits) (double dv, int ndigits, int flags, int*decpt, int*signum, char**endPtr); /* 249 */

} TclIntStubs;

#ifdef __cplusplus
extern "C" {
#endif
extern const TclIntStubs *tclIntStubsPtr;
#ifdef __cplusplus







>







854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
    void (*tclDbDumpActiveObjects) (FILE *outFile); /* 243 */
    Tcl_HashTable * (*tclGetNamespaceChildTable) (Tcl_Namespace *nsPtr); /* 244 */
    Tcl_HashTable * (*tclGetNamespaceCommandTable) (Tcl_Namespace *nsPtr); /* 245 */
    int (*tclInitRewriteEnsemble) (Tcl_Interp *interp, int numRemoved, int numInserted, Tcl_Obj *const *objv); /* 246 */
    void (*tclResetRewriteEnsemble) (Tcl_Interp *interp, int isRootEnsemble); /* 247 */
    int (*tclCopyChannel) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, Tcl_WideInt toRead, Tcl_Obj *cmdPtr); /* 248 */
    char* (*tclDoubleDigits) (double dv, int ndigits, int flags, int*decpt, int*signum, char**endPtr); /* 249 */
    void (*tclSetSlaveCancelFlags) (Tcl_Interp *interp, int flags, int force); /* 250 */
} TclIntStubs;

#ifdef __cplusplus
extern "C" {
#endif
extern const TclIntStubs *tclIntStubsPtr;
#ifdef __cplusplus
1273
1274
1275
1276
1277
1278
1279


1280
1281
1282
1283
1284
1285
1286
1287
1288
	(tclIntStubsPtr->tclInitRewriteEnsemble) /* 246 */
#define TclResetRewriteEnsemble \
	(tclIntStubsPtr->tclResetRewriteEnsemble) /* 247 */
#define TclCopyChannel \
	(tclIntStubsPtr->tclCopyChannel) /* 248 */
#define TclDoubleDigits \
	(tclIntStubsPtr->tclDoubleDigits) /* 249 */



#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLINTDECLS */







>
>









1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
	(tclIntStubsPtr->tclInitRewriteEnsemble) /* 246 */
#define TclResetRewriteEnsemble \
	(tclIntStubsPtr->tclResetRewriteEnsemble) /* 247 */
#define TclCopyChannel \
	(tclIntStubsPtr->tclCopyChannel) /* 248 */
#define TclDoubleDigits \
	(tclIntStubsPtr->tclDoubleDigits) /* 249 */
#define TclSetSlaveCancelFlags \
	(tclIntStubsPtr->tclSetSlaveCancelFlags) /* 250 */

#endif /* defined(USE_TCL_STUBS) */

/* !END!: Do not edit above this line. */

#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT

#endif /* _TCLINTDECLS */
Changes to generic/tclInterp.c.
2092
2093
2094
2095
2096
2097
2098


































































2099
2100
2101
2102
2103
2104
2105
    slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave;
    return slavePtr->masterInterp;
}

/*
 *----------------------------------------------------------------------
 *


































































 * Tcl_GetInterpPath --
 *
 *	Sets the result of the asking interpreter to a proper Tcl list
 *	containing the names of interpreters between the asking and target
 *	interpreters. The target interpreter must be either the same as the
 *	asking interpreter or one of its slaves (including recursively).
 *







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
    slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave;
    return slavePtr->masterInterp;
}

/*
 *----------------------------------------------------------------------
 *
 * TclSetSlaveCancelFlags --
 *
 *	This function marks all slave interpreters belonging to a given
 *	interpreter as being canceled or not canceled, depending on the
 *	provided flags.
 *
 * Results:
 *	None.
 *
 * Side effects:
 *	None.
 *
 *----------------------------------------------------------------------
 */

void
TclSetSlaveCancelFlags(
    Tcl_Interp *interp,		/* Set cancel flags of this interpreter. */
    int flags,			/* Collection of OR-ed bits that control
				 * the cancellation of the script. Only
				 * TCL_CANCEL_UNWIND is currently
				 * supported. */
    int force)			/* Non-zero to ignore numLevels for the purpose
				 * of resetting the cancellation flags. */
{
    Master *masterPtr;		/* Master record of given interpreter. */
    Tcl_HashEntry *hPtr;	/* Search element. */
    Tcl_HashSearch hashSearch;	/* Search variable. */
    Slave *slavePtr;		/* Slave record of interpreter. */
    Interp *iPtr;

    if (interp == NULL) {
	return;
    }

    flags &= (CANCELED | TCL_CANCEL_UNWIND);

    masterPtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->master;

    hPtr = Tcl_FirstHashEntry(&masterPtr->slaveTable, &hashSearch);
    for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&hashSearch)) {
	slavePtr = Tcl_GetHashValue(hPtr);
	iPtr = (Interp *) slavePtr->slaveInterp;

	if (iPtr == NULL) {
	    continue;
	}

	if (flags == 0) {
	    TclResetCancellation((Tcl_Interp *) iPtr, force);
	} else {
	    TclSetCancelFlags(iPtr, flags);
	}

	/*
	 * Now, recursively handle this for the slaves of this slave
	 * interpreter.
	 */

	TclSetSlaveCancelFlags((Tcl_Interp *) iPtr, flags, force);
    }
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_GetInterpPath --
 *
 *	Sets the result of the asking interpreter to a proper Tcl list
 *	containing the names of interpreters between the asking and target
 *	interpreters. The target interpreter must be either the same as the
 *	asking interpreter or one of its slaves (including recursively).
 *
2713
2714
2715
2716
2717
2718
2719










2720
2721
2722
2723
2724
2725
2726
    Tcl_Interp *slaveInterp,	/* The slave interpreter in which command
				 * will be evaluated. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;











    Tcl_Preserve(slaveInterp);
    Tcl_AllowExceptions(slaveInterp);

    if (objc == 1) {
	/*
	 * TIP #280: Make actual argument location available to eval'd script.
	 */







>
>
>
>
>
>
>
>
>
>







2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
    Tcl_Interp *slaveInterp,	/* The slave interpreter in which command
				 * will be evaluated. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int result;

    /*
     * TIP #285: If necessary, reset the cancellation flags for the slave
     * interpreter now; otherwise, canceling a script in a master interpreter
     * can result in a situation where a slave interpreter can no longer
     * evaluate any scripts unless somebody calls the TclResetCancellation
     * function for that particular Tcl_Interp.
     */

    TclSetSlaveCancelFlags(slaveInterp, 0, 0);

    Tcl_Preserve(slaveInterp);
    Tcl_AllowExceptions(slaveInterp);

    if (objc == 1) {
	/*
	 * TIP #280: Make actual argument location available to eval'd script.
	 */
Changes to generic/tclOODecls.h.
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

/*
 * WARNING: This file is automatically generated by the tools/genStubs.tcl
 * script. Any modifications to the function declarations below should be made
 * in the generic/tclOO.decls script.
 */

#if defined(USE_TCLOO_STUBS)
extern const char *TclOOInitializeStubs(Tcl_Interp *, const char *version);
#define Tcl_OOInitStubs(interp) TclOOInitializeStubs((interp),TCLOO_VERSION)
#else
#define Tcl_OOInitStubs(interp) \
	Tcl_PkgRequire((interp),"TclOO",TCLOO_VERSION,0)
#endif








|







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

/*
 * WARNING: This file is automatically generated by the tools/genStubs.tcl
 * script. Any modifications to the function declarations below should be made
 * in the generic/tclOO.decls script.
 */

#if defined(USE_TCL_STUBS)
extern const char *TclOOInitializeStubs(Tcl_Interp *, const char *version);
#define Tcl_OOInitStubs(interp) TclOOInitializeStubs((interp),TCLOO_VERSION)
#else
#define Tcl_OOInitStubs(interp) \
	Tcl_PkgRequire((interp),"TclOO",TCLOO_VERSION,0)
#endif

Changes to generic/tclStubInit.c.
302
303
304
305
306
307
308

309
310
311
312
313
314
315
    TclDbDumpActiveObjects, /* 243 */
    TclGetNamespaceChildTable, /* 244 */
    TclGetNamespaceCommandTable, /* 245 */
    TclInitRewriteEnsemble, /* 246 */
    TclResetRewriteEnsemble, /* 247 */
    TclCopyChannel, /* 248 */
    TclDoubleDigits, /* 249 */

};

static const TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
    TclGetAndDetachPids, /* 0 */







>







302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    TclDbDumpActiveObjects, /* 243 */
    TclGetNamespaceChildTable, /* 244 */
    TclGetNamespaceCommandTable, /* 245 */
    TclInitRewriteEnsemble, /* 246 */
    TclResetRewriteEnsemble, /* 247 */
    TclCopyChannel, /* 248 */
    TclDoubleDigits, /* 249 */
    TclSetSlaveCancelFlags, /* 250 */
};

static const TclIntPlatStubs tclIntPlatStubs = {
    TCL_STUB_MAGIC,
    0,
#if !defined(__WIN32__) && !defined(MAC_OSX_TCL) /* UNIX */
    TclGetAndDetachPids, /* 0 */
Changes to win/makefile.vc.
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508


#---------------------------------------------------------------------
# Link flags
#---------------------------------------------------------------------

!if $(DEBUG)
ldebug	= -debug:full -debugtype:cv
!else
ldebug	= -release -opt:ref -opt:icf,3
!if $(SYMBOLS)
ldebug	= $(ldebug) -debug:full -debugtype:cv
!endif
!endif

### Declarations common to all linker options
lflags	= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)

!if $(PROFILE)







|



|







490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508


#---------------------------------------------------------------------
# Link flags
#---------------------------------------------------------------------

!if $(DEBUG)
ldebug	= -debug -debugtype:cv
!else
ldebug	= -release -opt:ref -opt:icf,3
!if $(SYMBOLS)
ldebug	= $(ldebug) -debug -debugtype:cv
!endif
!endif

### Declarations common to all linker options
lflags	= -nologo -machine:$(MACHINE) $(LINKERFLAGS) $(ldebug)

!if $(PROFILE)
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
@TCL_MAJOR_VERSION@  $(TCL_MAJOR_VERSION)
@TCL_MINOR_VERSION@  $(TCL_MINOR_VERSION)
@TCL_PATCH_LEVEL@    $(TCL_PATCH_LEVEL)
@CC@                 $(CC)
@DEFS@               $(TCL_CFLAGS)
@CFLAGS_DEBUG@       -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MDd
@CFLAGS_OPTIMIZE@    -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MD
@LDFLAGS_DEBUG@      -nologo -machine:$(MACHINE) -debug:full -debugtype:cv
@LDFLAGS_OPTIMIZE@   -nologo -machine:$(MACHINE) -release -opt:ref -opt:icf,3
@TCL_DBGX@           $(SUFX)
@TCL_LIB_FILE@       $(PROJECT)$(VERSION)$(SUFX).lib
@TCL_NEEDS_EXP_FILE@
@LIBS@               $(baselibs)
@prefix@             $(_INSTALLDIR)
@exec_prefix@        $(BIN_INSTALL_DIR)







|







827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
@TCL_MAJOR_VERSION@  $(TCL_MAJOR_VERSION)
@TCL_MINOR_VERSION@  $(TCL_MINOR_VERSION)
@TCL_PATCH_LEVEL@    $(TCL_PATCH_LEVEL)
@CC@                 $(CC)
@DEFS@               $(TCL_CFLAGS)
@CFLAGS_DEBUG@       -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MDd
@CFLAGS_OPTIMIZE@    -nologo -c -W3 -YX -Fp$(TMP_DIR)\ -MD
@LDFLAGS_DEBUG@      -nologo -machine:$(MACHINE) -debug -debugtype:cv
@LDFLAGS_OPTIMIZE@   -nologo -machine:$(MACHINE) -release -opt:ref -opt:icf,3
@TCL_DBGX@           $(SUFX)
@TCL_LIB_FILE@       $(PROJECT)$(VERSION)$(SUFX).lib
@TCL_NEEDS_EXP_FILE@
@LIBS@               $(baselibs)
@prefix@             $(_INSTALLDIR)
@exec_prefix@        $(BIN_INSTALL_DIR)