Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch mig-alloc-reform Excluding Merge-Ins
This is equivalent to a diff from 58f4f4ca46 to 76befed959
2013-02-14
| ||
09:01 | Improve some comments and quoting, no change in functionality. Only check for refCount == 0x6161616... check-in: 37c5e68b61 user: jan.nijtmans tags: trunk | |
2013-02-11
| ||
19:01 | merge trunk check-in: 29af322735 user: dgp tags: dgp-refactor | |
13:50 | merge trunk Leaf check-in: 76befed959 user: mig tags: mig-alloc-reform | |
13:48 | fix no-thread build check-in: db817d8d11 user: mig tags: mig-alloc-reform | |
09:38 | Merge trunk. Various Tcl_NewIntObj/Tcl_NewBooleanObj -> Tcl_NewLongObj modifications check-in: 1b58c7107b user: jan.nijtmans tags: novem | |
08:57 | Fix [Bug 3603553]. check-in: 58f4f4ca46 user: dkf tags: trunk | |
08:54 | Correction to comment in re key buffer size. Closed-Leaf check-in: 7ac67a7adf user: dkf tags: bug-3603553 | |
2013-02-10
| ||
13:26 | Unbreak msvc builds, by depending on tclPort.h for inclusion of <sys/stat.h> check-in: 4ef9e63656 user: jan.nijtmans tags: trunk | |
Added README.mig-alloc-reform.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | What is mig-alloc-reform? 1. A massive simplification of the memory management in Tcl core. a. removal of the Tcl stack, each BC allocates its own stacklet b. TclStackAlloc is gone, replaced with ckalloc; goodbye to sometimes hard sync problems c. removal of the allocCache slot in struct Interp d. retirement of the (unused) Tcl allocator USE_TCLALLOC; replacement with a single-thread special case of zippy e. unify all allocator options in a single file tclAlloc.c d. exploit fast TSD via __thread where available (autoconferry still missing, enable by hand with -DHAVE_FAST_TSD) f. small improvements in zippy's memory usage: . try to split blocks in the shared cache before allocating new ones from the system . use the same bucket for Tcl_Objs and smallest allocs 2. New allocator options a. purify build (but stop using them, see below). This is suitable to use with a preloaded malloc replacement b. (~NEW) native build: call to sys malloc, but maintain zippy's Tcl_Obj caches (per thread, if threads enabled). Can be switched to run as a purify build via an env var at startup. This is suitable to use with a preloaded malloc replacement. The threaded variant is new. c. zippy build d. (NEW) multi build: this is a build that can function as any of the other three. Per default it runs as zippy, but can be switched to native or purify via an env var at startup. May or may not be used for deployment, but it will definitely be very useful for development: no need to recompile in order to valgrind, just set an env var! How do you use it? Options are: 1. Don't pay any attention to it, build as always. You will get the same allocator as before 2. Select the build you want with compiler flags -DTCL_ALLOCATOR=(aNATIVE|aPURIFY|aZIPPY|aMULTI) 3. Select behaviour at startup: native can be switched to purify, multi can be switched to any of the others. Define the env var TCL_ALLOCATOR when starting up and you're good to go ** PERFORMANCE NOTES ** * do enable HAVE_FAST_TSD on threaded build where available! Without that it is probably slower than before. Note that __thread is not available on macosx, but the "slow" version should be quite fast there (or so they say) * not measured, but: purify, native and zippy builds should be just as fast as before. The obj-alloc macros have been removed while developing. It is not certain that they provide a speedup, this will be measured and acted accordingly * multi build should be a only a tad slower, may even be suitable as default build on all platforms * zippy stats not enabled by default, -DZIPPY_STATS switches them on ** TO DO LIST ** * DEFINITELY - test like crazy - timings: versus older version (in unthreaded, fast-tsd and slow-tsd builds). Determine if the obj-alloc macros should be reenabled - autoconferry to auto-detect HAVE_FAST_TSD - autoconferry to choose allocator flags? Keep USE_THREAD_ALLOC and USE_TCLALLOC for back compat with external build scripts only (and set them too!), but set also the new variants TCL_ALLOCATOR=(aNATIVE|aPURIFY|aZIPPY|aMULTI) - Makefile.in and autoconferry changes in windows, mac - choose allocators from the command line instead of env vars? - verify interaction with memdebug (should be 'none', but ...) * MAYBE - build zippy as malloc-replacement, compile always aNATIVE and preload alternatives |
Changes to generic/tclAlloc.c.
1 2 3 | /* * tclAlloc.c -- * | | < < | < | < < < > > > < < > > > | | < < | < | > > > | < < < < | | < < < < < < < > > | | | < < < < < < < < < < < < < < > > | < > > > > > > < < | | > > > > > > | > | | | < < < < | > > > > > > > | < < > > > > > < < | | > | > > | < < < > | > | < < | < > > | < < > | < > > | > > < < < | > > < < | > | | < > | | < | < > > | > | < > > | | < < < < < | > | | | < > > | | | | > > > > | > > | | | > > > > > > > | | > > > > > | | < < < > | < < | < < | | < < | < < < < | < | < < < | | < < | < < < < < < < < | | < > | > | < > < < < | | < | < < > | > | > > < < > < < | < | | < < | < > > > | < < | < < < < | > | > | | > | > | | < < < | > | > | | > | > < < | | > | | < < < | | | < | < < < > | | | < | < | > > | > | > > > > > > > | > > | | < > | < < | > > > > | < < < < > > > > | < < < | | < < | | < < | | | | | | < < < | | < < < < > > > | < < | < > < < < < | < < > > | > | | < | > | > | > | < < < > | | < < < < < < < | < < < | < < | < < < < < < | < < < < < < < | < < < < | < < < < < < | < < < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | < < < < < < < < < < < < < < | < < < < < < < < < < < | < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < | < < < | > < < | < < < < | < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | < | < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | /* * tclAlloc.c -- * * This is the generic part of the Tcl allocator. It handles the * freeObjLists and defines which main allocator will be used. * * Copyright (c) 2013 by Miguel Sofer. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclAlloc.h" /* * Parameters for the per-thread Tcl_Obj cache: * - if >NOBJHIGH free objects, move some to the shared cache * - if no objects are available, create NOBJALLOC of them */ #define NOBJHIGH 1200 #define NOBJALLOC ((NOBJHIGH*2)/3) /* * The Tcl_Obj per-thread cache. */ typedef struct Cache { Tcl_Obj *firstObjPtr; /* List of free objects for thread */ int numObjects; /* Number of objects for thread */ void *allocCachePtr; } Cache; static Cache sharedCache; #define sharedPtr (&sharedCache) #if defined(TCL_THREADS) static Tcl_Mutex *objLockPtr; static Cache * GetCache(void); static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove); #if defined(HAVE_FAST_TSD) static __thread Cache *tcachePtr; # define GETCACHE(cachePtr) \ do { \ if (!tcachePtr) { \ tcachePtr = GetCache(); \ } \ (cachePtr) = tcachePtr; \ } while (0) #else /* THREADS, not HAVE_FAST_TSD */ # define GETCACHE(cachePtr) \ do { \ (cachePtr) = TclpGetAllocCache(); \ if ((cachePtr) == NULL) { \ (cachePtr) = GetCache(); \ } \ } while (0) #endif /* FAST TSD */ #else /* NOT THREADS */ #define GETCACHE(cachePtr) \ (cachePtr) = (&sharedCache) #endif /* THREADS */ /* *---------------------------------------------------------------------- * * GetCache --- * * Gets per-thread memory cache, allocating it if necessary. * * Results: * Pointer to cache. * * Side effects: * None. * *---------------------------------------------------------------------- */ #if defined(TCL_THREADS) static Cache * GetCache(void) { Cache *cachePtr; /* * Get this thread's cache, allocating if necessary. */ cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { cachePtr = calloc(1, sizeof(Cache)); if (cachePtr == NULL) { Tcl_Panic("alloc: could not allocate new cache"); } cachePtr->allocCachePtr= NULL; TclpSetAllocCache(cachePtr); } return cachePtr; } #endif /* * TclSetSharedAllocCache, TclSetAllocCache, TclGetAllocCache * * These are utility functions for the loadable allocator. */ void TclSetSharedAllocCache( void *allocCachePtr) { sharedPtr->allocCachePtr = allocCachePtr; } void TclSetAllocCache( void *allocCachePtr) { Cache *cachePtr; GETCACHE(cachePtr); cachePtr->allocCachePtr = allocCachePtr; } void * TclGetAllocCache(void) { Cache *cachePtr; GETCACHE(cachePtr); return cachePtr->allocCachePtr; } /* *------------------------------------------------------------------------- * * TclInitAlloc -- * * Initialize the memory system. * * Results: * None. * * Side effects: * Initialize the mutex used to serialize obj allocations. * Call the allocator-specific initialization. * *------------------------------------------------------------------------- */ void TclInitAlloc(void) { /* * Set the params for the correct allocator */ #if defined(TCL_THREADS) Tcl_Mutex *initLockPtr; TCL_THREADED = 1; initLockPtr = Tcl_GetAllocMutex(); Tcl_MutexLock(initLockPtr); objLockPtr = TclpNewAllocMutex(); TclXpInitAlloc(); Tcl_MutexUnlock(initLockPtr); #else TCL_THREADED = 0; TclXpInitAlloc(); #endif /* THREADS */ #ifdef PURIFY TCL_PURIFY = 1; #else TCL_PURIFY = (getenv("TCL_PURIFY") != NULL); #endif } /* *---------------------------------------------------------------------- * * TclFinalizeAlloc -- * * This procedure is used to destroy all private resources used in this * file. * * Results: * None. * * Side effects: * Call the allocator-specific finalization. * *---------------------------------------------------------------------- */ void TclFinalizeAlloc(void) { #if defined(TCL_THREADS) TclpFreeAllocMutex(objLockPtr); objLockPtr = NULL; TclpFreeAllocCache(NULL); #endif TclXpFinalizeAlloc(); } /* *---------------------------------------------------------------------- * * TclFreeAllocCache -- * * Flush and delete a cache, removing from list of caches. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #if defined(TCL_THREADS) void TclFreeAllocCache( void *arg) { Cache *cachePtr = arg; /* * Flush objs. */ if (cachePtr->numObjects > 0) { Tcl_MutexLock(objLockPtr); MoveObjs(cachePtr, sharedPtr, cachePtr->numObjects); Tcl_MutexUnlock(objLockPtr); } /* * Flush the external allocator cache */ TclXpFreeAllocCache(cachePtr->allocCachePtr); } #endif /* *---------------------------------------------------------------------- * * TclSmallAlloc -- * * Allocate a Tcl_Obj sized block from the per-thread cache. * * Results: * Pointer to uninitialized memory. * * Side effects: * May move blocks from shared cached or allocate new blocks if * list is empty. * *---------------------------------------------------------------------- */ void * TclSmallAlloc(void) { register Cache *cachePtr; register Tcl_Obj *objPtr; int numMove; Tcl_Obj *newObjsPtr; GETCACHE(cachePtr); /* * Pop the first object. */ if(cachePtr->firstObjPtr) { haveObj: objPtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr->internalRep.otherValuePtr; cachePtr->numObjects--; return objPtr; } /* * Do it AFTER looking at the queue, so that it doesn't slow down * non-purify small allocs. */ if (TCL_PURIFY) { Tcl_Obj *objPtr = (Tcl_Obj *) TclpAlloc(sizeof(Tcl_Obj)); if (objPtr == NULL) { Tcl_Panic("alloc: could not allocate a new object"); } return objPtr; } /* * Get this thread's obj list structure and move or allocate new objs if * necessary. */ #if defined(TCL_THREADS) Tcl_MutexLock(objLockPtr); numMove = sharedPtr->numObjects; if (numMove > 0) { if (numMove > NOBJALLOC) { numMove = NOBJALLOC; } MoveObjs(sharedPtr, cachePtr, numMove); } Tcl_MutexUnlock(objLockPtr); if (cachePtr->firstObjPtr) { goto haveObj; } #endif cachePtr->numObjects = numMove = NOBJALLOC; newObjsPtr = malloc(sizeof(Tcl_Obj) * numMove); if (newObjsPtr == NULL) { Tcl_Panic("alloc: could not allocate %d new objects", numMove); } while (--numMove >= 0) { objPtr = &newObjsPtr[numMove]; objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; } goto haveObj; } /* *---------------------------------------------------------------------- * * TclSmallFree -- * * Return a free Tcl_Obj-sized block to the per-thread cache. * * Results: * None. * * Side effects: * May move free blocks to shared list upon hitting high water mark. * *---------------------------------------------------------------------- */ void TclSmallFree( void *ptr) { Cache *cachePtr; Tcl_Obj *objPtr = ptr; if (TCL_PURIFY) { TclpFree((char *) ptr); return; } GETCACHE(cachePtr); /* * Get this thread's list and push on the free Tcl_Obj. */ objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; cachePtr->numObjects++; #if defined(TCL_THREADS) /* * If the number of free objects has exceeded the high water mark, move * some blocks to the shared list. */ if (cachePtr->numObjects > NOBJHIGH) { Tcl_MutexLock(objLockPtr); MoveObjs(cachePtr, sharedPtr, NOBJALLOC); Tcl_MutexUnlock(objLockPtr); } #endif } /* *---------------------------------------------------------------------- * * MoveObjs -- * * Move Tcl_Obj's between caches. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #if defined(TCL_THREADS) static void MoveObjs( Cache *fromPtr, Cache *toPtr, int numMove) { register Tcl_Obj *objPtr = fromPtr->firstObjPtr; Tcl_Obj *fromFirstObjPtr = objPtr; toPtr->numObjects += numMove; fromPtr->numObjects -= numMove; /* * Find the last object to be moved; set the next one (the first one not * to be moved) as the first object in the 'from' cache. */ while (--numMove) { objPtr = objPtr->internalRep.otherValuePtr; } fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr; /* * Move all objects as a block - they are already linked to each other, we * just have to update the first and last. */ objPtr->internalRep.otherValuePtr = toPtr->firstObjPtr; toPtr->firstObjPtr = fromFirstObjPtr; } #endif /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: |
︙ | ︙ |
Added generic/tclAlloc.h.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | /* * tclAlloc.h -- * * This defines the interface for pluggable memory allocators for Tcl. * * Copyright (c) 2013 by Miguel Sofer. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLALLOC #define _TCLALLOC /* * These functions must be exported by the allocator. */ char * TclpAlloc(unsigned int reqSize); char * TclpRealloc(char *ptr, unsigned int reqSize); void TclpFree(char *ptr); void * TclSmallAlloc(void); void TclSmallFree(void *ptr); void TclInitAlloc(void); void TclFinalizeAlloc(void); void TclFreeAllocCache(void *ptr); /* * The allocator should allow for "purify mode" by checking the environment * variable TCL_PURIFY at initialization. If it is set to any value, it should * just shunt to plain malloc. This is used for debugging; the value can be * treated as a constant, it does not change in a running process. */ /* * This macro is used to properly align the memory allocated by Tcl, giving * the same alignment as the native malloc. */ #if defined(__APPLE__) #define ALLOCALIGN 16 #else #define ALLOCALIGN (2*sizeof(void *)) #endif #define ALIGN(x) (((x) + ALLOCALIGN - 1) & ~(ALLOCALIGN - 1)) #endif |
Added generic/tclAllocNative.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | /* * tclAllocNative.c -- * * This is the basic native allocator for Tcl, using zippy's per-thread * free obj lists. * * Copyright (c) 2013 by Miguel Sofer. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #define OBJQ_ONLY 1 #include "tclAllocZippy.c" char * TclpAlloc( unsigned int reqSize) { return malloc(reqSize); } char * TclpRealloc( char *ptr, unsigned int reqSize) { return realloc(ptr, reqSize); } void TclpFree( char *ptr) { free(ptr); } |
Added generic/tclAllocPurify.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | /* * tclAllocPurify.c -- * * This is the native allocator for Tcl, suitable for preloading anything else. * * Copyright (c) 2013 by Miguel Sofer. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ /* This is needed just for sizeof(Tcl_Obj) and malloc*/ #include "tclInt.h" char * TclpAlloc( unsigned int reqSize) { return malloc(reqSize); } char * TclpRealloc( char *ptr, unsigned int reqSize) { return realloc(ptr, reqSize); } void TclpFree( char *ptr) { free(ptr); } void * TclSmallAlloc(void) { return malloc(sizeof(Tcl_Obj)); } void TclSmallFree( void *ptr) { free(ptr); } void TclInitAlloc(void) { } void TclFinalizeAlloc(void) { } void TclFreeAllocCache( void *ptr) { } |
Added generic/tclAllocZippy.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 | /* * tclAllocZippy.c -- * * This is a very fast storage allocator for used with threads (designed * avoid lock contention). The basic strategy is to allocate memory in * fixed size blocks from block caches. * * The Initial Developer of the Original Code is America Online, Inc. * Portions created by AOL are Copyright (C) 1999 America Online, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #define NATIVE_T (defined(OBJQ_ONLY) && defined(TCL_THREADS)) #define NATIVE_U (defined(OBJQ_ONLY) && !defined(TCL_THREADS)) #define NATIVE (NATIVE_T || NATIVE_U) #define ZIPPY_T (!defined(OBJQ_ONLY) && defined(TCL_THREADS)) #define ZIPPY_U (!defined(OBJQ_ONLY) && !defined(TCL_THREADS)) #define ZIPPY (ZIPPY_T || ZIPPY_U) /* * The following define the number of Tcl_Obj's to allocate/move at a time and * the high water mark to prune a per-thread cache. On a 32 bit system, * sizeof(Tcl_Obj) = 24 so 800 * 24 = ~16k. */ #define NOBJHIGH 1200 #define NOBJALLOC ((2*NOBJHIGH)/3) #if ZIPPY /* * If range checking is enabled, an additional byte will be allocated to store * the magic number at the end of the requested memory. */ #ifndef RCHECK #ifdef NDEBUG #define RCHECK 0 #else #define RCHECK 1 #endif #endif /* * This macro is used to properly align the memory allocated by Tcl, giving * the same alignment as the native malloc. */ #if defined(__APPLE__) #define TCL_ALLOCALIGN 16 #else #define TCL_ALLOCALIGN (2*sizeof(void *)) #endif #define ALIGN(x) (((x) + TCL_ALLOCALIGN - 1) & ~(TCL_ALLOCALIGN - 1)) /* * The following union stores accounting information for each block including * two small magic numbers and a bucket number when in use or a next pointer * when free. The original requested size (not including the Block overhead) * is also maintained. */ typedef union Block { struct { union { union Block *next; /* Next in free list. */ struct { unsigned char magic1; /* First magic number. */ unsigned char bucket; /* Bucket block allocated from. */ unsigned char unused; /* Padding. */ unsigned char magic2; /* Second magic number. */ } s; } u; size_t reqSize; /* Requested allocation size. */ } b; unsigned char padding[TCL_ALLOCALIGN]; } Block; #define nextBlock b.u.next #define sourceBucket b.u.s.bucket #define magicNum1 b.u.s.magic1 #define magicNum2 b.u.s.magic2 #define MAGIC 0xEF #define blockReqSize b.reqSize /* * The following defines the minimum and and maximum block sizes and the number * of buckets in the bucket cache. */ #define MINALLOC ((sizeof(Block) + 8 + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1)) #define NBUCKETS (11 - (MINALLOC >> 5)) #define MAXALLOC (MINALLOC << (NBUCKETS - 1)) /* * The following structure defines a bucket of blocks with various accounting * and statistics information. */ typedef struct Bucket { Block *firstPtr; /* First block available */ long numFree; /* Number of blocks available */ /* All fields below for accounting only */ #if ZIPPY long numRemoves; /* Number of removes from bucket */ long numInserts; /* Number of inserts into bucket */ long numWaits; /* Number of waits to acquire a lock */ long numLocks; /* Number of locks acquired */ long totalAssigned; /* Total space assigned to bucket */ #endif } Bucket; #endif /* ZIPPY */ /* * The following structure defines a cache of buckets and objs, of which there * will be (at most) one per thread. Any changes need to be reflected in the * struct AllocCache defined in tclInt.h, possibly also in the initialisation * code in Tcl_CreateInterp(). */ typedef struct Cache { Tcl_Obj *firstObjPtr; /* List of free objects for thread */ int numObjects; /* Number of objects for thread */ #if ZIPPY struct Cache *nextPtr; /* Linked list of cache entries */ int totalAssigned; /* Total space assigned to thread */ Bucket buckets[NBUCKETS]; /* The buckets for this thread */ Tcl_ThreadId owner; /* Which thread's cache is this? */ #endif } Cache; #if ZIPPY /* * The following array specifies various per-bucket limits and locks. The * values are statically initialized to avoid calculating them repeatedly. */ static struct { size_t blockSize; /* Bucket blocksize. */ int maxBlocks; /* Max blocks before move to share. */ #if ZIPPY_T int numMove; /* Num blocks to move to share. */ Tcl_Mutex *lockPtr; /* Share bucket lock. */ #endif } bucketInfo[NBUCKETS]; #endif /* ZIPPY */ /* * Static functions defined in this file. */ #if ZIPPY #if ZIPPY_T static Cache * GetCache(void); static void LockBucket(Cache *cachePtr, int bucket); static void UnlockBucket(Cache *cachePtr, int bucket); static void PutBlocks(Cache *cachePtr, int bucket, int numMove); static int GetBlocks(Cache *cachePtr, int bucket); #else /* ZIPPY_U */ #define GetBlocks(cachePtr, bucket) 0 #endif /* ZIPPY_U */ static void InitBuckets(void); static Block * Ptr2Block(char *ptr); static char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize); #endif /* ZIPPY */ #ifdef TCL_THREADS static void MoveObjs(Cache *fromPtr, Cache *toPtr, int numMove); #endif /* * Local variables defined in this file and initialized at startup. */ static Cache sharedCache; static Cache *sharedPtr = &sharedCache; #ifdef TCL_THREADS static Tcl_Mutex *objLockPtr; #if ZIPPY_T static Tcl_Mutex *listLockPtr; static Cache *firstCachePtr = &sharedCache; #endif #if defined(HAVE_FAST_TSD) static __thread Cache *tcachePtr; # define GETCACHE(cachePtr) \ do { \ if (!tcachePtr) { \ tcachePtr = GetCache(); \ } \ (cachePtr) = tcachePtr; \ } while (0) #else /* FAST_TSD */ # define GETCACHE(cachePtr) \ do { \ (cachePtr) = TclpGetAllocCache(); \ if ((cachePtr) == NULL) { \ (cachePtr) = GetCache(); \ } \ } while (0) #endif /* FAST_TSD */ #else /* TCL_THREADS */ #define GETCACHE(cachePtr) \ (cachePtr) = sharedPtr #endif /* *---------------------------------------------------------------------- * * GetCache --- * * Gets per-thread memory cache, allocating it if necessary. * * Results: * Pointer to cache. * * Side effects: * None. * *---------------------------------------------------------------------- */ #if ZIPPY static void InitBuckets(void) { int i; for (i = 0; i < NBUCKETS; ++i) { bucketInfo[i].blockSize = MINALLOC << i; bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i); #if ZIPPY_T bucketInfo[i].numMove = i < NBUCKETS - 1 ? 1 << (NBUCKETS - 2 - i) : 1; bucketInfo[i].lockPtr = TclpNewAllocMutex(); #endif } } #endif #ifdef TCL_THREADS static Cache * GetCache(void) { Cache *cachePtr; /* * Get this thread's cache, allocating if necessary. */ cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { cachePtr = calloc(1, sizeof(Cache)); if (cachePtr == NULL) { Tcl_Panic("alloc: could not allocate new cache"); } #if ZIPPY_T Tcl_MutexLock(listLockPtr); cachePtr->nextPtr = firstCachePtr; firstCachePtr = cachePtr; Tcl_MutexUnlock(listLockPtr); cachePtr->owner = Tcl_GetCurrentThread(); #endif TclpSetAllocCache(cachePtr); } return cachePtr; } #endif /* *---------------------------------------------------------------------- * * TclFreeAllocCache -- * * Flush and delete a cache, removing from list of caches. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_THREADS void TclFreeAllocCache( void *arg) { Cache *cachePtr = arg; #if ZIPPY_T Cache **nextPtrPtr; register unsigned int bucket; /* * Flush blocks. */ for (bucket = 0; bucket < NBUCKETS; ++bucket) { if (cachePtr->buckets[bucket].numFree > 0) { PutBlocks(cachePtr, bucket, cachePtr->buckets[bucket].numFree); } } /* * Remove from pool list. */ Tcl_MutexLock(listLockPtr); nextPtrPtr = &firstCachePtr; while (*nextPtrPtr != cachePtr) { nextPtrPtr = &(*nextPtrPtr)->nextPtr; } *nextPtrPtr = cachePtr->nextPtr; cachePtr->nextPtr = NULL; Tcl_MutexUnlock(listLockPtr); #endif /* * Flush objs. */ if (cachePtr->numObjects > 0) { Tcl_MutexLock(objLockPtr); MoveObjs(cachePtr, sharedPtr, cachePtr->numObjects); Tcl_MutexUnlock(objLockPtr); } free(cachePtr); } #endif /* TCL_THREADS */ /* *---------------------------------------------------------------------- * * TclpAlloc -- * * Allocate memory. * * Results: * Pointer to memory just beyond Block pointer. * * Side effects: * May allocate more blocks for a bucket. * *---------------------------------------------------------------------- */ #if ZIPPY char * TclpAlloc( unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; register int bucket; size_t size; #ifndef __LP64__ if (sizeof(int) >= sizeof(size_t)) { /* An unsigned int overflow can also be a size_t overflow */ const size_t zero = 0; const size_t max = ~zero; if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } #endif GETCACHE(cachePtr); /* * Increment the requested size to include room for the Block structure. * Call malloc() directly if the required amount is greater than the * largest block, otherwise pop the smallest block large enough, * allocating more blocks if necessary. */ blockPtr = NULL; size = reqSize + sizeof(Block); #if RCHECK size++; #endif if (size > MAXALLOC) { bucket = NBUCKETS; blockPtr = malloc(size); if (blockPtr != NULL) { cachePtr->totalAssigned += reqSize; } } else { bucket = 0; while (bucketInfo[bucket].blockSize < size) { bucket++; } if (cachePtr->buckets[bucket].numFree || GetBlocks(cachePtr, bucket)) { blockPtr = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr->nextBlock; #if ZIPPY_T cachePtr->buckets[bucket].numFree--; cachePtr->buckets[bucket].numRemoves++; cachePtr->buckets[bucket].totalAssigned += reqSize; #endif } } if (blockPtr == NULL) { return NULL; } return Block2Ptr(blockPtr, bucket, reqSize); } /* *---------------------------------------------------------------------- * * TclpFree -- * * Return blocks to the thread block cache. * * Results: * None. * * Side effects: * May move blocks to shared cache. * *---------------------------------------------------------------------- */ void TclpFree( char *ptr) { Cache *cachePtr; Block *blockPtr; int bucket; if (ptr == NULL) { return; } GETCACHE(cachePtr); /* * Get the block back from the user pointer and call system free directly * for large blocks. Otherwise, push the block back on the bucket and move * blocks to the shared cache if there are now too many free. */ blockPtr = Ptr2Block(ptr); bucket = blockPtr->sourceBucket; if (bucket == NBUCKETS) { cachePtr->totalAssigned -= blockPtr->blockReqSize; free(blockPtr); return; } cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; cachePtr->buckets[bucket].numFree++; cachePtr->buckets[bucket].numInserts++; #if ZIPPY_T if (cachePtr != sharedPtr && cachePtr->buckets[bucket].numFree > bucketInfo[bucket].maxBlocks) { PutBlocks(cachePtr, bucket, bucketInfo[bucket].numMove); } #endif } /* *---------------------------------------------------------------------- * * TclpRealloc -- * * Re-allocate memory to a larger or smaller size. * * Results: * Pointer to memory just beyond Block pointer. * * Side effects: * Previous memory, if any, may be freed. * *---------------------------------------------------------------------- */ char * TclpRealloc( char *ptr, unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; void *newPtr; size_t size, min; int bucket; if (ptr == NULL) { return TclpAlloc(reqSize); } #ifndef __LP64__ if (sizeof(int) >= sizeof(size_t)) { /* An unsigned int overflow can also be a size_t overflow */ const size_t zero = 0; const size_t max = ~zero; if (((size_t) reqSize) > max - sizeof(Block) - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } #endif GETCACHE(cachePtr); /* * If the block is not a system block and fits in place, simply return the * existing pointer. Otherwise, if the block is a system block and the new * size would also require a system block, call realloc() directly. */ blockPtr = Ptr2Block(ptr); size = reqSize + sizeof(Block); #if RCHECK size++; #endif bucket = blockPtr->sourceBucket; if (bucket != NBUCKETS) { if (bucket > 0) { min = bucketInfo[bucket-1].blockSize; } else { min = 0; } if (size > min && size <= bucketInfo[bucket].blockSize) { cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; cachePtr->buckets[bucket].totalAssigned += reqSize; return Block2Ptr(blockPtr, bucket, reqSize); } } else if (size > MAXALLOC) { cachePtr->totalAssigned -= blockPtr->blockReqSize; cachePtr->totalAssigned += reqSize; blockPtr = realloc(blockPtr, size); if (blockPtr == NULL) { return NULL; } return Block2Ptr(blockPtr, NBUCKETS, reqSize); } /* * Finally, perform an expensive malloc/copy/free. */ newPtr = TclpAlloc(reqSize); if (newPtr != NULL) { if (reqSize > blockPtr->blockReqSize) { reqSize = blockPtr->blockReqSize; } memcpy(newPtr, ptr, reqSize); TclpFree(ptr); } return newPtr; } #endif /* OBJQ_ONLY */ /* *---------------------------------------------------------------------- * * TclSmallAlloc -- * * Allocate a Tcl_Obj from the per-thread cache. * * Results: * Pointer to uninitialized Tcl_Obj. * * Side effects: * May move Tcl_Obj's from shared cached or allocate new Tcl_Obj's if * list is empty. * * Note: * If this code is updated, the changes need to be reflected in the macro * TclAllocObjStorageEx() defined in tclInt.h * *---------------------------------------------------------------------- */ void * TclSmallAlloc(void) { register Cache *cachePtr; register Tcl_Obj *objPtr; register int numMove; GETCACHE(cachePtr); /* * Get this thread's obj list structure and move or allocate new objs if * necessary. */ #if ZIPPY_T if (cachePtr->numObjects == 0) { Tcl_MutexLock(objLockPtr); numMove = sharedPtr->numObjects; if (numMove > 0) { if (numMove > NOBJALLOC) { numMove = NOBJALLOC; } MoveObjs(sharedPtr, cachePtr, numMove); } Tcl_MutexUnlock(objLockPtr); } #endif if (cachePtr->numObjects == 0) { Tcl_Obj *newObjsPtr; cachePtr->numObjects = numMove = NOBJALLOC; newObjsPtr = malloc(sizeof(Tcl_Obj) * numMove); if (newObjsPtr == NULL) { Tcl_Panic("alloc: could not allocate %d new objects", numMove); } while (--numMove >= 0) { objPtr = &newObjsPtr[numMove]; objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; } } /* * Pop the first object. */ objPtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr->internalRep.otherValuePtr; cachePtr->numObjects--; return objPtr; } /* *---------------------------------------------------------------------- * * TclSmallFree -- * * Return a free Tcl_Obj to the per-thread cache. * * Results: * None. * * Side effects: * May move free Tcl_Obj's to shared list upon hitting high water mark. * * Note: * If this code is updated, the changes need to be reflected in the macro * TclAllocObjStorageEx() defined in tclInt.h * *---------------------------------------------------------------------- */ void TclSmallFree( void *ptr) { Cache *cachePtr; Tcl_Obj *objPtr = ptr; GETCACHE(cachePtr); /* * Get this thread's list and push on the free Tcl_Obj. */ objPtr->internalRep.otherValuePtr = cachePtr->firstObjPtr; cachePtr->firstObjPtr = objPtr; cachePtr->numObjects++; /* * If the number of free objects has exceeded the high water mark, move * some blocks to the shared list. */ #if ZIPPY_T if (cachePtr->numObjects > NOBJHIGH) { Tcl_MutexLock(objLockPtr); MoveObjs(cachePtr, sharedPtr, NOBJALLOC); Tcl_MutexUnlock(objLockPtr); } #endif } /* *---------------------------------------------------------------------- * * Tcl_GetMemoryInfo -- * * Return a list-of-lists of memory stats. * * Results: * None. * * Side effects: * List appended to given dstring. * *---------------------------------------------------------------------- */ #if ZIPPY_T void Tcl_GetMemoryInfo( Tcl_DString *dsPtr) { Cache *cachePtr; char buf[200]; unsigned int n; Tcl_MutexLock(listLockPtr); cachePtr = firstCachePtr; while (cachePtr != NULL) { Tcl_DStringStartSublist(dsPtr); if (cachePtr == sharedPtr) { Tcl_DStringAppendElement(dsPtr, "shared"); } else { sprintf(buf, "thread%p", cachePtr->owner); Tcl_DStringAppendElement(dsPtr, buf); } for (n = 0; n < NBUCKETS; ++n) { sprintf(buf, "%lu %ld %ld %ld %ld %ld %ld", (unsigned long) bucketInfo[n].blockSize, cachePtr->buckets[n].numFree, cachePtr->buckets[n].numRemoves, cachePtr->buckets[n].numInserts, cachePtr->buckets[n].totalAssigned, cachePtr->buckets[n].numLocks, cachePtr->buckets[n].numWaits); Tcl_DStringAppendElement(dsPtr, buf); } Tcl_DStringEndSublist(dsPtr); cachePtr = cachePtr->nextPtr; } Tcl_MutexUnlock(listLockPtr); } #endif /* *---------------------------------------------------------------------- * * MoveObjs -- * * Move Tcl_Obj's between caches. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #ifdef TCL_THREADS static void MoveObjs( Cache *fromPtr, Cache *toPtr, int numMove) { register Tcl_Obj *objPtr = fromPtr->firstObjPtr; Tcl_Obj *fromFirstObjPtr = objPtr; toPtr->numObjects += numMove; fromPtr->numObjects -= numMove; /* * Find the last object to be moved; set the next one (the first one not * to be moved) as the first object in the 'from' cache. */ while (--numMove) { objPtr = objPtr->internalRep.otherValuePtr; } fromPtr->firstObjPtr = objPtr->internalRep.otherValuePtr; /* * Move all objects as a block - they are already linked to each other, we * just have to update the first and last. */ objPtr->internalRep.otherValuePtr = toPtr->firstObjPtr; toPtr->firstObjPtr = fromFirstObjPtr; } #endif /* *---------------------------------------------------------------------- * * Block2Ptr, Ptr2Block -- * * Convert between internal blocks and user pointers. * * Results: * User pointer or internal block. * * Side effects: * Invalid blocks will abort the server. * *---------------------------------------------------------------------- */ #if ZIPPY static char * Block2Ptr( Block *blockPtr, int bucket, unsigned int reqSize) { register void *ptr; blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC; blockPtr->sourceBucket = bucket; blockPtr->blockReqSize = reqSize; ptr = ((void *) (blockPtr + 1)); #if RCHECK ((unsigned char *)(ptr))[reqSize] = MAGIC; #endif return (char *) ptr; } static Block * Ptr2Block( char *ptr) { register Block *blockPtr; blockPtr = (((Block *) ptr) - 1); if (blockPtr->magicNum1 != MAGIC || blockPtr->magicNum2 != MAGIC) { Tcl_Panic("alloc: invalid block: %p: %x %x", blockPtr, blockPtr->magicNum1, blockPtr->magicNum2); } #if RCHECK if (((unsigned char *) ptr)[blockPtr->blockReqSize] != MAGIC) { Tcl_Panic("alloc: invalid block: %p: %x %x %x", blockPtr, blockPtr->magicNum1, blockPtr->magicNum2, ((unsigned char *) ptr)[blockPtr->blockReqSize]); } #endif return blockPtr; } #endif /* ZIPPY */ /* *---------------------------------------------------------------------- * * LockBucket, UnlockBucket -- * * Set/unset the lock to access a bucket in the shared cache. * * Results: * None. * * Side effects: * Lock activity and contention are monitored globally and on a per-cache * basis. * *---------------------------------------------------------------------- */ #if ZIPPY_T static void LockBucket( Cache *cachePtr, int bucket) { Tcl_MutexLock(bucketInfo[bucket].lockPtr); cachePtr->buckets[bucket].numLocks++; sharedPtr->buckets[bucket].numLocks++; } static void UnlockBucket( Cache *cachePtr, int bucket) { Tcl_MutexUnlock(bucketInfo[bucket].lockPtr); } #endif /* ZIPPY_T */ /* *---------------------------------------------------------------------- * * PutBlocks -- * * Return unused blocks to the shared cache. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ #if ZIPPY_T static void PutBlocks( Cache *cachePtr, int bucket, int numMove) { register Block *lastPtr, *firstPtr; register int n = numMove; /* * Before acquiring the lock, walk the block list to find the last block * to be moved. */ firstPtr = lastPtr = cachePtr->buckets[bucket].firstPtr; while (--n > 0) { lastPtr = lastPtr->nextBlock; } cachePtr->buckets[bucket].firstPtr = lastPtr->nextBlock; cachePtr->buckets[bucket].numFree -= numMove; /* * Aquire the lock and place the list of blocks at the front of the shared * cache bucket. */ LockBucket(cachePtr, bucket); lastPtr->nextBlock = sharedPtr->buckets[bucket].firstPtr; sharedPtr->buckets[bucket].firstPtr = firstPtr; sharedPtr->buckets[bucket].numFree += numMove; UnlockBucket(cachePtr, bucket); } #endif /* *---------------------------------------------------------------------- * * GetBlocks -- * * Get more blocks for a bucket. * * Results: * 1 if blocks where allocated, 0 otherwise. * * Side effects: * Cache may be filled with available blocks. * *---------------------------------------------------------------------- */ #if ZIPPY_T static int GetBlocks( Cache *cachePtr, int bucket) { register Block *blockPtr; register int n; /* * First, atttempt to move blocks from the shared cache. Note the * potentially dirty read of numFree before acquiring the lock which is a * slight performance enhancement. The value is verified after the lock is * actually acquired. */ if (cachePtr != sharedPtr && sharedPtr->buckets[bucket].numFree > 0) { LockBucket(cachePtr, bucket); if (sharedPtr->buckets[bucket].numFree > 0) { /* * Either move the entire list or walk the list to find the last * block to move. */ n = bucketInfo[bucket].numMove; if (n >= sharedPtr->buckets[bucket].numFree) { cachePtr->buckets[bucket].firstPtr = sharedPtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].numFree = sharedPtr->buckets[bucket].numFree; sharedPtr->buckets[bucket].firstPtr = NULL; sharedPtr->buckets[bucket].numFree = 0; } else { blockPtr = sharedPtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; sharedPtr->buckets[bucket].numFree -= n; cachePtr->buckets[bucket].numFree = n; while (--n > 0) { blockPtr = blockPtr->nextBlock; } sharedPtr->buckets[bucket].firstPtr = blockPtr->nextBlock; blockPtr->nextBlock = NULL; } } UnlockBucket(cachePtr, bucket); } if (cachePtr->buckets[bucket].numFree == 0) { register size_t size; /* * If no blocks could be moved from shared, first look for a larger * block in this cache to split up. */ blockPtr = NULL; n = NBUCKETS; size = 0; /* lint */ while (--n > bucket) { if (cachePtr->buckets[n].numFree > 0) { size = bucketInfo[n].blockSize; blockPtr = cachePtr->buckets[n].firstPtr; cachePtr->buckets[n].firstPtr = blockPtr->nextBlock; cachePtr->buckets[n].numFree--; break; } } /* * Otherwise, allocate a big new block directly. */ if (blockPtr == NULL) { size = MAXALLOC; blockPtr = malloc(size); if (blockPtr == NULL) { Tcl_Panic("FOO\n"); return 0; } } /* * Split the larger block into smaller blocks for this bucket. */ n = size / bucketInfo[bucket].blockSize; cachePtr->buckets[bucket].numFree = n; cachePtr->buckets[bucket].firstPtr = blockPtr; while (--n > 0) { blockPtr->nextBlock = (Block *) ((char *) blockPtr + bucketInfo[bucket].blockSize); blockPtr = blockPtr->nextBlock; } blockPtr->nextBlock = NULL; } return 1; } #endif /* ZIPPY_T */ /* *---------------------------------------------------------------------- * * TclFinalizeAlloc -- * * This procedure is used to destroy all private resources used in this * file. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclInitAlloc(void) { #ifdef TCL_THREADS #if ZIPPY_T listLockPtr = TclpNewAllocMutex(); InitBuckets(); #endif objLockPtr = TclpNewAllocMutex(); #endif #if ZIPPY_U InitBuckets(); #endif } void TclFinalizeAlloc(void) { #ifdef TCL_THREADS #if ZIPPY_T unsigned int i; for (i = 0; i < NBUCKETS; ++i) { TclpFreeAllocMutex(bucketInfo[i].lockPtr); bucketInfo[i].lockPtr = NULL; } TclpFreeAllocMutex(listLockPtr); listLockPtr = NULL; #endif TclpFreeAllocMutex(objLockPtr); objLockPtr = NULL; TclpFreeAllocCache(NULL); #endif } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclAssembly.c.
︙ | ︙ | |||
1160 1161 1162 1163 1164 1165 1166 | static AssemblyEnv* NewAssemblyEnv( CompileEnv* envPtr, /* Compilation environment being used for code * generation*/ int flags) /* Compilation flags (TCL_EVAL_DIRECT) */ { | < < | | | 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 | static AssemblyEnv* NewAssemblyEnv( CompileEnv* envPtr, /* Compilation environment being used for code * generation*/ int flags) /* Compilation flags (TCL_EVAL_DIRECT) */ { AssemblyEnv* assemEnvPtr = ckalloc(sizeof(AssemblyEnv)); /* Assembler environment under construction */ Tcl_Parse* parsePtr = ckalloc(sizeof(Tcl_Parse)); /* Parse of one line of assembly code */ assemEnvPtr->envPtr = envPtr; assemEnvPtr->parsePtr = parsePtr; assemEnvPtr->cmdLine = envPtr->line; assemEnvPtr->clNext = envPtr->clNext; |
︙ | ︙ | |||
1209 1210 1211 1212 1213 1214 1215 | *----------------------------------------------------------------------------- */ static void FreeAssemblyEnv( AssemblyEnv* assemEnvPtr) /* Environment to free */ { | < < < < < | 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 | *----------------------------------------------------------------------------- */ static void FreeAssemblyEnv( AssemblyEnv* assemEnvPtr) /* Environment to free */ { BasicBlock* thisBB; /* Pointer to a basic block being deleted */ BasicBlock* nextBB; /* Pointer to a deleted basic block's * successor */ /* * Free all the basic block structures. */ |
︙ | ︙ | |||
1242 1243 1244 1245 1246 1247 1248 | } /* * Dispose what's left. */ Tcl_DeleteHashTable(&assemEnvPtr->labelHash); | | | | 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 | } /* * Dispose what's left. */ Tcl_DeleteHashTable(&assemEnvPtr->labelHash); ckfree(assemEnvPtr->parsePtr); ckfree(assemEnvPtr); } /* *----------------------------------------------------------------------------- * * AssembleOneLine -- * |
︙ | ︙ |
Changes to generic/tclBasic.c.
︙ | ︙ | |||
721 722 723 724 725 726 727 | TclInitLimitSupport(interp); /* * Initialise the thread-specific data ekeko. Note that the thread's alloc * cache was already initialised by the call to alloc the interp struct. */ | < < < < < < | 721 722 723 724 725 726 727 728 729 730 731 732 733 734 | TclInitLimitSupport(interp); /* * Initialise the thread-specific data ekeko. Note that the thread's alloc * cache was already initialised by the call to alloc the interp struct. */ iPtr->asyncReadyPtr = TclGetAsyncReadyPtr(); iPtr->deferredCallbacks = NULL; /* * Create the core commands. Do it here, rather than calling * Tcl_CreateCommand, because it's faster (there's no need to check for a * pre-existing command by the same name). If a command has a Tcl_CmdProc |
︙ | ︙ | |||
2354 2355 2356 2357 2358 2359 2360 | ClientData clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ register int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Command *cmdPtr = clientData; int i, result; | | < | | 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 | ClientData clientData, /* Points to command's Command structure. */ Tcl_Interp *interp, /* Current interpreter. */ register int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { Command *cmdPtr = clientData; int i, result; const char **argv = ckalloc((unsigned)(objc + 1) * sizeof(char *)); for (i = 0; i < objc; i++) { argv[i] = Tcl_GetString(objv[i]); } argv[objc] = 0; /* * Invoke the command's string-based Tcl_CmdProc. */ result = cmdPtr->proc(cmdPtr->clientData, interp, objc, argv); ckfree((void *) argv); return result; } /* *---------------------------------------------------------------------- * * TclInvokeObjectCommand -- |
︙ | ︙ | |||
2403 2404 2405 2406 2407 2408 2409 | Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ register const char **argv) /* Argument strings. */ { Command *cmdPtr = clientData; Tcl_Obj *objPtr; int i, length, result; | | < | 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 | Tcl_Interp *interp, /* Current interpreter. */ int argc, /* Number of arguments. */ register const char **argv) /* Argument strings. */ { Command *cmdPtr = clientData; Tcl_Obj *objPtr; int i, length, result; Tcl_Obj **objv = ckalloc((unsigned)(argc * sizeof(Tcl_Obj *))); for (i = 0; i < argc; i++) { length = strlen(argv[i]); TclNewStringObj(objPtr, argv[i], length); Tcl_IncrRefCount(objPtr); objv[i] = objPtr; } |
︙ | ︙ | |||
2440 2441 2442 2443 2444 2445 2446 | * free the objv array if malloc'ed storage was used. */ for (i = 0; i < argc; i++) { objPtr = objv[i]; Tcl_DecrRefCount(objPtr); } | | | 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 | * free the objv array if malloc'ed storage was used. */ for (i = 0; i < argc; i++) { objPtr = objv[i]; Tcl_DecrRefCount(objPtr); } ckfree(objv); return result; } /* *---------------------------------------------------------------------- * * TclRenameCommand -- |
︙ | ︙ | |||
4571 4572 4573 4574 4575 4576 4577 | * to hold both the handler prefix and all words of the command invokation * itself. */ Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr, &handlerObjc, &handlerObjv); newObjc = objc + handlerObjc; | | | 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 | * to hold both the handler prefix and all words of the command invokation * itself. */ Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr, &handlerObjc, &handlerObjv); newObjc = objc + handlerObjc; newObjv = ckalloc((int) sizeof(Tcl_Obj *) * newObjc); /* * Copy command prefix from unknown handler and add on the real command's * full argument list. Note that we only use memcpy() once because we have * to increment the reference count of all the handler arguments anyway. */ |
︙ | ︙ | |||
4610 4611 4612 4613 4614 4615 4616 | * Release any resources we locked and allocated during the handler * call. */ for (i = 0; i < handlerObjc; ++i) { Tcl_DecrRefCount(newObjv[i]); } | | | 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 | * Release any resources we locked and allocated during the handler * call. */ for (i = 0; i < handlerObjc; ++i) { Tcl_DecrRefCount(newObjv[i]); } ckfree(newObjv); return TCL_ERROR; } if (lookupNsPtr) { savedNsPtr = varFramePtr->nsPtr; varFramePtr->nsPtr = lookupNsPtr; } |
︙ | ︙ | |||
4648 4649 4650 4651 4652 4653 4654 | /* * Release any resources we locked and allocated during the handler call. */ for (i = 0; i < objc; ++i) { Tcl_DecrRefCount(objv[i]); } | | | 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 | /* * Release any resources we locked and allocated during the handler call. */ for (i = 0; i < objc; ++i) { Tcl_DecrRefCount(objv[i]); } ckfree(objv); return result; } static int TEOV_RunEnterTraces( Tcl_Interp *interp, |
︙ | ︙ | |||
4945 4946 4947 4948 4949 4950 4951 | int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS); int gotParse = 0; unsigned int i, objectsUsed = 0; /* These variables keep track of how much * state has been allocated while evaluating * the script, so that it can be freed * properly if an error occurs. */ | | | | < | | | 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 | int allowExceptions = (iPtr->evalFlags & TCL_ALLOW_EXCEPTIONS); int gotParse = 0; unsigned int i, objectsUsed = 0; /* These variables keep track of how much * state has been allocated while evaluating * the script, so that it can be freed * properly if an error occurs. */ Tcl_Parse *parsePtr = ckalloc(sizeof(Tcl_Parse)); CmdFrame *eeFramePtr = ckalloc(sizeof(CmdFrame)); Tcl_Obj **stackObjArray = ckalloc(minObjs * sizeof(Tcl_Obj *)); int *expandStack = ckalloc(minObjs * sizeof(int)); int *linesStack = ckalloc(minObjs * sizeof(int)); /* TIP #280 Structures for tracking of command * locations. */ int *clNext = NULL; /* Pointer for the tracking of invisible * continuation lines. Initialized only if the * caller gave us a table of locations to * track, via scriptCLLocPtr. It always refers * to the table entry holding the location of |
︙ | ︙ | |||
5346 5347 5348 5349 5350 5351 5352 | * TIP #280. Release the local CmdFrame, and its contents. */ iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; if (eeFramePtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(eeFramePtr->data.eval.path); } | | | | | | | 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 | * TIP #280. Release the local CmdFrame, and its contents. */ iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; if (eeFramePtr->type == TCL_LOCATION_SOURCE) { Tcl_DecrRefCount(eeFramePtr->data.eval.path); } ckfree(linesStack); ckfree(expandStack); ckfree(stackObjArray); ckfree(eeFramePtr); ckfree(parsePtr); return code; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
5986 5987 5988 5989 5990 5991 5992 | * and TclInitCompileEnv), are special-cased to use the proper * line number directly instead of accessing the 'line' array. * * Note that we use (word==INTMIN) to signal that no command frame * should be pushed, as needed by alias and ensemble redirections. */ | | | 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 | * and TclInitCompileEnv), are special-cased to use the proper * line number directly instead of accessing the 'line' array. * * Note that we use (word==INTMIN) to signal that no command frame * should be pushed, as needed by alias and ensemble redirections. */ eoFramePtr = ckalloc(sizeof(CmdFrame)); eoFramePtr->nline = 0; eoFramePtr->line = NULL; eoFramePtr->type = TCL_LOCATION_EVAL_LIST; eoFramePtr->level = (iPtr->cmdFramePtr == NULL? 1 : iPtr->cmdFramePtr->level + 1); eoFramePtr->numLevels = iPtr->numLevels; |
︙ | ︙ | |||
6108 6109 6110 6111 6112 6113 6114 | * * First see if the word exists and is a literal. If not we go * through the easy dynamic branch. No need to perform more * complex invokations. */ int pc = 0; | | | 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 | * * First see if the word exists and is a literal. If not we go * through the easy dynamic branch. No need to perform more * complex invokations. */ int pc = 0; CmdFrame *ctxPtr = ckalloc(sizeof(CmdFrame)); *ctxPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctxPtr->data.eval.path is not used. * ctxPtr->data.tebc.codePtr is used instead. */ |
︙ | ︙ | |||
6149 6150 6151 6152 6153 6154 6155 | if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) { /* * Death of SrcInfo reference. */ Tcl_DecrRefCount(ctxPtr->data.eval.path); } | | | 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 | if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) { /* * Death of SrcInfo reference. */ Tcl_DecrRefCount(ctxPtr->data.eval.path); } ckfree(ctxPtr); } /* * Now release the lock on the continuation line information, if any, * and restore the caller's settings. */ |
︙ | ︙ | |||
6228 6229 6230 6231 6232 6233 6234 | /* * Remove the cmdFrame */ if (eoFramePtr) { iPtr->cmdFramePtr = eoFramePtr->nextPtr; | | | 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 | /* * Remove the cmdFrame */ if (eoFramePtr) { iPtr->cmdFramePtr = eoFramePtr->nextPtr; ckfree(eoFramePtr); } TclDecrRefCount(listPtr); return result; } /* |
︙ | ︙ |
Changes to generic/tclCkalloc.c.
︙ | ︙ | |||
1307 1308 1309 1310 1311 1312 1313 | TclpFree((char *) curTagPtr); curTagPtr = NULL; } allocHead = NULL; Tcl_MutexUnlock(ckallocMutexPtr); #endif | < < < < | 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 | TclpFree((char *) curTagPtr); curTagPtr = NULL; } allocHead = NULL; Tcl_MutexUnlock(ckallocMutexPtr); #endif } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 |
︙ | ︙ |
Changes to generic/tclCmdAH.c.
︙ | ︙ | |||
2412 2413 2414 2415 2416 2417 2418 | ForIterData *iterPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "start test next command"); return TCL_ERROR; } | | | 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 | ForIterData *iterPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "start test next command"); return TCL_ERROR; } TclCkSmallAlloc(sizeof(ForIterData), iterPtr); iterPtr->cond = objv[2]; iterPtr->body = objv[4]; iterPtr->next = objv[3]; iterPtr->msg = "\n (\"for\" body line %d)"; iterPtr->word = 4; TclNRAddCallback(interp, ForSetupCallback, iterPtr, NULL, NULL, NULL); |
︙ | ︙ | |||
2440 2441 2442 2443 2444 2445 2446 | { ForIterData *iterPtr = data[0]; if (result != TCL_OK) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" initial command)"); } | | | 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 | { ForIterData *iterPtr = data[0]; if (result != TCL_OK) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" initial command)"); } TclSmallFree(iterPtr); return result; } TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); return TCL_OK; } int |
︙ | ︙ | |||
2478 2479 2480 2481 2482 2483 2484 | result = TCL_OK; Tcl_ResetResult(interp); break; case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(iterPtr->msg, Tcl_GetErrorLine(interp))); } | | | | | | 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 | result = TCL_OK; Tcl_ResetResult(interp); break; case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(iterPtr->msg, Tcl_GetErrorLine(interp))); } TclSmallFree(iterPtr); return result; } static int ForCondCallback( ClientData data[], Tcl_Interp *interp, int result) { Interp *iPtr = (Interp *) interp; ForIterData *iterPtr = data[0]; Tcl_Obj *boolObj = data[1]; int value; if (result != TCL_OK) { Tcl_DecrRefCount(boolObj); TclSmallFree(iterPtr); return result; } else if (Tcl_GetBooleanFromObj(interp, boolObj, &value) != TCL_OK) { Tcl_DecrRefCount(boolObj); TclSmallFree(iterPtr); return TCL_ERROR; } Tcl_DecrRefCount(boolObj); if (value) { /* TIP #280. */ if (iterPtr->next) { TclNRAddCallback(interp, ForNextCallback, iterPtr, NULL, NULL, NULL); } else { TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); } return TclNREvalObjEx(interp, iterPtr->body, 0, iPtr->cmdFramePtr, iterPtr->word); } TclSmallFree(iterPtr); return result; } static int ForNextCallback( ClientData data[], Tcl_Interp *interp, |
︙ | ︙ | |||
2556 2557 2558 2559 2560 2561 2562 | int result) { ForIterData *iterPtr = data[0]; if ((result != TCL_BREAK) && (result != TCL_OK)) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" loop-end command)"); | | | 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 | int result) { ForIterData *iterPtr = data[0]; if ((result != TCL_BREAK) && (result != TCL_OK)) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" loop-end command)"); TclSmallFree(iterPtr); } return result; } TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, NULL, NULL); return result; } |
︙ | ︙ | |||
2656 2657 2658 2659 2660 2661 2662 | * statePtr->argvList[i]. * * The setting up of all of these pointers is moderately messy, but allows * the rest of this code to be simple and for us to use a single memory * allocation for better performance. */ | | | 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 | * statePtr->argvList[i]. * * The setting up of all of these pointers is moderately messy, but allows * the rest of this code to be simple and for us to use a single memory * allocation for better performance. */ statePtr = ckalloc( sizeof(struct ForeachState) + 3 * numLists * sizeof(int) + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *))); memset(statePtr, 0, sizeof(struct ForeachState) + 3 * numLists * sizeof(int) + 2 * numLists * (sizeof(Tcl_Obj **) + sizeof(Tcl_Obj *))); statePtr->varvList = (Tcl_Obj ***) (statePtr + 1); statePtr->argvList = statePtr->varvList + numLists; |
︙ | ︙ | |||
2879 2880 2881 2882 2883 2884 2885 | if (statePtr->aCopyList[i]) { TclDecrRefCount(statePtr->aCopyList[i]); } } if (statePtr->resultList != NULL) { TclDecrRefCount(statePtr->resultList); } | | | 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 | if (statePtr->aCopyList[i]) { TclDecrRefCount(statePtr->aCopyList[i]); } } if (statePtr->resultList != NULL) { TclDecrRefCount(statePtr->resultList); } ckfree(statePtr); } /* *---------------------------------------------------------------------- * * Tcl_FormatObjCmd -- * |
︙ | ︙ |
Changes to generic/tclCmdIL.c.
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | break; case TCL_LOCATION_BC: { /* * Execution of bytecode. Talk to the BC engine to fill out the frame. */ | | | 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 | break; case TCL_LOCATION_BC: { /* * Execution of bytecode. Talk to the BC engine to fill out the frame. */ CmdFrame *fPtr = ckalloc(sizeof(CmdFrame)); *fPtr = *framePtr; /* * Note: * Type BC => f.data.eval.path is not used. * f.data.tebc.codePtr is used instead. |
︙ | ︙ | |||
1369 1370 1371 1372 1373 1374 1375 | */ Tcl_DecrRefCount(fPtr->data.eval.path); } ADD_PAIR("cmd", Tcl_NewStringObj(fPtr->cmd.str.cmd, fPtr->cmd.str.len)); | | | 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 | */ Tcl_DecrRefCount(fPtr->data.eval.path); } ADD_PAIR("cmd", Tcl_NewStringObj(fPtr->cmd.str.cmd, fPtr->cmd.str.len)); ckfree(fPtr); break; } case TCL_LOCATION_SOURCE: /* * Evaluation of a script file. */ |
︙ | ︙ | |||
3055 3056 3057 3058 3059 3060 3061 | } break; case LSEARCH_INDEX: { /* -index */ Tcl_Obj **indices; int j; if (sortInfo.indexc > 1) { | | | 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 | } break; case LSEARCH_INDEX: { /* -index */ Tcl_Obj **indices; int j; if (sortInfo.indexc > 1) { ckfree(sortInfo.indexv); } if (i > objc-4) { if (startPtr != NULL) { Tcl_DecrRefCount(startPtr); } Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"-index\" option must be followed by list index", |
︙ | ︙ | |||
3091 3092 3093 3094 3095 3096 3097 | sortInfo.indexv = NULL; break; case 1: sortInfo.indexv = &sortInfo.singleIndex; break; default: sortInfo.indexv = | | | 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 | sortInfo.indexv = NULL; break; case 1: sortInfo.indexv = &sortInfo.singleIndex; break; default: sortInfo.indexv = ckalloc(sizeof(int) * sortInfo.indexc); } /* * Fill the array by parsing each index. We don't know whether * their scale is sensible yet, but we at least perform the * syntactic check here. */ |
︙ | ︙ | |||
3202 3203 3204 3205 3206 3207 3208 | /* * If the search started past the end of the list, we just return a * "did not match anything at all" result straight away. [Bug 1374778] */ if (offset > listc-1) { if (sortInfo.indexc > 1) { | | | 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 | /* * If the search started past the end of the list, we just return a * "did not match anything at all" result straight away. [Bug 1374778] */ if (offset > listc-1) { if (sortInfo.indexc > 1) { ckfree(sortInfo.indexv); } if (allMatches || inlineReturn) { Tcl_ResetResult(interp); } else { Tcl_SetObjResult(interp, Tcl_NewIntObj(-1)); } return TCL_OK; |
︙ | ︙ | |||
3527 3528 3529 3530 3531 3532 3533 | /* * Cleanup the index list array. */ done: if (sortInfo.indexc > 1) { | | | 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 | /* * Cleanup the index list array. */ done: if (sortInfo.indexc > 1) { ckfree(sortInfo.indexv); } return result; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3821 3822 3823 3824 3825 3826 3827 | sortInfo.indexv = NULL; break; case 1: sortInfo.indexv = &sortInfo.singleIndex; break; default: sortInfo.indexv = | | | 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 | sortInfo.indexv = NULL; break; case 1: sortInfo.indexv = &sortInfo.singleIndex; break; default: sortInfo.indexv = ckalloc(sizeof(int) * sortInfo.indexc); allocatedIndexVector = 1; /* Cannot use indexc field, as it * might be decreased by 1 later. */ } for (j=0 ; j<sortInfo.indexc ; j++) { TclGetIntForIndexM(interp, indexv[j], SORTIDX_END, &sortInfo.indexv[j]); } |
︙ | ︙ | |||
3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 | sortInfo.indexv = NULL; } else { sortInfo.indexc--; /* * Do not shrink the actual memory block used; that doesn't * work with TclStackAlloc-allocated memory. [Bug 2918962] */ for (i = 0; i < sortInfo.indexc; i++) { sortInfo.indexv[i] = sortInfo.indexv[i+1]; } } } | > | 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 | sortInfo.indexv = NULL; } else { sortInfo.indexc--; /* * Do not shrink the actual memory block used; that doesn't * work with TclStackAlloc-allocated memory. [Bug 2918962] * FIXME: TclStackAlloc is now retired, we could shrink it. */ for (i = 0; i < sortInfo.indexc; i++) { sortInfo.indexv[i] = sortInfo.indexv[i+1]; } } } |
︙ | ︙ | |||
3957 3958 3959 3960 3961 3962 3963 | } /* * The following loop creates a SortElement for each list element and * begins sorting it into the sublists as it appears. */ | | | 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 | } /* * The following loop creates a SortElement for each list element and * begins sorting it into the sublists as it appears. */ elementArray = ckalloc(length * sizeof(SortElement)); for (i=0; i < length; i++){ idx = groupSize * i + groupOffset; if (indexc) { /* * If this is an indexed sort, retrieve the corresponding element */ |
︙ | ︙ | |||
4081 4082 4083 4084 4085 4086 4087 | } } listRepPtr->elemCount = i; Tcl_SetObjResult(interp, resultPtr); } done1: | | | | 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 | } } listRepPtr->elemCount = i; Tcl_SetObjResult(interp, resultPtr); } done1: ckfree(elementArray); done: if (sortInfo.sortMode == SORTMODE_COMMAND) { TclDecrRefCount(sortInfo.compareCmdPtr); TclDecrRefCount(listObj); sortInfo.compareCmdPtr = NULL; } done2: if (allocatedIndexVector) { ckfree(sortInfo.indexv); } return sortInfo.resultCode; } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to generic/tclCmdMZ.c.
︙ | ︙ | |||
1899 1900 1901 1902 1903 1904 1905 | mapWithDict = 1; /* * Copy the dictionary out into an array; that's the easiest way to * adapt this code... */ | | | 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 | mapWithDict = 1; /* * Copy the dictionary out into an array; that's the easiest way to * adapt this code... */ mapElemv = ckalloc(sizeof(Tcl_Obj *) * mapElemc); Tcl_DictObjFirst(interp, objv[objc-2], &search, mapElemv+0, mapElemv+1, &done); for (i=2 ; i<mapElemc ; i+=2) { Tcl_DictObjNext(&search, mapElemv+i, mapElemv+i+1, &done); } Tcl_DictObjDone(&search); } else { |
︙ | ︙ | |||
2010 2011 2012 2013 2014 2015 2016 | /* * Precompute pointers to the unicode string and length. This saves us * repeated function calls later, significantly speeding up the * algorithm. We only need the lowercase first char in the nocase * case. */ | | | | | 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 | /* * Precompute pointers to the unicode string and length. This saves us * repeated function calls later, significantly speeding up the * algorithm. We only need the lowercase first char in the nocase * case. */ mapStrings = ckalloc(mapElemc*2*sizeof(Tcl_UniChar *)); mapLens = ckalloc(mapElemc * 2 * sizeof(int)); if (nocase) { u2lc = ckalloc(mapElemc * sizeof(Tcl_UniChar)); } for (index = 0; index < mapElemc; index++) { mapStrings[index] = Tcl_GetUnicodeFromObj(mapElemv[index], mapLens+index); if (nocase && ((index % 2) == 0)) { u2lc[index/2] = Tcl_UniCharToLower(*mapStrings[index]); } |
︙ | ︙ | |||
2063 2064 2065 2066 2067 2068 2069 | Tcl_AppendUnicodeToObj(resultPtr, mapStrings[index+1], mapLens[index+1]); break; } } } if (nocase) { | | | | | | 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 | Tcl_AppendUnicodeToObj(resultPtr, mapStrings[index+1], mapLens[index+1]); break; } } } if (nocase) { ckfree(u2lc); } ckfree(mapLens); ckfree(mapStrings); } if (p != ustring1) { /* * Put the rest of the unmapped chars onto result. */ Tcl_AppendUnicodeToObj(resultPtr, p, ustring1 - p); } Tcl_SetObjResult(interp, resultPtr); done: if (mapWithDict) { ckfree(mapElemv); } if (copySource) { Tcl_DecrRefCount(sourceObj); } return TCL_OK; } |
︙ | ︙ | |||
3849 3850 3851 3852 3853 3854 3855 | /* * We've got a match. Find a body to execute, skipping bodies that are * "-". */ matchFound: | | | 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 | /* * We've got a match. Find a body to execute, skipping bodies that are * "-". */ matchFound: ctxPtr = ckalloc(sizeof(CmdFrame)); *ctxPtr = *iPtr->cmdFramePtr; if (splitObjs) { /* * We have to perform the GetSrc and other type dependent handling of * the frame here because we are munging with the line numbers, * something the other commands like if, etc. are not doing. Them are |
︙ | ︙ | |||
3966 3967 3968 3969 3970 3971 3972 | int overflow = (patternLength > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s%s\" arm line %d)", (overflow ? limit : patternLength), pattern, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } | | | 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 | int overflow = (patternLength > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s%s\" arm line %d)", (overflow ? limit : patternLength), pattern, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } ckfree(ctxPtr); return result; } /* *---------------------------------------------------------------------- * * Tcl_ThrowObjCmd -- |
︙ | ︙ | |||
4746 4747 4748 4749 4750 4751 4752 | return TCL_ERROR; } /* * We reuse [for]'s callback, passing a NULL for the 'next' script. */ | | | 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 | return TCL_ERROR; } /* * We reuse [for]'s callback, passing a NULL for the 'next' script. */ TclCkSmallAlloc(sizeof(ForIterData), iterPtr); iterPtr->cond = objv[1]; iterPtr->body = objv[2]; iterPtr->next = NULL; iterPtr->msg = "\n (\"while\" body line %d)"; iterPtr->word = 2; TclNRAddCallback(interp, TclNRForIterCallback, iterPtr, NULL, |
︙ | ︙ |
Changes to generic/tclCompCmds.c.
︙ | ︙ | |||
1678 1679 1680 1681 1682 1683 1684 | * Assemble the instruction metadata. This is complex enough that it is * represented as auxData; it holds an ordered list of variable indices * that are to be used. */ duiPtr = ckalloc(sizeof(DictUpdateInfo) + sizeof(int) * (numVars - 1)); duiPtr->length = numVars; | < | | 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 | * Assemble the instruction metadata. This is complex enough that it is * represented as auxData; it holds an ordered list of variable indices * that are to be used. */ duiPtr = ckalloc(sizeof(DictUpdateInfo) + sizeof(int) * (numVars - 1)); duiPtr->length = numVars; keyTokenPtrs = ckalloc(sizeof(Tcl_Token *) * numVars); tokenPtr = TokenAfter(dictVarTokenPtr); for (i=0 ; i<numVars ; i++) { /* * Put keys to one side for later compilation to bytecode. */ |
︙ | ︙ | |||
1717 1718 1719 1720 1721 1722 1723 | goto failedUpdateInfoAssembly; } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { failedUpdateInfoAssembly: ckfree(duiPtr); | | | 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 | goto failedUpdateInfoAssembly; } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { failedUpdateInfoAssembly: ckfree(duiPtr); ckfree(keyTokenPtrs); return TclCompileBasicMin2ArgCmd(interp, parsePtr, cmdPtr, envPtr); } bodyTokenPtr = tokenPtr; /* * The list of variables to bind is stored in auxiliary data so that it * can't be snagged by literal sharing and forced to shimmer dangerously. |
︙ | ︙ | |||
1782 1783 1784 1785 1786 1787 1788 | TclEmitInt4( infoIndex, envPtr); TclEmitOpcode( INST_RETURN_STK, envPtr); if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { Tcl_Panic("TclCompileDictCmd(update): bad jump distance %d", (int) (CurrentOffset(envPtr) - jumpFixup.codeOffset)); } | | | 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 | TclEmitInt4( infoIndex, envPtr); TclEmitOpcode( INST_RETURN_STK, envPtr); if (TclFixupForwardJumpToHere(envPtr, &jumpFixup, 127)) { Tcl_Panic("TclCompileDictCmd(update): bad jump distance %d", (int) (CurrentOffset(envPtr) - jumpFixup.codeOffset)); } ckfree(keyTokenPtrs); envPtr->currStackDepth = savedStackDepth + 1; return TCL_OK; } int TclCompileDictAppendCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ |
︙ | ︙ | |||
2600 2601 2602 2603 2604 2605 2606 | bodyIndex = i-1; /* * Allocate storage for the varcList and varvList arrays if necessary. */ numLists = (numWords - 2)/2; | | | < | 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 | bodyIndex = i-1; /* * Allocate storage for the varcList and varvList arrays if necessary. */ numLists = (numWords - 2)/2; varcList = ckalloc(numLists * sizeof(int)); memset(varcList, 0, numLists * sizeof(int)); varvList = (const char ***) ckalloc(numLists * sizeof(const char **)); memset((char*) varvList, 0, numLists * sizeof(const char **)); /* * Break up each var list and set the varcList and varvList arrays. Don't * compile the foreach inline if any var name needs substitutions or isn't * a scalar, or if any var list needs substitutions. */ |
︙ | ︙ | |||
2855 2856 2857 2858 2859 2860 2861 | done: for (loopIndex = 0; loopIndex < numLists; loopIndex++) { if (varvList[loopIndex] != NULL) { ckfree(varvList[loopIndex]); } } | | | | 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 | done: for (loopIndex = 0; loopIndex < numLists; loopIndex++) { if (varvList[loopIndex] != NULL) { ckfree(varvList[loopIndex]); } } ckfree((void *)varvList); ckfree(varcList); return code; } /* *---------------------------------------------------------------------- * * DupForeachInfo -- |
︙ | ︙ | |||
5527 5528 5529 5530 5531 5532 5533 | return TCL_OK; } /* * Allocate some working space. */ | | | 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 | return TCL_OK; } /* * Allocate some working space. */ objv = ckalloc(numOptionWords * sizeof(Tcl_Obj *)); /* * Scan through the return options. If any are unknown at compile time, * there is no value in bytecompiling. Save the option values known in an * objv array for merging into a return options dictionary. */ |
︙ | ︙ | |||
5551 5552 5553 5554 5555 5556 5557 | } status = TclMergeReturnOptions(interp, objc, objv, &returnOpts, &code, &level); cleanup: while (--objc >= 0) { TclDecrRefCount(objv[objc]); } | | | 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 | } status = TclMergeReturnOptions(interp, objc, objv, &returnOpts, &code, &level); cleanup: while (--objc >= 0) { TclDecrRefCount(objv[objc]); } ckfree(objv); if (TCL_ERROR == status) { /* * Something was bogus in the return options. Clear the error message, * and report back to the compiler that this must be interpreted at * runtime. */ |
︙ | ︙ | |||
6098 6099 6100 6101 6102 6103 6104 | if ((elName != NULL) && elNameChars) { /* * An array element, the element name is a simple string: * assemble the corresponding token. */ | | | 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 | if ((elName != NULL) && elNameChars) { /* * An array element, the element name is a simple string: * assemble the corresponding token. */ elemTokenPtr = ckalloc(sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = elNameChars; elemTokenPtr->numComponents = 0; elemTokenCount = 1; } |
︙ | ︙ | |||
6151 6152 6153 6154 6155 6156 6157 | if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ | | | 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 | if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ elemTokenPtr = ckalloc(n * sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = remainingChars; elemTokenPtr->numComponents = 0; elemTokenCount = n; |
︙ | ︙ | |||
6240 6241 6242 6243 6244 6245 6246 | CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { | | | 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 | CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { ckfree(elemTokenPtr); } *localIndexPtr = localIndex; *simpleVarNamePtr = simpleVarName; *isScalarPtr = (elName == NULL); return TCL_OK; } |
︙ | ︙ |
Changes to generic/tclCompCmdsSZ.c.
︙ | ︙ | |||
733 734 735 736 737 738 739 | int code = TCL_ERROR; DefineLineInformation; /* TIP #280 */ if (numArgs == 0) { return TCL_ERROR; } | | | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 | int code = TCL_ERROR; DefineLineInformation; /* TIP #280 */ if (numArgs == 0) { return TCL_ERROR; } objv = ckalloc(/*numArgs*/ numOpts * sizeof(Tcl_Obj *)); for (objc = 0; objc < /*numArgs*/ numOpts; objc++) { objv[objc] = Tcl_NewObj(); Tcl_IncrRefCount(objv[objc]); if (!TclWordKnownAtCompileTime(wordTokenPtr, objv[objc])) { objc++; goto cleanup; |
︙ | ︙ | |||
766 767 768 769 770 771 772 | code = TclSubstOptions(NULL, numOpts, objv, &flags); } cleanup: while (--objc >= 0) { TclDecrRefCount(objv[objc]); } | | | 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 | code = TclSubstOptions(NULL, numOpts, objv, &flags); } cleanup: while (--objc >= 0) { TclDecrRefCount(objv[objc]); } ckfree(objv); if (/*toSubst == NULL*/ code != TCL_OK) { return TCL_ERROR; } SetLineInformation(numArgs); TclSubstCompile(interp, wordTokenPtr[1].start, wordTokenPtr[1].size, flags, mapPtr->loc[eclIndex].line[numArgs], envPtr); |
︙ | ︙ | |||
1427 1428 1429 1430 1431 1432 1433 | /* * Generate a test for each arm. */ contFixIndex = -1; contFixCount = 0; | | | | 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 | /* * Generate a test for each arm. */ contFixIndex = -1; contFixCount = 0; fixupArray = ckalloc(sizeof(JumpFixup) * numBodyTokens); fixupTargetArray = ckalloc(sizeof(int) * numBodyTokens); memset(fixupTargetArray, 0, numBodyTokens * sizeof(int)); fixupCount = 0; foundDefault = 0; for (i=0 ; i<numBodyTokens ; i+=2) { nextArmFixupIndex = -1; envPtr->currStackDepth = savedStackDepth + 1; if (i!=numBodyTokens-2 || bodyToken[numBodyTokens-2]->size != 7 || |
︙ | ︙ | |||
1627 1628 1629 1630 1631 1632 1633 | for (j=i-1 ; j>=0 ; j--) { if (fixupTargetArray[j] > fixupArray[i].codeOffset) { fixupTargetArray[j] += 3; } } } } | | | | 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 | for (j=i-1 ; j>=0 ; j--) { if (fixupTargetArray[j] > fixupArray[i].codeOffset) { fixupTargetArray[j] += 3; } } } } ckfree(fixupTargetArray); ckfree(fixupArray); envPtr->currStackDepth = savedStackDepth + 1; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
1690 1691 1692 1693 1694 1695 1696 | * * Start by allocating the jump table itself, plus some workspace. */ jtPtr = ckalloc(sizeof(JumptableInfo)); Tcl_InitHashTable(&jtPtr->hashTable, TCL_STRING_KEYS); infoIndex = TclCreateAuxData(jtPtr, &tclJumptableInfoType, envPtr); | | | 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | * * Start by allocating the jump table itself, plus some workspace. */ jtPtr = ckalloc(sizeof(JumptableInfo)); Tcl_InitHashTable(&jtPtr->hashTable, TCL_STRING_KEYS); infoIndex = TclCreateAuxData(jtPtr, &tclJumptableInfoType, envPtr); finalFixups = ckalloc(sizeof(int) * (numBodyTokens/2)); foundDefault = 0; mustGenerate = 1; /* * Next, issue the instruction to do the jump, together with what we want * to do if things do not work out (jump to either the default clause or * the "default" default, which just sets the result to empty). Note that |
︙ | ︙ | |||
1829 1830 1831 1832 1833 1834 1835 | envPtr->codeStart+finalFixups[i]+1); } /* * Clean up all our temporary space and return. */ | | | 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 | envPtr->codeStart+finalFixups[i]+1); } /* * Clean up all our temporary space and return. */ ckfree(finalFixups); envPtr->currStackDepth = savedStackDepth + 1; } /* *---------------------------------------------------------------------- * * DupJumptableInfo, FreeJumptableInfo -- |
︙ | ︙ | |||
2135 2136 2137 2138 2139 2140 2141 | /* * Extract information about what handlers there are. */ numHandlers = numWords >> 2; numWords -= numHandlers * 4; if (numHandlers > 0) { | | | | | | | 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 | /* * Extract information about what handlers there are. */ numHandlers = numWords >> 2; numWords -= numHandlers * 4; if (numHandlers > 0) { handlerTokens = ckalloc(sizeof(Tcl_Token*)*numHandlers); matchClauses = ckalloc(sizeof(Tcl_Obj *) * numHandlers); memset(matchClauses, 0, sizeof(Tcl_Obj *) * numHandlers); matchCodes = ckalloc(sizeof(int) * numHandlers); resultVarIndices = ckalloc(sizeof(int) * numHandlers); optionVarIndices = ckalloc(sizeof(int) * numHandlers); for (i=0 ; i<numHandlers ; i++) { Tcl_Obj *tmpObj, **objv; int objc; if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { goto failedToCompile; |
︙ | ︙ | |||
2299 2300 2301 2302 2303 2304 2305 | failedToCompile: if (numHandlers > 0) { for (i=0 ; i<numHandlers ; i++) { if (matchClauses[i]) { TclDecrRefCount(matchClauses[i]); } } | | | | | | | 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 | failedToCompile: if (numHandlers > 0) { for (i=0 ; i<numHandlers ; i++) { if (matchClauses[i]) { TclDecrRefCount(matchClauses[i]); } } ckfree(optionVarIndices); ckfree(resultVarIndices); ckfree(matchCodes); ckfree(matchClauses); ckfree(handlerTokens); } return result; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2380 2381 2382 2383 2384 2385 2386 | /* * Now we handle all the registered 'on' and 'trap' handlers in order. * For us to be here, there must be at least one handler. * * Slight overallocation, but reduces size of this function. */ | | | | 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 | /* * Now we handle all the registered 'on' and 'trap' handlers in order. * For us to be here, there must be at least one handler. * * Slight overallocation, but reduces size of this function. */ addrsToFix = ckalloc(sizeof(int)*numHandlers); forwardsToFix = ckalloc(sizeof(int)*numHandlers); for (i=0 ; i<numHandlers ; i++) { sprintf(buf, "%d", matchCodes[i]); OP( DUP); PUSH( buf); OP( EQ); JUMP(notCodeJumpSource, JUMP_FALSE4); |
︙ | ︙ | |||
2470 2471 2472 2473 2474 2475 2476 | * Fix all the jumps from taken clauses to here (which is the end of the * [try]). */ for (i=0 ; i<numHandlers ; i++) { FIXJUMP(addrsToFix[i]); } | | | | 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 | * Fix all the jumps from taken clauses to here (which is the end of the * [try]). */ for (i=0 ; i<numHandlers ; i++) { FIXJUMP(addrsToFix[i]); } ckfree(forwardsToFix); ckfree(addrsToFix); envPtr->currStackDepth = savedStackDepth + 1; return TCL_OK; } static int IssueTryFinallyInstructions( Tcl_Interp *interp, |
︙ | ︙ | |||
2535 2536 2537 2538 2539 2540 2541 | */ if (numHandlers) { /* * Slight overallocation, but reduces size of this function. */ | | | | 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 | */ if (numHandlers) { /* * Slight overallocation, but reduces size of this function. */ addrsToFix = ckalloc(sizeof(int)*numHandlers); forwardsToFix = ckalloc(sizeof(int)*numHandlers); for (i=0 ; i<numHandlers ; i++) { sprintf(buf, "%d", matchCodes[i]); OP( DUP); PUSH( buf); OP( EQ); JUMP(notCodeJumpSource, JUMP_FALSE4); |
︙ | ︙ | |||
2670 2671 2672 2673 2674 2675 2676 | * Fix all the jumps from taken clauses to here (the start of the * finally clause). */ for (i=0 ; i<numHandlers-1 ; i++) { FIXJUMP(addrsToFix[i]); } | | | | 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 | * Fix all the jumps from taken clauses to here (the start of the * finally clause). */ for (i=0 ; i<numHandlers-1 ; i++) { FIXJUMP(addrsToFix[i]); } ckfree(forwardsToFix); ckfree(addrsToFix); } /* * Drop the result code. */ OP( POP); |
︙ | ︙ | |||
3109 3110 3111 3112 3113 3114 3115 | if ((elName != NULL) && elNameChars) { /* * An array element, the element name is a simple string: * assemble the corresponding token. */ | | | 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 | if ((elName != NULL) && elNameChars) { /* * An array element, the element name is a simple string: * assemble the corresponding token. */ elemTokenPtr = ckalloc(sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = elNameChars; elemTokenPtr->numComponents = 0; elemTokenCount = 1; } |
︙ | ︙ | |||
3162 3163 3164 3165 3166 3167 3168 | if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ | | | 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 | if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ elemTokenPtr = ckalloc(n * sizeof(Tcl_Token)); allocedTokens = 1; elemTokenPtr->type = TCL_TOKEN_TEXT; elemTokenPtr->start = elName; elemTokenPtr->size = remainingChars; elemTokenPtr->numComponents = 0; elemTokenCount = n; |
︙ | ︙ | |||
3250 3251 3252 3253 3254 3255 3256 | CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { | | | 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 | CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { ckfree(elemTokenPtr); } *localIndexPtr = localIndex; *simpleVarNamePtr = simpleVarName; *isScalarPtr = (elName == NULL); return TCL_OK; } |
︙ | ︙ |
Changes to generic/tclCompExpr.c.
︙ | ︙ | |||
913 914 915 916 917 918 919 | goto error; } scanned = tokenPtr->size; break; case SCRIPT: { Tcl_Parse *nestedPtr = | | | 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 | goto error; } scanned = tokenPtr->size; break; case SCRIPT: { Tcl_Parse *nestedPtr = ckalloc(sizeof(Tcl_Parse)); tokenPtr = parsePtr->tokenPtr + parsePtr->numTokens; tokenPtr->type = TCL_TOKEN_COMMAND; tokenPtr->start = start; tokenPtr->numComponents = 0; end = start + numBytes; |
︙ | ︙ | |||
948 949 950 951 952 953 954 | parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->incomplete = 1; code = TCL_ERROR; errCode = "UNBALANCED"; break; } } | | | 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 | parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->incomplete = 1; code = TCL_ERROR; errCode = "UNBALANCED"; break; } } ckfree(nestedPtr); end = start; start = tokenPtr->start; scanned = end - start; tokenPtr->size = scanned; parsePtr->numTokens++; break; } /* SCRIPT case */ |
︙ | ︙ | |||
1831 1832 1833 1834 1835 1836 1837 | * the parsed expression; any previous * information in the structure is ignored. */ { int code; OpNode *opTree = NULL; /* Will point to the tree of operators. */ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals. */ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names. */ | | | 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 | * the parsed expression; any previous * information in the structure is ignored. */ { int code; OpNode *opTree = NULL; /* Will point to the tree of operators. */ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals. */ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names. */ Tcl_Parse *exprParsePtr = ckalloc(sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions. */ if (numBytes < 0) { numBytes = (start ? strlen(start) : 0); } code = ParseExpr(interp, start, numBytes, &opTree, litList, funcList, |
︙ | ︙ | |||
1853 1854 1855 1856 1857 1858 1859 | opTree, exprParsePtr->tokenPtr, parsePtr); } else { parsePtr->term = exprParsePtr->term; parsePtr->errorType = exprParsePtr->errorType; } Tcl_FreeParse(exprParsePtr); | | | 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 | opTree, exprParsePtr->tokenPtr, parsePtr); } else { parsePtr->term = exprParsePtr->term; parsePtr->errorType = exprParsePtr->errorType; } Tcl_FreeParse(exprParsePtr); ckfree(exprParsePtr); ckfree(opTree); return code; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2123 2124 2125 2126 2127 2128 2129 | int numBytes, /* Number of bytes in script. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int optimize) /* 0 for one-off expressions. */ { OpNode *opTree = NULL; /* Will point to the tree of operators */ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals */ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names*/ | | | 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 | int numBytes, /* Number of bytes in script. */ CompileEnv *envPtr, /* Holds resulting instructions. */ int optimize) /* 0 for one-off expressions. */ { OpNode *opTree = NULL; /* Will point to the tree of operators */ Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals */ Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names*/ Tcl_Parse *parsePtr = ckalloc(sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions */ int code = ParseExpr(interp, script, numBytes, &opTree, litList, funcList, parsePtr, 0 /* parseOnly */); if (code == TCL_OK) { /* |
︙ | ︙ | |||
2151 2152 2153 2154 2155 2156 2157 | CompileExprTree(interp, opTree, 0, &litObjv, funcObjv, parsePtr->tokenPtr, envPtr, optimize); } else { TclCompileSyntaxError(interp, envPtr); } Tcl_FreeParse(parsePtr); | | | 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 | CompileExprTree(interp, opTree, 0, &litObjv, funcObjv, parsePtr->tokenPtr, envPtr, optimize); } else { TclCompileSyntaxError(interp, envPtr); } Tcl_FreeParse(parsePtr); ckfree(parsePtr); Tcl_DecrRefCount(funcList); Tcl_DecrRefCount(litList); ckfree(opTree); } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
2194 2195 2196 2197 2198 2199 2200 | /* * Note we are compiling an expression with literal arguments. This means * there can be no [info frame] calls when we execute the resulting * bytecode, so there's no need to tend to TIP 280 issues. */ | | | | 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 | /* * Note we are compiling an expression with literal arguments. This means * there can be no [info frame] calls when we execute the resulting * bytecode, so there's no need to tend to TIP 280 issues. */ envPtr = ckalloc(sizeof(CompileEnv)); TclInitCompileEnv(interp, envPtr, NULL, 0, NULL, 0); CompileExprTree(interp, nodes, index, litObjvPtr, NULL, NULL, envPtr, 0 /* optimize */); TclEmitOpcode(INST_DONE, envPtr); Tcl_IncrRefCount(byteCodeObj); TclInitByteCodeObj(byteCodeObj, envPtr); TclFreeCompileEnv(envPtr); ckfree(envPtr); byteCodePtr = byteCodeObj->internalRep.twoPtrValue.ptr1; TclNRExecuteByteCode(interp, byteCodePtr); code = TclNRRunCallbacks(interp, TCL_OK, rootPtr); Tcl_DecrRefCount(byteCodeObj); return code; } |
︙ | ︙ | |||
2259 2260 2261 2262 2263 2264 2265 | JumpList *freePtr, *newJump; if (nodePtr->mark == MARK_LEFT) { next = nodePtr->left; switch (nodePtr->lexeme) { case QUESTION: | | | | | | | 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 | JumpList *freePtr, *newJump; if (nodePtr->mark == MARK_LEFT) { next = nodePtr->left; switch (nodePtr->lexeme) { case QUESTION: newJump = ckalloc(sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; newJump = ckalloc(sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; jumpPtr->depth = envPtr->currStackDepth; convert = 1; break; case AND: case OR: newJump = ckalloc(sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; newJump = ckalloc(sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; newJump = ckalloc(sizeof(JumpList)); newJump->next = jumpPtr; jumpPtr = newJump; jumpPtr->depth = envPtr->currStackDepth; break; } } else if (nodePtr->mark == MARK_RIGHT) { next = nodePtr->right; |
︙ | ︙ | |||
2382 2383 2384 2385 2386 2387 2388 | } TclFixupForwardJump(envPtr, &jumpPtr->jump, jumpPtr->offset - jumpPtr->jump.codeOffset, 127); convert |= jumpPtr->convert; envPtr->currStackDepth = jumpPtr->depth + 1; freePtr = jumpPtr; jumpPtr = jumpPtr->next; | | | | 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 | } TclFixupForwardJump(envPtr, &jumpPtr->jump, jumpPtr->offset - jumpPtr->jump.codeOffset, 127); convert |= jumpPtr->convert; envPtr->currStackDepth = jumpPtr->depth + 1; freePtr = jumpPtr; jumpPtr = jumpPtr->next; ckfree(freePtr); freePtr = jumpPtr; jumpPtr = jumpPtr->next; ckfree(freePtr); break; case AND: case OR: CLANG_ASSERT(jumpPtr); TclEmitForwardJump(envPtr, (nodePtr->lexeme == AND) ? TCL_FALSE_JUMP : TCL_TRUE_JUMP, &jumpPtr->next->jump); |
︙ | ︙ | |||
2409 2410 2411 2412 2413 2414 2415 | (nodePtr->lexeme == AND) ? "0" : "1", 1), envPtr); TclFixupForwardJumpToHere(envPtr, &jumpPtr->next->next->jump, 127); convert = 0; envPtr->currStackDepth = jumpPtr->depth + 1; freePtr = jumpPtr; jumpPtr = jumpPtr->next; | | | | | 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 | (nodePtr->lexeme == AND) ? "0" : "1", 1), envPtr); TclFixupForwardJumpToHere(envPtr, &jumpPtr->next->next->jump, 127); convert = 0; envPtr->currStackDepth = jumpPtr->depth + 1; freePtr = jumpPtr; jumpPtr = jumpPtr->next; ckfree(freePtr); freePtr = jumpPtr; jumpPtr = jumpPtr->next; ckfree(freePtr); freePtr = jumpPtr; jumpPtr = jumpPtr->next; ckfree(freePtr); break; default: TclEmitOpcode(instruction[nodePtr->lexeme], envPtr); convert = 0; break; } if (nodePtr == rootPtr) { |
︙ | ︙ | |||
2619 2620 2621 2622 2623 2624 2625 | { int code = TCL_OK; if (objc < 3) { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); } else { TclOpCmdClientData *occdPtr = clientData; | < | | | 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 | { int code = TCL_OK; if (objc < 3) { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); } else { TclOpCmdClientData *occdPtr = clientData; Tcl_Obj **litObjv = ckalloc(2 * (objc-2) * sizeof(Tcl_Obj *)); OpNode *nodes = ckalloc(2 * (objc-2) * sizeof(OpNode)); unsigned char lexeme; int i, lastAnd = 1; Tcl_Obj *const *litObjPtrPtr = litObjv; ParseLexeme(occdPtr->op, strlen(occdPtr->op), &lexeme, NULL); litObjv[0] = objv[1]; |
︙ | ︙ | |||
2661 2662 2663 2664 2665 2666 2667 | nodes[2*(objc-2)-1].right = OT_LITERAL; nodes[0].right = lastAnd; nodes[lastAnd].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr); | | | | 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 | nodes[2*(objc-2)-1].right = OT_LITERAL; nodes[0].right = lastAnd; nodes[lastAnd].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr); ckfree(nodes); ckfree(litObjv); } return code; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2748 2749 2750 2751 2752 2753 2754 | code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr); Tcl_DecrRefCount(litObjv[decrMe]); return code; } else { Tcl_Obj *const *litObjv = objv + 1; | | | 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 | code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr); Tcl_DecrRefCount(litObjv[decrMe]); return code; } else { Tcl_Obj *const *litObjv = objv + 1; OpNode *nodes = ckalloc((objc-1) * sizeof(OpNode)); int i, lastOp = OT_LITERAL; nodes[0].lexeme = START; nodes[0].mark = MARK_RIGHT; if (lexeme == EXPON) { for (i=objc-2; i>0; i--) { nodes[i].lexeme = lexeme; |
︙ | ︙ | |||
2781 2782 2783 2784 2785 2786 2787 | } } nodes[0].right = lastOp; nodes[lastOp].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjv); | | | 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 | } } nodes[0].right = lastOp; nodes[lastOp].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjv); ckfree(nodes); return code; } } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to generic/tclCompile.c.
︙ | ︙ | |||
1311 1312 1313 1314 1315 1316 1317 | /* * Initialize the compiler using the context, making counting absolute * to that context. Note that the context can be byte code execution. * In that case we have to fill out the missing pieces (line, path, * ...) which may make change the type as well. */ | | | 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 | /* * Initialize the compiler using the context, making counting absolute * to that context. Note that the context can be byte code execution. * In that case we have to fill out the missing pieces (line, path, * ...) which may make change the type as well. */ CmdFrame *ctxPtr = ckalloc(sizeof(CmdFrame)); int pc = 0; *ctxPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctx.data.eval.path is not used. * ctx.data.tebc.codePtr is used instead. |
︙ | ︙ | |||
1364 1365 1366 1367 1368 1369 1370 | */ Tcl_IncrRefCount(envPtr->extCmdMapPtr->path); } } } | | | 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 | */ Tcl_IncrRefCount(envPtr->extCmdMapPtr->path); } } } ckfree(ctxPtr); } envPtr->extCmdMapPtr->start = envPtr->line; /* * Initialize the data about invisible continuation lines as empty, i.e. * not used. The caller (TclSetByteCodeFromAny) will set this up, if such |
︙ | ︙ | |||
1570 1571 1572 1573 1574 1575 1576 | Command *cmdPtr; Tcl_Token *tokenPtr; int bytesLeft, isFirstCmd, wordIdx, currCmdIndex, commandLength, objIndex; Tcl_DString ds; /* TIP #280 */ ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr; int *wlines, wlineat, cmdLine, *clNext; | | | 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | Command *cmdPtr; Tcl_Token *tokenPtr; int bytesLeft, isFirstCmd, wordIdx, currCmdIndex, commandLength, objIndex; Tcl_DString ds; /* TIP #280 */ ExtCmdLoc *eclPtr = envPtr->extCmdMapPtr; int *wlines, wlineat, cmdLine, *clNext; Tcl_Parse *parsePtr = ckalloc(sizeof(Tcl_Parse)); Tcl_DStringInit(&ds); if (numBytes < 0) { numBytes = strlen(script); } Tcl_ResetResult(interp); |
︙ | ︙ | |||
2008 2009 2010 2011 2012 2013 2014 | */ if (envPtr->codeNext == entryCodeNext) { TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr); } envPtr->numSrcBytes = p - script; | | | 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 | */ if (envPtr->codeNext == entryCodeNext) { TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr); } envPtr->numSrcBytes = p - script; ckfree(parsePtr); Tcl_DStringFree(&ds); } /* *---------------------------------------------------------------------- * * TclCompileTokens -- |
︙ | ︙ |
Changes to generic/tclDictObj.c.
︙ | ︙ | |||
2395 2396 2397 2398 2399 2400 2401 | return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); return TCL_ERROR; } | | | | | 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 | return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); return TCL_ERROR; } searchPtr = ckalloc(sizeof(Tcl_DictSearch)); if (Tcl_DictObjFirst(interp, objv[2], searchPtr, &keyObj, &valueObj, &done) != TCL_OK) { ckfree(searchPtr); return TCL_ERROR; } if (done) { ckfree(searchPtr); return TCL_OK; } TclListObjGetElements(NULL, objv[1], &varc, &varv); keyVarObj = varv[0]; valueVarObj = varv[1]; scriptObj = objv[3]; |
︙ | ︙ | |||
2452 2453 2454 2455 2456 2457 2458 | */ error: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); | | | 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 | */ error: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); ckfree(searchPtr); return TCL_ERROR; } static int DictForLoopCallback( ClientData data[], Tcl_Interp *interp, |
︙ | ︙ | |||
2534 2535 2536 2537 2538 2539 2540 | */ done: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); | | | 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 | */ done: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); ckfree(searchPtr); return result; } /* *---------------------------------------------------------------------- * * DictMapNRCmd -- |
︙ | ︙ | |||
2586 2587 2588 2589 2590 2591 2592 | return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); return TCL_ERROR; } | | | | | 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 | return TCL_ERROR; } if (varc != 2) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "must have exactly two variable names", -1)); return TCL_ERROR; } storagePtr = ckalloc(sizeof(DictMapStorage)); if (Tcl_DictObjFirst(interp, objv[2], &storagePtr->search, &keyObj, &valueObj, &done) != TCL_OK) { ckfree(storagePtr); return TCL_ERROR; } if (done) { /* * Note that this exit leaves an empty value in the result (due to * command calling conventions) but that is OK since an empty value is * an empty dictionary. */ ckfree(storagePtr); return TCL_OK; } TclNewObj(storagePtr->accumulatorObj); TclListObjGetElements(NULL, objv[1], &varc, &varv); storagePtr->keyVarObj = varv[0]; storagePtr->valueVarObj = varv[1]; storagePtr->scriptObj = objv[3]; |
︙ | ︙ | |||
2655 2656 2657 2658 2659 2660 2661 | error: TclDecrRefCount(storagePtr->keyVarObj); TclDecrRefCount(storagePtr->valueVarObj); TclDecrRefCount(storagePtr->scriptObj); TclDecrRefCount(storagePtr->accumulatorObj); Tcl_DictObjDone(&storagePtr->search); | | | 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 | error: TclDecrRefCount(storagePtr->keyVarObj); TclDecrRefCount(storagePtr->valueVarObj); TclDecrRefCount(storagePtr->scriptObj); TclDecrRefCount(storagePtr->accumulatorObj); Tcl_DictObjDone(&storagePtr->search); ckfree(storagePtr); return TCL_ERROR; } static int DictMapLoopCallback( ClientData data[], Tcl_Interp *interp, |
︙ | ︙ | |||
2745 2746 2747 2748 2749 2750 2751 | done: TclDecrRefCount(storagePtr->keyVarObj); TclDecrRefCount(storagePtr->valueVarObj); TclDecrRefCount(storagePtr->scriptObj); TclDecrRefCount(storagePtr->accumulatorObj); Tcl_DictObjDone(&storagePtr->search); | | | 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 | done: TclDecrRefCount(storagePtr->keyVarObj); TclDecrRefCount(storagePtr->valueVarObj); TclDecrRefCount(storagePtr->scriptObj); TclDecrRefCount(storagePtr->accumulatorObj); Tcl_DictObjDone(&storagePtr->search); ckfree(storagePtr); return result; } /* *---------------------------------------------------------------------- * * DictSetCmd -- |
︙ | ︙ |
Changes to generic/tclEvent.c.
︙ | ︙ | |||
1039 1040 1041 1042 1043 1044 1045 1046 1047 | /* * Initialize locks used by the memory allocators before anything * interesting happens so we can use the allocators in the * implementation of self-initializing locks. */ TclInitThreadStorage(); /* Creates master hash table for * thread local storage */ | > < < < | 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 | /* * Initialize locks used by the memory allocators before anything * interesting happens so we can use the allocators in the * implementation of self-initializing locks. */ TclInitAlloc(); /* Process wide allocator init */ TclInitThreadStorage(); /* Creates master hash table for * thread local storage */ #ifdef TCL_MEM_DEBUG TclInitDbCkalloc(); /* Process wide mutex init */ #endif TclpInitPlatform(); /* Creates signal handler(s) */ TclInitDoubleConversion(); /* Initializes constants for * converting to/from double. */ |
︙ | ︙ | |||
1216 1217 1218 1219 1220 1221 1222 | /* * Free synchronization objects. There really should only be one thread * alive at this moment. */ TclFinalizeSynchronization(); | < < < < < < < < | 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 | /* * Free synchronization objects. There really should only be one thread * alive at this moment. */ TclFinalizeSynchronization(); /* * We defer unloading of packages until very late to avoid memory access * issues. Both exit callbacks and synchronization variables may be stored * in packages. * * Note that TclFinalizeLoad unloads packages in the reverse of the order * they were loaded in (i.e. last to be loaded is the first to be |
︙ | ︙ | |||
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 | TclResetFilesystem(); /* * At this point, there should no longer be any ckalloc'ed memory. */ TclFinalizeMemorySubsystem(); alreadyFinalized: TclFinalizeLock(); } /* *---------------------------------------------------------------------- | > > > > > > > > | 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 | TclResetFilesystem(); /* * At this point, there should no longer be any ckalloc'ed memory. */ TclFinalizeMemorySubsystem(); /* * Close down the thread-specific object allocator. */ TclFinalizeAlloc(); alreadyFinalized: TclFinalizeLock(); } /* *---------------------------------------------------------------------- |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
170 171 172 173 174 175 176 177 | * Helpers for NR - non-recursive calls to TEBC * Minimal data required to fully reconstruct the execution state. */ typedef struct TEBCdata { ByteCode *codePtr; /* Constant until the BC returns */ /* -----------------------------------------*/ const unsigned char *pc; /* These fields are used on return TO this */ | > | > | | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | * Helpers for NR - non-recursive calls to TEBC * Minimal data required to fully reconstruct the execution state. */ typedef struct TEBCdata { ByteCode *codePtr; /* Constant until the BC returns */ /* -----------------------------------------*/ Tcl_Obj **tosPtr; const unsigned char *pc; /* These fields are used on return TO this */ unsigned long catchDepth; /* this level: they record the state when a */ int cleanup; /* new codePtr was received for NR */ Tcl_Obj *auxObjList; /* execution. */ int checkInterp; unsigned int capacity; CmdFrame cmdFrame; void *stack[1]; /* Start of the actual combined catch and obj * stacks; the struct will be expanded as * necessary */ } TEBCdata; #define TEBC_YIELD() \ do { \ TD->tosPtr = tosPtr; \ TD->pc = pc; \ TD->cleanup = cleanup; \ TclNRAddCallback(interp, TEBCresume, TD, INT2PTR(1), NULL, NULL); \ } while (0) #define TEBC_DATA_DIG() \ do { \ pc = TD->pc; \ cleanup = TD->cleanup; \ tosPtr = TD->tosPtr; \ } while (0) #define PUSH_TAUX_OBJ(objPtr) \ do { \ objPtr->internalRep.ptrAndLongRep.ptr = auxObjList; \ auxObjList = objPtr; \ } while (0) |
︙ | ︙ | |||
311 312 313 314 315 316 317 | } \ goto cleanupV_pushObjResultPtr; \ } else { \ goto cleanupV; \ } \ } while (0) | < < < < < < < < < < < < < < | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 | } \ goto cleanupV_pushObjResultPtr; \ } else { \ goto cleanupV; \ } \ } while (0) /* * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT * increments the object's ref count since it makes the stack have another * reference pointing to the object. However, POP_OBJECT does not decrement * the ref count. This is because the stack may hold the only reference to the * object, so the object would be destroyed if its ref count were decremented * before the caller had a chance to, e.g., store it in a variable. It is the |
︙ | ︙ | |||
699 700 701 702 703 704 705 | static void PrintByteCodeInfo(ByteCode *codePtr); static const char * StringForResultCode(int result); static void ValidatePcAndStackTop(ByteCode *codePtr, const unsigned char *pc, int stackTop, int checkStack); #endif /* TCL_COMPILE_DEBUG */ static ByteCode * CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr); | < < < < < < < | 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 | static void PrintByteCodeInfo(ByteCode *codePtr); static const char * StringForResultCode(int result); static void ValidatePcAndStackTop(ByteCode *codePtr, const unsigned char *pc, int stackTop, int checkStack); #endif /* TCL_COMPILE_DEBUG */ static ByteCode * CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr); static void DupExprCodeInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); MODULE_SCOPE int TclCompareTwoNumbers(Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); static Tcl_Obj * ExecuteExtendedBinaryMathOp(Tcl_Interp *interp, int opcode, Tcl_Obj **constants, Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); static Tcl_Obj * ExecuteExtendedUnaryMathOp(int opcode, Tcl_Obj *valuePtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, int catchOnly, ByteCode *codePtr); static const char * GetSrcInfoForPc(const unsigned char *pc, ByteCode *codePtr, int *lengthPtr, const unsigned char **pcBeg); static void IllegalExprOperandType(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj *opndPtr); static void InitByteCodeExecution(Tcl_Interp *interp); static void ReleaseDictIterator(Tcl_Obj *objPtr); static Tcl_NRPostProc CopyCallback; static Tcl_NRPostProc ExprObjCallback; static Tcl_NRPostProc TEBCresume; /* * The structure below defines a bytecode Tcl object type to hold the |
︙ | ︙ | |||
861 862 863 864 865 866 867 | TclCreateExecEnv( Tcl_Interp *interp, /* Interpreter for which the execution * environment is being created. */ int size) /* The initial stack size, in number of words * [sizeof(Tcl_Obj*)] */ { ExecEnv *eePtr = ckalloc(sizeof(ExecEnv)); | < < < < < < < < < | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 | TclCreateExecEnv( Tcl_Interp *interp, /* Interpreter for which the execution * environment is being created. */ int size) /* The initial stack size, in number of words * [sizeof(Tcl_Obj*)] */ { ExecEnv *eePtr = ckalloc(sizeof(ExecEnv)); TclNewBooleanObj(eePtr->constants[0], 0); Tcl_IncrRefCount(eePtr->constants[0]); TclNewBooleanObj(eePtr->constants[1], 1); Tcl_IncrRefCount(eePtr->constants[1]); eePtr->interp = interp; eePtr->callbackPtr = NULL; eePtr->corPtr = NULL; eePtr->rewind = 0; Tcl_MutexLock(&execMutex); if (!execInitialized) { TclInitAuxDataTypeTable(); InitByteCodeExecution(interp); execInitialized = 1; } Tcl_MutexUnlock(&execMutex); |
︙ | ︙ | |||
908 909 910 911 912 913 914 | * Side effects: * Storage for an ExecEnv and its contained storage (e.g. the evaluation * stack) is freed. * *---------------------------------------------------------------------- */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 | * Side effects: * Storage for an ExecEnv and its contained storage (e.g. the evaluation * stack) is freed. * *---------------------------------------------------------------------- */ void TclDeleteExecEnv( ExecEnv *eePtr) /* Execution environment to free. */ { cachedInExit = TclInExit(); /* * Delete all stacks in this exec env. */ TclDecrRefCount(eePtr->constants[0]); TclDecrRefCount(eePtr->constants[1]); if (eePtr->callbackPtr && !cachedInExit) { Tcl_Panic("Deleting execEnv with pending TEOV callbacks!"); } if (eePtr->corPtr && !cachedInExit) { Tcl_Panic("Deleting execEnv with existing coroutine"); |
︙ | ︙ | |||
983 984 985 986 987 988 989 | TclFinalizeExecution(void) { Tcl_MutexLock(&execMutex); execInitialized = 0; Tcl_MutexUnlock(&execMutex); TclFinalizeAuxDataTypeTable(); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 927 928 929 930 931 932 933 934 935 936 937 938 939 940 | TclFinalizeExecution(void) { Tcl_MutexLock(&execMutex); execInitialized = 0; Tcl_MutexUnlock(&execMutex); TclFinalizeAuxDataTypeTable(); } /* *-------------------------------------------------------------- * * Tcl_ExprObj -- * * Evaluate an expression in a Tcl_Obj. |
︙ | ︙ | |||
1731 1732 1733 1734 1735 1736 1737 | if (!hePtr) { return codePtr; } eclPtr = Tcl_GetHashValue(hePtr); redo = 0; | | | 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 | if (!hePtr) { return codePtr; } eclPtr = Tcl_GetHashValue(hePtr); redo = 0; ctxCopyPtr = ckalloc(sizeof(CmdFrame)); *ctxCopyPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctx.data.eval.path is not used. * ctx.data.tebc.codePtr used instead */ |
︙ | ︙ | |||
1769 1770 1771 1772 1773 1774 1775 | redo = ((eclPtr->type == TCL_LOCATION_SOURCE) && (eclPtr->start != ctxCopyPtr->line[word])) || ((eclPtr->type == TCL_LOCATION_BC) && (ctxCopyPtr->type == TCL_LOCATION_SOURCE)); } | | | 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 | redo = ((eclPtr->type == TCL_LOCATION_SOURCE) && (eclPtr->start != ctxCopyPtr->line[word])) || ((eclPtr->type == TCL_LOCATION_BC) && (ctxCopyPtr->type == TCL_LOCATION_SOURCE)); } ckfree(ctxCopyPtr); if (!redo) { return codePtr; } } } recompileObj: |
︙ | ︙ | |||
1943 1944 1945 1946 1947 1948 1949 | * * Side effects: * Almost certainly, depending on the ByteCode's instructions. * *---------------------------------------------------------------------- */ #define bcFramePtr (&TD->cmdFrame) | | | | > > > > > > > > > > > > > > < < < < | < | > | | > | 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 | * * Side effects: * Almost certainly, depending on the ByteCode's instructions. * *---------------------------------------------------------------------- */ #define bcFramePtr (&TD->cmdFrame) #define catchStack (TD->stack) #define initTosPtr ((Tcl_Obj **) &TD->stack[codePtr->maxExceptDepth - 1]) /* * The execution uses a unified stack: first a TEBCdata, immediately * above it the catch stack, then the execution stack. * * Make sure the catch stack is large enough to hold the maximum number of * catch commands that could ever be executing at the same time (this will * be no more than the exception range array's depth). Make sure the * execution stack is large enough to execute this ByteCode. */ // FIXME! The "+1" should not be necessary, temporary until we fix BC issues #define capacity2size(cap) \ (offsetof(TEBCdata, stack) + sizeof(void *)*(cap + codePtr->maxExceptDepth + 1)) int TclNRExecuteByteCode( Tcl_Interp *interp, /* Token for command interpreter. */ ByteCode *codePtr) /* The bytecode sequence to interpret. */ { Interp *iPtr = (Interp *) interp; TEBCdata *TD; if (iPtr->execEnvPtr->rewind) { return TCL_ERROR; } codePtr->refCount++; /* * Reserve the stack, setup the TEBCdataPtr (TD) and CallFrame * * The execution uses a unified stack: first a TEBCdata, immediately * above it a CmdFrame, then the catch stack, then the execution stack. * * Make sure the catch stack is large enough to hold the maximum number of * catch commands that could ever be executing at the same time (this will * be no more than the exception range array's depth). Make sure the * execution stack is large enough to execute this ByteCode. */ TD = ckalloc(capacity2size(codePtr->maxStackDepth)); TD->codePtr = codePtr; TD->tosPtr = initTosPtr; TD->pc = codePtr->codeStart; TD->catchDepth = -1; TD->cleanup = 0; TD->auxObjList = NULL; TD->checkInterp = 0; TD->capacity = codePtr->maxStackDepth; /* * TIP #280: Initialize the frame. Do not push it yet: it will be pushed * every time that we call out from this TD, popped when we return to it. */ bcFramePtr->type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED) |
︙ | ︙ | |||
2069 2070 2071 2072 2073 2074 2075 | /* * These macros are just meant to save some global variables that are not * used too frequently */ TEBCdata *TD = data[0]; #define auxObjList (TD->auxObjList) | | | | | 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 | /* * These macros are just meant to save some global variables that are not * used too frequently */ TEBCdata *TD = data[0]; #define auxObjList (TD->auxObjList) #define catchDepth (TD->catchDepth) #define codePtr (TD->codePtr) #define checkInterp (TD->checkInterp) /* Indicates when a check of interp readyness * is necessary. Set by checkInterp = 1 */ /* * Globals: variables that store state, must remain valid at all times. */ Tcl_Obj **tosPtr; /* Cached pointer to top of evaluation * stack. */ |
︙ | ︙ | |||
2136 2137 2138 2139 2140 2141 2142 | TclArgumentBCRelease((Tcl_Interp *) iPtr, bcFramePtr); } if (codePtr->flags & TCL_BYTECODE_RECOMPILE) { iPtr->flags |= ERR_ALREADY_LOGGED; codePtr->flags &= ~TCL_BYTECODE_RECOMPILE; } | | | 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 | TclArgumentBCRelease((Tcl_Interp *) iPtr, bcFramePtr); } if (codePtr->flags & TCL_BYTECODE_RECOMPILE) { iPtr->flags |= ERR_ALREADY_LOGGED; codePtr->flags &= ~TCL_BYTECODE_RECOMPILE; } checkInterp = 1; if (result == TCL_OK) { #ifndef TCL_COMPILE_DEBUG if (*pc == INST_POP) { NEXT_INST_V(1, cleanup, 0); } #endif /* |
︙ | ︙ | |||
2256 2257 2258 2259 2260 2261 2262 | /* * Check for asynchronous handlers [Bug 746722]; we do the check every * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1). */ if ((instructionCount++ & ASYNC_CHECK_COUNT_MASK) == 0) { | < | | | | | 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 | /* * Check for asynchronous handlers [Bug 746722]; we do the check every * ASYNC_CHECK_COUNT_MASK instruction, of the form (2**n-1). */ if ((instructionCount++ & ASYNC_CHECK_COUNT_MASK) == 0) { if (TclAsyncReady(iPtr)) { result = Tcl_AsyncInvoke(interp, result); if (result == TCL_ERROR) { checkInterp = 1; goto gotError; } } if (TclCanceled(iPtr)) { if (Tcl_Canceled(interp, TCL_LEAVE_ERR_MSG) == TCL_ERROR) { checkInterp = 1; goto gotError; } } if (TclLimitReady(iPtr->limit)) { if (Tcl_LimitCheck(interp) == TCL_ERROR) { checkInterp = 1; goto gotError; } } checkInterp = 1; } /* * These two instructions account for 26% of all instructions (according * to measurements on tclbench by Ben Vitale * [http://www.cs.toronto.edu/syslab/pubs/tcl2005-vitale-zaleski.pdf] * Resolving them before the switch reduces the cost of branch |
︙ | ︙ | |||
2696 2697 2698 2699 2700 2701 2702 | TclNewObj(objPtr); objPtr->internalRep.ptrAndLongRep.value = CURR_DEPTH; PUSH_TAUX_OBJ(objPtr); NEXT_INST_F(1, 0, 0); case INST_EXPAND_STKTOP: { int i; | | < > > | < < | | | | < < < > > > | < > | > | < < > | 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 | TclNewObj(objPtr); objPtr->internalRep.ptrAndLongRep.value = CURR_DEPTH; PUSH_TAUX_OBJ(objPtr); NEXT_INST_F(1, 0, 0); case INST_EXPAND_STKTOP: { int i; unsigned int reqWords; /* * Make sure that the element at stackTop is a list; if not, just * leave with an error. Note that the element from the expand list * will be removed at checkForCatch. */ objPtr = OBJ_AT_TOS; if (TclListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { TRACE_WITH_OBJ(("%.30s => ERROR: ", O2S(objPtr)), Tcl_GetObjResult(interp)); goto gotError; } /* * Make sure there is enough room in the stack to expand this list * *and* process the rest of the command (at least up to the next * argument expansion or command end). The operand is the current * stack depth, as seen by the compiler. */ reqWords = /* how many were needed originally */ codePtr->maxStackDepth /* plus how many we already consumed in previous expansions */ + (CURR_DEPTH - TclGetInt4AtPtr(pc+1)) /* plus how many are needed for this expansion */ + objc - 1; (void) POP_OBJECT(); if (reqWords > TD->capacity) { ptrdiff_t depth; unsigned int size = capacity2size(reqWords); depth = tosPtr - initTosPtr; TD = ckrealloc(TD, size); TD->capacity = reqWords; tosPtr = initTosPtr + depth; } /* * Expand the list at stacktop onto the stack; free the list. Knowing * that it has a freeIntRepProc we use Tcl_DecrRefCount(). */ for (i = 0; i < objc; i++) { PUSH_OBJECT(objv[i]); } Tcl_DecrRefCount(objPtr); NEXT_INST_F(5, 0, 0); } case INST_EXPR_STK: { ByteCode *newCodePtr; bcFramePtr->data.tebc.pc = (char *) pc; iPtr->cmdFramePtr = bcFramePtr; newCodePtr = CompileExprObj(interp, OBJ_AT_TOS); checkInterp = 1; cleanup = 1; pc++; TEBC_YIELD(); return TclNRExecuteByteCode(interp, newCodePtr); } /* |
︙ | ︙ | |||
2842 2843 2844 2845 2846 2847 2848 | iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc, codePtr, bcFramePtr, pc - codePtr->codeStart); } | < < | 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 | iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc, codePtr, bcFramePtr, pc - codePtr->codeStart); } pc += pcAdjustment; TEBC_YIELD(); return TclNREvalObjv(interp, objc, objv, TCL_EVAL_NOERR, NULL); #if TCL_SUPPORT_84_BYTECODE case INST_CALL_BUILTIN_FUNC1: |
︙ | ︙ | |||
2990 2991 2992 2993 2994 2995 2996 | if (iPtr->flags & INTERP_DEBUG_FRAME) { TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc, codePtr, bcFramePtr, pc - codePtr->codeStart); } iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = opnd; iPtr->ensembleRewrite.numInsertedObjs = 1; | < | | 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 | if (iPtr->flags & INTERP_DEBUG_FRAME) { TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc, codePtr, bcFramePtr, pc - codePtr->codeStart); } iPtr->ensembleRewrite.sourceObjs = objv; iPtr->ensembleRewrite.numRemovedObjs = opnd; iPtr->ensembleRewrite.numInsertedObjs = 1; pc += 6; TEBC_YIELD(); TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL); TclSkipTailcall(interp); return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE, NULL, INT_MIN); /* * ----------------------------------------------------------------- * Start of INST_LOAD instructions. * * WARNING: more 'goto' here than your doctor recommended! The different * instructions set the value of some variables and then jump to some * common execution code. |
︙ | ︙ | |||
3132 3133 3134 3135 3136 3137 3138 | doCallPtrGetVar: /* * There are either errors or the variable is traced: call * TclPtrGetVar to process fully. */ | < < > | 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 | doCallPtrGetVar: /* * There are either errors or the variable is traced: call * TclPtrGetVar to process fully. */ objResultPtr = TclPtrGetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, TCL_LEAVE_ERR_MSG, opnd); checkInterp = 1; if (!objResultPtr) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(pcAdjustment, cleanup, 1); |
︙ | ︙ | |||
3379 3380 3381 3382 3383 3384 3385 | varPtr = varPtr->value.linkPtr; } cleanup = 1; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; doCallPtrSetVar: | < < > | 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 | varPtr = varPtr->value.linkPtr; } cleanup = 1; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; doCallPtrSetVar: objResultPtr = TclPtrSetVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, valuePtr, storeFlags, opnd); checkInterp = 1; if (!objResultPtr) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } #ifndef TCL_COMPILE_DEBUG if (*(pc+pcAdjustment) == INST_POP) { NEXT_INST_V((pcAdjustment+1), cleanup, 0); |
︙ | ︙ | |||
3643 3644 3645 3646 3647 3648 3649 | Tcl_DecrRefCount(incrPtr); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } Tcl_DecrRefCount(incrPtr); } else { | < < > | 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 | Tcl_DecrRefCount(incrPtr); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } Tcl_DecrRefCount(incrPtr); } else { objResultPtr = TclPtrIncrObjVar(interp, varPtr, arrayPtr, part1Ptr, part2Ptr, incrPtr, TCL_LEAVE_ERR_MSG, opnd); checkInterp = 1; Tcl_DecrRefCount(incrPtr); if (objResultPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } |
︙ | ︙ | |||
3678 3679 3680 3681 3682 3683 3684 | opnd = TclGetUInt4AtPtr(pc+1); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (ReadTraced(varPtr)) { | < < > | 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 | opnd = TclGetUInt4AtPtr(pc+1); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (ReadTraced(varPtr)) { TclObjCallVarTraces(iPtr, NULL, varPtr, NULL, NULL, TCL_TRACE_READS, 0, opnd); checkInterp = 1; if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, NULL); varPtr = NULL; } } /* |
︙ | ︙ | |||
3714 3715 3716 3717 3718 3719 3720 | goto doneExistArray; } } varPtr = TclLookupArrayElement(interp, NULL, part2Ptr, 0, "access", 0, 1, arrayPtr, opnd); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { | < < > | 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 | goto doneExistArray; } } varPtr = TclLookupArrayElement(interp, NULL, part2Ptr, 0, "access", 0, 1, arrayPtr, opnd); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { TclObjCallVarTraces(iPtr, arrayPtr, varPtr, NULL, part2Ptr, TCL_TRACE_READS, 0, opnd); checkInterp = 1; } if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); varPtr = NULL; } } doneExistArray: |
︙ | ︙ | |||
3747 3748 3749 3750 3751 3752 3753 | TRACE(("\"%.30s\" => ", O2S(part1Ptr))); doExistStk: varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, 0, "access", /*createPart1*/0, /*createPart2*/1, &arrayPtr); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { | < < > | 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 | TRACE(("\"%.30s\" => ", O2S(part1Ptr))); doExistStk: varPtr = TclObjLookupVarEx(interp, part1Ptr, part2Ptr, 0, "access", /*createPart1*/0, /*createPart2*/1, &arrayPtr); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr,part2Ptr, TCL_TRACE_READS, 0, -1); checkInterp = 1; } if (TclIsVarUndefined(varPtr)) { TclCleanupVar(varPtr, arrayPtr); varPtr = NULL; } } objResultPtr = TCONST(!varPtr || TclIsVarUndefined(varPtr) ? 0 : 1); |
︙ | ︙ | |||
3794 3795 3796 3797 3798 3799 3800 | goto slowUnsetScalar; } varPtr->value.objPtr = NULL; NEXT_INST_F(6, 0, 0); } slowUnsetScalar: | < | | 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 | goto slowUnsetScalar; } varPtr->value.objPtr = NULL; NEXT_INST_F(6, 0, 0); } slowUnsetScalar: if (TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, flags, opnd) != TCL_OK && flags) { goto errorInUnset; } checkInterp = 1; NEXT_INST_F(6, 0, 0); case INST_UNSET_ARRAY: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; opnd = TclGetUInt4AtPtr(pc+2); part2Ptr = OBJ_AT_TOS; arrayPtr = LOCAL(opnd); |
︙ | ︙ | |||
3836 3837 3838 3839 3840 3841 3842 | * Don't need to do anything here. */ NEXT_INST_F(6, 1, 0); } } slowUnsetArray: | < | < | | < < > | 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 | * Don't need to do anything here. */ NEXT_INST_F(6, 1, 0); } } slowUnsetArray: varPtr = TclLookupArrayElement(interp, NULL, part2Ptr, flags, "unset", 0, 0, arrayPtr, opnd); if (!varPtr) { if (flags & TCL_LEAVE_ERR_MSG) { goto errorInUnset; } } else if (TclPtrUnsetVar(interp, varPtr, arrayPtr, NULL, part2Ptr, flags, opnd) != TCL_OK && (flags & TCL_LEAVE_ERR_MSG)) { goto errorInUnset; } checkInterp = 1; NEXT_INST_F(6, 1, 0); case INST_UNSET_ARRAY_STK: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; cleanup = 2; part2Ptr = OBJ_AT_TOS; /* element name */ part1Ptr = OBJ_UNDER_TOS; /* array name */ TRACE(("%s \"%.30s(%.30s)\"\n", (flags?"normal":"noerr"), O2S(part1Ptr), O2S(part2Ptr))); goto doUnsetStk; case INST_UNSET_STK: flags = TclGetUInt1AtPtr(pc+1) ? TCL_LEAVE_ERR_MSG : 0; cleanup = 1; part2Ptr = NULL; part1Ptr = OBJ_AT_TOS; /* variable name */ TRACE(("%s \"%.30s\"\n", (flags?"normal":"noerr"), O2S(part1Ptr))); doUnsetStk: if (TclObjUnsetVar2(interp, part1Ptr, part2Ptr, flags) != TCL_OK && (flags & TCL_LEAVE_ERR_MSG)) { goto errorInUnset; } checkInterp = 1; NEXT_INST_V(2, cleanup, 0); errorInUnset: checkInterp = 1; TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; /* * This is really an unset operation these days. Do not issue. */ case INST_DICT_DONE: opnd = TclGetUInt4AtPtr(pc+1); TRACE(("%u\n", opnd)); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (TclIsVarDirectUnsettable(varPtr) && !TclIsVarInHash(varPtr)) { if (!TclIsVarUndefined(varPtr)) { TclDecrRefCount(varPtr->value.objPtr); } varPtr->value.objPtr = NULL; } else { TclPtrUnsetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); checkInterp = 1; } NEXT_INST_F(5, 0, 0); } /* * End of INST_UNSET instructions. * ----------------------------------------------------------------- |
︙ | ︙ | |||
3933 3934 3935 3936 3937 3938 3939 | part1Ptr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(part1Ptr))); varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, 0, NULL, /*createPart1*/0, /*createPart2*/0, &arrayPtr); doArrayExists: if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { | < < | 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 | part1Ptr = OBJ_AT_TOS; TRACE(("\"%.30s\" => ", O2S(part1Ptr))); varPtr = TclObjLookupVarEx(interp, part1Ptr, NULL, 0, NULL, /*createPart1*/0, /*createPart2*/0, &arrayPtr); doArrayExists: if (varPtr && (varPtr->flags & VAR_TRACED_ARRAY) && (TclIsVarArray(varPtr) || TclIsVarUndefined(varPtr))) { result = TclObjCallVarTraces(iPtr, arrayPtr, varPtr, part1Ptr, NULL, (TCL_LEAVE_ERR_MSG|TCL_NAMESPACE_ONLY| TCL_GLOBAL_ONLY|TCL_TRACE_ARRAY), 1, opnd); if (result == TCL_ERROR) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } if (varPtr && TclIsVarArray(varPtr) && !TclIsVarUndefined(varPtr)) { |
︙ | ︙ | |||
4238 4239 4240 4241 4242 4243 4244 | int i1, i2, iResult; value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; if (TclGetBooleanFromObj(NULL, valuePtr, &i1) != TCL_OK) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); | < < > < < > | 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 | int i1, i2, iResult; value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; if (TclGetBooleanFromObj(NULL, valuePtr, &i1) != TCL_OK) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; goto gotError; } if (TclGetBooleanFromObj(NULL, value2Ptr, &i2) != TCL_OK) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(value2Ptr), (value2Ptr->typePtr? value2Ptr->typePtr->name : "null"))); IllegalExprOperandType(interp, pc, value2Ptr); checkInterp = 1; goto gotError; } if (*pc == INST_LOR) { iResult = (i1 || i2); } else { iResult = (i1 && i2); |
︙ | ︙ | |||
5348 5349 5350 5351 5352 5353 5354 | valuePtr = OBJ_UNDER_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || (type1==TCL_NUMBER_DOUBLE) || (type1==TCL_NUMBER_NAN)) { TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr), O2S(value2Ptr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); | < < > < < > | 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 | valuePtr = OBJ_UNDER_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || (type1==TCL_NUMBER_DOUBLE) || (type1==TCL_NUMBER_NAN)) { TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(valuePtr), O2S(value2Ptr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; goto gotError; } if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) || (type2==TCL_NUMBER_DOUBLE) || (type2==TCL_NUMBER_NAN)) { TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(valuePtr), O2S(value2Ptr), (value2Ptr->typePtr? value2Ptr->typePtr->name : "null"))); IllegalExprOperandType(interp, pc, value2Ptr); checkInterp = 1; goto gotError; } /* * Check for common, simple case. */ |
︙ | ︙ | |||
5419 5420 5421 5422 5423 5424 5425 | } case INST_RSHIFT: if (l2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #if 0 | < | | 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 | } case INST_RSHIFT: if (l2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #if 0 Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "domain error: argument not in valid range", NULL); checkInterp = 1; #endif goto gotError; } else if (l1 == 0) { TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); |
︙ | ︙ | |||
5467 5468 5469 5470 5471 5472 5473 | } case INST_LSHIFT: if (l2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #if 0 | < | < < > | 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 | } case INST_LSHIFT: if (l2 < 0) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "negative shift argument", -1)); #if 0 Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "domain error: argument not in valid range", NULL); checkInterp = 1; #endif goto gotError; } else if (l1 == 0) { TRACE(("%s %s => ", O2S(valuePtr), O2S(value2Ptr))); objResultPtr = TCONST(0); TRACE(("%s\n", O2S(objResultPtr))); NEXT_INST_F(1, 2, 1); } else if (l2 > (long) INT_MAX) { /* * Technically, we could hold the value (1 << (INT_MAX+1)) * in an mp_int, but since we're using mp_mul_2d() to do * the work, and it takes only an int argument, that's a * good place to draw the line. */ Tcl_SetObjResult(interp, Tcl_NewStringObj( "integer value too large to represent", -1)); #if 0 Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", "integer value too large to represent", NULL); checkInterp = 1; #endif goto gotError; } else { int shift = (int) l2; /* * Handle shifts within the native long range. |
︙ | ︙ | |||
5576 5577 5578 5579 5580 5581 5582 | valuePtr = OBJ_UNDER_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || IsErroringNaNType(type1)) { TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(value2Ptr), O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name: "null"))); | < < > < < > | 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 | valuePtr = OBJ_UNDER_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || IsErroringNaNType(type1)) { TRACE(("%.20s %.20s => ILLEGAL 1st TYPE %s\n", O2S(value2Ptr), O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name: "null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; goto gotError; } #ifdef ACCEPT_NAN if (type1 == TCL_NUMBER_NAN) { /* * NaN first argument -> result is also NaN. */ NEXT_INST_F(1, 1, 0); } #endif if ((GetNumberFromObj(NULL, value2Ptr, &ptr2, &type2) != TCL_OK) || IsErroringNaNType(type2)) { TRACE(("%.20s %.20s => ILLEGAL 2nd TYPE %s\n", O2S(value2Ptr), O2S(valuePtr), (value2Ptr->typePtr? value2Ptr->typePtr->name: "null"))); IllegalExprOperandType(interp, pc, value2Ptr); checkInterp = 1; goto gotError; } #ifdef ACCEPT_NAN if (type2 == TCL_NUMBER_NAN) { /* * NaN second argument -> result is also NaN. |
︙ | ︙ | |||
5746 5747 5748 5749 5750 5751 5752 | valuePtr = OBJ_AT_TOS; /* TODO - check claim that taking address of b harms performance */ /* TODO - consider optimization search for constants */ if (TclGetBooleanFromObj(NULL, valuePtr, &b) != TCL_OK) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); | < < > < < > | 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 | valuePtr = OBJ_AT_TOS; /* TODO - check claim that taking address of b harms performance */ /* TODO - consider optimization search for constants */ if (TclGetBooleanFromObj(NULL, valuePtr, &b) != TCL_OK) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s\n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; goto gotError; } /* TODO: Consider peephole opt. */ objResultPtr = TCONST(!b); NEXT_INST_F(1, 1, 1); } case INST_BITNOT: valuePtr = OBJ_AT_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || (type1==TCL_NUMBER_NAN) || (type1==TCL_NUMBER_DOUBLE)) { /* * ... ~$NonInteger => raise an error. */ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; goto gotError; } if (type1 == TCL_NUMBER_LONG) { l1 = *((const long *) ptr1); if (Tcl_IsShared(valuePtr)) { TclNewLongObj(objResultPtr, ~l1); NEXT_INST_F(1, 1, 1); |
︙ | ︙ | |||
5793 5794 5795 5796 5797 5798 5799 | case INST_UMINUS: valuePtr = OBJ_AT_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || IsErroringNaNType(type1)) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); | < < > | 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 | case INST_UMINUS: valuePtr = OBJ_AT_TOS; if ((GetNumberFromObj(NULL, valuePtr, &ptr1, &type1) != TCL_OK) || IsErroringNaNType(type1)) { TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name : "null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; goto gotError; } switch (type1) { case TCL_NUMBER_NAN: /* -NaN => NaN */ NEXT_INST_F(1, 0, 0); case TCL_NUMBER_LONG: |
︙ | ︙ | |||
5839 5840 5841 5842 5843 5844 5845 | if (*pc == INST_UPLUS) { /* * ... +$NonNumeric => raise an error. */ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name:"null"))); | < < > < < > < < > | 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 | if (*pc == INST_UPLUS) { /* * ... +$NonNumeric => raise an error. */ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name:"null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; goto gotError; } /* ... TryConvertToNumeric($NonNumeric) is acceptable */ TRACE(("\"%.20s\" => not numeric\n", O2S(valuePtr))); NEXT_INST_F(1, 0, 0); } if (IsErroringNaNType(type1)) { if (*pc == INST_UPLUS) { /* * ... +$NonNumeric => raise an error. */ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name:"null"))); IllegalExprOperandType(interp, pc, valuePtr); checkInterp = 1; } else { /* * Numeric conversion of NaN -> error. */ TRACE(("\"%.20s\" => IEEE FLOATING PT ERROR\n", O2S(objResultPtr))); TclExprFloatError(interp, *((const double *) ptr1)); checkInterp = 1; } goto gotError; } /* * Ensure that the numeric value has a string rep the same as the * formatted version of its internal rep. This is used, e.g., to make |
︙ | ︙ | |||
5914 5915 5916 5917 5918 5919 5920 | /* * End of numeric operator instructions. * ----------------------------------------------------------------- */ case INST_BREAK: /* | < < > < < > | 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 | /* * End of numeric operator instructions. * ----------------------------------------------------------------- */ case INST_BREAK: /* Tcl_ResetResult(interp); checkInterp = 1; */ result = TCL_BREAK; cleanup = 0; goto processExceptionReturn; case INST_CONTINUE: /* Tcl_ResetResult(interp); checkInterp = 1; */ result = TCL_CONTINUE; cleanup = 0; goto processExceptionReturn; { ForeachInfo *infoPtr; |
︙ | ︙ | |||
6059 6060 6061 6062 6063 6064 6065 | if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = valuePtr; Tcl_IncrRefCount(valuePtr); } } else { | < < > | | 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 | if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = valuePtr; Tcl_IncrRefCount(valuePtr); } } else { if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, valuePtr, TCL_LEAVE_ERR_MSG, varIndex)==NULL){ checkInterp = 1; TRACE_WITH_OBJ(( "%u => ERROR init. index temp %d: ", opnd,varIndex), Tcl_GetObjResult(interp)); TclDecrRefCount(listPtr); goto gotError; } checkInterp = 1; } valIndex++; } TclDecrRefCount(listPtr); listTmpIndex++; } } |
︙ | ︙ | |||
6101 6102 6103 6104 6105 6106 6107 | case INST_BEGIN_CATCH4: /* * Record start of the catch command with exception range index equal * to the operand. Push the current stack depth onto the special catch * stack. */ | | | | | < < > | | 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 | case INST_BEGIN_CATCH4: /* * Record start of the catch command with exception range index equal * to the operand. Push the current stack depth onto the special catch * stack. */ catchStack[++catchDepth] = INT2PTR(CURR_DEPTH); TRACE(("%u => catchDepth=%d, stackTop=%d\n", TclGetUInt4AtPtr(pc+1), (int) (catchDepth), (int) CURR_DEPTH)); NEXT_INST_F(5, 0, 0); case INST_END_CATCH: catchDepth--; Tcl_ResetResult(interp); checkInterp = 1; result = TCL_OK; TRACE(("=> catchDepth=%d\n", (int) (catchDepth))); NEXT_INST_F(1, 0, 0); case INST_PUSH_RESULT: objResultPtr = Tcl_GetObjResult(interp); TRACE_WITH_OBJ(("=> "), objResultPtr); /* |
︙ | ︙ | |||
6135 6136 6137 6138 6139 6140 6141 | case INST_PUSH_RETURN_CODE: TclNewIntObj(objResultPtr, result); TRACE(("=> %u\n", result)); NEXT_INST_F(1, 0, 1); case INST_PUSH_RETURN_OPTIONS: | < < > | 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 | case INST_PUSH_RETURN_CODE: TclNewIntObj(objResultPtr, result); TRACE(("=> %u\n", result)); NEXT_INST_F(1, 0, 1); case INST_PUSH_RETURN_OPTIONS: objResultPtr = Tcl_GetReturnOptions(interp, result); checkInterp = 1; TRACE_WITH_OBJ(("=> "), objResultPtr); NEXT_INST_F(1, 0, 1); case INST_RETURN_CODE_BRANCH: { int code; if (TclGetIntFromObj(NULL, OBJ_AT_TOS, &code) != TCL_OK) { |
︙ | ︙ | |||
6214 6215 6216 6217 6218 6219 6220 | TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); } if (objResultPtr) { TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); } | < | | 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 | TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); } if (objResultPtr) { TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); } Tcl_SetObjResult(interp, Tcl_ObjPrintf( "key \"%s\" not known in dictionary", TclGetString(OBJ_AT_TOS))); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", TclGetString(OBJ_AT_TOS), NULL); checkInterp = 1; TRACE_WITH_OBJ(("%u => ERROR ", opnd), Tcl_GetObjResult(interp)); } else { if (*pc == INST_DICT_EXISTS) { dictNotExists: objResultPtr = TCONST(0); TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); |
︙ | ︙ | |||
6250 6251 6252 6253 6254 6255 6256 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u %u => ", opnd, opnd2)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { | < < > | 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u %u => ", opnd, opnd2)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { dictPtr = TclPtrGetVar(interp, varPtr, NULL,NULL,NULL, 0, opnd2); checkInterp = 1; } if (dictPtr == NULL) { TclNewObj(dictPtr); allocateDict = 1; } else { allocateDict = Tcl_IsShared(dictPtr); if (allocateDict) { |
︙ | ︙ | |||
6324 6325 6326 6327 6328 6329 6330 | TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); | < < > | 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 | TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, dictPtr, TCL_LEAVE_ERR_MSG, opnd2); checkInterp = 1; TclDecrRefCount(dictPtr); if (objResultPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } |
︙ | ︙ | |||
6354 6355 6356 6357 6358 6359 6360 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { | < < > | 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); checkInterp = 1; } if (dictPtr == NULL) { TclNewObj(dictPtr); allocateDict = 1; } else { allocateDict = Tcl_IsShared(dictPtr); if (allocateDict) { |
︙ | ︙ | |||
6460 6461 6462 6463 6464 6465 6466 | TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); | < < > | 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 | TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, dictPtr, TCL_LEAVE_ERR_MSG, opnd); checkInterp = 1; TclDecrRefCount(dictPtr); if (objResultPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } } |
︙ | ︙ | |||
6565 6566 6567 6568 6569 6570 6571 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { | < < > < | | < < > | 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, TCL_LEAVE_ERR_MSG, opnd); checkInterp = 1; if (dictPtr == NULL) { goto gotError; } } if (TclListObjGetElements(interp, OBJ_AT_TOS, &length, &keyPtrPtr) != TCL_OK) { goto gotError; } if (length != duiPtr->length) { Tcl_Panic("dictUpdateStart argument length mismatch"); } for (i=0 ; i<length ; i++) { if (Tcl_DictObjGet(interp, dictPtr, keyPtrPtr[i], &valuePtr) != TCL_OK) { goto gotError; } varPtr = LOCAL(duiPtr->varIndices[i]); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } if (valuePtr == NULL) { TclObjUnsetVar2(interp, localName(iPtr->varFramePtr, duiPtr->varIndices[i]), NULL, 0); } else if (TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, valuePtr, TCL_LEAVE_ERR_MSG, duiPtr->varIndices[i]) == NULL) { checkInterp = 1; goto gotError; } checkInterp = 1; } NEXT_INST_F(9, 0, 0); case INST_DICT_UPDATE_END: opnd = TclGetUInt4AtPtr(pc+1); opnd2 = TclGetUInt4AtPtr(pc+5); varPtr = LOCAL(opnd); duiPtr = codePtr->auxDataArrayPtr[opnd2].clientData; while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { dictPtr = TclPtrGetVar(interp, varPtr, NULL, NULL, NULL, 0, opnd); checkInterp = 1; } if (dictPtr == NULL) { NEXT_INST_F(9, 1, 0); } if (Tcl_DictObjSize(interp, dictPtr, &length) != TCL_OK || TclListObjGetElements(interp, OBJ_AT_TOS, &length, &keyPtrPtr) != TCL_OK) { |
︙ | ︙ | |||
6644 6645 6646 6647 6648 6649 6650 | while (TclIsVarLink(var2Ptr)) { var2Ptr = var2Ptr->value.linkPtr; } if (TclIsVarDirectReadable(var2Ptr)) { valuePtr = var2Ptr->value.objPtr; } else { | < < > < < > | 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 | while (TclIsVarLink(var2Ptr)) { var2Ptr = var2Ptr->value.linkPtr; } if (TclIsVarDirectReadable(var2Ptr)) { valuePtr = var2Ptr->value.objPtr; } else { valuePtr = TclPtrGetVar(interp, var2Ptr, NULL, NULL, NULL, 0, duiPtr->varIndices[i]); checkInterp = 1; } if (valuePtr == NULL) { Tcl_DictObjRemove(interp, dictPtr, keyPtrPtr[i]); } else if (dictPtr == valuePtr) { Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], Tcl_DuplicateObj(valuePtr)); } else { Tcl_DictObjPut(interp, dictPtr, keyPtrPtr[i], valuePtr); } } if (TclIsVarDirectWritable(varPtr)) { Tcl_IncrRefCount(dictPtr); TclDecrRefCount(varPtr->value.objPtr); varPtr->value.objPtr = dictPtr; } else { objResultPtr = TclPtrSetVar(interp, varPtr, NULL, NULL, NULL, dictPtr, TCL_LEAVE_ERR_MSG, opnd); checkInterp = 1; if (objResultPtr == NULL) { if (allocdict) { TclDecrRefCount(dictPtr); } goto gotError; } } |
︙ | ︙ | |||
6711 6712 6713 6714 6715 6716 6717 | varPtr = TclObjLookupVarEx(interp, varNamePtr, NULL, TCL_LEAVE_ERR_MSG, "set", 1, 1, &arrayPtr); if (varPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); TclDecrRefCount(keysPtr); goto gotError; } | < < | 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 | varPtr = TclObjLookupVarEx(interp, varNamePtr, NULL, TCL_LEAVE_ERR_MSG, "set", 1, 1, &arrayPtr); if (varPtr == NULL) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); TclDecrRefCount(keysPtr); goto gotError; } result = TclDictWithFinish(interp, varPtr,arrayPtr,varNamePtr,NULL,-1, objc, objv, keysPtr); TclDecrRefCount(keysPtr); if (result != TCL_OK) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } TRACE_APPEND(("OK\n")); NEXT_INST_F(1, 2, 0); |
︙ | ︙ | |||
6737 6738 6739 6740 6741 6742 6743 | if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } | < < | 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 | if (TclListObjGetElements(interp, listPtr, &objc, &objv) != TCL_OK) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } result = TclDictWithFinish(interp, varPtr, NULL, NULL, NULL, opnd, objc, objv, keysPtr); if (result != TCL_OK) { TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } TRACE_APPEND(("OK\n")); NEXT_INST_F(5, 2, 0); } |
︙ | ︙ | |||
6854 6855 6856 6857 6858 6859 6860 | /* * Division by zero in an expression. Control only reaches this point * by "goto divideByZero". */ divideByZero: | < | < > < < | > < > | 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 | /* * Division by zero in an expression. Control only reaches this point * by "goto divideByZero". */ divideByZero: Tcl_SetResult(interp, "divide by zero", TCL_STATIC); Tcl_SetErrorCode(interp, "ARITH", "DIVZERO", "divide by zero", NULL); checkInterp = 1; goto gotError; /* * Exponentiation of zero by negative number in an expression. Control * only reaches this point by "goto exponOfZero". */ exponOfZero: Tcl_SetResult(interp, "exponentiation of zero by negative power", TCL_STATIC); Tcl_SetErrorCode(interp, "ARITH", "DOMAIN", "exponentiation of zero by negative power", NULL); checkInterp = 1; /* * Almost all error paths feed through here rather than assigning to * result themselves (for a small but consistent saving). */ gotError: |
︙ | ︙ | |||
6897 6898 6899 6900 6901 6902 6903 | if (iPtr->execEnvPtr->rewind) { goto abnormalReturn; } if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { const unsigned char *pcBeg; bytes = GetSrcInfoForPc(pc, codePtr, &length, &pcBeg); | < < > | < | | 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 6470 6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 | if (iPtr->execEnvPtr->rewind) { goto abnormalReturn; } if ((result == TCL_ERROR) && !(iPtr->flags & ERR_ALREADY_LOGGED)) { const unsigned char *pcBeg; bytes = GetSrcInfoForPc(pc, codePtr, &length, &pcBeg); TclLogCommandInfo(interp, codePtr->source, bytes, bytes ? length : 0, pcBeg, tosPtr); checkInterp = 1; } iPtr->flags &= ~ERR_ALREADY_LOGGED; /* * Clear all expansions that may have started after the last * INST_BEGIN_CATCH. */ while (auxObjList) { if ((catchDepth >=0) && (PTR2INT(catchStack[catchDepth]) > PTR2INT(auxObjList->internalRep.twoPtrValue.ptr1))) { break; } POP_TAUX_OBJ(); } /* * We must not catch if the script in progress has been canceled with |
︙ | ︙ | |||
6952 6953 6954 6955 6956 6957 6958 | if (traceInstructions) { fprintf(stdout, " ... limit exceeded, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } | | | 6507 6508 6509 6510 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 | if (traceInstructions) { fprintf(stdout, " ... limit exceeded, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } if (catchDepth == -1) { #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... no enclosing catch, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; |
︙ | ︙ | |||
6987 6988 6989 6990 6991 6992 6993 | * "exception". It was found either by checkForCatch just above or by * an instruction during break, continue, or error processing. Jump to * its catchOffset after unwinding the operand stack to the depth it * had when starting to execute the range's catch command. */ processCatch: | | | | | | 6542 6543 6544 6545 6546 6547 6548 6549 6550 6551 6552 6553 6554 6555 6556 6557 6558 6559 6560 6561 6562 6563 6564 6565 | * "exception". It was found either by checkForCatch just above or by * an instruction during break, continue, or error processing. Jump to * its catchOffset after unwinding the operand stack to the depth it * had when starting to execute the range's catch command. */ processCatch: while (CURR_DEPTH > PTR2INT(catchStack[catchDepth])) { valuePtr = POP_OBJECT(); TclDecrRefCount(valuePtr); } #ifdef TCL_COMPILE_DEBUG if (traceInstructions) { fprintf(stdout, " ... found catch at %d, catchDepth=%d, " "unwound to %ld, new pc %u\n", rangePtr->codeOffset, (int) catchDepth, PTR2INT(catchStack[catchDepth]), (unsigned) rangePtr->catchOffset); } #endif pc = (codePtr->codeStart + rangePtr->catchOffset); NEXT_INST_F(0, 0, 0); /* Restart the execution loop at pc. */ /* * end of infinite loop dispatching on instructions. |
︙ | ︙ | |||
7045 7046 7047 7048 7049 7050 7051 | CLANG_ASSERT(bcFramePtr); } iPtr->cmdFramePtr = bcFramePtr->nextPtr; if (--codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); } | | | 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 | CLANG_ASSERT(bcFramePtr); } iPtr->cmdFramePtr = bcFramePtr->nextPtr; if (--codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); } ckfree(TD); /* free my stack */ return result; /* * INST_START_CMD failure case removed where it doesn't bother that much * * Remark that if the interpreter is marked for deletion its |
︙ | ︙ | |||
7089 7090 7091 7092 7093 7094 7095 | goto instEvalStk; } } #undef codePtr #undef iPtr #undef bcFramePtr | < | | 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 | goto instEvalStk; } } #undef codePtr #undef iPtr #undef bcFramePtr #undef initTosPtr #undef auxObjList #undef catchDepth #undef TCONST /* *---------------------------------------------------------------------- * * ExecuteExtendedBinaryMathOp, ExecuteExtendedUnaryMathOp -- * |
︙ | ︙ |
Changes to generic/tclFCmd.c.
︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 | * Use objStrings as a list object. */ if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) { goto end; } attributeStringsAllocated = (const char **) | | | 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 | * Use objStrings as a list object. */ if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) { goto end; } attributeStringsAllocated = (const char **) ckalloc((1+numObjStrings) * sizeof(char *)); for (index = 0; index < numObjStrings; index++) { Tcl_ListObjIndex(interp, objStrings, index, &objPtr); attributeStringsAllocated[index] = TclGetString(objPtr); } attributeStringsAllocated[index] = NULL; attributeStrings = attributeStringsAllocated; } else if (objStrings != NULL) { |
︙ | ︙ | |||
1134 1135 1136 1137 1138 1139 1140 | /* * Free up the array we allocated and drop our reference to any list of * attribute names issued by the filesystem. */ end: if (attributeStringsAllocated != NULL) { | | | 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 | /* * Free up the array we allocated and drop our reference to any list of * attribute names issued by the filesystem. */ end: if (attributeStringsAllocated != NULL) { ckfree((void *) attributeStringsAllocated); } if (objStrings != NULL) { Tcl_DecrRefCount(objStrings); } return result; } |
︙ | ︙ |
Changes to generic/tclFileName.c.
︙ | ︙ | |||
1445 1446 1447 1448 1449 1450 1451 | * platform. */ Tcl_ListObjLength(interp, typePtr, &length); if (length <= 0) { goto skipTypes; } | | | 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 | * platform. */ Tcl_ListObjLength(interp, typePtr, &length); if (length <= 0) { goto skipTypes; } globTypes = ckalloc(sizeof(Tcl_GlobTypeData)); globTypes->type = 0; globTypes->perm = 0; globTypes->macType = NULL; globTypes->macCreator = NULL; while (--length >= 0) { int len; |
︙ | ︙ | |||
1665 1666 1667 1668 1669 1670 1671 | if (globTypes != NULL) { if (globTypes->macType != NULL) { Tcl_DecrRefCount(globTypes->macType); } if (globTypes->macCreator != NULL) { Tcl_DecrRefCount(globTypes->macCreator); } | | | 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 | if (globTypes != NULL) { if (globTypes->macType != NULL) { Tcl_DecrRefCount(globTypes->macType); } if (globTypes->macCreator != NULL) { Tcl_DecrRefCount(globTypes->macCreator); } ckfree(globTypes); } return result; } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to generic/tclIOCmd.c.
︙ | ︙ | |||
927 928 929 930 931 932 933 | /* * Create the string argument array "argv". Make sure argv is large enough * to hold the argc arguments plus 1 extra for the zero end-of-argv word. */ argc = objc - skip; | | | | 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 | /* * Create the string argument array "argv". Make sure argv is large enough * to hold the argc arguments plus 1 extra for the zero end-of-argv word. */ argc = objc - skip; argv = ckalloc((unsigned)(argc + 1) * sizeof(char *)); /* * Copy the string conversions of each (post option) object into the * argument vector. */ for (i = 0; i < argc; i++) { argv[i] = TclGetString(objv[i + skip]); } argv[argc] = NULL; chan = Tcl_OpenCommandChannel(interp, argc, argv, (background ? 0 : ignoreStderr ? TCL_STDOUT : TCL_STDOUT|TCL_STDERR)); /* * Free the argv array. */ ckfree((void *) argv); if (chan == NULL) { return TCL_ERROR; } if (background) { /* |
︙ | ︙ |
Changes to generic/tclIndexObj.c.
︙ | ︙ | |||
965 966 967 968 969 970 971 | } else { elementStr = TclGetStringFromObj(origObjv[i], &elemLen); } flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { | | < | | 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 | } else { elementStr = TclGetStringFromObj(origObjv[i], &elemLen); } flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { char *quotedElementStr = ckalloc((unsigned)len + 1); len = TclConvertElement(elementStr, elemLen, quotedElementStr, flags); Tcl_AppendToObj(objPtr, quotedElementStr, len); ckfree(quotedElementStr); } else { Tcl_AppendToObj(objPtr, elementStr, elemLen); } AFTER_FIRST_WORD; /* |
︙ | ︙ | |||
1021 1022 1023 1024 1025 1026 1027 | */ elementStr = TclGetStringFromObj(objv[i], &elemLen); flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { | | < | | 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 | */ elementStr = TclGetStringFromObj(objv[i], &elemLen); flags = 0; len = TclScanElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { char *quotedElementStr = ckalloc((unsigned) len + 1); len = TclConvertElement(elementStr, elemLen, quotedElementStr, flags); Tcl_AppendToObj(objPtr, quotedElementStr, len); ckfree(quotedElementStr); } else { Tcl_AppendToObj(objPtr, elementStr, elemLen); } } AFTER_FIRST_WORD; |
︙ | ︙ |
Changes to generic/tclInt.decls.
︙ | ︙ | |||
30 31 32 33 34 35 36 | #} #declare 1 { # int TclAccessDeleteProc(TclAccessProc_ *proc) #} #declare 2 { # int TclAccessInsertProc(TclAccessProc_ *proc) #} | | | < > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #} #declare 1 { # int TclAccessDeleteProc(TclAccessProc_ *proc) #} #declare 2 { # int TclAccessInsertProc(TclAccessProc_ *proc) #} #declare 3 { # void TclAllocateFreeObjects(void) #} # Replaced by TclpChdir in 8.1: # declare 4 { # int TclChdir(Tcl_Interp *interp, char *dirName) # } declare 5 { int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan) |
︙ | ︙ | |||
285 286 287 288 289 290 291 | #declare 67 { # int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc) #} # Replaced by Tcl_FSAccess in 8.4: #declare 68 { # int TclpAccess(const char *path, int mode) #} | | | < > | | < > | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | #declare 67 { # int TclOpenFileChannelInsertProc(TclOpenFileChannelProc_ *proc) #} # Replaced by Tcl_FSAccess in 8.4: #declare 68 { # int TclpAccess(const char *path, int mode) #} #declare 69 { # char *TclpAlloc(unsigned int size) #} #declare 70 { # int TclpCopyFile(const char *source, const char *dest) #} #declare 71 { # int TclpCopyDirectory(const char *source, const char *dest, # Tcl_DString *errorPtr) #} #declare 72 { # int TclpCreateDirectory(const char *path) #} #declare 73 { # int TclpDeleteFile(const char *path) #} #declare 74 { # void TclpFree(char *ptr) #} declare 75 { unsigned long TclpGetClicks(void) } declare 76 { unsigned long TclpGetSeconds(void) } |
︙ | ︙ | |||
328 329 330 331 332 333 334 | # int TclpListVolumes(Tcl_Interp *interp) #} # Replaced by Tcl_FSOpenFileChannel in 8.4: #declare 80 { # Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, char *fileName, # char *modeString, int permissions) #} | | | < > | 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 | # int TclpListVolumes(Tcl_Interp *interp) #} # Replaced by Tcl_FSOpenFileChannel in 8.4: #declare 80 { # Tcl_Channel TclpOpenFileChannel(Tcl_Interp *interp, char *fileName, # char *modeString, int permissions) #} #declare 81 { # char *TclpRealloc(char *ptr, unsigned int size) #} #declare 82 { # int TclpRemoveDirectory(const char *path, int recursive, # Tcl_DString *errorPtr) #} #declare 83 { # int TclpRenameFile(const char *source, const char *dest) #} |
︙ | ︙ | |||
866 867 868 869 870 871 872 | } declare 213 { Tcl_Obj *TclGetObjNameOfExecutable(void) } declare 214 { void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding) } | | | < > | | < > | | < > | 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 | } declare 213 { Tcl_Obj *TclGetObjNameOfExecutable(void) } declare 214 { void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding) } #declare 215 { # void *TclStackAlloc(Tcl_Interp *interp, unsigned int numBytes) #} #declare 216 { # void TclStackFree(Tcl_Interp *interp, void *freePtr) #} declare 217 { int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame) } declare 218 { void TclPopStackFrame(Tcl_Interp *interp) } # for use in tclTest.c declare 224 { TclPlatformType *TclGetPlatform(void) } # declare 225 { Tcl_Obj *TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags) } #declare 226 { # int TclObjBeingDeleted(Tcl_Obj *objPtr) #} declare 227 { void TclSetNsPath(Namespace *nsPtr, int pathLength, Tcl_Namespace *pathAry[]) } # Used to be needed for TclOO-extension; unneeded now that TclOO is in the # core and NRE-enabled # declare 228 { |
︙ | ︙ |
Changes to generic/tclInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 | /* * tclInt.h -- * * Declarations of things used internally by the Tcl interpreter. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Daniel A. Steffen <[email protected]> * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /* * tclInt.h -- * * Declarations of things used internally by the Tcl interpreter. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1994-1998 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001, 2002 by Kevin B. Kenny. All rights reserved. * Copyright (c) 2007 Daniel A. Steffen <[email protected]> * Copyright (c) 2006-2008 by Joe Mistachkin. All rights reserved. * Copyright (c) 2008-2011 by Miguel Sofer. All rights reserved. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifndef _TCLINT #define _TCLINT |
︙ | ︙ | |||
1389 1390 1391 1392 1393 1394 1395 | /* * This is a convenience macro used to initialize a thread local storage ptr. */ #define TCL_TSD_INIT(keyPtr) \ (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) | < < < < < < < | 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 | /* * This is a convenience macro used to initialize a thread local storage ptr. */ #define TCL_TSD_INIT(keyPtr) \ (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) /* * Forward declaration to prevent errors when the forward references to * Tcl_Parse and CompileEnv are encountered in the procedure type CompileProc * declared below. */ struct CompileEnv; |
︙ | ︙ | |||
1437 1438 1439 1440 1441 1442 1443 | * The type of procedure called from the compilation hook point in * SetByteCodeFromAny. */ typedef int (CompileHookProc)(Tcl_Interp *interp, struct CompileEnv *compEnvPtr, ClientData clientData); | < < < < < < < < < < < < < | 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 | * The type of procedure called from the compilation hook point in * SetByteCodeFromAny. */ typedef int (CompileHookProc)(Tcl_Interp *interp, struct CompileEnv *compEnvPtr, ClientData clientData); /* * The data structure defining the execution environment for ByteCode's. * There is one ExecEnv structure per Tcl interpreter. It holds the evaluation * stack that holds command operands and results. The stack grows towards * increasing addresses. The member stackPtr points to the stackItems of the * currently active execution stack. */ |
︙ | ︙ | |||
1487 1488 1489 1490 1491 1492 1493 | * holds the nesting numLevels at yield. */ int nargs; /* Number of args required for resuming this * coroutine; -2 means "0 or 1" (default), -1 * means "any" */ } CoroutineData; typedef struct ExecEnv { | < < | 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 | * holds the nesting numLevels at yield. */ int nargs; /* Number of args required for resuming this * coroutine; -2 means "0 or 1" (default), -1 * means "any" */ } CoroutineData; typedef struct ExecEnv { Tcl_Obj *constants[2]; /* Pointers to constant "0" and "1" objs. */ struct Tcl_Interp *interp; struct NRE_callback *callbackPtr; /* Top callback in NRE's stack. */ struct CoroutineData *corPtr; int rewind; } ExecEnv; |
︙ | ︙ | |||
1767 1768 1769 1770 1771 1772 1773 | * Values for the selection mode, i.e the package require preferences. */ enum PkgPreferOptions { PKG_PREFER_LATEST, PKG_PREFER_STABLE }; | < < < < < < < < < < < < < < < < < < | 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 | * Values for the selection mode, i.e the package require preferences. */ enum PkgPreferOptions { PKG_PREFER_LATEST, PKG_PREFER_STABLE }; /* *---------------------------------------------------------------- * This structure defines an interpreter, which is a collection of commands * plus other state information related to interpreting commands, such as * variable storage. Primary responsibility for this data structure is in * tclBasic.c, but almost every Tcl source file uses something in here. *---------------------------------------------------------------- |
︙ | ︙ | |||
2118 2119 2120 2121 2122 2123 2124 | * Note that these are the same for all interps in the same thread. They * just have to be initialised for the thread's master interp, slaves * inherit the value. * * They are used by the macros defined below. */ | < < < < | 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 | * Note that these are the same for all interps in the same thread. They * just have to be initialised for the thread's master interp, slaves * inherit the value. * * They are used by the macros defined below. */ int *asyncReadyPtr; /* Pointer to the asyncReady indicator for * this interp's thread; see tclAsync.c */ /* * The pointer to the object system root ekeko. c.f. TIP #257. */ void *objectFoundation; /* Pointer to the Foundation structure of the * object system, which contains things like |
︙ | ︙ | |||
2349 2350 2351 2352 2353 2354 2355 | * The macro below is used to modify a "char" value (e.g. by casting it to an * unsigned character) so that it can be used safely with macros such as * isspace. */ #define UCHAR(c) ((unsigned char) (c)) | < < < < < < < < < < < | 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 | * The macro below is used to modify a "char" value (e.g. by casting it to an * unsigned character) so that it can be used safely with macros such as * isspace. */ #define UCHAR(c) ((unsigned char) (c)) /* * This macro is used to determine the offset needed to safely allocate any * data structure in memory. Given a starting offset or size, it "rounds up" * or "aligns" the offset to the next 8-byte boundary so that any data * structure can be placed at the resulting offset without fear of an * alignment error. * |
︙ | ︙ | |||
2746 2747 2748 2749 2750 2751 2752 | */ MODULE_SCOPE const Tcl_HashKeyType tclArrayHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclOneWordHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclStringHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclObjHashKeyType; | < < < < < < < | 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 | */ MODULE_SCOPE const Tcl_HashKeyType tclArrayHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclOneWordHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclStringHashKeyType; MODULE_SCOPE const Tcl_HashKeyType tclObjHashKeyType; #ifdef TCL_COMPILE_STATS MODULE_SCOPE long tclObjsAlloced; MODULE_SCOPE long tclObjsFreed; #define TCL_MAX_SHARED_OBJ_STATS 5 MODULE_SCOPE long tclObjsShared[TCL_MAX_SHARED_OBJ_STATS]; #endif /* TCL_COMPILE_STATS */ |
︙ | ︙ | |||
2940 2941 2942 2943 2944 2945 2946 | MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr, Tcl_Obj *objPtr); MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, Tcl_DString *toAppendPtr); MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr); | < < | 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 | MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); MODULE_SCOPE char * TclDStringAppendObj(Tcl_DString *dsPtr, Tcl_Obj *objPtr); MODULE_SCOPE char * TclDStringAppendDString(Tcl_DString *dsPtr, Tcl_DString *toAppendPtr); MODULE_SCOPE Tcl_Obj * TclDStringToObj(Tcl_DString *dsPtr); MODULE_SCOPE void TclFinalizeAsync(void); MODULE_SCOPE void TclFinalizeDoubleConversion(void); MODULE_SCOPE void TclFinalizeEncodingSubsystem(void); MODULE_SCOPE void TclFinalizeEnvironment(void); MODULE_SCOPE void TclFinalizeEvaluation(void); MODULE_SCOPE void TclFinalizeExecution(void); MODULE_SCOPE void TclFinalizeIOSubsystem(void); MODULE_SCOPE void TclFinalizeFilesystem(void); MODULE_SCOPE void TclResetFilesystem(void); MODULE_SCOPE void TclFinalizeLoad(void); MODULE_SCOPE void TclFinalizeLock(void); MODULE_SCOPE void TclFinalizeMemorySubsystem(void); MODULE_SCOPE void TclFinalizeNotifier(void); MODULE_SCOPE void TclFinalizeObjects(void); MODULE_SCOPE void TclFinalizePreserve(void); MODULE_SCOPE void TclFinalizeSynchronization(void); MODULE_SCOPE void TclFinalizeThreadData(void); MODULE_SCOPE void TclFinalizeThreadObjects(void); MODULE_SCOPE double TclFloor(const mp_int *a); MODULE_SCOPE void TclFormatNaN(double value, char *buffer); MODULE_SCOPE int TclFSFileAttrIndex(Tcl_Obj *pathPtr, const char *attributeName, int *indexPtr); MODULE_SCOPE int TclNREvalFile(Tcl_Interp *interp, Tcl_Obj *pathPtr, |
︙ | ︙ | |||
3000 3001 3002 3003 3004 3005 3006 | MODULE_SCOPE Tcl_Obj * TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr); MODULE_SCOPE int TclInfoGlobalsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclInfoLocalsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclInfoVarsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); | < | 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 | MODULE_SCOPE Tcl_Obj * TclInfoFrame(Tcl_Interp *interp, CmdFrame *framePtr); MODULE_SCOPE int TclInfoGlobalsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclInfoLocalsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE int TclInfoVarsCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); MODULE_SCOPE void TclInitDbCkalloc(void); MODULE_SCOPE void TclInitDoubleConversion(void); MODULE_SCOPE void TclInitEmbeddedConfigurationInformation( Tcl_Interp *interp); MODULE_SCOPE void TclInitEncodingSubsystem(void); MODULE_SCOPE void TclInitIOSubsystem(void); MODULE_SCOPE void TclInitLimitSupport(Tcl_Interp *interp); |
︙ | ︙ | |||
3137 3138 3139 3140 3141 3142 3143 | MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Command *cmdPtr); MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr); MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue, Tcl_Encoding encoding); MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result); | < < | 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 | MODULE_SCOPE int TclSetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); MODULE_SCOPE void TclSetCmdNameObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Command *cmdPtr); MODULE_SCOPE void TclSetDuplicateObj(Tcl_Obj *dupPtr, Tcl_Obj *objPtr); MODULE_SCOPE void TclSetProcessGlobalValue(ProcessGlobalValue *pgvPtr, Tcl_Obj *newValue, Tcl_Encoding encoding); MODULE_SCOPE void TclSignalExitThread(Tcl_ThreadId id, int result); MODULE_SCOPE int TclStringMatch(const char *str, int strLen, const char *pattern, int ptnLen, int flags); MODULE_SCOPE int TclStringMatchObj(Tcl_Obj *stringObj, Tcl_Obj *patternObj, int flags); MODULE_SCOPE Tcl_Obj * TclStringObjReverse(Tcl_Obj *objPtr); MODULE_SCOPE void TclSubstCompile(Tcl_Interp *interp, const char *bytes, int numBytes, int flags, int line, |
︙ | ︙ | |||
3995 3996 3997 3998 3999 4000 4001 | tclObjsFreed++ #else # define TclIncrObjsAllocated() # define TclIncrObjsFreed() #endif /* TCL_COMPILE_STATS */ # define TclAllocObjStorage(objPtr) \ | | | | 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 | tclObjsFreed++ #else # define TclIncrObjsAllocated() # define TclIncrObjsFreed() #endif /* TCL_COMPILE_STATS */ # define TclAllocObjStorage(objPtr) \ (objPtr) = TclSmallAlloc() # define TclFreeObjStorage(objPtr) \ TclSmallFree(objPtr) #ifndef TCL_MEM_DEBUG # define TclNewObj(objPtr) \ TclIncrObjsAllocated(); \ TclAllocObjStorage(objPtr); \ (objPtr)->refCount = 0; \ (objPtr)->bytes = tclEmptyStringRep; \ |
︙ | ︙ | |||
4033 4034 4035 4036 4037 4038 4039 | TclFreeObjStorage(objPtr); \ TclIncrObjsFreed(); \ } else { \ TclFreeObj(objPtr); \ } \ } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 | TclFreeObjStorage(objPtr); \ TclIncrObjsFreed(); \ } else { \ TclFreeObj(objPtr); \ } \ } #else /* TCL_MEM_DEBUG */ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file, int line); # define TclDbNewObj(objPtr, file, line) \ do { \ TclIncrObjsAllocated(); \ |
︙ | ︙ | |||
4161 4162 4163 4164 4165 4166 4167 | # define TclDecrRefCount(objPtr) \ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__) # define TclNewListObjDirect(objc, objv) \ TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__) | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 | # define TclDecrRefCount(objPtr) \ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__) # define TclNewListObjDirect(objc, objv) \ TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__) #endif /* TCL_MEM_DEBUG */ /* * Macros that drive the allocator behaviour */ #if defined(TCL_THREADS) /* * The TCL_THREADS mode is like the regular mode but allocates Tcl_Obj's from * per-thread caches. */ MODULE_SCOPE void TclpFreeAllocCache(void *); MODULE_SCOPE void * TclpGetAllocCache(void); MODULE_SCOPE void TclpSetAllocCache(void *); MODULE_SCOPE void TclFreeAllocCache(void *); MODULE_SCOPE void TclpFreeAllocMutex(Tcl_Mutex *mutex); MODULE_SCOPE Tcl_Mutex *TclpNewAllocMutex(void); #endif MODULE_SCOPE char * TclpAlloc(unsigned int size); MODULE_SCOPE char * TclpRealloc(char * ptr, unsigned int size); MODULE_SCOPE void TclpFree(char * ptr); MODULE_SCOPE void * TclSmallAlloc(); MODULE_SCOPE void TclSmallFree(void *ptr); MODULE_SCOPE void TclInitAlloc(void); MODULE_SCOPE void TclFinalizeAlloc(void); #define TclCkSmallAlloc(nbytes, memPtr) \ do { \ TCL_CT_ASSERT((nbytes)<=sizeof(Tcl_Obj)); \ memPtr = TclSmallAlloc(); \ } while (0) /* * Support for Clang Static Analyzer <http://clang-analyzer.llvm.org> */ #if defined(PURIFY) && defined(__clang__) #if __has_feature(attribute_analyzer_noreturn) && \ !defined(Tcl_Panic) && defined(Tcl_Panic_TCL_DECLARED) void Tcl_Panic(const char *, ...) __attribute__((analyzer_noreturn)); #endif #if !defined(CLANG_ASSERT) #include <assert.h> #define CLANG_ASSERT(x) assert(x) #endif #elif !defined(CLANG_ASSERT) #define CLANG_ASSERT(x) #endif /* PURIFY && __clang__ */ /* *---------------------------------------------------------------- * Macro used by the Tcl core to set a Tcl_Obj's string representation to a * copy of the "len" bytes starting at "bytePtr". This code works even if the * byte array contains NULLs as long as the length is correct. Because "len" * is referenced multiple times, it should be as simple an expression as |
︙ | ︙ | |||
4698 4699 4700 4701 4702 4703 4704 4705 | * Adapted with permission from * http://www.pixelbeat.org/programming/gcc/static_assert.html */ #define TCL_CT_ASSERT(e) \ {enum { ct_assert_value = 1/(!!(e)) };} /* | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 | * Adapted with permission from * http://www.pixelbeat.org/programming/gcc/static_assert.html */ #define TCL_CT_ASSERT(e) \ {enum { ct_assert_value = 1/(!!(e)) };} /* * Support for Clang Static Analyzer <http://clang-analyzer.llvm.org> */ #define CLANG_ASSERT(x) /* *---------------------------------------------------------------- * Parameters, structs and macros for the non-recursive engine (NRE) *---------------------------------------------------------------- */ |
︙ | ︙ | |||
4809 4810 4811 4812 4813 4814 4815 | callbackPtr->data[3] = (ClientData)(data3); \ callbackPtr->nextPtr = TOP_CB(interp); \ TOP_CB(interp) = callbackPtr; \ } while (0) #if NRE_USE_SMALL_ALLOC #define TCLNR_ALLOC(interp, ptr) \ | | | | 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 | callbackPtr->data[3] = (ClientData)(data3); \ callbackPtr->nextPtr = TOP_CB(interp); \ TOP_CB(interp) = callbackPtr; \ } while (0) #if NRE_USE_SMALL_ALLOC #define TCLNR_ALLOC(interp, ptr) \ TclCkSmallAlloc(sizeof(NRE_callback), (ptr)) #define TCLNR_FREE(interp, ptr) TclSmallFree(ptr) #else #define TCLNR_ALLOC(interp, ptr) \ (ptr = ((ClientData) ckalloc(sizeof(NRE_callback)))) #define TCLNR_FREE(interp, ptr) ckfree((char *) (ptr)) #endif #if NRE_ENABLE_ASSERTS |
︙ | ︙ |
Changes to generic/tclIntDecls.h.
︙ | ︙ | |||
55 56 57 58 59 60 61 | /* * Exported function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ | | < | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | /* * Exported function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ /* Slot 3 is reserved */ /* Slot 4 is reserved */ /* 5 */ EXTERN int TclCleanupChildren(Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 6 */ EXTERN void TclCleanupCommand(Command *cmdPtr); /* 7 */ |
︙ | ︙ | |||
197 198 199 200 201 202 203 | /* 64 */ EXTERN int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* Slot 68 is reserved */ | | < | < | < | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | /* 64 */ EXTERN int TclObjInvoke(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* Slot 68 is reserved */ /* Slot 69 is reserved */ /* Slot 70 is reserved */ /* Slot 71 is reserved */ /* Slot 72 is reserved */ /* Slot 73 is reserved */ /* Slot 74 is reserved */ /* 75 */ EXTERN unsigned long TclpGetClicks(void); /* 76 */ EXTERN unsigned long TclpGetSeconds(void); /* 77 */ EXTERN void TclpGetTime(Tcl_Time *time); /* Slot 78 is reserved */ /* Slot 79 is reserved */ /* Slot 80 is reserved */ /* Slot 81 is reserved */ /* Slot 82 is reserved */ /* Slot 83 is reserved */ /* Slot 84 is reserved */ /* Slot 85 is reserved */ /* Slot 86 is reserved */ /* Slot 87 is reserved */ /* 88 */ |
︙ | ︙ | |||
510 511 512 513 514 515 516 | /* 212 */ EXTERN void TclpFindExecutable(const char *argv0); /* 213 */ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void); /* 214 */ EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding); | | < | < | < | 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 | /* 212 */ EXTERN void TclpFindExecutable(const char *argv0); /* 213 */ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void); /* 214 */ EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding); /* Slot 215 is reserved */ /* Slot 216 is reserved */ /* 217 */ EXTERN int TclPushStackFrame(Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 218 */ EXTERN void TclPopStackFrame(Tcl_Interp *interp); /* Slot 219 is reserved */ /* Slot 220 is reserved */ /* Slot 221 is reserved */ /* Slot 222 is reserved */ /* Slot 223 is reserved */ /* 224 */ EXTERN TclPlatformType * TclGetPlatform(void); /* 225 */ EXTERN Tcl_Obj * TclTraceDictPath(Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags); /* Slot 226 is reserved */ /* 227 */ EXTERN void TclSetNsPath(Namespace *nsPtr, int pathLength, Tcl_Namespace *pathAry[]); /* Slot 228 is reserved */ /* 229 */ EXTERN int TclPtrMakeUpvar(Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index); |
︙ | ︙ | |||
614 615 616 617 618 619 620 | typedef struct TclIntStubs { int magic; void *hooks; void (*reserved0)(void); void (*reserved1)(void); void (*reserved2)(void); | | | 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 | typedef struct TclIntStubs { int magic; void *hooks; void (*reserved0)(void); void (*reserved1)(void); void (*reserved2)(void); void (*reserved3)(void); void (*reserved4)(void); int (*tclCleanupChildren) (Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan); /* 5 */ void (*tclCleanupCommand) (Command *cmdPtr); /* 6 */ int (*tclCopyAndCollapse) (int count, const char *src, char *dst); /* 7 */ int (*tclCopyChannelOld) (Tcl_Interp *interp, Tcl_Channel inChan, Tcl_Channel outChan, int toRead, Tcl_Obj *cmdPtr); /* 8 */ int (*tclCreatePipeline) (Tcl_Interp *interp, int argc, const char **argv, Tcl_Pid **pidArrayPtr, TclFile *inPipePtr, TclFile *outPipePtr, TclFile *errFilePtr); /* 9 */ int (*tclCreateProc) (Tcl_Interp *interp, Namespace *nsPtr, const char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr, Proc **procPtrPtr); /* 10 */ |
︙ | ︙ | |||
680 681 682 683 684 685 686 | int (*tclObjCommandComplete) (Tcl_Obj *cmdPtr); /* 62 */ int (*tclObjInterpProc) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 63 */ int (*tclObjInvoke) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 64 */ void (*reserved65)(void); void (*reserved66)(void); void (*reserved67)(void); void (*reserved68)(void); | | | | | 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 | int (*tclObjCommandComplete) (Tcl_Obj *cmdPtr); /* 62 */ int (*tclObjInterpProc) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 63 */ int (*tclObjInvoke) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[], int flags); /* 64 */ void (*reserved65)(void); void (*reserved66)(void); void (*reserved67)(void); void (*reserved68)(void); void (*reserved69)(void); void (*reserved70)(void); void (*reserved71)(void); void (*reserved72)(void); void (*reserved73)(void); void (*reserved74)(void); unsigned long (*tclpGetClicks) (void); /* 75 */ unsigned long (*tclpGetSeconds) (void); /* 76 */ void (*tclpGetTime) (Tcl_Time *time); /* 77 */ void (*reserved78)(void); void (*reserved79)(void); void (*reserved80)(void); void (*reserved81)(void); void (*reserved82)(void); void (*reserved83)(void); void (*reserved84)(void); void (*reserved85)(void); void (*reserved86)(void); void (*reserved87)(void); char * (*tclPrecTraceProc) (ClientData clientData, Tcl_Interp *interp, const char *name1, const char *name2, int flags); /* 88 */ |
︙ | ︙ | |||
826 827 828 829 830 831 832 | Tcl_Channel (*tclpOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* 208 */ void (*reserved209)(void); void (*reserved210)(void); void (*reserved211)(void); void (*tclpFindExecutable) (const char *argv0); /* 212 */ Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */ void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */ | | | | | 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 | Tcl_Channel (*tclpOpenFileChannel) (Tcl_Interp *interp, Tcl_Obj *pathPtr, int mode, int permissions); /* 208 */ void (*reserved209)(void); void (*reserved210)(void); void (*reserved211)(void); void (*tclpFindExecutable) (const char *argv0); /* 212 */ Tcl_Obj * (*tclGetObjNameOfExecutable) (void); /* 213 */ void (*tclSetObjNameOfExecutable) (Tcl_Obj *name, Tcl_Encoding encoding); /* 214 */ void (*reserved215)(void); void (*reserved216)(void); int (*tclPushStackFrame) (Tcl_Interp *interp, Tcl_CallFrame **framePtrPtr, Tcl_Namespace *namespacePtr, int isProcCallFrame); /* 217 */ void (*tclPopStackFrame) (Tcl_Interp *interp); /* 218 */ void (*reserved219)(void); void (*reserved220)(void); void (*reserved221)(void); void (*reserved222)(void); void (*reserved223)(void); TclPlatformType * (*tclGetPlatform) (void); /* 224 */ Tcl_Obj * (*tclTraceDictPath) (Tcl_Interp *interp, Tcl_Obj *rootPtr, int keyc, Tcl_Obj *const keyv[], int flags); /* 225 */ void (*reserved226)(void); void (*tclSetNsPath) (Namespace *nsPtr, int pathLength, Tcl_Namespace *pathAry[]); /* 227 */ void (*reserved228)(void); int (*tclPtrMakeUpvar) (Tcl_Interp *interp, Var *otherP1Ptr, const char *myName, int myFlags, int index); /* 229 */ Var * (*tclObjLookupVar) (Tcl_Interp *interp, Tcl_Obj *part1Ptr, const char *part2, int flags, const char *msg, const int createPart1, const int createPart2, Var **arrayPtrPtr); /* 230 */ int (*tclGetNamespaceFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_Namespace **nsPtrPtr); /* 231 */ int (*tclEvalObjEx) (Tcl_Interp *interp, Tcl_Obj *objPtr, int flags, const CmdFrame *invoker, int word); /* 232 */ void (*tclGetSrcInfoForPc) (CmdFrame *contextPtr); /* 233 */ |
︙ | ︙ | |||
881 882 883 884 885 886 887 | /* * Inline function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ | | < | 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | /* * Inline function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ /* Slot 3 is reserved */ /* Slot 4 is reserved */ #define TclCleanupChildren \ (tclIntStubsPtr->tclCleanupChildren) /* 5 */ #define TclCleanupCommand \ (tclIntStubsPtr->tclCleanupCommand) /* 6 */ #define TclCopyAndCollapse \ (tclIntStubsPtr->tclCopyAndCollapse) /* 7 */ |
︙ | ︙ | |||
986 987 988 989 990 991 992 | (tclIntStubsPtr->tclObjInterpProc) /* 63 */ #define TclObjInvoke \ (tclIntStubsPtr->tclObjInvoke) /* 64 */ /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* Slot 68 is reserved */ | < | | < < | | 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 | (tclIntStubsPtr->tclObjInterpProc) /* 63 */ #define TclObjInvoke \ (tclIntStubsPtr->tclObjInvoke) /* 64 */ /* Slot 65 is reserved */ /* Slot 66 is reserved */ /* Slot 67 is reserved */ /* Slot 68 is reserved */ /* Slot 69 is reserved */ /* Slot 70 is reserved */ /* Slot 71 is reserved */ /* Slot 72 is reserved */ /* Slot 73 is reserved */ /* Slot 74 is reserved */ #define TclpGetClicks \ (tclIntStubsPtr->tclpGetClicks) /* 75 */ #define TclpGetSeconds \ (tclIntStubsPtr->tclpGetSeconds) /* 76 */ #define TclpGetTime \ (tclIntStubsPtr->tclpGetTime) /* 77 */ /* Slot 78 is reserved */ /* Slot 79 is reserved */ /* Slot 80 is reserved */ /* Slot 81 is reserved */ /* Slot 82 is reserved */ /* Slot 83 is reserved */ /* Slot 84 is reserved */ /* Slot 85 is reserved */ /* Slot 86 is reserved */ /* Slot 87 is reserved */ #define TclPrecTraceProc \ |
︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 | /* Slot 211 is reserved */ #define TclpFindExecutable \ (tclIntStubsPtr->tclpFindExecutable) /* 212 */ #define TclGetObjNameOfExecutable \ (tclIntStubsPtr->tclGetObjNameOfExecutable) /* 213 */ #define TclSetObjNameOfExecutable \ (tclIntStubsPtr->tclSetObjNameOfExecutable) /* 214 */ | < | < | | < | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 | /* Slot 211 is reserved */ #define TclpFindExecutable \ (tclIntStubsPtr->tclpFindExecutable) /* 212 */ #define TclGetObjNameOfExecutable \ (tclIntStubsPtr->tclGetObjNameOfExecutable) /* 213 */ #define TclSetObjNameOfExecutable \ (tclIntStubsPtr->tclSetObjNameOfExecutable) /* 214 */ /* Slot 215 is reserved */ /* Slot 216 is reserved */ #define TclPushStackFrame \ (tclIntStubsPtr->tclPushStackFrame) /* 217 */ #define TclPopStackFrame \ (tclIntStubsPtr->tclPopStackFrame) /* 218 */ /* Slot 219 is reserved */ /* Slot 220 is reserved */ /* Slot 221 is reserved */ /* Slot 222 is reserved */ /* Slot 223 is reserved */ #define TclGetPlatform \ (tclIntStubsPtr->tclGetPlatform) /* 224 */ #define TclTraceDictPath \ (tclIntStubsPtr->tclTraceDictPath) /* 225 */ /* Slot 226 is reserved */ #define TclSetNsPath \ (tclIntStubsPtr->tclSetNsPath) /* 227 */ /* Slot 228 is reserved */ #define TclPtrMakeUpvar \ (tclIntStubsPtr->tclPtrMakeUpvar) /* 229 */ #define TclObjLookupVar \ (tclIntStubsPtr->tclObjLookupVar) /* 230 */ |
︙ | ︙ |
Changes to generic/tclInterp.c.
︙ | ︙ | |||
1129 1130 1131 1132 1133 1134 1135 | const char *const *argv) /* These are the additional args. */ { Tcl_Obj *slaveObjPtr, *targetObjPtr; Tcl_Obj **objv; int i; int result; | | | | 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 | const char *const *argv) /* These are the additional args. */ { Tcl_Obj *slaveObjPtr, *targetObjPtr; Tcl_Obj **objv; int i; int result; objv = ckalloc((unsigned) sizeof(Tcl_Obj *) * argc); for (i = 0; i < argc; i++) { objv[i] = Tcl_NewStringObj(argv[i], -1); Tcl_IncrRefCount(objv[i]); } slaveObjPtr = Tcl_NewStringObj(slaveCmd, -1); Tcl_IncrRefCount(slaveObjPtr); targetObjPtr = Tcl_NewStringObj(targetCmd, -1); Tcl_IncrRefCount(targetObjPtr); result = AliasCreate(slaveInterp, slaveInterp, targetInterp, slaveObjPtr, targetObjPtr, argc, objv); for (i = 0; i < argc; i++) { Tcl_DecrRefCount(objv[i]); } ckfree(objv); Tcl_DecrRefCount(targetObjPtr); Tcl_DecrRefCount(slaveObjPtr); return result; } /* |
︙ | ︙ | |||
1827 1828 1829 1830 1831 1832 1833 | prefc = aliasPtr->objc; prefv = &aliasPtr->objPtr; cmdc = prefc + objc - 1; if (cmdc <= ALIAS_CMDV_PREALLOC) { cmdv = cmdArr; } else { | | | 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 | prefc = aliasPtr->objc; prefv = &aliasPtr->objPtr; cmdc = prefc + objc - 1; if (cmdc <= ALIAS_CMDV_PREALLOC) { cmdv = cmdArr; } else { cmdv = ckalloc(cmdc * sizeof(Tcl_Obj *)); } prefv = &aliasPtr->objPtr; memcpy(cmdv, prefv, (size_t) (prefc * sizeof(Tcl_Obj *))); memcpy(cmdv+prefc, objv+1, (size_t) ((objc-1) * sizeof(Tcl_Obj *))); Tcl_ResetResult(targetInterp); |
︙ | ︙ | |||
1894 1895 1896 1897 1898 1899 1900 | Tcl_Release(targetInterp); } for (i=0; i<cmdc; i++) { Tcl_DecrRefCount(cmdv[i]); } if (cmdv != cmdArr) { | | | 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 | Tcl_Release(targetInterp); } for (i=0; i<cmdc; i++) { Tcl_DecrRefCount(cmdv[i]); } if (cmdv != cmdArr) { ckfree(cmdv); } return result; #undef ALIAS_CMDV_PREALLOC } /* *---------------------------------------------------------------------- |
︙ | ︙ |
Changes to generic/tclListObj.c.
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 78 79 80 81 82 | * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ static List * NewListIntRep( int objc, Tcl_Obj *const objv[], int p) { List *listRepPtr; | > > > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | * Side effects: * The ref counts of the elements in objv are incremented since the * resulting list now refers to them. * *---------------------------------------------------------------------- */ #define Elems2Size(n) \ (sizeof(List) - sizeof(Tcl_Obj *) + n*sizeof(Tcl_Obj *)) #define Size2Elems(s) \ (s - (sizeof(List) - sizeof(Tcl_Obj *)))/sizeof(Tcl_Obj *) static List * NewListIntRep( int objc, Tcl_Obj *const objv[], int p) { List *listRepPtr; |
︙ | ︙ | |||
584 585 586 587 588 589 590 591 592 593 594 595 596 597 | return result; } } listRepPtr = ListRepPtr(listPtr); numElems = listRepPtr->elemCount; numRequired = numElems + 1 ; needGrow = (numRequired > listRepPtr->maxElemCount); isShared = (listRepPtr->refCount > 1); if (numRequired > LIST_MAX) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "max length of a Tcl list (%d elements) exceeded", | > | 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 | return result; } } listRepPtr = ListRepPtr(listPtr); numElems = listRepPtr->elemCount; numRequired = numElems + 1 ; needGrow = (numRequired > listRepPtr->maxElemCount); isShared = (listRepPtr->refCount > 1); if (numRequired > LIST_MAX) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "max length of a Tcl list (%d elements) exceeded", |
︙ | ︙ |
Changes to generic/tclNamesp.c.
︙ | ︙ | |||
461 462 463 464 465 466 467 | * If new variables are created, they will be * created in the frame. If 0, the frame is * for a "namespace eval" or "namespace * inscope" command and var references are * treated as references to namespace * variables. */ { | | | | 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | * If new variables are created, they will be * created in the frame. If 0, the frame is * for a "namespace eval" or "namespace * inscope" command and var references are * treated as references to namespace * variables. */ { *framePtrPtr = ckalloc(sizeof(CallFrame)); return Tcl_PushCallFrame(interp, *framePtrPtr, namespacePtr, isProcCallFrame); } void TclPopStackFrame( Tcl_Interp *interp) /* Interpreter with call frame to pop. */ { CallFrame *freePtr = ((Interp *) interp)->framePtr; Tcl_PopCallFrame(interp); ckfree(freePtr); } /* *---------------------------------------------------------------------- * * EstablishErrorCodeTraces -- * |
︙ | ︙ | |||
2637 2638 2639 2640 2641 2642 2643 | Tcl_HashEntry *hPtr; register Namespace *nsPtr; Namespace *trailNsPtr, *shadowNsPtr; Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp); int found, i; int trailFront = -1; int trailSize = 5; /* Formerly NUM_TRAIL_ELEMS. */ | | < | 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 | Tcl_HashEntry *hPtr; register Namespace *nsPtr; Namespace *trailNsPtr, *shadowNsPtr; Namespace *globalNsPtr = (Namespace *) TclGetGlobalNamespace(interp); int found, i; int trailFront = -1; int trailSize = 5; /* Formerly NUM_TRAIL_ELEMS. */ Namespace **trailPtr = ckalloc(trailSize * sizeof(Namespace *)); /* * Start at the namespace containing the new command, and work up through * the list of parents. Stop just before the global namespace, since the * global namespace can't "shadow" its own entries. * * The namespace "trail" list we build consists of the names of each |
︙ | ︙ | |||
2727 2728 2729 2730 2731 2732 2733 | * the trailPtr array. */ trailFront++; if (trailFront == trailSize) { int newSize = 2 * trailSize; | < | | | 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 | * the trailPtr array. */ trailFront++; if (trailFront == trailSize) { int newSize = 2 * trailSize; trailPtr = ckrealloc(trailPtr, newSize * sizeof(Namespace *)); trailSize = newSize; } trailPtr[trailFront] = nsPtr; } ckfree(trailPtr); } /* *---------------------------------------------------------------------- * * TclGetNamespaceFromObj, GetNamespaceFromObj -- * |
︙ | ︙ | |||
3974 3975 3976 3977 3978 3979 3980 | * There is a path given, so parse it into an array of namespace pointers. */ if (TclListObjGetElements(interp, objv[1], &nsObjc, &nsObjv) != TCL_OK) { goto badNamespace; } if (nsObjc != 0) { | < | | | 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 | * There is a path given, so parse it into an array of namespace pointers. */ if (TclListObjGetElements(interp, objv[1], &nsObjc, &nsObjv) != TCL_OK) { goto badNamespace; } if (nsObjc != 0) { namespaceList = ckalloc(sizeof(Tcl_Namespace *) * nsObjc); for (i=0 ; i<nsObjc ; i++) { if (TclGetNamespaceFromObj(interp, nsObjv[i], &namespaceList[i]) != TCL_OK) { goto badNamespace; } } } /* * Now we have the list of valid namespaces, install it as the path. */ TclSetNsPath(nsPtr, nsObjc, namespaceList); result = TCL_OK; badNamespace: if (namespaceList != NULL) { ckfree(namespaceList); } return result; } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to generic/tclOOCall.c.
︙ | ︙ | |||
101 102 103 104 105 106 107 | TclOODeleteContext( CallContext *contextPtr) { register Object *oPtr = contextPtr->oPtr; TclOODeleteChain(contextPtr->callPtr); if (oPtr != NULL) { | | | 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | TclOODeleteContext( CallContext *contextPtr) { register Object *oPtr = contextPtr->oPtr; TclOODeleteChain(contextPtr->callPtr); if (oPtr != NULL) { ckfree(contextPtr); DelRef(oPtr); } } /* * ---------------------------------------------------------------------- * |
︙ | ︙ | |||
1100 1101 1102 1103 1104 1105 1106 | TclOODeleteChain(oPtr->selfCls->destructorChainPtr); } oPtr->selfCls->destructorChainPtr = callPtr; callPtr->refCount++; } returnContext: | | | 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 | TclOODeleteChain(oPtr->selfCls->destructorChainPtr); } oPtr->selfCls->destructorChainPtr = callPtr; callPtr->refCount++; } returnContext: contextPtr = ckalloc(sizeof(CallContext)); contextPtr->oPtr = oPtr; AddRef(oPtr); contextPtr->callPtr = callPtr; contextPtr->skip = 2; contextPtr->index = 0; return contextPtr; } |
︙ | ︙ | |||
1441 1442 1443 1444 1445 1446 1447 | * extra argument when handled by some method types, and "filter" is * special because it's a filter method). The second word is the name of * the method in question (which differs for "unknown" and "filter" types) * and the third word is the full name of the class that declares the * method (or "object" if it is declared on the instance). */ | | | 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 | * extra argument when handled by some method types, and "filter" is * special because it's a filter method). The second word is the name of * the method in question (which differs for "unknown" and "filter" types) * and the third word is the full name of the class that declares the * method (or "object" if it is declared on the instance). */ objv = ckalloc(callPtr->numChain * sizeof(Tcl_Obj *)); for (i=0 ; i<callPtr->numChain ; i++) { struct MInvoke *miPtr = &callPtr->chain[i]; descObjs[0] = miPtr->isFilter ? filterLiteral : callPtr->flags & OO_UNKNOWN_METHOD ? fPtr->unknownMethodNameObj |
︙ | ︙ | |||
1478 1479 1480 1481 1482 1483 1484 | Tcl_DecrRefCount(objectLiteral); /* * Finish building the description and return it. */ resultObj = Tcl_NewListObj(callPtr->numChain, objv); | | | 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 | Tcl_DecrRefCount(objectLiteral); /* * Finish building the description and return it. */ resultObj = Tcl_NewListObj(callPtr->numChain, objv); ckfree(objv); return resultObj; } /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclOODefineCmds.c.
︙ | ︙ | |||
541 542 543 544 545 546 547 | } if (matchedStr != NULL) { /* * Got one match, and only one match! */ | | | | 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 | } if (matchedStr != NULL) { /* * Got one match, and only one match! */ Tcl_Obj **newObjv = ckalloc(sizeof(Tcl_Obj*)*(objc-1)); int result; newObjv[0] = Tcl_NewStringObj(matchedStr, -1); Tcl_IncrRefCount(newObjv[0]); if (objc > 2) { memcpy(newObjv+1, objv+2, sizeof(Tcl_Obj *) * (objc-2)); } result = Tcl_EvalObjv(interp, objc-1, newObjv, 0); Tcl_DecrRefCount(newObjv[0]); ckfree(newObjv); return result; } noMatch: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid command name \"%s\"", soughtStr)); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "COMMAND", soughtStr, NULL); |
︙ | ︙ | |||
1649 1650 1651 1652 1653 1654 1655 | } if (!isInstanceMixin && !oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } | | | 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 | } if (!isInstanceMixin && !oPtr->classPtr) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "attempt to misuse API", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } mixins = ckalloc(sizeof(Class *) * (objc-1)); for (i=1 ; i<objc ; i++) { Class *clsPtr = GetClassInOuterContext(interp, objv[i], "may only mix in classes"); if (clsPtr == NULL) { goto freeAndError; |
︙ | ︙ | |||
1673 1674 1675 1676 1677 1678 1679 | if (isInstanceMixin) { TclOOObjectSetMixins(oPtr, objc-1, mixins); } else { TclOOClassSetMixins(interp, oPtr->classPtr, objc-1, mixins); } | | | | 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 | if (isInstanceMixin) { TclOOObjectSetMixins(oPtr, objc-1, mixins); } else { TclOOClassSetMixins(interp, oPtr->classPtr, objc-1, mixins); } ckfree(mixins); return TCL_OK; freeAndError: ckfree(mixins); return TCL_ERROR; } /* * ---------------------------------------------------------------------- * * TclOODefineRenameMethodObjCmd -- |
︙ | ︙ | |||
2086 2087 2088 2089 2090 2091 2092 | Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } else if (Tcl_ListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } | | | | | 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 2116 2117 2118 2119 2120 2121 | Tcl_SetErrorCode(interp, "TCL", "OO", "MONKEY_BUSINESS", NULL); return TCL_ERROR; } else if (Tcl_ListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } mixins = ckalloc(sizeof(Class *) * mixinc); for (i=0 ; i<mixinc ; i++) { mixins[i] = GetClassInOuterContext(interp, mixinv[i], "may only mix in classes"); if (mixins[i] == NULL) { goto freeAndError; } if (TclOOIsReachable(oPtr->classPtr, mixins[i])) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "may not mix a class into itself", -1)); Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL); goto freeAndError; } } TclOOClassSetMixins(interp, oPtr->classPtr, mixinc, mixins); ckfree(mixins); return TCL_OK; freeAndError: ckfree(mixins); return TCL_ERROR; } /* * ---------------------------------------------------------------------- * * ClassSuperGet, ClassSuperSet -- |
︙ | ︙ | |||
2527 2528 2529 2530 2531 2532 2533 | } objv += Tcl_ObjectContextSkippedArgs(context); if (Tcl_ListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } | | | | | 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 | } objv += Tcl_ObjectContextSkippedArgs(context); if (Tcl_ListObjGetElements(interp, objv[0], &mixinc, &mixinv) != TCL_OK) { return TCL_ERROR; } mixins = ckalloc(sizeof(Class *) * mixinc); for (i=0 ; i<mixinc ; i++) { mixins[i] = GetClassInOuterContext(interp, mixinv[i], "may only mix in classes"); if (mixins[i] == NULL) { ckfree(mixins); return TCL_ERROR; } } TclOOObjectSetMixins(oPtr, mixinc, mixins); ckfree(mixins); return TCL_OK; } /* * ---------------------------------------------------------------------- * * ObjectVarsGet, ObjectVarsSet -- |
︙ | ︙ |
Changes to generic/tclOOMethod.c.
︙ | ︙ | |||
682 683 684 685 686 687 688 | Tcl_ObjectContextSkippedArgs(context)); } /* * Allocate the special frame data. */ | | | | 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | Tcl_ObjectContextSkippedArgs(context)); } /* * Allocate the special frame data. */ fdPtr = ckalloc(sizeof(PMFrameData)); /* * Create a call frame for this method. */ result = PushMethodCallFrame(interp, (CallContext *) context, pmPtr, objc, objv, fdPtr); if (result != TCL_OK) { ckfree(fdPtr); return result; } pmPtr->refCount++; /* * Give the pre-call callback a chance to do some setup and, possibly, * veto the call. |
︙ | ︙ | |||
715 716 717 718 719 720 721 | * Restore the old cmdPtr so that a subsequent use of [info frame] * won't crash on us. [Bug 3001438] */ pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; Tcl_PopCallFrame(interp); | | | | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 | * Restore the old cmdPtr so that a subsequent use of [info frame] * won't crash on us. [Bug 3001438] */ pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr; Tcl_PopCallFrame(interp); ckfree(fdPtr->framePtr); if (--pmPtr->refCount < 1) { DeleteProcedureMethodRecord(pmPtr); } ckfree(fdPtr); return result; } } /* * Now invoke the body of the method. */ |
︙ | ︙ | |||
770 771 772 773 774 775 776 | * are inlining DeleteProcedureMethod() here; this location is highly * sensitive when it comes to performance! */ if (--pmPtr->refCount < 1) { DeleteProcedureMethodRecord(pmPtr); } | | | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | * are inlining DeleteProcedureMethod() here; this location is highly * sensitive when it comes to performance! */ if (--pmPtr->refCount < 1) { DeleteProcedureMethodRecord(pmPtr); } ckfree(fdPtr); return result; } static int PushMethodCallFrame( Tcl_Interp *interp, /* Current interpreter. */ CallContext *contextPtr, /* Current method call context. */ |
︙ | ︙ | |||
1436 1437 1438 1439 1440 1441 1442 | FinalizeForwardCall( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **argObjs = data[0]; | | | 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 | FinalizeForwardCall( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **argObjs = data[0]; ckfree(argObjs); return result; } /* * ---------------------------------------------------------------------- * * DeleteForwardMethod, CloneForwardMethod -- |
︙ | ︙ | |||
1565 1566 1567 1568 1569 1570 1571 | * array of rewritten arguments. */ { Interp *iPtr = (Interp *) interp; int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); Tcl_Obj **argObjs; unsigned len = rewriteLength + objc - toRewrite; | | | 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 | * array of rewritten arguments. */ { Interp *iPtr = (Interp *) interp; int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); Tcl_Obj **argObjs; unsigned len = rewriteLength + objc - toRewrite; argObjs = ckalloc(sizeof(Tcl_Obj *) * len); memcpy(argObjs, rewriteObjs, rewriteLength * sizeof(Tcl_Obj *)); memcpy(argObjs + rewriteLength, objv + toRewrite, sizeof(Tcl_Obj *) * (objc - toRewrite)); /* * Now plumb this into the core ensemble rewrite logging system so that * Tcl_WrongNumArgs() can rewrite its result appropriately. The rules for |
︙ | ︙ |
Changes to generic/tclObj.c.
︙ | ︙ | |||
22 23 24 25 26 27 28 | * Table of all object types. */ static Tcl_HashTable typeTable; static int typeTableInitialized = 0; /* 0 means not yet initialized. */ TCL_DECLARE_MUTEX(tableMutex) | < < < < < < < < < < < | < | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | * Table of all object types. */ static Tcl_HashTable typeTable; static int typeTableInitialized = 0; /* 0 means not yet initialized. */ TCL_DECLARE_MUTEX(tableMutex) #if (defined(TCL_THREADS) && TCL_MEM_DEBUG) static Tcl_Mutex tclObjMutex; #endif /* * Pointer to a heap-allocated string of length zero that the Tcl core uses as * the value of an empty string representation for an object. This value is * shared by all new objects allocated by Tcl_NewObj. */ |
︙ | ︙ | |||
494 495 496 497 498 499 500 | { Tcl_MutexLock(&tableMutex); if (typeTableInitialized) { Tcl_DeleteHashTable(&typeTable); typeTableInitialized = 0; } Tcl_MutexUnlock(&tableMutex); | < < < < < < < < < | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 | { Tcl_MutexLock(&tableMutex); if (typeTableInitialized) { Tcl_DeleteHashTable(&typeTable); typeTableInitialized = 0; } Tcl_MutexUnlock(&tableMutex); } /* *---------------------------------------------------------------------- * * TclGetContLineTable -- * |
︙ | ︙ | |||
1237 1238 1239 1240 1241 1242 1243 | return Tcl_NewObj(); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 | return Tcl_NewObj(); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * TclFreeObj -- * * This function frees the memory associated with the argument object. * It is called by the tcl.h macro Tcl_DecrRefCount when an object's ref * count is zero. It is only "public" since it must be callable by that * macro wherever the macro is used. It should not be directly called by * clients. |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) * with 'length == -1'. */ TclInvalidateStringRep(objPtr); | < | 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 | /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) * with 'length == -1'. */ TclInvalidateStringRep(objPtr); if (ObjDeletePending(context)) { PushObjToDelete(context, objPtr); } else { TCL_DTRACE_OBJ_FREE(objPtr); if ((typePtr != NULL) && (typePtr->freeIntRepProc != NULL)) { ObjDeletionLock(context); |
︙ | ︙ | |||
1403 1404 1405 1406 1407 1408 1409 | /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) * with 'length == -1'. */ TclInvalidateStringRep(objPtr); | < | 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 | /* * Invalidate the string rep first so we can use the bytes value for our * pointer chain, and signal an obj deletion (as opposed to shimmering) * with 'length == -1'. */ TclInvalidateStringRep(objPtr); if (!objPtr->typePtr || !objPtr->typePtr->freeIntRepProc) { /* * objPtr can be freed safely, as it will not attempt to free any * other objects: it will not cause recursive calls to this function. */ |
︙ | ︙ | |||
1482 1483 1484 1485 1486 1487 1488 | Tcl_EventuallyFree(Tcl_GetHashValue(hPtr), ContLineLocFree); Tcl_DeleteHashEntry(hPtr); } } } } #endif /* TCL_MEM_DEBUG */ | < < < < < < < < < < < < < < < < < < < < < < < < < | 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 | Tcl_EventuallyFree(Tcl_GetHashValue(hPtr), ContLineLocFree); Tcl_DeleteHashEntry(hPtr); } } } } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * * Tcl_DuplicateObj -- * * Create and return a new object that is a duplicate of the argument |
︙ | ︙ |
Changes to generic/tclParse.c.
︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 | * Command substitution. Call Tcl_ParseCommand recursively (and * repeatedly) to parse the nested command(s), then throw away the * parse information. */ src++; numBytes--; | | | | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 | * Command substitution. Call Tcl_ParseCommand recursively (and * repeatedly) to parse the nested command(s), then throw away the * parse information. */ src++; numBytes--; nestedPtr = ckalloc(sizeof(Tcl_Parse)); while (1) { if (Tcl_ParseCommand(parsePtr->interp, src, numBytes, 1, nestedPtr) != TCL_OK) { parsePtr->errorType = nestedPtr->errorType; parsePtr->term = nestedPtr->term; parsePtr->incomplete = nestedPtr->incomplete; ckfree(nestedPtr); return TCL_ERROR; } src = nestedPtr->commandStart + nestedPtr->commandSize; numBytes = parsePtr->end - src; Tcl_FreeParse(nestedPtr); /* |
︙ | ︙ | |||
1178 1179 1180 1181 1182 1183 1184 | if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( "missing close-bracket", -1)); } parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->term = tokenPtr->start; parsePtr->incomplete = 1; | | | | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 | if (parsePtr->interp != NULL) { Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj( "missing close-bracket", -1)); } parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->term = tokenPtr->start; parsePtr->incomplete = 1; ckfree(nestedPtr); return TCL_ERROR; } } ckfree(nestedPtr); tokenPtr->type = TCL_TOKEN_COMMAND; tokenPtr->size = src - tokenPtr->start; parsePtr->numTokens++; } else if (*src == '\\') { if (noSubstBS) { tokenPtr->type = TCL_TOKEN_TEXT; tokenPtr->size = 1; |
︙ | ︙ | |||
1542 1543 1544 1545 1546 1547 1548 | * character must be "$". */ const char **termPtr) /* If non-NULL, points to word to fill in with * character just after last one in the * variable specifier. */ { register Tcl_Obj *objPtr; int code; | | | | | | 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 | * character must be "$". */ const char **termPtr) /* If non-NULL, points to word to fill in with * character just after last one in the * variable specifier. */ { register Tcl_Obj *objPtr; int code; Tcl_Parse *parsePtr = ckalloc(sizeof(Tcl_Parse)); if (Tcl_ParseVarName(interp, start, -1, parsePtr, 0) != TCL_OK) { ckfree(parsePtr); return NULL; } if (termPtr != NULL) { *termPtr = start + parsePtr->tokenPtr->size; } if (parsePtr->numTokens == 1) { /* * There isn't a variable name after all: the $ is just a $. */ ckfree(parsePtr); return "$"; } code = TclSubstTokens(interp, parsePtr->tokenPtr, parsePtr->numTokens, NULL, 1, NULL, NULL); ckfree(parsePtr); if (code != TCL_OK) { return NULL; } objPtr = Tcl_GetObjResult(interp); /* * At this point we should have an object containing the value of a |
︙ | ︙ | |||
2026 2027 2028 2029 2030 2031 2032 | * error. We'll do additional parsing to determine what length * to claim for the final TCL_TOKEN_COMMAND token. */ Tcl_Token *tokenPtr; const char *lastTerm = parsePtr->term; Tcl_Parse *nestedPtr = | | | | 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 | * error. We'll do additional parsing to determine what length * to claim for the final TCL_TOKEN_COMMAND token. */ Tcl_Token *tokenPtr; const char *lastTerm = parsePtr->term; Tcl_Parse *nestedPtr = ckalloc(sizeof(Tcl_Parse)); while (TCL_OK == Tcl_ParseCommand(NULL, p, length, 0, nestedPtr)) { Tcl_FreeParse(nestedPtr); p = nestedPtr->term + (nestedPtr->term < nestedPtr->end); length = nestedPtr->end - p; if ((length == 0) && (nestedPtr->term == nestedPtr->end)) { /* * If we run out of string, blame the missing close * bracket on the last command, and do not evaluate it * during substitution. */ break; } lastTerm = nestedPtr->term; } ckfree(nestedPtr); if (lastTerm == parsePtr->term) { /* * Parse error in first command. No commands to subst, add * no more tokens. */ break; |
︙ | ︙ |
Changes to generic/tclPreserve.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * Copyright (c) 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * The following data structure is used to keep track of all the Tcl_Preserve * calls that are still in effect. It grows as needed to accommodate any * number of calls in effect. */ | > > > > > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | * Copyright (c) 1994-1998 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" /* * Only use this file if we are NOT using the new code in tclAlloc.c */ /* * The following data structure is used to keep track of all the Tcl_Preserve * calls that are still in effect. It grows as needed to accommodate any * number of calls in effect. */ |
︙ | ︙ | |||
41 42 43 44 45 46 47 | * *firstRefPtr. */ static int inUse = 0; /* Count of structures currently in use in * refArray. */ TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */ #define INITIAL_SIZE 2 /* Initial number of reference slots to make */ | < < < < < < < < < < < < < < < < < < < < < | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | * *firstRefPtr. */ static int inUse = 0; /* Count of structures currently in use in * refArray. */ TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */ #define INITIAL_SIZE 2 /* Initial number of reference slots to make */ /* *---------------------------------------------------------------------- * * TclFinalizePreserve -- * * Called during exit processing to clean up the reference array. |
︙ | ︙ | |||
293 294 295 296 297 298 299 300 301 302 303 304 305 306 | if (freeProc == TCL_DYNAMIC) { ckfree(clientData); } else { freeProc(clientData); } } /* *--------------------------------------------------------------------------- * * TclHandleCreate -- * * Allocate a handle that contains enough information to determine if an * arbitrary malloc'd block has been deleted. This is used to avoid the | > > > > > > > > > > > > > > > > > > > > > > | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 | if (freeProc == TCL_DYNAMIC) { ckfree(clientData); } else { freeProc(clientData); } } /* * The following data structure is used to keep track of whether an arbitrary * block of memory has been deleted. This is used by the TclHandle code to * avoid the more time-expensive algorithm of Tcl_Preserve(). This mechanism * is mainly used when we have lots of references to a few big, expensive * objects that we don't want to live any longer than necessary. */ typedef struct HandleStruct { void *ptr; /* Pointer to the memory block being tracked. * This field will become NULL when the memory * block is deleted. This field must be the * first in the structure. */ #ifdef TCL_MEM_DEBUG void *ptr2; /* Backup copy of the above pointer used to * ensure that the contents of the handle are * not changed by anyone else. */ #endif int refCount; /* Number of TclHandlePreserve() calls in * effect on this handle. */ } HandleStruct; /* *--------------------------------------------------------------------------- * * TclHandleCreate -- * * Allocate a handle that contains enough information to determine if an * arbitrary malloc'd block has been deleted. This is used to avoid the |
︙ | ︙ |
Changes to generic/tclProc.c.
︙ | ︙ | |||
223 224 225 226 227 228 229 | * this file. The differences are the different index of the body in the * line array of the context, and the lamdba code requires some special * processing. Find a way to factor the common elements into a single * function. */ if (iPtr->cmdFramePtr) { | | | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | * this file. The differences are the different index of the body in the * line array of the context, and the lamdba code requires some special * processing. Find a way to factor the common elements into a single * function. */ if (iPtr->cmdFramePtr) { CmdFrame *contextPtr = ckalloc(sizeof(CmdFrame)); *contextPtr = *iPtr->cmdFramePtr; if (contextPtr->type == TCL_LOCATION_BC) { /* * Retrieve source information from the bytecode, if possible. If * the information is retrieved successfully, context.type will be * TCL_LOCATION_SOURCE and the reference held by |
︙ | ︙ | |||
301 302 303 304 305 306 307 | * 'contextPtr' is going out of scope; account for the reference * that it's holding to the path name. */ Tcl_DecrRefCount(contextPtr->data.eval.path); contextPtr->data.eval.path = NULL; } | | | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | * 'contextPtr' is going out of scope; account for the reference * that it's holding to the path name. */ Tcl_DecrRefCount(contextPtr->data.eval.path); contextPtr->data.eval.path = NULL; } ckfree(contextPtr); } /* * Optimize for no-op procs: if the body is not precompiled (like a TclPro * procbody), and the argument list is just "args" and the body is empty, * define a compileProc to compile a no-op. * |
︙ | ︙ | |||
1113 1114 1115 1116 1117 1118 1119 | const char *final = NULL; /* * Build up desired argument list for Tcl_WrongNumArgs */ numArgs = framePtr->procPtr->numArgs; | < | | 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 | const char *final = NULL; /* * Build up desired argument list for Tcl_WrongNumArgs */ numArgs = framePtr->procPtr->numArgs; desiredObjs = ckalloc((int) sizeof(Tcl_Obj *) * (numArgs+1)); if (framePtr->isProcCallFrame & FRAME_IS_LAMBDA) { desiredObjs[0] = Tcl_NewStringObj("lambdaExpr", -1); } else { ((Interp *) interp)->ensembleRewrite.numInsertedObjs -= skip - 1; #ifdef AVOID_HACKS_FOR_ITCL |
︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 | Tcl_ResetResult(interp); Tcl_WrongNumArgs(interp, numArgs+1, desiredObjs, final); for (i=0 ; i<=numArgs ; i++) { Tcl_DecrRefCount(desiredObjs[i]); } | | | 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 | Tcl_ResetResult(interp); Tcl_WrongNumArgs(interp, numArgs+1, desiredObjs, final); for (i=0 ; i<=numArgs ; i++) { Tcl_DecrRefCount(desiredObjs[i]); } ckfree(desiredObjs); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclInitCompiledLocals -- |
︙ | ︙ | |||
1468 1469 1470 1471 1472 1473 1474 | /* * Create the "compiledLocals" array. Make sure it is large enough to hold * all the procedure's compiled local variables, including its formal * parameters. */ | | | 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 | /* * Create the "compiledLocals" array. Make sure it is large enough to hold * all the procedure's compiled local variables, including its formal * parameters. */ varPtr = ckalloc((int)(localCt * sizeof(Var))); framePtr->compiledLocals = varPtr; framePtr->numCompiledLocals = localCt; /* * Match and assign the call's actual parameters to the procedure's formal * arguments. The formal arguments are described by the first numArgs * entries in both the Proc structure's local variable list and the call |
︙ | ︙ | |||
1759 1760 1761 1762 1763 1764 1765 | CallFrame *freePtr; ByteCode *codePtr; result = InitArgsAndLocals(interp, procNameObj, skip); if (result != TCL_OK) { freePtr = iPtr->framePtr; Tcl_PopCallFrame(interp); /* Pop but do not free. */ | | | | 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 | CallFrame *freePtr; ByteCode *codePtr; result = InitArgsAndLocals(interp, procNameObj, skip); if (result != TCL_OK) { freePtr = iPtr->framePtr; Tcl_PopCallFrame(interp); /* Pop but do not free. */ ckfree(freePtr->compiledLocals); /* Free compiledLocals. */ ckfree(freePtr); /* Free CallFrame. */ return TCL_ERROR; } #if defined(TCL_COMPILE_DEBUG) if (tclTraceExec >= 1) { register CallFrame *framePtr = iPtr->varFramePtr; register int i; |
︙ | ︙ | |||
1931 1932 1933 1934 1935 1936 1937 | * cannot be freed before the frame is popped, as the local variables must * be deleted. But the compiledLocals must be freed first, as they were * allocated later on the stack. */ freePtr = iPtr->framePtr; Tcl_PopCallFrame(interp); /* Pop but do not free. */ | | | | 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 | * cannot be freed before the frame is popped, as the local variables must * be deleted. But the compiledLocals must be freed first, as they were * allocated later on the stack. */ freePtr = iPtr->framePtr; Tcl_PopCallFrame(interp); /* Pop but do not free. */ ckfree(freePtr->compiledLocals); /* Free compiledLocals. */ ckfree(freePtr); /* Free CallFrame. */ return result; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2549 2550 2551 2552 2553 2554 2555 | * this file. The differences are the different index of the body in the * line array of the context, and the special processing mentioned in the * previous paragraph to track into the list. Find a way to factor the * common elements into a single function. */ if (iPtr->cmdFramePtr) { | | | 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 | * this file. The differences are the different index of the body in the * line array of the context, and the special processing mentioned in the * previous paragraph to track into the list. Find a way to factor the * common elements into a single function. */ if (iPtr->cmdFramePtr) { CmdFrame *contextPtr = ckalloc(sizeof(CmdFrame)); *contextPtr = *iPtr->cmdFramePtr; if (contextPtr->type == TCL_LOCATION_BC) { /* * Retrieve the source context from the bytecode. This call * accounts for the reference to the source file, if any, held in * 'context.data.eval.path'. |
︙ | ︙ | |||
2610 2611 2612 2613 2614 2615 2616 | /* * 'contextPtr' is going out of scope. Release the reference that * it's holding to the source file path */ Tcl_DecrRefCount(contextPtr->data.eval.path); } | | | 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 | /* * 'contextPtr' is going out of scope. Release the reference that * it's holding to the source file path */ Tcl_DecrRefCount(contextPtr->data.eval.path); } ckfree(contextPtr); } Tcl_SetHashValue(Tcl_CreateHashEntry(iPtr->linePBodyPtr, procPtr, &isNew), cfPtr); /* * Set the namespace for this lambda: given by objv[2] understood as a * global reference, or else global per default. |
︙ | ︙ | |||
2748 2749 2750 2751 2752 2753 2754 | nsObjPtr = lambdaPtr->internalRep.twoPtrValue.ptr2; result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); if (result != TCL_OK) { return TCL_ERROR; } | | | 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 | nsObjPtr = lambdaPtr->internalRep.twoPtrValue.ptr2; result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); if (result != TCL_OK) { return TCL_ERROR; } extraPtr = ckalloc(sizeof(ApplyExtraData)); memset(&extraPtr->cmd, 0, sizeof(Command)); procPtr->cmdPtr = &extraPtr->cmd; extraPtr->cmd.nsPtr = (Namespace *) nsPtr; /* * TIP#280 (semi-)HACK! * |
︙ | ︙ | |||
2799 2800 2801 2802 2803 2804 2805 | { ApplyExtraData *extraPtr = data[0]; if (extraPtr->isRootEnsemble) { ((Interp *) interp)->ensembleRewrite.sourceObjs = NULL; } | | | 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 | { ApplyExtraData *extraPtr = data[0]; if (extraPtr->isRootEnsemble) { ((Interp *) interp)->ensembleRewrite.sourceObjs = NULL; } ckfree(extraPtr); return result; } /* *---------------------------------------------------------------------- * * MakeLambdaError -- |
︙ | ︙ |
Changes to generic/tclScan.c.
︙ | ︙ | |||
255 256 257 258 259 260 261 | int *totalSubs) /* The number of variables that will be * required. */ { int gotXpg, gotSequential, value, i, flags; char *end; Tcl_UniChar ch; int objIndex, xpgSize, nspace = numVars; | | | 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | int *totalSubs) /* The number of variables that will be * required. */ { int gotXpg, gotSequential, value, i, flags; char *end; Tcl_UniChar ch; int objIndex, xpgSize, nspace = numVars; int *nassign = ckalloc(nspace * sizeof(int)); char buf[TCL_UTF_MAX+1]; Tcl_Obj *errorMsg; /* Place to build an error messages. Note that * these are messy operations because we do * not want to use the formatting engine; * we're inside there! */ /* |
︙ | ︙ | |||
476 477 478 479 480 481 482 | value = nspace; if (xpgSize) { nspace = xpgSize; } else { nspace += 16; /* formerly STATIC_LIST_SIZE */ } | < | | 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | value = nspace; if (xpgSize) { nspace = xpgSize; } else { nspace += 16; /* formerly STATIC_LIST_SIZE */ } nassign = ckrealloc(nassign, nspace * sizeof(int)); for (i = value; i < nspace; i++) { nassign[i] = 0; } } nassign[objIndex]++; objIndex++; } |
︙ | ︙ | |||
522 523 524 525 526 527 528 | "variable is not assigned by any conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", NULL); goto error; } } | | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 | "variable is not assigned by any conversion specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", NULL); goto error; } } ckfree(nassign); return TCL_OK; badIndex: if (gotXpg) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "\"%n$\" argument index out of range", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", NULL); } else { Tcl_SetObjResult(interp, Tcl_NewStringObj( "different numbers of variable names and field specifiers", -1)); Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", NULL); } error: ckfree(nassign); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_ScanObjCmd -- |
︙ | ︙ |
Changes to generic/tclStubInit.c.
︙ | ︙ | |||
214 215 216 217 218 219 220 | static const TclIntStubs tclIntStubs = { TCL_STUB_MAGIC, 0, 0, /* 0 */ 0, /* 1 */ 0, /* 2 */ | | | 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | static const TclIntStubs tclIntStubs = { TCL_STUB_MAGIC, 0, 0, /* 0 */ 0, /* 1 */ 0, /* 2 */ 0, /* 3 */ 0, /* 4 */ TclCleanupChildren, /* 5 */ TclCleanupCommand, /* 6 */ TclCopyAndCollapse, /* 7 */ TclCopyChannelOld, /* 8 */ TclCreatePipeline, /* 9 */ TclCreateProc, /* 10 */ |
︙ | ︙ | |||
280 281 282 283 284 285 286 | TclObjCommandComplete, /* 62 */ TclObjInterpProc, /* 63 */ TclObjInvoke, /* 64 */ 0, /* 65 */ 0, /* 66 */ 0, /* 67 */ 0, /* 68 */ | | | | | 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | TclObjCommandComplete, /* 62 */ TclObjInterpProc, /* 63 */ TclObjInvoke, /* 64 */ 0, /* 65 */ 0, /* 66 */ 0, /* 67 */ 0, /* 68 */ 0, /* 69 */ 0, /* 70 */ 0, /* 71 */ 0, /* 72 */ 0, /* 73 */ 0, /* 74 */ TclpGetClicks, /* 75 */ TclpGetSeconds, /* 76 */ TclpGetTime, /* 77 */ 0, /* 78 */ 0, /* 79 */ 0, /* 80 */ 0, /* 81 */ 0, /* 82 */ 0, /* 83 */ 0, /* 84 */ 0, /* 85 */ 0, /* 86 */ 0, /* 87 */ TclPrecTraceProc, /* 88 */ |
︙ | ︙ | |||
426 427 428 429 430 431 432 | TclpOpenFileChannel, /* 208 */ 0, /* 209 */ 0, /* 210 */ 0, /* 211 */ TclpFindExecutable, /* 212 */ TclGetObjNameOfExecutable, /* 213 */ TclSetObjNameOfExecutable, /* 214 */ | | | | | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | TclpOpenFileChannel, /* 208 */ 0, /* 209 */ 0, /* 210 */ 0, /* 211 */ TclpFindExecutable, /* 212 */ TclGetObjNameOfExecutable, /* 213 */ TclSetObjNameOfExecutable, /* 214 */ 0, /* 215 */ 0, /* 216 */ TclPushStackFrame, /* 217 */ TclPopStackFrame, /* 218 */ 0, /* 219 */ 0, /* 220 */ 0, /* 221 */ 0, /* 222 */ 0, /* 223 */ TclGetPlatform, /* 224 */ TclTraceDictPath, /* 225 */ 0, /* 226 */ TclSetNsPath, /* 227 */ 0, /* 228 */ TclPtrMakeUpvar, /* 229 */ TclObjLookupVar, /* 230 */ TclGetNamespaceFromObj, /* 231 */ TclEvalObjEx, /* 232 */ TclGetSrcInfoForPc, /* 233 */ |
︙ | ︙ |
Changes to generic/tclTest.c.
︙ | ︙ | |||
6780 6781 6782 6783 6784 6785 6786 | Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; static ptrdiff_t *refDepth = NULL; ptrdiff_t depth; | | < < | | | 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794 6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 | Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; static ptrdiff_t *refDepth = NULL; ptrdiff_t depth; Tcl_Obj *levels[5]; int i = 0; NRE_callback *cbPtr = iPtr->execEnvPtr->callbackPtr; if (refDepth == NULL) { refDepth = &depth; } depth = (refDepth - &depth); levels[0] = Tcl_NewIntObj(depth); levels[1] = Tcl_NewIntObj(iPtr->numLevels); levels[2] = Tcl_NewIntObj(iPtr->cmdFramePtr->level); levels[3] = Tcl_NewIntObj(iPtr->varFramePtr->level); while (cbPtr) { i++; cbPtr = cbPtr->nextPtr; } levels[4] = Tcl_NewIntObj(i); Tcl_SetObjResult(interp, Tcl_NewListObj(5, levels)); return TCL_OK; } /* *---------------------------------------------------------------------- * * TestconcatobjCmd -- |
︙ | ︙ |
Deleted generic/tclThreadAlloc.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to generic/tclTrace.c.
︙ | ︙ | |||
1675 1676 1677 1678 1679 1680 1681 | char *commandCopy; int traceCode; /* * Copy the command characters into a new string. */ | | | | 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 | char *commandCopy; int traceCode; /* * Copy the command characters into a new string. */ commandCopy = ckalloc((unsigned) numChars + 1); memcpy(commandCopy, command, (size_t) numChars); commandCopy[numChars] = '\0'; /* * Call the trace function then free allocated storage. */ traceCode = tracePtr->proc(tracePtr->clientData, (Tcl_Interp *) iPtr, iPtr->numLevels, commandCopy, (Tcl_Command) cmdPtr, objc, objv); ckfree(commandCopy); return traceCode; } /* *---------------------------------------------------------------------- * * CommandObjTraceDeleted -- |
︙ | ︙ | |||
2263 2264 2265 2266 2267 2268 2269 | int i; /* * This is a bit messy because we have to emulate the old trace interface, * which uses strings for everything. */ | | | | 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 | int i; /* * This is a bit messy because we have to emulate the old trace interface, * which uses strings for everything. */ argv = (const char **) ckalloc( (unsigned) ((objc + 1) * sizeof(const char *))); for (i = 0; i < objc; i++) { argv[i] = Tcl_GetString(objv[i]); } argv[objc] = 0; /* * Invoke the command function. Note that we cast away const-ness on two * parameters for compatibility with legacy code; the code MUST NOT modify * either command or argv. */ data->proc(data->clientData, interp, level, (char *) command, cmdPtr->proc, cmdPtr->clientData, objc, argv); ckfree((void *) argv); return TCL_OK; } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Added normBench.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 | TCL_INTERP: 1:8.6b1.2 2:8.6b1.2 3:8.6b1.2 4:8.6b1.2 5:8.6b1.2 6:8.6b1.2 7:8.6b1.2 8:8.5.9 STARTED 2011-03-28 10:53:26 (runbench.tcl v1.30) Benchmark 1:8.6b1.2 /home/mig/tcl/branch.base/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:12 elapsed Benchmark 2:8.6b1.2 /home/mig/tcl/branch.multi/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:08 elapsed Benchmark 3:8.6b1.2 /home/mig/tcl/branch.native/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:13 elapsed Benchmark 4:8.6b1.2 /home/mig/tcl/branch.tsd/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:08 elapsed Benchmark 5:8.6b1.2 /home/mig/tcl/no280.tsd/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:07 elapsed Benchmark 6:8.6b1.2 /home/mig/tcl/trunk.base/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:10 elapsed Benchmark 7:8.6b1.2 /home/mig/tcl/trunk.tsd/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:07 elapsed Benchmark 8:8.5.9 /home/mig/tcl/core8.5/unix/tclsh aabbccdeeefffghkllmmmmnpprrssstuuvw 00:01:09 elapsed R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 000 VERSIONS: 1:8.6b1.2 2:8.6b1.2 3:8.6b1.2 4:8.6b1.2 5:8.6b1.2 6:8.6b1.2 7:8.6b1.2 8:8.5.9 001 ARRAY format genKeys 50 0.94 0.79 0.96 0.87 0.77 0.91 0.82 1.00 002 ARRAY format genKeys 500 0.92 0.80 0.95 0.87 0.77 0.91 0.82 1.00 003 ARRAY makeHash 500 50 0.93 0.89 0.79 0.89 0.83 0.95 0.90 1.00 004 ascii85 strlen 2690 1.00 0.95 1.00 0.93 0.94 0.94 0.92 1.00 005 ascii85 strlen 269000 0.97 0.94 0.97 0.91 0.92 0.93 0.90 1.00 006 BASE64 decode 10 1.04 0.95 1.04 0.96 0.88 1.03 0.95 1.00 007 BASE64 decode 100 1.07 0.95 1.05 0.99 0.89 1.05 0.96 1.00 008 BASE64 decode 1000 1.08 0.96 1.05 0.99 0.89 1.04 0.98 1.00 009 BASE64 decode 10000 1.06 0.98 1.03 0.98 0.89 1.04 0.96 1.00 010 BASE64 decode2 10 1.05 0.95 1.05 0.97 0.88 1.02 0.95 1.00 011 BASE64 decode2 100 1.07 0.99 1.05 1.00 0.89 1.06 0.98 1.00 012 BASE64 decode2 1000 1.06 0.99 1.04 1.00 0.90 1.05 0.98 1.00 013 BASE64 decode2 10000 1.05 0.98 1.03 0.99 0.89 1.03 0.96 1.00 014 BASE64 decode3 10 1.07 1.00 1.07 0.99 0.90 1.04 0.97 1.00 015 BASE64 decode3 100 1.04 0.99 1.03 0.96 0.89 1.03 0.97 1.00 016 BASE64 decode3 1000 1.02 1.00 1.02 0.96 0.90 1.03 0.97 1.00 017 BASE64 decode3 10000 1.02 1.00 1.02 0.95 0.91 1.03 0.98 1.00 018 BASE64 encode 10 1.07 1.00 1.09 1.06 0.97 1.05 1.02 1.00 019 BASE64 encode 100 1.07 1.02 1.05 1.08 1.00 1.04 1.03 1.00 020 BASE64 encode 1000 1.07 1.04 1.05 1.08 1.00 1.05 1.04 1.00 021 BASE64 encode 10000 1.07 1.04 1.06 1.09 1.00 1.05 1.04 1.00 022 BASE64 encode2 10 1.08 1.02 1.09 1.06 0.95 1.06 1.02 1.00 023 BASE64 encode2 100 1.09 1.07 1.07 1.11 1.02 1.09 1.07 1.00 024 BASE64 encode2 1000 1.10 1.07 1.07 1.11 1.02 1.09 1.07 1.00 025 BASE64 encode2 10000 1.10 1.08 1.07 1.15 1.02 1.09 1.08 1.00 026 BASE64 encode3 10 1.07 0.99 1.09 1.00 0.94 1.03 0.97 1.00 027 BASE64 encode3 100 1.06 1.04 1.07 1.04 0.99 1.05 1.00 1.00 028 BASE64 encode3 1000 1.06 1.03 1.04 1.04 0.99 1.04 1.01 1.00 029 BASE64 encode3 10000 1.07 1.03 1.04 1.07 0.99 1.05 1.03 1.00 030 BIN bitset-v1 1000 chars 1.60 1.46 1.44 1.41 1.31 1.43 1.31 1.00 031 BIN bitset-v1 5000 chars 1.62 1.50 1.44 1.44 1.31 1.41 1.35 1.00 032 BIN bitset-v1 10000 chars 1.62 1.50 1.44 1.44 1.32 1.43 1.33 1.00 033 BIN bitset-v2 1000 chars 1.31 1.19 1.19 1.18 1.08 1.15 1.10 1.00 034 BIN bitset-v2 5000 chars 1.29 1.18 1.15 1.18 1.07 1.14 1.09 1.00 035 BIN bitset-v2 10000 chars 1.29 1.17 1.15 1.18 1.07 1.13 1.08 1.00 036 BIN bitset-v3 1000 chars 0.88 0.81 0.86 0.83 0.65 0.88 0.82 1.00 037 BIN bitset-v3 5000 chars 0.88 0.80 0.84 0.83 0.65 0.86 0.80 1.00 038 BIN bitset-v3 10000 chars 0.88 0.80 0.83 0.83 0.65 0.87 0.83 1.00 039 BIN c scan, 1000b 0.93 0.88 1.04 0.88 0.81 0.95 0.90 1.00 040 BIN c scan, 5000b 0.95 0.93 0.97 0.93 0.93 0.96 0.96 1.00 041 BIN c scan, 10000b 0.96 0.96 1.00 0.94 0.96 0.96 0.96 1.00 042 BIN chars, 10000b 0.87 0.80 0.82 0.81 0.72 0.87 0.81 1.00 043 BIN rand string 100b 1.34 1.21 1.27 1.17 1.39 1.19 1.14 1.00 044 BIN rand string 5000b 1.36 1.24 1.29 1.18 1.42 1.21 1.16 1.00 045 BIN rand2 string 100b 1.24 1.14 1.06 1.13 1.29 1.08 1.05 1.00 046 BIN rand2 string 5000b 1.24 1.14 1.04 1.13 1.36 1.07 1.05 1.00 047 BIN u char, 10000b 0.94 0.94 0.97 0.95 0.97 0.99 0.97 1.00 048 CATCH error, complex 1.08 0.98 1.15 0.96 0.92 1.04 0.98 1.00 049 CATCH no catch used 1.41 1.19 1.44 1.16 1.27 1.11 1.06 1.00 050 CATCH return error 1.07 0.96 1.13 0.95 0.92 1.04 0.96 1.00 051 CATCH return except 1.39 1.20 1.44 1.18 1.26 1.11 1.06 1.00 052 CATCH return ok 1.40 1.24 1.50 1.20 1.25 1.12 1.08 1.00 053 DATA access in a list 1.08 1.08 1.13 1.02 1.06 1.09 1.13 1.00 054 DATA access in an array 1.06 1.06 1.18 1.04 1.07 1.10 1.08 1.00 055 DATA create in a list 1.04 1.02 1.01 0.99 0.79 1.02 1.04 1.00 056 DATA create in an array 1.02 0.96 1.17 0.97 0.87 1.05 1.01 1.00 057 ENC iso2022-jp, gets 1.12 1.00 0.99 1.00 1.04 1.10 0.95 1.00 058 ENC iso2022-jp, read 1.12 1.00 0.97 0.99 0.93 1.06 0.91 1.00 059 ENC iso2022-jp, read & size 0.96 0.86 0.83 0.86 0.80 0.90 0.79 1.00 060 ENC iso8859-2, gets 0.37 0.35 0.39 0.35 0.35 0.36 0.34 1.00 061 ENC iso8859-2, read 0.25 0.25 0.27 0.25 0.25 0.25 0.25 1.00 062 ENC iso8859-2, read & size 0.28 0.27 0.30 0.28 0.27 0.28 0.27 1.00 063 EVAL cmd and mixed lists 0.81 0.75 1.09 0.75 0.64 0.83 0.77 1.00 064 EVAL cmd eval as list 1.46 1.24 1.42 1.22 1.06 1.24 1.10 1.00 065 EVAL cmd eval as string 1.03 0.92 1.11 0.93 0.75 0.93 0.85 1.00 066 EVAL cmd eval in list obj var 1.43 1.19 1.32 1.19 1.06 1.19 1.08 1.00 067 EVAL cmd eval in list obj {*} 1.52 1.31 1.61 1.31 1.25 1.36 1.26 1.00 068 EVAL list cmd and mixed lists 0.84 0.79 1.12 0.78 0.65 0.83 0.78 1.00 069 EVAL list cmd and pure lists 1.01 0.89 0.99 0.98 0.93 0.91 1.01 1.00 070 EXPR $a != $b dbl 1.60 1.43 1.83 1.45 1.40 1.38 1.38 1.00 071 EXPR $a != $b int 1.55 1.32 1.68 1.35 1.30 1.25 1.20 1.00 072 EXPR $a != $b str (!= len) 1.14 1.00 1.16 1.05 0.94 0.98 0.95 1.00 073 EXPR $a != $b str (== len) 1.23 1.08 1.27 1.13 1.03 1.09 1.03 1.00 074 EXPR $a == $b dbl 1.57 1.45 1.83 1.48 1.40 1.38 1.33 1.00 075 EXPR $a == $b int 1.56 1.36 1.69 1.44 1.36 1.26 1.23 1.00 076 EXPR $a == $b str (!= len) 1.15 1.01 1.16 1.07 0.97 0.95 0.98 1.00 077 EXPR $a == $b str (== len) 1.27 1.10 1.26 1.15 1.06 1.06 1.05 1.00 078 EXPR abs as expr 1.69 1.50 1.94 1.53 1.58 1.44 1.36 1.00 079 EXPR abs builtin 1.67 1.44 1.81 1.47 1.51 1.37 1.28 1.00 080 EXPR braced 1.42 1.26 1.40 1.23 1.36 1.25 1.16 1.00 081 EXPR builtin dyn 1.11 1.03 1.25 1.00 0.80 1.04 0.98 1.00 082 EXPR builtin sin 1.67 1.42 1.63 1.35 1.46 1.27 1.21 1.00 083 EXPR cast double 1.68 1.38 1.79 1.40 1.51 1.32 1.26 1.00 084 EXPR cast int 1.79 1.52 1.67 1.54 1.42 1.31 1.23 1.00 085 EXPR fifty operands 1.05 0.96 1.15 0.94 0.96 0.95 0.92 1.00 086 EXPR incr with expr 1.65 1.39 1.87 1.35 1.32 1.23 1.19 1.00 087 EXPR incr with incr 1.71 1.43 1.93 1.43 1.39 1.32 1.25 1.00 088 EXPR inline 1.28 1.21 1.18 1.21 1.22 1.21 1.13 1.00 089 EXPR one operand 1.75 1.46 2.04 1.54 1.39 1.32 1.29 1.00 090 EXPR rand range 1.71 1.49 1.61 1.49 1.58 1.34 1.28 1.00 091 EXPR rand range func 1.77 1.47 1.67 1.48 1.48 1.31 1.24 1.00 092 EXPR ten operands 1.33 1.18 1.53 1.16 1.14 1.12 1.04 1.00 093 EXPR unbraced 1.03 0.97 1.25 0.95 0.81 0.98 0.96 1.00 094 EXPR unbraced long 0.89 0.86 1.04 0.86 0.81 0.91 0.93 1.00 095 EXPR UpdStrOfDbl+1.23 prec0 1.18 1.01 1.28 1.05 1.03 1.03 1.00 1.00 096 EXPR UpdStrOfDbl+1.23 prec12 1.28 1.09 1.29 1.11 1.13 1.07 1.02 1.00 097 EXPR UpdStrOfDbl+1.23 prec17 1.15 1.04 1.19 1.06 1.08 1.05 1.01 1.00 098 EXPR UpdStrOfDbl+1e-4 prec0 1.15 1.00 1.22 1.01 1.05 1.03 0.98 1.00 099 EXPR UpdStrOfDbl+1e-4 prec12 1.27 1.08 1.28 1.12 1.14 1.08 1.02 1.00 100 EXPR UpdStrOfDbl+1e-4 prec17 1.14 1.01 1.17 1.06 1.06 1.04 0.98 1.00 101 EXPR UpdStrOfDbl+1e27 prec0 0.98 0.89 1.14 0.88 0.91 0.93 0.87 1.00 102 EXPR UpdStrOfDbl+1e27 prec12 1.29 1.10 1.31 1.10 1.11 1.08 1.00 1.00 103 EXPR UpdStrOfDbl+1e27 prec17 0.99 0.90 1.14 0.89 0.92 0.98 0.92 1.00 104 FCOPY binary: 160K 1.01 1.02 1.02 1.02 1.02 1.01 1.03 1.00 105 FCOPY encoding: 160K 0.90 0.90 0.86 0.90 0.95 0.94 0.86 1.00 106 FCOPY std: 160K 1.02 1.02 1.01 1.02 1.02 1.03 1.03 1.00 107 FILE exec interp 1.08 1.06 1.15 1.08 1.61 1.13 1.07 1.00 108 FILE exec interp: pkg require 1.04 1.03 1.10 1.03 1.20 1.05 1.03 1.00 109 FILE exists tmpfile (obj) 1.29 1.23 1.23 1.25 1.16 1.19 1.18 1.00 110 FILE exists ~ 1.32 1.20 1.23 1.24 1.15 1.18 1.15 1.00 111 FILE exists! tmpfile (obj) 1.30 1.27 1.22 1.28 1.18 1.22 1.20 1.00 112 FILE exists! tmpfile (str) 1.12 1.08 1.06 1.05 1.01 1.07 1.05 1.00 113 FILE glob tmpdir (60 entries) 0.93 0.94 1.02 0.91 0.88 0.94 0.90 1.00 114 FILE glob / all subcommands 1.07 1.04 1.07 1.05 1.00 1.07 1.02 1.00 115 FILE glob / atime 1.02 0.98 1.02 0.97 0.91 0.98 0.94 1.00 116 FILE glob / attributes 0.98 0.96 1.00 0.98 0.95 0.98 0.97 1.00 117 FILE glob / dirname 1.25 1.20 1.28 1.19 1.10 1.23 1.13 1.00 118 FILE glob / executable 1.03 0.98 1.01 0.97 0.92 0.99 0.96 1.00 119 FILE glob / exists 1.04 1.00 1.04 0.99 0.93 1.01 0.98 1.00 120 FILE glob / extension 1.19 1.14 1.26 1.12 1.05 1.20 1.06 1.00 121 FILE glob / isdirectory 1.06 1.01 1.06 1.01 0.93 1.02 0.98 1.00 122 FILE glob / isfile 1.05 1.02 1.06 1.00 0.93 1.01 0.98 1.00 123 FILE glob / mtime 1.05 1.01 1.08 1.00 0.93 1.05 0.99 1.00 124 FILE glob / owned 1.05 1.00 1.07 1.00 0.92 1.03 0.98 1.00 125 FILE glob / readable 1.03 1.00 1.05 0.99 0.93 1.00 0.97 1.00 126 FILE glob / rootname 1.19 1.13 1.23 1.11 1.04 1.18 1.06 1.00 127 FILE glob / size 1.02 1.01 1.05 0.99 0.93 1.00 0.96 1.00 128 FILE glob / tail 1.25 1.20 1.29 1.19 1.11 1.25 1.12 1.00 129 FILE glob / writable 1.02 1.02 1.05 0.99 0.93 1.01 0.97 1.00 130 FILE recurse / -dir 1.03 1.01 1.10 0.99 0.95 1.04 0.98 1.00 131 FILE recurse / cd 1.06 1.03 1.13 1.03 0.99 1.07 1.01 1.00 132 FORMAT gen 1.16 0.98 1.26 0.99 0.98 1.02 0.97 1.00 133 GCCont_cpb::cGCC 50 0.93 0.90 0.92 0.88 0.76 0.92 0.85 1.00 134 GCCont_cpb::cGCC 500 0.89 0.89 0.83 0.88 0.73 0.90 0.84 1.00 135 GCCont_cpb::cGCC 5000 0.87 0.86 0.80 0.86 0.71 0.88 0.81 1.00 136 GCCont_cpbre1::cGCC 50 1.03 1.01 0.97 1.00 0.94 1.02 1.00 1.00 137 GCCont_cpbre1::cGCC 500 1.02 1.02 0.97 1.00 0.98 1.01 1.00 1.00 138 GCCont_cpbre1::cGCC 5000 1.02 1.01 0.97 0.99 0.99 0.99 0.99 1.00 139 GCCont_cpbre2::cGCC 50 1.02 1.00 0.97 0.97 0.94 0.99 0.96 1.00 140 GCCont_cpbre2::cGCC 500 1.03 1.03 0.98 0.99 1.00 1.00 0.99 1.00 141 GCCont_cpbre2::cGCC 5000 1.02 1.03 0.98 0.99 1.00 1.00 1.00 1.00 142 GCCont_cpbrs2::cGCC 50 0.97 0.91 0.98 0.89 0.83 0.91 0.84 1.00 143 GCCont_cpbrs2::cGCC 500 0.83 0.83 0.86 0.83 0.81 0.81 0.82 1.00 144 GCCont_cpbrs2::cGCC 5000 0.80 0.81 0.80 0.81 0.81 0.78 0.82 1.00 145 GCCont_cpbrs::cGCC1 50 0.99 0.96 0.98 0.92 0.88 0.98 0.96 1.00 146 GCCont_cpbrs::cGCC1 500 0.89 0.88 0.89 0.87 0.85 0.87 0.88 1.00 147 GCCont_cpbrs::cGCC1 5000 0.86 0.86 0.85 0.86 0.85 0.84 0.87 1.00 148 GCCont_cpbrs::cGCC2 50 0.98 0.94 0.95 0.91 0.85 0.95 0.93 1.00 149 GCCont_cpbrs::cGCC2 500 0.85 0.84 0.85 0.82 0.80 0.83 0.84 1.00 150 GCCont_cpbrs::cGCC2 5000 0.80 0.80 0.80 0.80 0.80 0.78 0.81 1.00 151 GCCont_cpbrs_trap::cGCC 50 1.01 0.99 0.98 0.97 0.94 1.04 0.99 1.00 152 GCCont_cpbrs_trap::cGCC 500 1.01 1.01 0.97 0.98 0.97 1.03 0.98 1.00 153 GCCont_cpbrs_trap::cGCC 5000 1.00 1.00 0.96 0.98 0.97 1.02 0.99 1.00 154 GCCont_expr::cGCC 50 0.95 0.91 1.12 0.91 0.82 0.94 0.94 1.00 155 GCCont_expr::cGCC 500 0.87 0.85 1.00 0.86 0.78 0.90 0.91 1.00 156 GCCont_expr::cGCC 5000 0.87 0.86 0.95 0.86 0.78 0.90 0.93 1.00 157 GCCont_i::cGCC1 50 0.95 0.92 0.94 0.91 0.83 0.97 0.90 1.00 158 GCCont_i::cGCC1 500 0.92 0.89 0.91 0.88 0.81 0.95 0.95 1.00 159 GCCont_i::cGCC1 5000 0.91 0.88 0.90 0.89 0.80 0.95 0.95 1.00 160 GCCont_i::cGCC2 50 0.95 0.91 0.93 0.90 0.82 0.93 0.88 1.00 161 GCCont_i::cGCC2 500 0.92 0.90 0.89 0.90 0.82 0.93 0.88 1.00 162 GCCont_i::cGCC2 5000 0.92 0.90 0.89 0.90 0.81 0.94 0.88 1.00 163 GCCont_i::cGCC3 50 0.95 0.88 0.93 0.87 0.79 0.94 0.87 1.00 164 GCCont_i::cGCC3 500 0.90 0.84 0.88 0.84 0.77 0.92 0.86 1.00 165 GCCont_i::cGCC3 5000 0.90 0.84 0.87 0.84 0.75 0.92 0.86 1.00 166 GCCont_r1::cGCC 50 1.10 1.06 1.13 1.07 1.10 1.08 1.06 1.00 167 GCCont_r1::cGCC 500 1.11 1.07 1.14 1.10 1.11 1.12 1.07 1.00 168 GCCont_r1::cGCC 5000 1.12 1.07 1.14 1.10 1.11 1.11 1.08 1.00 169 GCCont_r2::cGCC 50 1.02 0.96 1.04 0.97 0.89 1.02 0.95 1.00 170 GCCont_r2::cGCC 500 0.99 0.95 1.03 0.96 0.92 1.02 1.01 1.00 171 GCCont_r2::cGCC 5000 0.98 0.93 1.01 0.96 0.90 0.98 0.99 1.00 172 GCCont_r3::cGCC 50 1.02 0.98 1.05 0.98 0.90 1.02 0.95 1.00 173 GCCont_r3::cGCC 500 1.00 0.95 1.03 0.97 0.94 1.00 1.00 1.00 174 GCCont_r3::cGCC 5000 0.98 0.94 1.01 0.96 0.92 1.00 1.00 1.00 175 GCCont_rsf1::cGCC 50 0.94 0.88 0.94 0.87 0.78 0.94 0.89 1.00 176 GCCont_rsf1::cGCC 500 0.88 0.82 0.85 0.82 0.73 0.89 0.84 1.00 177 GCCont_rsf1::cGCC 5000 0.85 0.81 0.82 0.80 0.71 0.87 0.81 1.00 178 GCCont_rsf2::cGCC1 50 0.98 0.93 0.98 0.91 0.84 0.98 0.92 1.00 179 GCCont_rsf2::cGCC1 500 0.89 0.86 0.87 0.85 0.76 0.89 0.86 1.00 180 GCCont_rsf2::cGCC1 5000 0.87 0.84 0.83 0.84 0.74 0.88 0.84 1.00 181 GCCont_rsf2::cGCC2 50 0.99 0.93 1.01 0.91 0.84 0.96 0.91 1.00 182 GCCont_rsf2::cGCC2 500 0.88 0.84 0.87 0.84 0.75 0.89 0.85 1.00 183 GCCont_rsf2::cGCC2 5000 0.87 0.82 0.83 0.83 0.73 0.87 0.83 1.00 184 GCCont_rsf3::cGCC 50 0.98 0.93 0.99 0.90 0.84 0.97 0.90 1.00 185 GCCont_rsf3::cGCC 500 0.89 0.85 0.87 0.84 0.75 0.89 0.85 1.00 186 GCCont_rsf3::cGCC 5000 0.87 0.81 0.83 0.83 0.73 0.87 0.83 1.00 187 GCCont_turing::cGCC 50 0.90 0.85 0.93 0.85 0.80 0.82 0.80 1.00 188 GCCont_turing::cGCC 500 0.72 0.70 0.72 0.71 0.69 0.70 0.70 1.00 189 GCCont_turing::cGCC 5000 0.67 0.69 0.68 0.67 0.65 0.66 0.67 1.00 190 HEAPSORT size 10 1.03 1.03 1.08 1.04 1.01 1.02 1.01 1.00 191 HEAPSORT size 50 1.02 1.01 1.06 1.03 0.98 1.02 0.99 1.00 192 HEAPSORT size 100 1.01 1.00 1.04 1.01 0.97 1.01 0.98 1.00 193 HEAPSORT2 size 10 1.10 1.09 1.10 1.10 1.06 1.06 1.06 1.00 194 HEAPSORT2 size 50 1.09 1.08 1.05 1.09 1.06 1.06 1.05 1.00 195 HEAPSORT2 size 100 1.10 1.09 1.05 1.09 1.06 1.07 1.06 1.00 196 IF 1/0 check 1.51 1.29 1.80 1.31 1.26 1.23 1.14 1.00 197 IF else true al 1.41 1.24 1.48 1.31 1.24 1.23 1.20 1.00 198 IF else true numeric 1.55 1.33 1.65 1.41 1.29 1.25 1.22 1.00 199 IF elseif true al 1.32 1.22 1.39 1.24 1.20 1.15 1.15 1.00 200 IF elseif true numeric 1.50 1.31 1.65 1.35 1.27 1.25 1.17 1.00 201 IF if false al/al 1.50 1.29 1.57 1.34 1.30 1.23 1.21 1.00 202 IF if false al/num 1.54 1.28 1.65 1.40 1.30 1.21 1.21 1.00 203 IF if false num/num 1.55 1.32 1.84 1.41 1.30 1.23 1.20 1.00 204 IF if true al 1.46 1.30 1.61 1.31 1.28 1.19 1.17 1.00 205 IF if true al/al 1.46 1.29 1.57 1.29 1.25 1.14 1.14 1.00 206 IF if true num/num 1.58 1.37 1.74 1.40 1.33 1.23 1.21 1.00 207 IF if true numeric 1.57 1.40 1.86 1.45 1.33 1.26 1.24 1.00 208 IF multi 1st true 1.55 1.32 1.75 1.39 1.32 1.27 1.25 1.00 209 IF multi 2nd true 1.52 1.33 1.73 1.40 1.33 1.27 1.25 1.00 210 IF multi 9th true 1.36 1.23 1.44 1.27 1.21 1.19 1.15 1.00 211 IF multi default true 1.41 1.24 1.52 1.32 1.24 1.20 1.18 1.00 212 KLIST shuffle0 llength 1 0.95 0.93 1.00 0.88 0.82 0.95 0.90 1.00 213 KLIST shuffle0 llength 10 0.95 0.91 0.93 0.88 0.76 0.96 0.86 1.00 214 KLIST shuffle0 llength 100 0.93 0.86 0.91 0.86 0.76 0.95 0.86 1.00 215 KLIST shuffle0 llength 1000 0.94 0.88 0.92 0.88 0.79 0.95 0.88 1.00 216 KLIST shuffle0 llength 10000 0.95 0.90 0.92 0.90 0.90 0.98 0.93 1.00 217 KLIST shuffle1-s llength 1 1.36 1.23 1.34 1.19 1.22 1.13 1.09 1.00 218 KLIST shuffle1-s llength 10 1.29 1.21 1.27 1.15 1.21 1.12 1.06 1.00 219 KLIST shuffle1-s llength 100 1.15 1.10 1.28 1.06 1.10 1.12 0.99 1.00 220 KLIST shuffle1-s llength 1000 1.02 1.00 1.11 1.01 0.95 1.01 0.91 1.00 221 KLIST shuffle1a llength 1 1.48 1.33 1.53 1.29 1.35 1.21 1.15 1.00 222 KLIST shuffle1a llength 10 1.54 1.38 1.55 1.35 1.44 1.25 1.19 1.00 223 KLIST shuffle1a llength 100 1.56 1.37 1.56 1.35 1.45 1.26 1.20 1.00 224 KLIST shuffle1a llength 1000 1.53 1.36 1.53 1.36 1.45 1.25 1.21 1.00 225 KLIST shuffle1a llength 10000 1.54 1.37 1.56 1.37 1.46 1.26 1.22 1.00 226 KLIST shuffle2 llength 1 1.24 1.14 1.26 1.13 1.13 1.06 1.05 1.00 227 KLIST shuffle2 llength 10 1.22 1.12 1.24 1.12 1.13 1.09 1.08 1.00 228 KLIST shuffle2 llength 100 1.24 1.13 1.26 1.13 1.14 1.11 1.10 1.00 229 KLIST shuffle2 llength 1000 1.19 1.11 1.21 1.12 1.10 1.11 1.09 1.00 230 KLIST shuffle2 llength 10000 1.16 1.10 1.12 1.09 1.08 1.08 1.07 1.00 231 KLIST shuffle3 llength 1 1.42 1.29 1.43 1.25 1.24 1.15 1.09 1.00 232 KLIST shuffle3 llength 10 1.54 1.37 1.50 1.38 1.47 1.24 1.20 1.00 233 KLIST shuffle3 llength 100 1.55 1.38 1.49 1.39 1.49 1.25 1.21 1.00 234 KLIST shuffle3 llength 1000 1.54 1.36 1.48 1.39 1.45 1.22 1.20 1.00 235 KLIST shuffle3 llength 10000 1.24 1.17 1.24 1.18 1.22 1.09 1.05 1.00 236 KLIST shuffle4 llength 1 1.36 1.23 1.38 1.21 1.21 1.13 1.07 1.00 237 KLIST shuffle4 llength 10 1.52 1.36 1.48 1.34 1.43 1.24 1.19 1.00 238 KLIST shuffle4 llength 100 1.54 1.38 1.50 1.38 1.47 1.25 1.21 1.00 239 KLIST shuffle4 llength 1000 1.56 1.40 1.50 1.41 1.48 1.26 1.22 1.00 240 KLIST shuffle4 llength 10000 1.55 1.37 1.46 1.36 1.47 1.26 1.21 1.00 241 KLIST shuffle5-s llength 1 1.34 1.16 1.29 1.16 1.12 1.09 1.02 1.00 242 KLIST shuffle5-s llength 10 1.30 1.21 1.28 1.14 1.19 1.09 1.04 1.00 243 KLIST shuffle5-s llength 100 1.27 1.18 1.22 1.11 1.15 1.08 1.02 1.00 244 KLIST shuffle5-s llength 1000 1.07 1.02 1.04 1.01 0.97 0.98 0.93 1.00 245 KLIST shuffle5a llength 1 1.40 1.25 1.43 1.22 1.20 1.14 1.07 1.00 246 KLIST shuffle5a llength 10 1.44 1.33 1.46 1.28 1.31 1.18 1.13 1.00 247 KLIST shuffle5a llength 100 1.46 1.35 1.42 1.30 1.35 1.19 1.14 1.00 248 KLIST shuffle5a llength 1000 1.45 1.34 1.46 1.29 1.34 1.20 1.16 1.00 249 KLIST shuffle5a llength 10000 1.21 1.20 1.22 1.17 1.17 1.10 1.09 1.00 250 KLIST shuffle6 llength 1 1.35 1.14 1.44 1.19 0.95 1.02 0.98 1.00 251 KLIST shuffle6 llength 10 1.26 1.21 1.19 1.17 1.25 1.16 1.11 1.00 252 KLIST shuffle6 llength 100 1.27 1.23 1.20 1.17 1.28 1.17 1.14 1.00 253 KLIST shuffle6 llength 1000 1.26 1.22 1.20 1.19 1.29 1.17 1.15 1.00 254 KLIST shuffle6 llength 10000 1.30 1.25 1.19 1.23 1.31 1.20 1.17 1.00 255 LIST append to list 1.38 1.20 1.60 1.18 1.13 1.07 1.00 1.00 256 LIST concat APPEND 2x10 0.94 0.82 1.08 0.82 0.69 0.92 0.84 1.00 257 LIST concat APPEND 2x100 0.85 0.76 1.15 0.76 0.60 0.88 0.77 1.00 258 LIST concat APPEND 2x1000 0.85 0.77 1.09 0.77 0.64 0.89 0.79 1.00 259 LIST concat APPEND 2x10000 0.85 0.78 1.06 0.78 0.65 0.89 0.79 1.00 260 LIST concat CONCAT 2x10 1.20 1.13 1.32 1.08 1.07 1.09 1.02 1.00 261 LIST concat CONCAT 2x100 1.15 1.08 1.27 1.06 1.06 1.06 1.02 1.00 262 LIST concat CONCAT 2x1000 0.99 1.01 0.99 0.97 0.97 0.96 0.99 1.00 263 LIST concat CONCAT 2x10000 0.90 0.92 1.03 0.92 1.01 0.96 1.02 1.00 264 LIST concat EVAL/LAPPEND 2x10 1.19 1.06 1.19 1.05 0.92 1.06 0.98 1.00 265 LIST concat EVAL/LAPPEND 2x100 1.13 1.06 1.21 1.05 0.94 1.06 1.01 1.00 266 LIST concat EVAL/LAPPEND 2x1000 1.13 1.10 0.99 1.11 1.00 1.11 1.14 1.00 267 LIST concat EVAL/LAPPEND 2x10000 0.89 0.89 0.98 0.87 0.96 0.95 0.99 1.00 268 LIST concat FOREACH/LAPPEND 2x10 0.97 0.90 0.93 0.88 0.75 0.91 0.84 1.00 269 LIST concat FOREACH/LAPPEND 2x100 0.89 0.81 0.81 0.80 0.67 0.88 0.81 1.00 270 LIST concat FOREACH/LAPPEND 2x1000 0.91 0.81 0.81 0.81 0.66 0.89 0.81 1.00 271 LIST concat FOREACH/LAPPEND 2x10000 0.88 0.77 0.80 0.79 0.64 0.88 0.80 1.00 272 LIST concat SET 2x10 0.91 0.82 1.06 0.80 0.67 0.92 0.82 1.00 273 LIST concat SET 2x100 0.81 0.72 1.14 0.72 0.57 0.87 0.76 1.00 274 LIST concat SET 2x1000 0.83 0.74 1.07 0.73 0.62 0.87 0.76 1.00 275 LIST concat SET 2x10000 0.85 0.76 1.08 0.76 0.63 0.87 0.78 1.00 276 LIST exact search, first item 1.76 1.38 1.64 1.44 1.40 1.36 1.24 1.00 277 LIST exact search, last item 1.22 1.12 1.21 1.15 1.19 1.16 1.13 1.00 278 LIST exact search, middle item 1.38 1.18 1.31 1.20 1.24 1.24 1.16 1.00 279 LIST exact search, non-item 1.13 1.10 1.13 1.10 1.13 1.15 1.14 1.00 280 LIST exact search, typed item 0.90 0.87 0.92 0.89 0.92 0.99 0.90 1.00 281 LIST exact search, untyped item 1.21 1.11 1.20 1.12 1.16 1.13 1.10 1.00 282 LIST index first element 1.69 1.31 1.82 1.31 1.28 1.33 1.18 1.00 283 LIST index last element 1.64 1.28 1.90 1.31 1.28 1.31 1.18 1.00 284 LIST index middle element 1.67 1.31 1.74 1.31 1.28 1.31 1.18 1.00 285 LIST insert an item at "end" 0.96 0.94 0.98 0.86 1.02 0.99 0.89 1.00 286 LIST insert an item at middle 0.94 0.93 0.96 0.85 1.00 0.98 0.88 1.00 287 LIST insert an item at start 0.95 0.92 0.97 0.85 1.03 1.03 0.88 1.00 288 LIST iterate list 1.10 1.08 1.01 1.06 0.99 1.14 1.09 1.00 289 LIST join list 1.22 1.21 1.22 1.21 1.23 1.22 1.21 1.00 290 LIST large, early range 1.23 1.06 1.31 1.06 1.07 1.03 1.01 1.00 291 LIST large, late range 1.25 1.06 1.31 1.05 1.07 1.05 1.01 1.00 292 LIST length, pure list 1.50 1.29 1.81 1.29 1.14 1.21 1.10 1.00 293 LIST list 0.96 0.84 0.91 0.85 0.73 0.96 0.83 1.00 294 LIST lset foreach l 1.07 1.02 1.09 0.98 0.85 0.98 0.97 1.00 295 LIST lset foreach list 1.04 0.98 1.11 0.97 0.84 0.98 0.98 1.00 296 LIST lset foreach ""s l 0.97 0.90 0.88 0.92 0.78 0.97 0.90 1.00 297 LIST lset foreach ""s list 0.99 0.94 0.91 0.94 0.80 0.98 0.91 1.00 298 LIST regexp search, first item 1.65 1.35 1.64 1.38 1.35 1.31 1.18 1.00 299 LIST regexp search, last item 1.03 0.99 1.01 1.00 0.98 1.00 0.99 1.00 300 LIST regexp search, non-item 1.00 0.95 0.98 0.96 0.96 0.99 0.97 1.00 301 LIST remove first element 0.98 1.04 1.01 0.96 1.02 0.97 0.90 1.00 302 LIST remove in mixed list 1.20 1.28 1.11 1.27 0.84 1.06 1.08 1.00 303 LIST remove last element 0.96 1.02 1.01 0.95 1.01 0.96 0.89 1.00 304 LIST remove middle element 0.88 0.90 0.89 0.79 0.88 0.86 0.80 1.00 305 LIST replace first el with multiple 0.95 0.99 1.00 0.94 1.02 0.96 0.89 1.00 306 LIST replace first element 0.89 0.89 0.90 0.80 0.89 0.90 0.82 1.00 307 LIST replace in mixed list 1.13 1.14 1.12 1.12 0.85 1.09 1.05 1.00 308 LIST replace last el with multiple 0.90 0.92 0.94 0.90 0.96 0.90 0.81 1.00 309 LIST replace last element 0.85 0.90 0.93 0.80 0.88 0.89 0.83 1.00 310 LIST replace middle el with multiple 0.89 0.89 0.93 0.82 0.92 0.93 0.86 1.00 311 LIST replace middle element 0.95 0.96 0.99 0.91 0.96 0.93 0.84 1.00 312 LIST replace range 1.35 1.15 1.48 1.15 1.27 1.20 1.18 1.00 313 LIST reverse core 1.01 1.00 1.10 0.99 1.15 0.99 0.96 1.00 314 LIST reverse lappend 1.08 1.06 1.12 1.08 1.12 1.06 1.12 1.00 315 LIST small, early range 1.37 1.12 1.29 1.12 1.11 1.09 1.05 1.00 316 LIST small, late range 1.35 1.12 1.32 1.09 1.08 1.06 1.03 1.00 317 LIST sort 1.01 1.01 1.02 1.01 1.02 1.01 1.01 1.00 318 LIST sorted search, first item 1.58 1.30 1.53 1.33 1.37 1.30 1.18 1.00 319 LIST sorted search, last item 1.57 1.28 1.52 1.33 1.33 1.28 1.20 1.00 320 LIST sorted search, middle item 1.54 1.28 1.51 1.30 1.34 1.26 1.16 1.00 321 LIST sorted search, non-item 1.59 1.31 1.54 1.36 1.36 1.31 1.17 1.00 322 LIST sorted search, typed item 1.61 1.32 1.51 1.36 1.32 1.25 1.14 1.00 323 LIST typed sort 1.10 1.08 1.11 1.12 1.09 1.09 1.06 1.00 324 LOOP for (to 1000) 1.21 1.16 1.25 1.19 1.12 1.18 1.18 1.00 325 LOOP for, iterate list 1.09 1.04 1.19 1.02 1.11 1.15 1.14 1.00 326 LOOP for, iterate string 1.01 0.94 1.05 0.94 1.04 1.03 0.96 1.00 327 LOOP foreach, iterate list 0.80 0.71 0.71 0.71 0.60 0.90 0.73 1.00 328 LOOP foreach, iterate string 0.81 0.72 0.74 0.73 0.62 0.87 0.74 1.00 329 LOOP while (to 1000) 1.22 1.17 1.28 1.19 1.12 1.19 1.19 1.00 330 LOOP while 1 (to 1000) 1.17 1.15 1.18 1.18 1.13 1.23 1.13 1.00 331 MAP ([chars])-case regsub 1.01 0.99 0.98 0.97 0.96 1.00 0.98 1.00 332 MAP http mapReply 1.03 1.04 1.05 1.00 0.96 1.06 1.05 1.00 333 MAP regsub -nocase, no match 0.99 1.11 1.01 0.99 1.02 0.98 0.97 1.00 334 MAP regsub 1 val 0.49 0.58 0.46 0.50 0.50 0.49 0.50 1.00 335 MAP regsub 1 val -nocase 0.73 0.82 0.71 0.74 0.74 0.71 0.72 1.00 336 MAP regsub 2 val 0.48 0.52 0.45 0.49 0.46 0.45 0.47 1.00 337 MAP regsub 2 val -nocase 0.67 0.73 0.63 0.65 0.64 0.64 0.65 1.00 338 MAP regsub 3 val 0.45 0.49 0.43 0.45 0.43 0.43 0.44 1.00 339 MAP regsub 3 val -nocase 0.66 0.72 0.62 0.65 0.63 0.62 0.64 1.00 340 MAP regsub 4 val 0.44 0.49 0.43 0.45 0.42 0.42 0.43 1.00 341 MAP regsub 4 val -nocase 0.64 0.71 0.62 0.63 0.62 0.61 0.62 1.00 342 MAP regsub short 0.96 0.90 1.04 0.91 0.83 0.82 0.84 1.00 343 MAP regsub, no match 1.00 1.50 1.00 0.99 0.99 1.00 1.00 1.00 344 MAP string -nocase, no match 0.82 0.82 0.82 0.83 0.81 0.82 0.82 1.00 345 MAP string 1 val 0.42 0.42 0.39 0.43 0.42 0.41 0.41 1.00 346 MAP string 1 val -nocase 0.65 0.65 0.67 0.71 0.67 0.70 0.70 1.00 347 MAP string 2 val 0.67 0.67 0.71 0.70 0.67 0.66 0.67 1.00 348 MAP string 2 val -nocase 0.80 0.80 0.78 0.80 0.79 0.79 0.79 1.00 349 MAP string 3 val 0.70 0.70 0.73 0.75 0.71 0.70 0.71 1.00 350 MAP string 3 val -nocase 0.83 0.83 0.82 0.83 0.82 0.82 0.84 1.00 351 MAP string 4 val 0.68 0.66 0.71 0.72 0.69 0.69 0.72 1.00 352 MAP string 4 val -nocase 0.82 0.83 0.83 0.83 0.83 0.82 0.82 1.00 353 MAP string short 1.02 0.92 1.04 0.91 0.82 0.87 0.84 1.00 354 MAP string, no match 0.65 0.65 0.74 0.66 0.63 0.64 0.64 1.00 355 MAP |-case regsub 1.01 1.01 0.96 0.96 0.97 1.01 0.99 1.00 356 MAP |-case strmap 1.16 1.06 1.22 1.01 0.93 1.02 0.97 1.00 357 MATRIX mult 5x5 0.84 0.77 0.83 0.75 0.65 0.85 0.77 1.00 358 MATRIX mult 10x10 0.83 0.75 0.80 0.73 0.63 0.85 0.75 1.00 359 MATRIX mult 15x15 0.82 0.73 0.79 0.73 0.62 0.84 0.74 1.00 360 MATRIX transposition-0 1.02 1.11 1.12 0.99 0.98 1.04 1.06 1.00 361 MATRIX transposition-1 1.03 1.00 1.06 1.00 1.01 1.04 1.01 1.00 362 MD5 msg len 10 1.14 1.01 1.12 1.00 0.99 1.00 0.95 1.00 363 MD5 msg len 100 1.17 1.04 1.15 1.02 1.01 1.01 0.95 1.00 364 MD5 msg len 1000 1.10 0.98 1.13 0.97 0.99 0.99 0.91 1.00 365 MD5 msg len 10000 0.99 0.88 1.15 0.86 0.93 0.96 0.88 1.00 366 MTHD array stored proc call 1.46 1.21 1.56 1.23 1.10 1.17 1.13 1.00 367 MTHD call absolute 1.80 1.46 1.88 1.45 1.47 1.31 1.27 1.00 368 MTHD call relative 1.67 1.36 1.71 1.36 1.41 1.27 1.22 1.00 369 MTHD direct ns proc call 1.61 1.32 1.84 1.32 1.29 1.23 1.16 1.00 370 MTHD imported ns proc call 1.87 1.48 1.97 1.48 1.42 1.35 1.29 1.00 371 MTHD indirect proc eval 1.29 1.07 1.32 1.05 0.98 1.05 0.97 1.00 372 MTHD indirect proc eval #2 1.36 1.15 1.44 1.12 0.99 1.11 1.02 1.00 373 MTHD inline call 1.40 1.27 1.40 1.20 1.13 1.27 1.20 1.00 374 MTHD interp alias proc call 2.08 1.74 2.18 1.72 1.44 1.56 1.51 1.00 375 MTHD ns lookup call 1.19 1.05 1.18 1.02 0.92 1.08 0.99 1.00 376 MTHD switch method call 1.30 1.10 1.40 1.14 1.01 1.09 0.99 1.00 377 NS alternating 1.12 0.96 1.20 0.95 0.98 1.02 0.93 1.00 378 PARSE html form upload (7978) 1.27 1.16 1.17 1.18 1.13 1.17 1.10 1.00 379 PARSE html form upload (993570) 1.27 1.15 1.16 1.18 1.12 1.18 1.08 1.00 380 PROC do-nothing, no args 1.83 1.54 1.92 1.50 1.50 1.42 1.38 1.00 381 PROC do-nothing, one arg 1.81 1.50 1.96 1.50 1.46 1.38 1.31 1.00 382 PROC empty, no args 1.75 1.50 2.12 1.50 1.38 1.38 1.38 1.00 383 PROC empty, use args 1.75 1.50 1.88 1.50 1.38 1.38 1.38 1.00 384 PROC explicit return 1.70 1.44 1.93 1.48 1.41 1.30 1.26 1.00 385 PROC explicit return (2) 1.74 1.44 2.15 1.48 1.41 1.30 1.26 1.00 386 PROC explicit return (3) 1.74 1.44 1.93 1.48 1.41 1.30 1.26 1.00 387 PROC heavily commented 1.81 1.50 2.08 1.54 1.46 1.35 1.31 1.00 388 PROC implicit return 1.79 1.46 2.18 1.50 1.43 1.32 1.32 1.00 389 PROC implicit return (2) 1.78 1.48 2.07 1.52 1.44 1.33 1.30 1.00 390 PROC implicit return (3) 1.81 1.50 2.00 1.54 1.50 1.35 1.31 1.00 391 PROC local links with global 1.07 1.06 1.13 1.05 1.05 1.06 1.04 1.00 392 PROC local links with upvar 1.06 1.05 1.13 1.04 1.04 1.04 1.04 1.00 393 PROC local links with variable 1.06 1.06 1.11 1.06 1.05 1.04 1.04 1.00 394 RE 1-char long-end 1.05 1.03 1.03 1.03 1.02 1.04 1.02 1.00 395 RE 1-char long-end catching 1.03 1.00 1.02 0.99 0.97 1.01 1.00 1.00 396 RE 1-char long-middle 1.09 1.06 1.06 1.05 1.03 1.06 1.04 1.00 397 RE 1-char long-middle catching 1.05 1.00 1.02 0.99 0.96 1.01 0.99 1.00 398 RE 1-char long-start 1.35 1.21 1.26 1.23 1.12 1.23 1.15 1.00 399 RE 1-char long-start catching 1.08 0.98 1.02 0.97 0.93 1.01 0.99 1.00 400 RE 1-char short 1.36 1.20 1.23 1.22 1.13 1.21 1.15 1.00 401 RE 1-char short catching 1.07 0.97 1.03 0.97 0.91 1.00 0.97 1.00 402 RE basic 1.38 1.19 1.28 1.19 1.13 1.24 1.16 1.00 403 RE basic catching 1.06 0.98 1.06 0.98 0.94 1.01 1.01 1.00 404 RE c-comment long 1.04 1.01 1.07 1.01 1.00 1.02 1.01 1.00 405 RE c-comment long catching 1.01 0.99 1.04 0.99 0.98 1.00 1.00 1.00 406 RE c-comment long nomatch 1.02 1.01 1.04 1.01 1.00 1.01 1.00 1.00 407 RE c-comment long nomatch catching 1.03 1.01 1.05 1.02 1.01 1.02 1.01 1.00 408 RE c-comment long pmatch 1.02 1.01 1.04 1.01 1.00 1.01 1.00 1.00 409 RE c-comment long pmatch catching 1.03 1.01 1.04 1.02 1.01 1.02 1.01 1.00 410 RE c-comment many *s 1.02 1.01 1.04 1.01 1.01 1.02 1.01 1.00 411 RE c-comment many *s catching 1.01 1.00 1.02 1.00 0.99 1.01 1.00 1.00 412 RE c-comment nomatch 1.23 1.08 1.37 1.08 1.02 1.13 1.05 1.00 413 RE c-comment nomatch catching 1.25 1.10 1.37 1.12 1.04 1.15 1.07 1.00 414 RE c-comment simple 1.12 1.05 1.17 1.05 1.02 1.08 1.04 1.00 415 RE c-comment simple catching 1.03 0.97 1.05 0.98 0.95 0.99 0.98 1.00 416 RE count all matches 1.04 1.01 1.01 1.02 1.02 1.01 1.00 1.00 417 RE extract all matches 0.97 0.92 0.95 0.92 0.91 0.96 0.94 1.00 418 RE ini file 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 419 RE ini file ng 1.00 1.00 1.00 1.00 1.00 1.00 1.00 1.00 420 RE literal regexp 1.25 1.18 1.18 1.14 1.11 1.20 1.15 1.00 421 RE n-char long-end 1.05 1.03 1.04 1.03 1.02 1.03 1.02 1.00 422 RE n-char long-end catching 1.03 0.99 1.01 0.99 0.97 0.99 0.99 1.00 423 RE n-char long-middle 1.09 1.05 1.07 1.05 1.03 1.05 1.04 1.00 424 RE n-char long-middle catching 1.04 0.97 1.01 0.98 0.95 0.98 0.98 1.00 425 RE n-char long-start 1.31 1.19 1.26 1.18 1.11 1.20 1.13 1.00 426 RE n-char long-start catching 1.08 0.97 1.01 0.97 0.92 0.98 0.97 1.00 427 RE n-char short 1.34 1.20 1.25 1.19 1.13 1.20 1.15 1.00 428 RE n-char short catching 1.06 0.96 1.00 0.96 0.90 0.97 0.97 1.00 429 RE static anchored match 1.63 1.37 1.83 1.37 1.33 1.27 1.20 1.00 430 RE static anchored match dot 1.66 1.38 1.78 1.41 1.34 1.25 1.19 1.00 431 RE static anchored nomatch 1.67 1.37 1.83 1.40 1.33 1.27 1.20 1.00 432 RE static anchored nomatch dot 1.79 1.46 2.00 1.50 1.46 1.32 1.29 1.00 433 RE static l-anchored match 1.70 1.40 1.87 1.43 1.37 1.30 1.23 1.00 434 RE static l-anchored nomatch 1.79 1.46 2.00 1.50 1.46 1.36 1.32 1.00 435 RE static long match 1.40 1.28 1.56 1.41 1.25 1.38 1.36 1.00 436 RE static long nomatch 1.00 0.94 1.14 1.07 0.93 1.05 1.04 1.00 437 RE static r-anchored match 1.68 1.42 1.84 1.42 1.39 1.29 1.26 1.00 438 RE static r-anchored nomatch 1.66 1.38 1.81 1.44 1.38 1.31 1.25 1.00 439 RE static short match 1.68 1.42 1.87 1.42 1.39 1.29 1.29 1.00 440 RE static short nomatch 1.73 1.43 1.97 1.47 1.43 1.33 1.37 1.00 441 RE var ***= directive match 1.13 1.00 1.25 1.10 0.99 1.13 1.07 1.00 442 RE var ***= directive nomatch 1.11 1.00 1.26 1.10 0.99 1.11 1.06 1.00 443 RE var . match 1.53 1.29 1.61 1.31 1.27 1.37 1.24 1.00 444 RE var [0-9] match 1.21 1.13 1.14 1.12 1.07 1.14 1.10 1.00 445 RE var \d match 1.25 1.15 1.15 1.15 1.07 1.15 1.10 1.00 446 RE var ^$ nomatch 1.54 1.29 1.65 1.31 1.27 1.33 1.23 1.00 447 RE var backtrack case 1.15 1.09 1.10 1.08 1.04 1.10 1.07 1.00 448 RE var-based regexp 1.21 1.18 1.14 1.11 1.10 1.19 1.15 1.00 449 READ 595K, cat 1.04 1.00 1.02 1.00 1.00 1.02 0.94 1.00 450 READ 595K, gets 1.00 0.92 0.97 0.94 0.93 0.96 0.88 1.00 451 READ 595K, glob-grep match 1.07 0.93 1.02 1.00 0.93 0.97 0.90 1.00 452 READ 595K, glob-grep nomatch 1.05 0.93 0.99 1.00 0.92 0.99 0.91 1.00 453 READ 595K, read 1.02 1.00 0.91 1.00 0.97 0.92 0.92 1.00 454 READ 595K, read & size 0.88 0.86 0.78 0.85 0.89 0.78 0.79 1.00 455 READ 595K, read dyn buf 1.00 0.98 0.89 0.98 0.93 0.90 0.90 1.00 456 READ 595K, read small buf 1.03 1.09 1.05 1.04 1.04 1.08 1.04 1.00 457 READ 3050b, cat 1.02 0.98 1.02 0.97 0.99 1.00 0.93 1.00 458 READ 3050b, gets 1.00 0.93 0.97 0.94 0.92 0.96 0.88 1.00 459 READ 3050b, glob-grep match 1.06 0.94 1.01 1.01 0.94 0.97 0.91 1.00 460 READ 3050b, glob-grep nomatch 1.04 0.92 1.00 0.99 0.94 0.99 0.90 1.00 461 READ 3050b, read 1.10 0.97 0.98 0.98 0.92 0.93 0.92 1.00 462 READ 3050b, read & size 0.97 0.87 0.87 0.87 0.81 0.83 0.83 1.00 463 READ 3050b, read dyn buf 1.06 0.98 0.99 0.97 0.94 0.93 0.93 1.00 464 READ 3050b, read small buf 1.04 1.03 1.04 1.02 1.05 1.10 1.04 1.00 465 READ bin 595K, cat 1.15 1.08 1.09 1.03 1.14 1.12 1.03 1.00 466 READ bin 595K, gets 1.06 0.96 1.01 0.93 1.02 1.04 0.96 1.00 467 READ bin 595K, glob-grep match 1.18 1.00 1.07 1.09 1.05 1.08 1.02 1.00 468 READ bin 595K, glob-grep nomatch 1.23 1.03 1.04 1.07 1.09 1.17 1.03 1.00 469 READ bin 595K, read 1.00 1.00 1.01 1.00 0.98 1.00 1.00 1.00 470 READ bin 595K, read & size 0.99 1.00 0.99 1.00 0.98 1.00 0.99 1.00 471 READ bin 595K, read dyn buf 1.01 1.01 1.01 1.01 0.99 1.01 1.00 1.00 472 READ bin 595K, read small buf 1.00 1.04 1.04 1.03 1.02 1.03 1.04 1.00 473 READ bin 3050b, cat 1.09 1.04 1.08 0.98 1.09 1.08 0.99 1.00 474 READ bin 3050b, gets 1.06 0.97 1.02 0.94 1.02 1.04 0.97 1.00 475 READ bin 3050b, glob-grep match 1.05 0.94 1.08 0.99 0.98 1.01 0.94 1.00 476 READ bin 3050b, glob-grep nomatch 1.05 0.92 1.03 0.98 0.97 1.05 0.94 1.00 477 READ bin 3050b, read 1.01 0.98 1.08 0.99 0.97 1.02 0.97 1.00 478 READ bin 3050b, read & size 1.04 1.00 1.09 1.01 0.97 1.04 0.97 1.00 479 READ bin 3050b, read dyn buf 1.01 1.00 1.08 1.01 1.01 1.03 0.99 1.00 480 READ bin 3050b, read small buf 1.04 1.06 1.09 1.05 1.05 1.06 1.08 1.00 481 SHA1 msg len 10 1.09 1.02 1.05 1.00 1.01 1.04 0.99 1.00 482 SHA1 msg len 100 1.10 1.03 1.06 1.01 1.02 1.05 1.00 1.00 483 SHA1 msg len 1000 1.11 1.05 1.08 1.03 1.05 1.08 1.02 1.00 484 SHA1 msg len 10000 1.11 1.05 1.07 1.03 1.05 1.07 1.01 1.00 485 SPLIT iter, 4000 uchars 0.83 0.77 0.79 0.77 0.67 0.85 0.79 1.00 486 SPLIT iter, 4010 chars 0.82 0.76 0.78 0.76 0.65 0.84 0.79 1.00 487 SPLIT iter, rand 100 c 0.85 0.75 1.02 0.75 0.63 0.86 0.76 1.00 488 SPLIT iter, rand 1000 c 0.85 0.76 0.86 0.77 0.65 0.86 0.78 1.00 489 SPLIT iter, rand 10000 c 0.86 0.79 0.81 0.79 0.68 0.87 0.80 1.00 490 SPLIT on 'c', 4000 uchars 0.86 0.77 0.87 0.78 0.62 0.89 0.79 1.00 491 SPLIT on 'c', 4010 chars 0.85 0.76 0.86 0.77 0.61 0.89 0.79 1.00 492 SPLIT on 'cz', 4000 uchars 0.91 0.84 0.92 0.83 0.72 0.94 0.86 1.00 493 SPLIT on 'cz', 4010 chars 0.89 0.82 0.90 0.83 0.71 0.92 0.85 1.00 494 SPLIT on 'c�', 4000 uchars 0.92 0.88 0.92 0.85 0.83 1.02 0.96 1.00 495 SPLIT on 'c�', 4010 chars 0.95 0.91 0.94 0.89 0.93 1.07 1.02 1.00 496 SPLIT, 4000 uchars 0.95 0.94 1.00 0.94 0.98 0.98 0.98 1.00 497 SPLIT, 4010 chars 0.96 0.93 0.99 0.93 0.95 0.96 0.96 1.00 498 SPLIT, rand 100 c 0.89 0.77 1.32 0.78 0.68 0.91 0.82 1.00 499 SPLIT, rand 1000 c 0.90 0.83 1.10 0.83 0.78 0.92 0.86 1.00 500 SPLIT, rand 10000 c 0.96 0.93 1.02 0.93 0.93 0.95 0.94 1.00 501 STR append 1.15 1.07 1.14 1.03 0.82 0.96 0.96 1.00 502 STR append (1KB + 1KB) 1.23 1.04 1.38 1.08 0.93 1.03 0.96 1.00 503 STR append (1MB + (1b+1K+1b)*100) 1.03 1.02 1.02 1.02 1.02 1.04 1.04 1.00 504 STR append (1MB + 1KB) 1.00 1.00 1.00 1.00 0.99 1.02 1.03 1.00 505 STR append (1MB + 1KB*20) 1.00 1.00 1.00 1.01 1.00 1.02 1.03 1.00 506 STR append (1MB + 1KB*1000) 1.07 1.05 1.06 1.06 1.07 1.06 1.08 1.00 507 STR append (1MB + 1MB*3) 1.00 1.00 1.00 1.00 1.00 1.01 1.01 1.00 508 STR append (1MB + 1MB*5) 1.00 1.00 1.00 1.00 1.00 1.01 1.01 1.00 509 STR append (1MB + 2b*1000) 1.06 1.05 1.07 1.06 1.07 1.04 1.05 1.00 510 STR append (10KB + 1KB) 1.17 1.10 1.02 1.10 0.91 0.98 0.97 1.00 511 STR first (failure) 1.05 1.03 1.08 1.03 0.83 1.04 1.03 1.00 512 STR first (failure) utf 1.06 1.04 1.07 1.05 0.84 1.05 1.06 1.00 513 STR first (success) 1.54 1.34 1.51 1.34 1.35 1.32 1.28 1.00 514 STR first (success) utf 1.53 1.31 1.49 1.32 1.32 1.31 1.27 1.00 515 STR first (total failure) 1.10 1.06 1.10 1.06 0.79 1.06 1.05 1.00 516 STR first (total failure) utf 1.10 1.07 1.10 1.06 0.79 1.06 1.05 1.00 517 STR index 0 1.36 1.17 1.41 1.14 1.16 1.16 1.07 1.00 518 STR index 100 1.39 1.18 1.42 1.16 1.16 1.18 1.09 1.00 519 STR index 500 1.39 1.18 1.42 1.16 1.18 1.16 1.07 1.00 520 STR info locals match 1.05 1.05 1.08 1.03 1.01 1.04 1.03 1.00 521 STR last (failure) 1.06 1.04 1.05 1.03 0.89 1.04 1.03 1.00 522 STR last (success) 1.57 1.33 1.50 1.32 1.35 1.33 1.29 1.00 523 STR last (total failure) 1.07 1.04 1.07 1.04 0.86 1.04 1.04 1.00 524 STR length (==4010) 1.52 1.27 1.65 1.27 1.22 1.20 1.15 1.00 525 STR length growing (1000) 1.16 1.06 1.10 1.14 1.10 1.13 1.14 1.00 526 STR length growing uc (1000) 1.18 1.07 1.07 1.13 1.09 1.11 1.15 1.00 527 STR length of a LIST 1.55 1.32 1.63 1.29 1.24 1.24 1.16 1.00 528 STR length static str 1.72 1.41 1.93 1.45 1.41 1.31 1.28 1.00 529 STR match, complex (failure) 0.89 0.89 1.04 1.02 0.87 1.01 1.01 1.00 530 STR match, complex (success early) 1.50 1.26 1.59 1.30 1.22 1.24 1.17 1.00 531 STR match, complex (success late) 0.93 0.96 1.05 1.02 0.87 1.02 1.01 1.00 532 STR match, complex (total failure) 0.85 0.83 1.04 1.02 0.83 1.02 1.01 1.00 533 STR match, exact (failure) 1.70 1.37 1.87 1.40 1.37 1.23 1.20 1.00 534 STR match, exact (success) 1.70 1.33 1.73 1.40 1.33 1.23 1.20 1.00 535 STR match, exact -nocase (failure) 1.76 1.41 1.83 1.48 1.41 1.31 1.28 1.00 536 STR match, exact -nocase (success) 1.49 1.29 1.62 1.29 1.27 1.18 1.16 1.00 537 STR match, recurse (fail backtrack) 1.01 1.01 1.02 1.01 1.01 1.01 1.01 1.00 538 STR match, recurse (fail bt1) 1.01 1.01 1.02 1.01 1.01 1.01 1.01 1.00 539 STR match, recurse (fail bt2) 1.02 1.01 1.03 1.02 1.01 1.01 1.01 1.00 540 STR match, recurse (fail ranchor) 0.80 0.80 1.00 1.00 0.80 1.00 1.00 1.00 541 STR match, recurse (success bt2) 1.11 1.07 1.15 1.09 1.06 1.07 1.04 1.00 542 STR match, recurse2 (fail) 0.85 0.86 1.00 1.00 0.85 1.00 1.00 1.00 543 STR match, recurse2 (success) 0.89 0.90 1.04 1.02 0.87 1.01 1.01 1.00 544 STR match, simple (failure) 1.73 1.43 1.87 1.47 1.43 1.30 1.30 1.00 545 STR match, simple (success) 1.68 1.42 1.90 1.45 1.39 1.29 1.29 1.00 546 STR range, index 100..200 of 4010 1.40 1.22 1.40 1.20 1.20 1.20 1.15 1.00 547 STR repeat, 4010 chars * 10 1.09 1.04 1.09 1.01 0.98 1.03 1.03 1.00 548 STR repeat, 4010 chars * 100 1.02 1.01 1.02 1.01 1.01 1.01 1.01 1.00 549 STR repeat, abcdefghij * 10 1.62 1.42 1.66 1.41 1.38 1.38 1.34 1.00 550 STR repeat, abcdefghij * 100 1.38 1.25 1.44 1.30 1.21 1.22 1.21 1.00 551 STR repeat, abcdefghij * 1000 1.07 1.05 1.08 1.19 1.04 1.04 1.04 1.00 552 STR replace, equal replacement 1.26 1.17 1.26 1.15 1.09 1.14 1.13 1.00 553 STR replace, longer replacement 1.16 1.08 1.09 1.09 0.97 1.09 1.07 1.00 554 STR replace, no replacement 1.54 1.41 1.34 1.31 1.16 1.14 1.08 1.00 555 STR reverse core, 10 c 1.45 1.26 1.52 1.27 1.25 1.26 1.21 1.00 556 STR reverse core, 10 uc 1.40 1.22 1.48 1.24 1.22 1.22 1.17 1.00 557 STR reverse core, 100 c 1.43 1.24 1.47 1.28 1.23 1.25 1.23 1.00 558 STR reverse core, 100 uc 1.42 1.25 1.47 1.27 1.20 1.25 1.19 1.00 559 STR reverse core, 400 c 1.29 1.13 1.42 1.22 1.11 1.16 1.20 1.00 560 STR reverse core, 400 uc 1.41 1.22 1.50 1.32 1.18 1.22 1.27 1.00 561 STR reverse iter/append, 10 c 1.10 0.99 1.27 0.99 1.06 1.05 0.98 1.00 562 STR reverse iter/append, 10 uc 1.08 0.96 1.21 0.99 1.04 1.03 0.96 1.00 563 STR reverse iter/append, 100 c 1.09 1.02 1.15 1.02 1.12 1.13 1.01 1.00 564 STR reverse iter/append, 100 uc 1.05 1.01 1.10 0.97 1.05 1.09 0.98 1.00 565 STR reverse iter/append, 400 c 1.09 1.05 1.12 1.02 1.14 1.14 1.02 1.00 566 STR reverse iter/append, 400 uc 1.03 1.00 1.09 0.98 1.06 1.09 0.98 1.00 567 STR reverse iter/set, 10 c 1.13 0.99 1.18 1.00 1.09 1.10 1.05 1.00 568 STR reverse iter/set, 10 uc 1.10 0.98 1.19 0.99 1.09 1.08 1.03 1.00 569 STR reverse iter/set, 100 c 1.07 1.00 1.16 0.99 1.11 1.10 1.02 1.00 570 STR reverse iter/set, 100 uc 1.04 0.98 1.12 0.97 1.09 1.08 1.00 1.00 571 STR reverse iter/set, 400 c 1.05 0.97 1.23 0.98 1.10 1.10 1.01 1.00 572 STR reverse iter/set, 400 uc 1.03 0.95 1.22 0.95 1.07 1.07 0.99 1.00 573 STR reverse recursive, 10 c 1.23 1.11 1.20 1.03 1.08 1.07 0.99 1.00 574 STR reverse recursive, 10 uc 1.26 1.14 1.24 1.07 1.10 1.10 1.02 1.00 575 STR reverse recursive, 100 c 1.22 1.11 1.22 1.05 1.07 1.05 0.98 1.00 576 STR reverse recursive, 100 uc 1.25 1.13 1.25 1.07 1.09 1.08 1.00 1.00 577 STR reverse recursive, 400 c 1.23 1.09 1.21 1.04 1.05 1.03 0.95 1.00 578 STR reverse recursive, 400 uc 1.23 1.10 1.22 1.05 1.06 1.04 0.96 1.00 579 STR str $a eq $b 1.40 1.19 1.46 1.26 1.16 1.16 1.11 1.00 580 STR str $a eq $b (same obj) 1.39 1.19 1.49 1.22 1.17 1.11 1.07 1.00 581 STR str $a equal "" 1.62 1.38 1.70 1.45 1.40 1.30 1.28 1.00 582 STR str $a ne $b 1.42 1.22 1.46 1.26 1.18 1.15 1.11 1.00 583 STR str $a ne $b (same obj) 1.36 1.19 1.44 1.24 1.16 1.13 1.09 1.00 584 STR str num == "" 1.52 1.29 1.62 1.37 1.29 1.21 1.17 1.00 585 STR strcmp bin long eq 1.20 1.16 1.19 1.15 1.11 1.14 1.11 1.00 586 STR strcmp bin long neq 1.20 1.15 1.25 1.15 1.10 1.14 1.11 1.00 587 STR strcmp bin long neqS 1.44 1.32 1.48 1.30 1.24 1.30 1.24 1.00 588 STR strcmp bin short eq 1.67 1.50 1.64 1.45 1.37 1.44 1.38 1.00 589 STR streq bin long eq 0.06 0.06 0.06 0.06 0.06 0.06 0.06 1.00 590 STR streq bin long neq 0.06 0.06 0.06 0.06 0.06 0.06 0.06 1.00 591 STR streq bin long neqS 0.04 0.04 0.04 0.04 0.03 0.03 0.03 1.00 592 STR streq bin short eq 1.01 0.93 1.03 0.91 0.84 0.88 0.85 1.00 593 STR string compare 1.44 1.15 1.47 1.18 1.11 1.17 1.06 1.00 594 STR string compare "" 1.35 1.18 1.42 1.19 1.15 1.08 1.06 1.00 595 STR string compare long 1.16 1.08 1.16 1.09 1.06 1.07 1.04 1.00 596 STR string compare long (same obj) 1.36 1.15 1.44 1.22 1.17 1.19 1.08 1.00 597 STR string compare mixed long 1.02 1.01 0.97 0.94 1.02 0.95 0.94 1.00 598 STR string compare uni long 0.99 0.98 1.03 1.01 1.16 1.01 1.01 1.00 599 STR string equal "" 1.75 1.46 1.83 1.52 1.46 1.42 1.37 1.00 600 STR string equal long (!= len) 1.30 1.22 1.42 1.18 1.16 1.17 1.14 1.00 601 STR string equal long (== len) 1.08 1.02 1.08 1.05 0.98 0.97 0.96 1.00 602 STR string equal long (same obj) 1.39 1.20 1.39 1.23 1.16 1.14 1.09 1.00 603 STR string equal mixed long 1.48 1.29 1.44 1.34 1.23 1.22 1.21 1.00 604 STR string equal uni long 1.46 1.41 1.50 1.44 1.35 1.36 1.35 1.00 605 STR/LIST length, obj shimmer 0.85 0.77 1.13 0.77 0.65 0.90 0.81 1.00 606 SWITCH 1st true 1.62 1.38 1.77 1.42 1.38 1.30 1.27 1.00 607 SWITCH 2nd true 1.67 1.41 1.85 1.46 1.38 1.31 1.28 1.00 608 SWITCH 9th true 1.67 1.41 1.85 1.44 1.38 1.31 1.31 1.00 609 SWITCH default true 1.64 1.33 1.82 1.41 1.33 1.23 1.21 1.00 610 TRACE all set (rwu) 1.07 0.95 1.16 0.98 0.92 0.92 0.85 1.00 611 TRACE no trace set 1.08 0.94 1.18 0.98 0.92 0.93 0.86 1.00 612 TRACE read 1.07 0.95 1.17 0.96 0.93 0.93 0.87 1.00 613 TRACE unset 1.07 0.95 1.16 0.98 0.92 0.92 0.86 1.00 614 TRACE write 1.06 0.95 1.18 0.98 0.93 0.93 0.85 1.00 615 UNSET catch var !exist 0.98 0.88 1.06 0.88 0.75 0.98 0.91 1.00 616 UNSET catch var exists 1.36 1.14 1.57 1.19 1.10 1.05 1.00 1.00 617 UNSET info check var !exist 1.84 1.50 2.12 1.62 1.44 1.38 1.28 1.00 618 UNSET info check var exists 1.42 1.17 1.47 1.25 1.10 1.07 1.00 1.00 619 UNSET nocomplain var !exist 1.34 1.07 1.49 1.10 1.00 0.98 0.93 1.00 620 UNSET nocomplain var exists 1.38 1.16 1.54 1.22 1.11 1.05 1.00 1.00 621 UNSET var exists 1.46 1.20 1.69 1.26 1.14 1.11 1.06 1.00 622 UPLEVEL none 0.84 0.74 0.83 0.73 0.65 0.80 0.78 1.00 623 UPLEVEL primed 1.06 0.93 1.14 0.94 0.84 0.94 0.86 1.00 624 UPLEVEL to nseval 1.20 1.09 1.19 1.13 0.95 1.13 1.10 1.00 625 UPLEVEL to proc 1.21 1.13 1.31 1.12 0.95 1.07 1.01 1.00 626 VAR 'array set' of 100 elems 1.08 1.07 1.11 1.09 1.01 1.02 1.01 1.00 627 VAR 100 'set's in array 1.10 1.05 1.09 1.08 1.03 1.05 1.03 1.00 628 VAR access global 1.35 1.16 1.55 1.24 1.09 1.11 1.05 1.00 629 VAR access local proc arg 1.70 1.38 1.84 1.43 1.38 1.27 1.24 1.00 630 VAR access locally set 1.75 1.42 1.89 1.47 1.39 1.33 1.28 1.00 631 VAR access upvar 1.45 1.12 1.62 1.21 1.12 1.09 1.09 1.00 632 VAR incr global var 1000x 0.88 0.83 0.86 0.85 0.72 0.90 0.88 1.00 633 VAR incr local var 1000x 0.86 0.84 0.86 0.83 0.71 0.88 0.85 1.00 634 VAR incr upvar var 1000x 0.87 0.87 0.87 0.85 0.72 0.89 0.83 1.00 635 VAR mset 1.36 1.18 1.47 1.24 1.05 1.13 1.11 1.00 636 VAR mset (foreach) 1.23 1.09 1.32 1.09 0.86 0.98 0.95 1.00 637 VAR ref absolute 0.98 0.93 1.05 0.99 0.79 0.95 0.94 1.00 638 VAR ref local 1.24 1.15 1.38 1.17 1.19 1.14 1.12 1.00 639 VAR ref variable 1.24 1.16 1.40 1.21 1.17 1.18 1.26 1.00 640 VAR set array element 1.45 1.21 1.68 1.30 1.11 1.15 1.06 1.00 641 VAR set scalar 1.82 1.46 2.11 1.50 1.43 1.32 1.29 1.00 642 WORDCOUNT wc1 1.00 0.97 0.97 0.96 0.92 1.02 0.99 1.00 643 WORDCOUNT wc2 0.98 0.91 1.10 0.91 0.84 0.99 0.95 1.00 644 WORDCOUNT wc3 0.98 0.94 1.14 0.93 0.86 1.01 0.96 1.00 644 BENCHMARKS 1:8.6b1.2 2:8.6b1.2 3:8.6b1.2 4:8.6b1.2 5:8.6b1.2 6:8.6b1.2 7:8.6b1.2 8:8.5.9 FINISHED 2011-03-28 13:14:44 |
Changes to tests/nre.test.
︙ | ︙ | |||
24 25 26 27 28 29 30 | # can now actually measure using testnrelevels. # if {[testConstraint testnrelevels]} { namespace eval testnre { namespace path ::tcl::mathop # | | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # can now actually measure using testnrelevels. # if {[testConstraint testnrelevels]} { namespace eval testnre { namespace path ::tcl::mathop # # [testnrelevels] returns a 5-list with: C-stack depth, iPtr->numlevels, # cmdFrame level, callFrame level and callback depth # variable last [testnrelevels] proc depthDiff {} { variable last set depth [testnrelevels] set res {} foreach t $depth l $last { |
︙ | ︙ |
Changes to tests/tailcall.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 | # The tests that risked blowing the C stack on failure have been removed: we # can now actually measure using testnrelevels. # if {[testConstraint testnrelevels]} { namespace eval testnre { # | | | | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | # The tests that risked blowing the C stack on failure have been removed: we # can now actually measure using testnrelevels. # if {[testConstraint testnrelevels]} { namespace eval testnre { # # [testnrelevels] returns a 5-list with: C-stack depth, iPtr->numlevels, # cmdFrame level, callFrame level and callback depth # variable last [testnrelevels] proc depthDiff {} { variable last set depth [testnrelevels] set res {} foreach t $depth l $last { |
︙ | ︙ | |||
65 66 67 68 69 70 71 | } tailcall a $i } } -body { a 0 } -cleanup { rename a {} | | | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | } tailcall a $i } } -body { a 0 } -cleanup { rename a {} } -result {0 0 0 0 0} test tailcall-0.2 {tailcall is constant space} -constraints testnrelevels -setup { set a { i { if {$i == 1} { depthDiff } if {[incr i] > 10} { return [depthDiff] } upvar 1 a a tailcall apply $a $i }} } -body { apply $a 0 } -cleanup { unset a } -result {0 0 0 0 0} test tailcall-0.3 {tailcall is constant space} -constraints testnrelevels -setup { proc a i { if {$i == 1} { depthDiff } if {[incr i] > 10} { return [depthDiff] } tailcall b $i } interp alias {} b {} a } -body { b 0 } -cleanup { rename a {} rename b {} } -result {0 0 0 0 0} test tailcall-0.4 {tailcall is constant space} -constraints testnrelevels -setup { namespace eval ::ns { namespace export * } proc ::ns::a i { if {$i == 1} { |
︙ | ︙ | |||
123 124 125 126 127 128 129 | namespace import ::ns::a rename a b } -body { b 0 } -cleanup { rename b {} namespace delete ::ns | | | | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | namespace import ::ns::a rename a b } -body { b 0 } -cleanup { rename b {} namespace delete ::ns } -result {0 0 0 0 0} test tailcall-0.5 {tailcall is constant space} -constraints testnrelevels -setup { proc b i { if {$i == 1} { depthDiff } if {[incr i] > 10} { return [depthDiff] } tailcall a b $i } namespace ensemble create -command a -map {b b} } -body { a b 0 } -cleanup { rename a {} rename b {} } -result {0 0 0 0 0} test tailcall-0.6 {tailcall is constant space} -constraints {testnrelevels knownBug} -setup { # # This test fails because ns-unknown is not NR-enabled # proc c i { if {$i == 1} { |
︙ | ︙ | |||
166 167 168 169 170 171 172 | namespace ensemble create -command a -unknown d } -body { a b 0 } -cleanup { rename a {} rename c {} rename d {} | | | | 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | namespace ensemble create -command a -unknown d } -body { a b 0 } -cleanup { rename a {} rename c {} rename d {} } -result {0 0 0 0 0} test tailcall-0.7 {tailcall is constant space} -constraints testnrelevels -setup { catch {rename foo {}} oo::class create foo { method b i { if {$i == 1} { depthDiff } if {[incr i] > 10} { return [depthDiff] } tailcall [self] b $i } } } -body { foo create a a b 0 } -cleanup { rename a {} rename foo {} } -result {0 0 0 0 0} test tailcall-1 {tailcall} -body { namespace eval a { variable x *::a proc xset {} { set tmp {} set ns {[namespace current]} |
︙ | ︙ |
Changes to unix/Makefile.in.
︙ | ︙ | |||
286 287 288 289 290 291 292 | TCLTEST_OBJS = tclTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \ tclThreadTest.o tclUnixTest.o XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \ tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | TCLTEST_OBJS = tclTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \ tclThreadTest.o tclUnixTest.o XTTEST_OBJS = xtTestInit.o tclTest.o tclTestObj.o tclTestProcBodyObj.o \ tclThreadTest.o tclUnixTest.o tclXtNotify.o tclXtTest.o #-------------------------------------------------------------------------- # Choose the default allocator to link in. Override with the env-var # TCL_ALLOCATOR if present. Note that all allocators will be compiled, # changing them just requires relinking. #-------------------------------------------------------------------------- PURIFY = tclAllocPurify.o PURIFY_FLAGS = -DPURIFY% -DTCL_ALLOCATOR=PURIFY NATIVE = tclAllocNative.o NATIVE_FLAGS = -DTCL_ALLOCATOR=NATIVE ZIPPY = tclAllocZippy.o ZIPPY_FLAGS = -DUSE_THREAD_ALLOC% -DTCL_ALLOCATOR=ZIPPY ALLOCATOR_DEFAULT = $(NATIVE) ALLOCATORS = $(PURIFY) $(NATIVE) $(ZIPPY) WHERE = $(CC_SWITCHES) $(CFLAGS) ifdef TCL_ALLOCATOR ALLOCATOR = $($(TCL_ALLOCATOR)) else ifneq (,$(filter $(PURIFY_FLAGS), $(WHERE))) ALLOCATOR = $(PURIFY) else ifneq (,$(filter $(NATIVE_FLAGS), $(WHERE))) ALLOCATOR = $(NATIVE) else ifneq (,$(filter $(ZIPPY_FLAGS), $(WHERE))) ALLOCATOR = $(ZIPPY) endif ifeq (,$(filter $(ALLOCATORS), $(ALLOCATOR))) ALLOCATOR = $(ALLOCATOR_DEFAULT) endif GENERIC_OBJS = $(ALLOCATOR) \ regcomp.o regexec.o regfree.o regerror.o \ tclAsync.o tclBasic.o tclBinary.o tclCkalloc.o tclClock.o \ tclCmdAH.o tclCmdIL.o tclCmdMZ.o tclCompCmds.o tclCompCmdsSZ.o \ tclCompExpr.o tclCompile.o tclConfig.o tclDate.o tclDictObj.o \ tclEncoding.o tclEnsemble.o \ tclEnv.o tclEvent.o tclExecute.o tclFCmd.o tclFileName.o tclGet.o \ tclHash.o tclHistory.o tclIndexObj.o tclInterp.o tclIO.o tclIOCmd.o \ tclIORChan.o tclIORTrans.o tclIOGT.o tclIOSock.o tclIOUtil.o \ tclLink.o tclListObj.o \ tclLiteral.o tclLoad.o tclMain.o tclNamesp.o tclNotify.o \ tclObj.o tclPanic.o tclParse.o tclPathObj.o tclPipe.o \ tclPkg.o tclPkgConfig.o tclPosixStr.o \ tclPreserve.o tclProc.o tclRegexp.o \ tclResolve.o tclResult.o tclScan.o tclStringObj.o \ tclStrToD.o tclThread.o \ tclThreadJoin.o tclThreadStorage.o tclStubInit.o \ tclTimer.o tclTrace.o tclUtf.o tclUtil.o tclVar.o tclZlib.o \ tclTomMathInterface.o \ tclAssembly.o OO_OBJS = tclOO.o tclOOBasic.o tclOOCall.o tclOODefineCmds.o tclOOInfo.o \ tclOOMethod.o tclOOStubInit.o TOMMATH_OBJS = bncore.o bn_reverse.o bn_fast_s_mp_mul_digs.o \ bn_fast_s_mp_sqr.o bn_mp_add.o bn_mp_and.o \ bn_mp_add_d.o bn_mp_clamp.o bn_mp_clear.o bn_mp_clear_multi.o \ |
︙ | ︙ | |||
380 381 382 383 384 385 386 | $(GENERIC_DIR)/tclRegexp.h GENERIC_SRCS = \ $(GENERIC_DIR)/regcomp.c \ $(GENERIC_DIR)/regexec.c \ $(GENERIC_DIR)/regfree.c \ $(GENERIC_DIR)/regerror.c \ | | > > | 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 | $(GENERIC_DIR)/tclRegexp.h GENERIC_SRCS = \ $(GENERIC_DIR)/regcomp.c \ $(GENERIC_DIR)/regexec.c \ $(GENERIC_DIR)/regfree.c \ $(GENERIC_DIR)/regerror.c \ $(GENERIC_DIR)/tclAllocNative.c \ $(GENERIC_DIR)/tclAllocPurify.c \ $(GENERIC_DIR)/tclAllocZippy.c \ $(GENERIC_DIR)/tclAssembly.c \ $(GENERIC_DIR)/tclAsync.c \ $(GENERIC_DIR)/tclBasic.c \ $(GENERIC_DIR)/tclBinary.c \ $(GENERIC_DIR)/tclCkalloc.c \ $(GENERIC_DIR)/tclClock.c \ $(GENERIC_DIR)/tclCmdAH.c \ |
︙ | ︙ | |||
443 444 445 446 447 448 449 | $(GENERIC_DIR)/tclStubInit.c \ $(GENERIC_DIR)/tclStringObj.c \ $(GENERIC_DIR)/tclStrToD.c \ $(GENERIC_DIR)/tclTest.c \ $(GENERIC_DIR)/tclTestObj.c \ $(GENERIC_DIR)/tclTestProcBodyObj.c \ $(GENERIC_DIR)/tclThread.c \ | < | 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | $(GENERIC_DIR)/tclStubInit.c \ $(GENERIC_DIR)/tclStringObj.c \ $(GENERIC_DIR)/tclStrToD.c \ $(GENERIC_DIR)/tclTest.c \ $(GENERIC_DIR)/tclTestObj.c \ $(GENERIC_DIR)/tclTestProcBodyObj.c \ $(GENERIC_DIR)/tclThread.c \ $(GENERIC_DIR)/tclThreadJoin.c \ $(GENERIC_DIR)/tclThreadStorage.c \ $(GENERIC_DIR)/tclTimer.c \ $(GENERIC_DIR)/tclTrace.c \ $(GENERIC_DIR)/tclUtil.c \ $(GENERIC_DIR)/tclVar.c \ $(GENERIC_DIR)/tclAssembly.c \ |
︙ | ︙ | |||
607 608 609 610 611 612 613 | libraries: doc: # The following target is configured by autoconf to generate either a shared # library or non-shared library for Tcl. | | | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 | libraries: doc: # The following target is configured by autoconf to generate either a shared # library or non-shared library for Tcl. ${LIB_FILE}: $(ALLOCATORS) ${OBJS} ${STUB_LIB_FILE} rm -f $@ @MAKE_LIB@ @if test "x$(DLL_INSTALL_DIR)" = "x$(BIN_INSTALL_DIR)"; then\ cp ${ZLIB_DIR}/win32/zlib1.dll .;\ fi |
︙ | ︙ | |||
1045 1046 1047 1048 1049 1050 1051 | regerror.o: $(REGHDRS) $(GENERIC_DIR)/regerrs.h $(GENERIC_DIR)/regerror.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regerror.c tclAppInit.o: $(UNIX_DIR)/tclAppInit.c $(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tclAppInit.c | > > > > > > | | | 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 | regerror.o: $(REGHDRS) $(GENERIC_DIR)/regerrs.h $(GENERIC_DIR)/regerror.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/regerror.c tclAppInit.o: $(UNIX_DIR)/tclAppInit.c $(CC) -c $(APP_CC_SWITCHES) $(UNIX_DIR)/tclAppInit.c tclAllocNative.o: $(GENERIC_DIR)/tclAllocNative.c $(GENERIC_DIR)/tclAllocZippy.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAllocNative.c tclAllocPurify.o: $(GENERIC_DIR)/tclAllocPurify.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAllocPurify.c tclAllocZippy.o: $(GENERIC_DIR)/tclAllocZippy.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAllocZippy.c tclAssembly.o: $(GENERIC_DIR)/tclAssembly.c $(COMPILEHDR) $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAssembly.c tclAsync.o: $(GENERIC_DIR)/tclAsync.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAsync.c |
︙ | ︙ | |||
1321 1322 1323 1324 1325 1326 1327 | tclTimer.o: $(GENERIC_DIR)/tclTimer.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTimer.c tclThread.o: $(GENERIC_DIR)/tclThread.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThread.c | < < < | 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 | tclTimer.o: $(GENERIC_DIR)/tclTimer.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclTimer.c tclThread.o: $(GENERIC_DIR)/tclThread.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThread.c tclThreadJoin.o: $(GENERIC_DIR)/tclThreadJoin.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadJoin.c tclThreadStorage.o: $(GENERIC_DIR)/tclThreadStorage.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclThreadStorage.c tclThreadTest.o: $(GENERIC_DIR)/tclThreadTest.c |
︙ | ︙ |
Changes to unix/tclUnixPipe.c.
︙ | ︙ | |||
426 427 428 429 430 431 432 | } /* * We need to allocate and convert this before the fork so it is properly * deallocated later */ | | | | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | } /* * We need to allocate and convert this before the fork so it is properly * deallocated later */ dsArray = ckalloc(argc * sizeof(Tcl_DString)); newArgv = ckalloc((argc+1) * sizeof(char *)); newArgv[argc] = NULL; for (i = 0; i < argc; i++) { newArgv[i] = Tcl_UtfToExternalDString(NULL, argv[i], -1, &dsArray[i]); } #ifdef USE_VFORK /* |
︙ | ︙ | |||
499 500 501 502 503 504 505 | /* * Free the mem we used for the fork */ for (i = 0; i < argc; i++) { Tcl_DStringFree(&dsArray[i]); } | | | | 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 | /* * Free the mem we used for the fork */ for (i = 0; i < argc; i++) { Tcl_DStringFree(&dsArray[i]); } ckfree(newArgv); ckfree(dsArray); if (pid == -1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "couldn't fork child process: %s", Tcl_PosixError(interp))); goto error; } |
︙ | ︙ |
Changes to unix/tclUnixThrd.c.
︙ | ︙ | |||
670 671 672 673 674 675 676 | sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]); return tsdPtr->nabuf; #else return inet_ntoa(addr); #endif } | | < | 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]); return tsdPtr->nabuf; #else return inet_ntoa(addr); #endif } #if defined(TCL_THREADS) /* * Additions by AOL for specialized thread memory allocator. */ static volatile int initialized = 0; static pthread_key_t key; typedef struct allocMutex { Tcl_Mutex tlock; pthread_mutex_t plock; } allocMutex; |
︙ | ︙ | |||
711 712 713 714 715 716 717 718 719 720 721 722 723 724 | allocMutex* lockPtr = (allocMutex*) mutex; if (!lockPtr) { return; } pthread_mutex_destroy(&lockPtr->plock); free(lockPtr); } void TclpFreeAllocCache( void *ptr) { if (ptr != NULL) { /* | > | 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 | allocMutex* lockPtr = (allocMutex*) mutex; if (!lockPtr) { return; } pthread_mutex_destroy(&lockPtr->plock); free(lockPtr); } void TclpFreeAllocCache( void *ptr) { if (ptr != NULL) { /* |
︙ | ︙ | |||
754 755 756 757 758 759 760 | void TclpSetAllocCache( void *arg) { pthread_setspecific(key, arg); } | | > | 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 | void TclpSetAllocCache( void *arg) { pthread_setspecific(key, arg); } #endif #ifdef TCL_THREADS void * TclpThreadCreateKey(void) { pthread_key_t *ptkeyPtr; ptkeyPtr = TclpSysAlloc(sizeof *ptkeyPtr, 0); if (NULL == ptkeyPtr) { |
︙ | ︙ |