Tcl Source Code

Check-in [5f8dcf50a2]
Login

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

Overview
Comment:Rewrite of parts of the [switch] compiler to better use the powers of TclFindElement() and do less parsing on its own. Needs review and testing.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dgp-switch-compile
Files: files | file ages | folders
SHA1: 5f8dcf50a20d1154bad524463f42f1904b03d07b
User & Date: dgp 2011-04-28 20:40:46
Context
2011-05-02
12:18
Tighten up the patch. check-in: a4d8498860 user: dgp tags: dgp-switch-compile
2011-04-28
20:40
Rewrite of parts of the [switch] compiler to better use the powers of TclFindElement() and do less p... check-in: 5f8dcf50a2 user: dgp tags: dgp-switch-compile
16:00
More isspace() callers. check-in: 88095bbde0 user: dgp tags: core-8-5-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclCompCmds.c.

3903
3904
3905
3906
3907
3908
3909

3910

3911
3912
3913
3914
3915
3916
3917
				 * there aren't any. */
    int contFixCount;		/* Number of continuation bodies pointing to
				 * the current (or next) real body. */

    int savedStackDepth = envPtr->currStackDepth;
    int noCase;			/* Has the -nocase flag been given? */
    int foundMode = 0;		/* Have we seen a mode flag yet? */

    int isListedArms = 0;

    int i, valueIndex;
    DefineLineInformation;	/* TIP #280 */
    int* clNext = envPtr->clNext;

    /*
     * Only handle the following versions:
     *   switch         ?--? word {pattern body ...}







>

>







3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
				 * there aren't any. */
    int contFixCount;		/* Number of continuation bodies pointing to
				 * the current (or next) real body. */

    int savedStackDepth = envPtr->currStackDepth;
    int noCase;			/* Has the -nocase flag been given? */
    int foundMode = 0;		/* Have we seen a mode flag yet? */
#if 0
    int isListedArms = 0;
#endif
    int i, valueIndex;
    DefineLineInformation;	/* TIP #280 */
    int* clNext = envPtr->clNext;

    /*
     * Only handle the following versions:
     *   switch         ?--? word {pattern body ...}
4043
4044
4045
4046
4047
4048
4049

4050
4051
4052
4053
4054
4055
4056
     * that in the case of the quoted bodies, this is tricky as we cannot use
     * copies of the string from the input token for the generated tokens (it
     * causes a crash during exception handling). When multiple tokens are
     * available at this point, this is pretty easy.
     */

    if (numWords == 1) {

	Tcl_DString bodyList;
	const char **argv = NULL, *tokenStartPtr, *p;
	int bline;		/* TIP #280: line of the pattern/action list,
				 * and start of list for when tracking the
				 * location. This list comes immediately after
				 * the value we switch on. */
	int isTokenBraced;







>







4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
     * that in the case of the quoted bodies, this is tricky as we cannot use
     * copies of the string from the input token for the generated tokens (it
     * causes a crash during exception handling). When multiple tokens are
     * available at this point, this is pretty easy.
     */

    if (numWords == 1) {
#if 0
	Tcl_DString bodyList;
	const char **argv = NULL, *tokenStartPtr, *p;
	int bline;		/* TIP #280: line of the pattern/action list,
				 * and start of list for when tracking the
				 * location. This list comes immediately after
				 * the value we switch on. */
	int isTokenBraced;
4081
4082
4083
4084
4085
4086
4087

4088

4089
4090
4091
4092
4093
4094
4095
	 */

	if (numWords == 0 || numWords % 2) {
	    ckfree((char *) argv);
	    return TCL_ERROR;
	}


	isListedArms = 1;

	bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * numWords);
	bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords);
	bodyLines = (int *) ckalloc(sizeof(int) * numWords);
	bodyNext  = (int **) ckalloc(sizeof(int*) * numWords);

	/*
	 * Locate the start of the arms within the overall word.







>

>







4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
	 */

	if (numWords == 0 || numWords % 2) {
	    ckfree((char *) argv);
	    return TCL_ERROR;
	}

#if 0
	isListedArms = 1;
#endif
	bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * numWords);
	bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * numWords);
	bodyLines = (int *) ckalloc(sizeof(int) * numWords);
	bodyNext  = (int **) ckalloc(sizeof(int*) * numWords);

	/*
	 * Locate the start of the arms within the overall word.
4174
4175
4176
4177
4178
4179
4180





















































































4181
4182
4183
4184
4185
4186
4187
	if (tokenStartPtr != tokenPtr[1].start+tokenPtr[1].size) {
	    ckfree((char *) bodyToken);
	    ckfree((char *) bodyTokenArray);
	    ckfree((char *) bodyLines);
	    ckfree((char *) bodyNext);
	    return TCL_ERROR;
	}






















































































    } else if (numWords % 2 || numWords == 0) {
	/*
	 * Odd number of words (>1) available, or no words at all available.
	 * Both are error cases, so punt and let the interpreted-version
	 * generate the error message. Note that the second case probably
	 * should get caught earlier, but it's easy to check here again anyway







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







4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
	if (tokenStartPtr != tokenPtr[1].start+tokenPtr[1].size) {
	    ckfree((char *) bodyToken);
	    ckfree((char *) bodyTokenArray);
	    ckfree((char *) bodyLines);
	    ckfree((char *) bodyNext);
	    return TCL_ERROR;
	}
#else
	CONST char *bytes, *p;
	int maxLen, braced, numBytes;
	int bline;		/* TIP #280: line of the pattern/action list,
				 * and start of list for when tracking the
				 * location. This list comes immediately after
				 * the value we switch on. */

	if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) {
	    return TCL_ERROR;
	}
	bytes = tokenPtr[1].start;
	numBytes = tokenPtr[1].size;

	/*
	 * A list can have at most one more element than the number
	 * of runs of element-separating white space.
	 */

	maxLen = TclCountSpaceRuns(bytes, numBytes, NULL) + 1;
	if (maxLen < 2) {
	    return TCL_ERROR;
	}
	bodyTokenArray = (Tcl_Token *) ckalloc(sizeof(Tcl_Token) * maxLen);
	bodyToken = (Tcl_Token **) ckalloc(sizeof(Tcl_Token *) * maxLen);
	bodyLines = (int *) ckalloc(sizeof(int) * maxLen);
	bodyNext  = (int **) ckalloc(sizeof(int*) * maxLen);

	bline = mapPtr->loc[eclIndex].line[valueIndex+1];
	p = bytes;
	numWords = 0;

	while (numBytes > 0) {
	    CONST char *start, *prevBytes = bytes;
	    int size;

	    if (TCL_OK != TclFindElement(NULL, bytes, numBytes, &start,
		    &bytes, &size, &braced)) {
	    abort:
		ckfree((char *) bodyToken);
		ckfree((char *) bodyTokenArray);
		ckfree((char *) bodyLines);
		ckfree((char *) bodyNext);
		return TCL_ERROR;
	    }
	    numBytes -= (bytes - prevBytes);

	    if (numWords == 0 && numBytes == 0) {
		break;
	    }

	    bodyTokenArray[numWords].type = TCL_TOKEN_TEXT;
	    bodyTokenArray[numWords].start = start;
	    bodyTokenArray[numWords].size = size;
	    bodyTokenArray[numWords].numComponents = 0;
	    bodyToken[numWords] = bodyTokenArray + numWords;

	    if (!braced) {
		while (size--) {
		    if (*start++ == '\\') {
			goto abort;
		    }
		}
	    }

	    /*
	     * TIP #280: Now determine the line the list element starts on
	     * (there is no need to do it earlier, due to the possibility of
	     * aborting, see above).
	     */

	    TclAdvanceLines(&bline, p, bodyTokenArray[numWords].start);
	    TclAdvanceContinuations (&bline, &clNext,
		    bodyTokenArray[numWords].start - envPtr->source);
	    bodyLines[numWords] = bline;
	    bodyNext[numWords] = clNext;
	    p = bodyTokenArray[numWords].start;

	    numWords++;
	}
	if (numWords % 2) {
	    goto abort;
	}

#endif

    } else if (numWords % 2 || numWords == 0) {
	/*
	 * Odd number of words (>1) available, or no words at all available.
	 * Both are error cases, so punt and let the interpreted-version
	 * generate the error message. Note that the second case probably
	 * should get caught earlier, but it's easy to check here again anyway
4201
4202
4203
4204
4205
4206
4207
4208

4209


4210
4211
4212
4213
4214
4215
4216
	for (i=0 ; i<numWords ; i++) {
	    /*
	     * We only handle the very simplest case. Anything more complex is
	     * a good reason to go to the interpreted case anyway due to
	     * traces, etc.
	     */

	    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD ||

		    tokenPtr->numComponents != 1) {


		ckfree((char *) bodyToken);
		ckfree((char *) bodyLines);
		ckfree((char *) bodyNext);
		return TCL_ERROR;
	    }
	    bodyToken[i] = tokenPtr+1;








|
>
|
>
>







4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
	for (i=0 ; i<numWords ; i++) {
	    /*
	     * We only handle the very simplest case. Anything more complex is
	     * a good reason to go to the interpreted case anyway due to
	     * traces, etc.
	     */

	    if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD
#if 0
		    || tokenPtr->numComponents != 1
#endif
		    ) {
		ckfree((char *) bodyToken);
		ckfree((char *) bodyLines);
		ckfree((char *) bodyNext);
		return TCL_ERROR;
	    }
	    bodyToken[i] = tokenPtr+1;

4251
4252
4253
4254
4255
4256
4257




4258




4259
4260
4261
4262
4263
4264
4265
    /*
     * Check if we can generate a jump table, since if so that's faster than
     * doing an explicit compare with each body. Note that we're definitely
     * over-conservative with determining whether we can do the jump table,
     * but it handles the most common case well enough.
     */





    if (isListedArms && mode == Switch_Exact && !noCase) {




	JumptableInfo *jtPtr;
	int infoIndex, isNew, *finalFixups, numRealBodies = 0, jumpLocation;
	int mustGenerate, jumpToDefault;
	Tcl_DString buffer;
	Tcl_HashEntry *hPtr;

	/*







>
>
>
>
|
>
>
>
>







4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
    /*
     * Check if we can generate a jump table, since if so that's faster than
     * doing an explicit compare with each body. Note that we're definitely
     * over-conservative with determining whether we can do the jump table,
     * but it handles the most common case well enough.
     */

    if (
#if 0
	    isListedArms &&
#endif
	    mode == Switch_Exact
#if 0
	    && !noCase
#endif
	    ) {
	JumptableInfo *jtPtr;
	int infoIndex, isNew, *finalFixups, numRealBodies = 0, jumpLocation;
	int mustGenerate, jumpToDefault;
	Tcl_DString buffer;
	Tcl_HashEntry *hPtr;

	/*