Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Comment: | development branch for allocator changes |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | mig-alloc-reform |
Files: | files | file ages | folders |
SHA1: |
80a014ef053fcb73efa85739d73b47c2 |
User & Date: | mig 2011-03-18 12:54:54 |
2011-03-18
| ||
13:10 | README addition check-in: bafa2025b3 user: mig tags: mig-alloc-reform | |
12:54 | development branch for allocator changes check-in: 80a014ef05 user: mig tags: mig-alloc-reform | |
2011-03-17
| ||
22:00 | Generate errorCode information on failure to parse expressions. check-in: 0c22db4f68 user: dkf 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 | 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 improvement in zippy's memory usage: try to split blocks in the shared cache before allocating new ones from the system 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 ** * 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 ** 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 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 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 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 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 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 | /* * tclAlloc.c -- * * This is a very flexible storage allocator for Tcl, for use with or * without threads. Depending on the compile flags, it builds as: * * (1) Build flags: TCL_ALLOC_NATIVE * NATIVE: use the native malloc and a per-thread Tcl_Obj pool, with * inter-thread recycling of objects. The per-thread pool can be * disabled at startup with an env var, thus providing the PURIFY * behaviour that is useful for valgrind and similar tools. Note that * the PURIFY costs are negligible when disabled, but when enabled * Tcl_Obj allocs will be even slower than in a full PURIFY build * NOTE: the obj pool shares all code with zippy's smallest allocs! * It does look overcomplicated for this particular case, but * keeping them together allows simpler maintenance and avoids * the need for separate debugging * TODO: in this case build ZIPPY as a preloadable malloc-replacement * * (2) Build flags: TCL_ALLOC_ZIPPY * ZIPPY: use the ex-tclThreadAlloc, essentially aolserver's * fast threaded allocator. Mods with respect to the original: * - change in the block sizes, so that the smallest alloc is * Tcl_Obj-sized * - share the Tcl_Obj pool with the smallest allocs pool for * improved cache usage * - split blocks in the shared pool before mallocing again for * improved cache usage * - ?change in the number of blocks to move to/from the shared * cache: it used to be a fixed number, it is now computed * to leave a fixed number in the thread's pool. This improves * sharing behaviour when one thread uses a lot of memory once * and rarely again (eg, at startup), at the cost of slowing * slightly threads that allocate/free large numbers of blocks * repeatedly * - stats and Tcl_GetMemoryInfo disabled per default, enable with * -DZIPPY_STATS * - adapt for unthreaded usage as replacement of the ex tclAlloc * - -DHAVE_FAST_TSD: use fast TSD via __thread where available * - (TODO!) build zippy as a pre-loadable library to use with a * native build as a malloc replacement. Difficulties are: * (a) make that portable (easy enough on modern elf/unix, to * be researched on win and mac) * (b) coordinate the Tcl_Obj pool and the smallest allocs, * as they are now addressed from different files. This * might require a special Tcl build with no * TclSmallAlloc, and a separate preloadable for use with * native builds? Or else separate them again, but that's * not really good I think. * * NOTES: * . this would be the best option, instead of MULTI. It * could be built in two versions (perf, debug/stats) * . would a preloaded zippy be slower than builtin? * Possibly, due to extra indirection. * * (3) Build flags: TCL_ALLOC_MULTI * MULTI: all of the above, selectable at startup with an env * var. This build will be very slightly slower than the specific * builds above, but is completely portable: it does not depend on * any help from the loader or such. * * All variants can be built for both threaded and unthreaded Tcl. * * The Initial Developer of the Original Code is America Online, Inc. * Portions created by AOL are Copyright (C) 1999 America Online, Inc. * * 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. */ #include "tclInt.h" /* * 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 #undef TclpAlloc #undef TclpRealloc #undef TclpFree #undef TclSmallAlloc #undef TclSmallFree #if (TCL_ALLOCATOR == aNATIVE) || (TCL_ALLOCATOR == aPURIFY) /* * Not much of this file is needed, most things are dealt with in the * macros. Just shunt the allocators for use by the library, the core * never calls this. * * This is all that is needed for a TCL_ALLOC_PURIFY build, a native build * needs the Tcl_Obj pools too. */ 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); } #endif /* end of common code for PURIFY and NATIVE*/ #if TCL_ALLOCATOR != aPURIFY /* * The rest of this file deals with ZIPPY and MULTI builds, as well as the * Tcl_Obj pools for NATIVE */ /* * Note: we rely on the optimizer to remove unneeded code, instead of setting * up a maze of #ifdefs all over the code. * We should insure that debug builds do at least this much optimization, right? */ #if TCL_ALLOCATOR == aZIPPY # define allocator aZIPPY # define ALLOCATOR_BASE aZIPPY #elif TCL_ALLOCATOR == aNATIVE /* Keep the option to switch PURIFY mode on! */ static int allocator = aNONE; # define ALLOCATOR_BASE aNATIVE # define RCHECK 0 # undef ZIPPY_STATS #else /* MULTI */ static int allocator = aNONE; # define ALLOCATOR_BASE aZIPPY #endif #if TCL_ALLOCATOR != aZIPPY static void ChooseAllocator(); #endif /* * 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 /* * The following struct 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 struct Block { union { struct 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. */ } Block; #define ALIGN(x) (((x) + TCL_ALLOCALIGN - 1) & ~(TCL_ALLOCALIGN - 1)) #define OFFSET ALIGN(sizeof(Block)) #define nextBlock u.next #define sourceBucket u.s.bucket #define magicNum1 u.s.magic1 #define magicNum2 u.s.magic2 #define MAGIC 0xEF #define blockReqSize reqSize /* * The following defines the minimum and maximum block sizes and the number * of buckets in the bucket cache. * 32b 64b Apple-32b * TCL_ALLOCALIGN 8 16 16 * sizeof(Block) 8 16 16 * OFFSET 8 16 16 * sizeof(Tcl_Obj) 24 48 24 * ALLOCBASE 24 48 24 * MINALLOC 24 48 24 * NBUCKETS 11 10 11 * MAXALLOC 24576 24576 24576 * small allocs 1024 512 1024 * at a time */ #if TCL_ALLOCATOR == aNATIVE #define MINALLOC MAX(OFFSET, sizeof(Tcl_Obj)) #else #define MINALLOC ALIGN(MAX(OFFSET+8, sizeof(Tcl_Obj))) #endif #define NBUCKETS 10 /* previously (11 - (MINALLOC >> 5)) */ #define MAXALLOC (MINALLOC << (NBUCKETS - 1)) #if TCL_ALLOCATOR == aNATIVE # define NBUCKETS_0 1 # define nBuckets 1 #else # define NBUCKETS_0 NBUCKETS # if TCL_ALLOCATOR == aZIPPY # define nBuckets NBUCKETS # else static int nBuckets = NBUCKETS; # endif #endif /* * The following structure defines a bucket of blocks, optionally with various * accounting and statistics information. */ typedef struct Bucket { Block *firstPtr; /* First block available */ long numFree; /* Number of blocks available */ #ifdef ZIPPY_STATS /* All fields below for accounting only */ 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; /* * The following structure defines a cache of buckets, at most one per * thread. */ typedef struct Cache { #if defined(TCL_THREADS) struct Cache *nextPtr; /* Linked list of cache entries */ #ifdef ZIPPY_STATS Tcl_ThreadId owner; /* Which thread's cache is this? */ #endif #endif #ifdef ZIPPY_STATS int totalAssigned; /* Total space assigned to thread */ #endif Bucket buckets[1]; /* The buckets for this thread */ } Cache; /* * 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. */ #if defined(TCL_THREADS) int maxBlocks; /* Max blocks before move to share. */ int numMove; /* Num blocks to move to share. */ Tcl_Mutex *lockPtr; /* Share bucket lock. */ #endif } bucketInfo[NBUCKETS_0]; /* * Static functions defined in this file. */ static Cache * GetCache(void); static int GetBlocks(Cache *cachePtr, int bucket); static inline Block * Ptr2Block(char *ptr); static inline char * Block2Ptr(Block *blockPtr, int bucket, unsigned int reqSize); #if defined(TCL_THREADS) static Cache *firstCachePtr = NULL; static Cache *sharedPtr = NULL; static Tcl_Mutex *listLockPtr; static Tcl_Mutex *objLockPtr; static void LockBucket(Cache *cachePtr, int bucket); static void UnlockBucket(Cache *cachePtr, int bucket); static void PutBlocks(Cache *cachePtr, int bucket, int numMove); #if defined(HAVE_FAST_TSD) static __thread Cache *tcachePtr; static __thread int allocInitialized = 0; # define GETCACHE(cachePtr) \ do { \ if (!allocInitialized) { \ allocInitialized = 1; \ tcachePtr = GetCache(); \ } \ (cachePtr) = tcachePtr; \ } while (0) #else # define GETCACHE(cachePtr) \ do { \ (cachePtr) = TclpGetAllocCache(); \ if ((cachePtr) == NULL) { \ (cachePtr) = GetCache(); \ } \ } while (0) #endif #else /* NOT THREADS! */ static int allocInitialized = 0; #define TclpSetAllocCache() #define PutBlocks(cachePtr, bucket, numMove) #define firstCachePtr sharedCachePtr # define GETCACHE(cachePtr) \ do { \ if (!allocInitialized) { \ allocInitialized = 1; \ GetCache(); \ } \ (cachePtr) = sharedPtr; \ } while (0) static void * TclpGetAllocCache(void) { if (!allocInitialized) { allocInitialized = 1; GetCache(); } return sharedPtr; } #endif /* *---------------------------------------------------------------------- * * Block2Ptr, Ptr2Block -- * * Convert between internal blocks and user pointers. * * Results: * User pointer or internal block. * * Side effects: * Invalid blocks will abort the server. * *---------------------------------------------------------------------- */ static inline 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 *) (((char *)blockPtr) + OFFSET); #if RCHECK ((unsigned char *)(ptr))[reqSize] = MAGIC; #endif return (char *) ptr; } static inline Block * Ptr2Block( char *ptr) { register Block *blockPtr; blockPtr = (Block *) (((char *) ptr) - OFFSET); 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; } /* *---------------------------------------------------------------------- * * GetCache --- * * Gets per-thread memory cache, allocating it if necessary. * * Results: * Pointer to cache. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Cache * GetCache(void) { Cache *cachePtr; unsigned int i; #if TCL_ALLOCATOR == aZIPPY #define allocSize (sizeof(Cache) + (NBUCKETS -1)*sizeof(Bucket)) #elif TCL_ALLOCATOR == aNATIVE #define allocSize sizeof(Cache) #else unsigned int allocSize; #endif /* * Set the params for the correct allocator */ #if TCL_ALLOCATOR != aZIPPY if (allocator == aNONE) { /* This insures that it is set just once, as any changes after * initialization guarantee a hard crash */ ChooseAllocator(); } #if TCL_ALLOCATOR == aMULTI if (allocator == aZIPPY) { allocSize = (sizeof(Cache) + (NBUCKETS -1)*sizeof(Bucket)); nBuckets = NBUCKETS; } else { allocSize = sizeof(Cache); nBuckets = 1; } #endif #endif /* * Check for first-time initialization. */ #if defined(TCL_THREADS) if (listLockPtr == NULL) { Tcl_Mutex *initLockPtr; initLockPtr = Tcl_GetAllocMutex(); Tcl_MutexLock(initLockPtr); if (listLockPtr == NULL) { listLockPtr = TclpNewAllocMutex(); objLockPtr = TclpNewAllocMutex(); #endif for (i = 0; i < nBuckets; ++i) { bucketInfo[i].blockSize = MINALLOC << i; #if defined(TCL_THREADS) /* TODO: clearer logic? Change move to keep? */ bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i); bucketInfo[i].numMove = i < NBUCKETS - 1 ? 1 << (NBUCKETS - 2 - i) : 1; bucketInfo[i].lockPtr = TclpNewAllocMutex(); #endif } #if defined(TCL_THREADS) sharedPtr = calloc(1, allocSize); firstCachePtr = sharedPtr; } Tcl_MutexUnlock(initLockPtr); } #endif if (allocator == aPURIFY) { bucketInfo[0].maxBlocks = 0; } /* * Get this thread's cache, allocating if necessary. */ cachePtr = TclpGetAllocCache(); if (cachePtr == NULL) { cachePtr = calloc(1, allocSize); if (cachePtr == NULL) { Tcl_Panic("alloc: could not allocate new cache"); } #if defined(TCL_THREADS) Tcl_MutexLock(listLockPtr); cachePtr->nextPtr = firstCachePtr; firstCachePtr = cachePtr; Tcl_MutexUnlock(listLockPtr); #ifdef ZIPPY_STATS cachePtr->owner = Tcl_GetCurrentThread(); #endif TclpSetAllocCache(cachePtr); #endif } return cachePtr; } #if defined(TCL_THREADS) /* *---------------------------------------------------------------------- * * TclFreeAllocCache -- * * Flush and delete a cache, removing from list of caches. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFreeAllocCache( void *arg) { Cache *cachePtr = arg; 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); free(cachePtr); } #endif #if TCL_ALLOCATOR != aNATIVE /* *---------------------------------------------------------------------- * * TclpAlloc -- * * Allocate memory. * * Results: * Pointer to memory just beyond Block pointer. * * Side effects: * May allocate more blocks for a bucket. * *---------------------------------------------------------------------- */ char * TclpAlloc( unsigned int reqSize) { Cache *cachePtr; Block *blockPtr; register int bucket; size_t size; if (allocator < aNONE) { return (void *) malloc(reqSize); } GETCACHE(cachePtr); #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 - OFFSET - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } #endif /* * 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 + OFFSET; #if RCHECK size++; #endif if (size > MAXALLOC) { bucket = nBuckets; blockPtr = malloc(size); #ifdef ZIPPY_STATS if (blockPtr != NULL) { cachePtr->totalAssigned += reqSize; } #endif } 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; cachePtr->buckets[bucket].numFree--; #ifdef ZIPPY_STATS 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 (allocator < aNONE) { return free((char *) ptr); } GETCACHE(cachePtr); if (ptr == NULL) { return; } /* * 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) { #ifdef ZIPPY_STATS cachePtr->totalAssigned -= blockPtr->blockReqSize; #endif free(blockPtr); return; } #ifdef ZIPPY_STATS cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; #endif blockPtr->nextBlock = cachePtr->buckets[bucket].firstPtr; cachePtr->buckets[bucket].firstPtr = blockPtr; cachePtr->buckets[bucket].numFree++; #ifdef ZIPPY_STATS cachePtr->buckets[bucket].numInserts++; #endif #if defined(TCL_THREADS) 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 (allocator < aNONE) { return (void *) realloc((char *) ptr, reqSize); } GETCACHE(cachePtr); 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 - OFFSET - RCHECK) { /* Requested allocation exceeds memory */ return NULL; } } #endif /* * 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 + OFFSET; #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) { #ifdef ZIPPY_STATS cachePtr->buckets[bucket].totalAssigned -= blockPtr->blockReqSize; cachePtr->buckets[bucket].totalAssigned += reqSize; #endif return Block2Ptr(blockPtr, bucket, reqSize); } } else if (size > MAXALLOC) { #ifdef ZIPPY_STATS cachePtr->totalAssigned -= blockPtr->blockReqSize; cachePtr->totalAssigned += reqSize; #endif 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; } #ifdef ZIPPY_STATS /* *---------------------------------------------------------------------- * * Tcl_GetMemoryInfo -- * * Return a list-of-lists of memory stats. * * Results: * None. * * Side effects: * List appended to given dstring. * *---------------------------------------------------------------------- */ 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 defined(TCL_THREADS) if (cachePtr == sharedPtr) { Tcl_DStringAppendElement(dsPtr, "shared"); } else { sprintf(buf, "thread%p", cachePtr->owner); Tcl_DStringAppendElement(dsPtr, buf); } #else Tcl_DStringAppendElement(dsPtr, "unthreaded"); #endif 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); #if defined(TCL_THREADS) cachePtr = cachePtr->nextPtr; #else cachePtr = NULL; #endif } Tcl_MutexUnlock(listLockPtr); } #endif /* ZIPPY_STATS */ #endif /* code above only for NATIVE allocator */ /* *---------------------------------------------------------------------- * * 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) { Cache *cachePtr; Block *blockPtr; Bucket *bucketPtr; GETCACHE(cachePtr); bucketPtr = &cachePtr->buckets[0]; blockPtr = bucketPtr->firstPtr; if (bucketPtr->numFree || GetBlocks(cachePtr, 0)) { blockPtr = bucketPtr->firstPtr; bucketPtr->firstPtr = blockPtr->nextBlock; bucketPtr->numFree--; #ifdef ZIPPY_STATS bucketPtr->numRemoves++; bucketPtr->totalAssigned += sizeof(Tcl_Obj); #endif } return blockPtr; } /* *---------------------------------------------------------------------- * * 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; Block *blockPtr = ptr; Bucket *bucketPtr; GETCACHE(cachePtr); bucketPtr = &cachePtr->buckets[0]; #ifdef ZIPPY_STATS bucketPtr->totalAssigned -= sizeof(Tcl_Obj); #endif blockPtr->nextBlock = bucketPtr->firstPtr; bucketPtr->firstPtr = blockPtr; bucketPtr->numFree++; #ifdef ZIPPY_STATS bucketPtr->numInserts++; #endif if (bucketPtr->numFree > bucketInfo[0].maxBlocks) { if (allocator == aPURIFY) { /* undo */ bucketPtr->numFree = 0; bucketPtr->firstPtr = NULL; free((char *) blockPtr); return; } #if defined(TCL_THREADS) PutBlocks(cachePtr, 0, bucketInfo[0].numMove); #endif } } #if defined(TCL_THREADS) /* *---------------------------------------------------------------------- * * 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. * *---------------------------------------------------------------------- */ static void LockBucket( Cache *cachePtr, int bucket) { #if 0 if (Tcl_MutexTryLock(bucketInfo[bucket].lockPtr) != TCL_OK) { Tcl_MutexLock(bucketInfo[bucket].lockPtr); cachePtr->buckets[bucket].numWaits++; sharedPtr->buckets[bucket].numWaits++; } #else Tcl_MutexLock(bucketInfo[bucket].lockPtr); #endif #ifdef ZIPPY_STATS cachePtr->buckets[bucket].numLocks++; sharedPtr->buckets[bucket].numLocks++; #endif } static void UnlockBucket( Cache *cachePtr, int bucket) { Tcl_MutexUnlock(bucketInfo[bucket].lockPtr); } /* *---------------------------------------------------------------------- * * PutBlocks -- * * Return unused blocks to the shared cache. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ 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. * *---------------------------------------------------------------------- */ static int GetBlocks( Cache *cachePtr, int bucket) { register Block *blockPtr = NULL; register int n; if (allocator == aPURIFY) { if (bucket) { Tcl_Panic("purify mode asking for blocks?"); } cachePtr->buckets[0].firstPtr = (Block *) calloc(1, MINALLOC); cachePtr->buckets[0].numFree = 1; return 1; } #if defined(TCL_THREADS) /* * 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); } #endif if (cachePtr->buckets[bucket].numFree == 0) { register size_t size; #if TCL_ALLOCATOR != aNATIVE /* * If no blocks could be moved from shared, first look for a larger * block in this cache OR the shared cache to split up. */ n = nBuckets; size = 0; /* lint */ while (--n > bucket) { size = bucketInfo[n].blockSize; if (cachePtr->buckets[n].numFree > 0) { blockPtr = cachePtr->buckets[n].firstPtr; cachePtr->buckets[n].firstPtr = blockPtr->nextBlock; cachePtr->buckets[n].numFree--; break; } else if (sharedPtr->buckets[n].numFree > 0){ LockBucket(cachePtr, n); if (sharedPtr->buckets[n].numFree > 0) { blockPtr = sharedPtr->buckets[n].firstPtr; sharedPtr->buckets[n].firstPtr = blockPtr->nextBlock; sharedPtr->buckets[n].numFree--; UnlockBucket(cachePtr, n); break; } UnlockBucket(cachePtr, n); } } #endif /* * Otherwise, allocate a big new block directly. */ if (blockPtr == NULL) { size = MAXALLOC; blockPtr = malloc(size); if (blockPtr == NULL) { 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; } /* *------------------------------------------------------------------------- * * TclInitAlloc -- * * Initialize the memory system. * * Results: * None. * * Side effects: * Initialize the mutex used to serialize allocations. * *------------------------------------------------------------------------- */ void TclInitAlloc(void) { } /* *---------------------------------------------------------------------- * * TclFinalizeAlloc -- * * This procedure is used to destroy all private resources used in this * file. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFinalizeAlloc(void) { #if defined(TCL_THREADS) unsigned int i; for (i = 0; i < nBuckets; ++i) { TclpFreeAllocMutex(bucketInfo[i].lockPtr); bucketInfo[i].lockPtr = NULL; } TclpFreeAllocMutex(objLockPtr); objLockPtr = NULL; TclpFreeAllocMutex(listLockPtr); listLockPtr = NULL; TclpFreeAllocCache(NULL); #endif } #if TCL_ALLOCATOR != aZIPPY static void ChooseAllocator() { char *choice = getenv("TCL_ALLOCATOR"); /* * This is only called with ALLOCATOR_BASE aZIPPY (when compiled with * aMULTI) or aNATIVE (when compiled with aNATIVE). */ allocator = ALLOCATOR_BASE; if (choice) { /* * Only override the base when requesting native or purify */ if (!strcmp(choice, "aNATIVE")) { allocator = aNATIVE; } else if (!strcmp(choice, "aPURIFY")) { allocator = aPURIFY; } } } #endif #endif /* end of !PURIFY */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclAssembly.c.
︙ | ︙ | |||
1091 1092 1093 1094 1095 1096 1097 | static AssemblyEnv* NewAssemblyEnv( CompileEnv* envPtr, /* Compilation environment being used for code * generation*/ int flags) /* Compilation flags (TCL_EVAL_DIRECT) */ { | < < | | | 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 | 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; |
︙ | ︙ | |||
1140 1141 1142 1143 1144 1145 1146 | *----------------------------------------------------------------------------- */ static void FreeAssemblyEnv( AssemblyEnv* assemEnvPtr) /* Environment to free */ { | < < < < < | 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 | *----------------------------------------------------------------------------- */ 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. */ |
︙ | ︙ | |||
1187 1188 1189 1190 1191 1192 1193 | Tcl_DeleteHashEntry(hashEntry); } /* * Dispose what's left. */ | | | | 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 | Tcl_DeleteHashEntry(hashEntry); } /* * Dispose what's left. */ ckfree(assemEnvPtr->parsePtr); ckfree(assemEnvPtr); } /* *----------------------------------------------------------------------------- * * AssembleOneLine -- * |
︙ | ︙ |
Changes to generic/tclBasic.c.
︙ | ︙ | |||
724 725 726 727 728 729 730 | 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. */ | < < < < < | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | 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->pendingObjDataPtr = NULL; 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 |
︙ | ︙ | |||
2315 2316 2317 2318 2319 2320 2321 | 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; | | < | | 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 | 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 -- |
︙ | ︙ | |||
2364 2365 2366 2367 2368 2369 2370 | 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; | | < | 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 | 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; } |
︙ | ︙ | |||
2401 2402 2403 2404 2405 2406 2407 | * free the objv array if malloc'ed storage was used. */ for (i = 0; i < argc; i++) { objPtr = objv[i]; Tcl_DecrRefCount(objPtr); } | | | 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 | * 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 -- |
︙ | ︙ | |||
4559 4560 4561 4562 4563 4564 4565 | * to hold both the handler prefix and all words of the command invokation * itself. */ Tcl_ListObjGetElements(NULL, currNsPtr->unknownHandlerPtr, &handlerObjc, &handlerObjv); newObjc = objc + handlerObjc; | | | 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 | * 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. */ |
︙ | ︙ | |||
4598 4599 4600 4601 4602 4603 4604 | * Release any resources we locked and allocated during the handler * call. */ for (i = 0; i < handlerObjc; ++i) { Tcl_DecrRefCount(newObjv[i]); } | | | 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 | * 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; } |
︙ | ︙ | |||
4636 4637 4638 4639 4640 4641 4642 | /* * Release any resources we locked and allocated during the handler call. */ for (i = 0; i < objc; ++i) { Tcl_DecrRefCount(objv[i]); } | | | 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 | /* * 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, |
︙ | ︙ | |||
4933 4934 4935 4936 4937 4938 4939 | 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. */ | | | | < | | | 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 | 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 |
︙ | ︙ | |||
5334 5335 5336 5337 5338 5339 5340 | * 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); } | | | | | | | 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 | * 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; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
5976 5977 5978 5979 5980 5981 5982 | * 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. */ | | | 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 | * 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; |
︙ | ︙ | |||
6094 6095 6096 6097 6098 6099 6100 | * * 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; | | | 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 | * * 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. */ |
︙ | ︙ | |||
6135 6136 6137 6138 6139 6140 6141 | if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) { /* * Death of SrcInfo reference. */ Tcl_DecrRefCount(ctxPtr->data.eval.path); } | | | 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 | 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. */ |
︙ | ︙ | |||
6214 6215 6216 6217 6218 6219 6220 | /* * Remove the cmdFrame */ if (eoFramePtr) { iPtr->cmdFramePtr = eoFramePtr->nextPtr; | | | 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 | /* * Remove the cmdFrame */ if (eoFramePtr) { iPtr->cmdFramePtr = eoFramePtr->nextPtr; ckfree(eoFramePtr); } TclDecrRefCount(listPtr); return result; } /* |
︙ | ︙ |
Changes to generic/tclCkalloc.c.
︙ | ︙ | |||
1292 1293 1294 1295 1296 1297 1298 | TclpFree((char *) curTagPtr); curTagPtr = NULL; } allocHead = NULL; Tcl_MutexUnlock(ckallocMutexPtr); #endif | < < < < | 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 | 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.
︙ | ︙ | |||
2344 2345 2346 2347 2348 2349 2350 | ForIterData *iterPtr; if (objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "start test next command"); return TCL_ERROR; } | | | 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 | 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); |
︙ | ︙ | |||
2372 2373 2374 2375 2376 2377 2378 | { ForIterData *iterPtr = data[0]; if (result != TCL_OK) { if (result == TCL_ERROR) { Tcl_AddErrorInfo(interp, "\n (\"for\" initial command)"); } | | | 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 | { 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 |
︙ | ︙ | |||
2410 2411 2412 2413 2414 2415 2416 | result = TCL_OK; Tcl_ResetResult(interp); break; case TCL_ERROR: Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(iterPtr->msg, Tcl_GetErrorLine(interp))); } | | | | | | 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 | 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, |
︙ | ︙ | |||
2488 2489 2490 2491 2492 2493 2494 | 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)"); | | | 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 | 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; } |
︙ | ︙ | |||
2556 2557 2558 2559 2560 2561 2562 | * 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. */ | | | 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 | * 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; |
︙ | ︙ | |||
2750 2751 2752 2753 2754 2755 2756 | if (statePtr->vCopyList[i]) { TclDecrRefCount(statePtr->vCopyList[i]); } if (statePtr->aCopyList[i]) { TclDecrRefCount(statePtr->aCopyList[i]); } } | | | 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 | if (statePtr->vCopyList[i]) { TclDecrRefCount(statePtr->vCopyList[i]); } if (statePtr->aCopyList[i]) { TclDecrRefCount(statePtr->aCopyList[i]); } } ckfree(statePtr); } /* *---------------------------------------------------------------------- * * Tcl_FormatObjCmd -- * |
︙ | ︙ |
Changes to generic/tclCmdIL.c.
︙ | ︙ | |||
1309 1310 1311 1312 1313 1314 1315 | break; case TCL_LOCATION_BC: { /* * Execution of bytecode. Talk to the BC engine to fill out the frame. */ | | | 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 | 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. |
︙ | ︙ | |||
1343 1344 1345 1346 1347 1348 1349 | */ Tcl_DecrRefCount(fPtr->data.eval.path); } ADD_PAIR("cmd", Tcl_NewStringObj(fPtr->cmd.str.cmd, fPtr->cmd.str.len)); | | | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 | */ 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. */ |
︙ | ︙ | |||
3012 3013 3014 3015 3016 3017 3018 | } break; case LSEARCH_INDEX: { /* -index */ Tcl_Obj **indices; int j; if (sortInfo.indexc > 1) { | | | 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 | } 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_AppendResult(interp, "\"-index\" option must be followed by list index", |
︙ | ︙ | |||
3047 3048 3049 3050 3051 3052 3053 | sortInfo.indexv = NULL; break; case 1: sortInfo.indexv = &sortInfo.singleIndex; break; default: sortInfo.indexv = | | | 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 | 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. */ |
︙ | ︙ | |||
3154 3155 3156 3157 3158 3159 3160 | /* * 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) { | | | 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 | /* * 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; |
︙ | ︙ | |||
3479 3480 3481 3482 3483 3484 3485 | /* * Cleanup the index list array. */ done: if (sortInfo.indexc > 1) { | | | 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 | /* * Cleanup the index list array. */ done: if (sortInfo.indexc > 1) { ckfree(sortInfo.indexv); } return result; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
3766 3767 3768 3769 3770 3771 3772 | sortInfo.indexv = NULL; break; case 1: sortInfo.indexv = &sortInfo.singleIndex; break; default: sortInfo.indexv = | | | 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 | 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]); } |
︙ | ︙ | |||
3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 | 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]; } } } | > | 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 | 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]; } } } |
︙ | ︙ | |||
3898 3899 3900 3901 3902 3903 3904 | } /* * The following loop creates a SortElement for each list element and * begins sorting it into the sublists as it appears. */ | | | 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 | } /* * 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 */ |
︙ | ︙ | |||
4022 4023 4024 4025 4026 4027 4028 | } } listRepPtr->elemCount = i; Tcl_SetObjResult(interp, resultPtr); } done1: | | | | 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 | } } 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.
︙ | ︙ | |||
1831 1832 1833 1834 1835 1836 1837 | mapWithDict = 1; /* * Copy the dictionary out into an array; that's the easiest way to * adapt this code... */ | | | 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 | 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 { |
︙ | ︙ | |||
1940 1941 1942 1943 1944 1945 1946 | /* * 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. */ | | | | | 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 | /* * 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]); } |
︙ | ︙ | |||
1993 1994 1995 1996 1997 1998 1999 | Tcl_AppendUnicodeToObj(resultPtr, mapStrings[index+1], mapLens[index+1]); break; } } } if (nocase) { | | | | | | 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 | 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; } |
︙ | ︙ | |||
3845 3846 3847 3848 3849 3850 3851 | /* * We've got a match. Find a body to execute, skipping bodies that are * "-". */ matchFound: | | | 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 | /* * 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 |
︙ | ︙ | |||
3962 3963 3964 3965 3966 3967 3968 | int overflow = (patternLength > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (\"%.*s%s\" arm line %d)", (overflow ? limit : patternLength), pattern, (overflow ? "..." : ""), Tcl_GetErrorLine(interp))); } | | | 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 | 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 -- |
︙ | ︙ | |||
4725 4726 4727 4728 4729 4730 4731 | return TCL_ERROR; } /* * We reuse [for]'s callback, passing a NULL for the 'next' script. */ | | | 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 | 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.
︙ | ︙ | |||
1017 1018 1019 1020 1021 1022 1023 | * 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; | < | | 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 | * 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. */ |
︙ | ︙ | |||
1056 1057 1058 1059 1060 1061 1062 | goto failedUpdateInfoAssembly; } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { failedUpdateInfoAssembly: ckfree(duiPtr); | | | 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 | goto failedUpdateInfoAssembly; } tokenPtr = TokenAfter(tokenPtr); } if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { failedUpdateInfoAssembly: ckfree(duiPtr); ckfree(keyTokenPtrs); return TCL_ERROR; } 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. |
︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 | 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)); } | | | 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 | 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); return TCL_OK; } int TclCompileDictAppendCmd( Tcl_Interp *interp, /* Used for looking up stuff. */ Tcl_Parse *parsePtr, /* Points to a parse structure for the command |
︙ | ︙ | |||
1633 1634 1635 1636 1637 1638 1639 | bodyIndex = i-1; /* * Allocate storage for the varcList and varvList arrays if necessary. */ numLists = (numWords - 2)/2; | | | < | 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 | 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. */ |
︙ | ︙ | |||
1863 1864 1865 1866 1867 1868 1869 | done: for (loopIndex = 0; loopIndex < numLists; loopIndex++) { if (varvList[loopIndex] != NULL) { ckfree(varvList[loopIndex]); } } | | | | 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 | done: for (loopIndex = 0; loopIndex < numLists; loopIndex++) { if (varvList[loopIndex] != NULL) { ckfree(varvList[loopIndex]); } } ckfree((void *)varvList); ckfree(varcList); return code; } /* *---------------------------------------------------------------------- * * DupForeachInfo -- |
︙ | ︙ | |||
3512 3513 3514 3515 3516 3517 3518 | return TCL_OK; } /* * Allocate some working space. */ | | | 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 | 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. */ |
︙ | ︙ | |||
3536 3537 3538 3539 3540 3541 3542 | } status = TclMergeReturnOptions(interp, objc, objv, &returnOpts, &code, &level); cleanup: while (--objc >= 0) { TclDecrRefCount(objv[objc]); } | | | 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 | } 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. */ |
︙ | ︙ | |||
4024 4025 4026 4027 4028 4029 4030 | if ((elName != NULL) && elNameChars) { /* * An array element, the element name is a simple string: * assemble the corresponding token. */ | | | 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 | 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; } |
︙ | ︙ | |||
4077 4078 4079 4080 4081 4082 4083 | if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ | | | 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 | 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; |
︙ | ︙ | |||
4165 4166 4167 4168 4169 4170 4171 | CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { | | | 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 | 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.
︙ | ︙ | |||
591 592 593 594 595 596 597 | int code = TCL_ERROR; DefineLineInformation; /* TIP #280 */ if (numArgs == 0) { return TCL_ERROR; } | | | 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 | 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; |
︙ | ︙ | |||
624 625 626 627 628 629 630 | code = TclSubstOptions(NULL, numOpts, objv, &flags); } cleanup: while (--objc >= 0) { TclDecrRefCount(objv[objc]); } | | | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | 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); |
︙ | ︙ | |||
1316 1317 1318 1319 1320 1321 1322 | /* * Generate a test for each arm. */ contFixIndex = -1; contFixCount = 0; | | | | 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 | /* * 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 || |
︙ | ︙ | |||
1516 1517 1518 1519 1520 1521 1522 | for (j=i-1 ; j>=0 ; j--) { if (fixupTargetArray[j] > fixupArray[i].codeOffset) { fixupTargetArray[j] += 3; } } } } | | | | 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 | for (j=i-1 ; j>=0 ; j--) { if (fixupTargetArray[j] > fixupArray[i].codeOffset) { fixupTargetArray[j] += 3; } } } } ckfree(fixupTargetArray); ckfree(fixupArray); envPtr->currStackDepth = savedStackDepth + 1; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
1578 1579 1580 1581 1582 1583 1584 | * * 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); | | | 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 | * * 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 |
︙ | ︙ | |||
1716 1717 1718 1719 1720 1721 1722 | envPtr->codeStart+finalFixups[i]+1); } /* * Clean up all our temporary space and return. */ | | | 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 | envPtr->codeStart+finalFixups[i]+1); } /* * Clean up all our temporary space and return. */ ckfree(finalFixups); } /* *---------------------------------------------------------------------- * * DupJumptableInfo, FreeJumptableInfo -- * |
︙ | ︙ | |||
1971 1972 1973 1974 1975 1976 1977 | /* * Extract information about what handlers there are. */ numHandlers = numWords >> 2; numWords -= numHandlers * 4; if (numHandlers > 0) { | | | | | | | 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 | /* * 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; |
︙ | ︙ | |||
2135 2136 2137 2138 2139 2140 2141 | failedToCompile: if (numHandlers > 0) { for (i=0 ; i<numHandlers ; i++) { if (matchClauses[i]) { TclDecrRefCount(matchClauses[i]); } } | | | | | | | 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 | 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; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2215 2216 2217 2218 2219 2220 2221 | /* * 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. */ | | | | 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 | /* * 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); |
︙ | ︙ | |||
2303 2304 2305 2306 2307 2308 2309 | * 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]); } | | | | 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 | * 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); return TCL_OK; } static int IssueTryFinallyInstructions( Tcl_Interp *interp, CompileEnv *envPtr, |
︙ | ︙ | |||
2366 2367 2368 2369 2370 2371 2372 | */ if (numHandlers) { /* * Slight overallocation, but reduces size of this function. */ | | | | 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 | */ 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); |
︙ | ︙ | |||
2499 2500 2501 2502 2503 2504 2505 | * 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]); } | | | | 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 | * 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); |
︙ | ︙ | |||
2896 2897 2898 2899 2900 2901 2902 | if ((elName != NULL) && elNameChars) { /* * An array element, the element name is a simple string: * assemble the corresponding token. */ | | | 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 | 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; } |
︙ | ︙ | |||
2949 2950 2951 2952 2953 2954 2955 | if (remainingChars) { /* * Make a first token with the extra characters in the first * token. */ | | | 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 | 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; |
︙ | ︙ | |||
3037 3038 3039 3040 3041 3042 3043 | CompileTokens(envPtr, varTokenPtr, interp); } if (removedParen) { varTokenPtr[removedParen].size++; } if (allocedTokens) { | | | 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 | 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.
︙ | ︙ | |||
916 917 918 919 920 921 922 | goto error; } scanned = tokenPtr->size; break; case SCRIPT: { Tcl_Parse *nestedPtr = | | | 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 | 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; |
︙ | ︙ | |||
951 952 953 954 955 956 957 | parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->incomplete = 1; code = TCL_ERROR; errCode = "UNBALANCED"; break; } } | | | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | 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 */ |
︙ | ︙ | |||
1817 1818 1819 1820 1821 1822 1823 | * 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. */ | | | 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 | * 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, |
︙ | ︙ | |||
1839 1840 1841 1842 1843 1844 1845 | opTree, exprParsePtr->tokenPtr, parsePtr); } else { parsePtr->term = exprParsePtr->term; parsePtr->errorType = exprParsePtr->errorType; } Tcl_FreeParse(exprParsePtr); | | | 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 | opTree, exprParsePtr->tokenPtr, parsePtr); } else { parsePtr->term = exprParsePtr->term; parsePtr->errorType = exprParsePtr->errorType; } Tcl_FreeParse(exprParsePtr); ckfree(exprParsePtr); ckfree(opTree); return code; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2068 2069 2070 2071 2072 2073 2074 | 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*/ | | | 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 | 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) { /* |
︙ | ︙ | |||
2096 2097 2098 2099 2100 2101 2102 | CompileExprTree(interp, opTree, 0, &litObjv, funcObjv, parsePtr->tokenPtr, envPtr, optimize); } else { TclCompileSyntaxError(interp, envPtr); } Tcl_FreeParse(parsePtr); | | | 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 | 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); } /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
2139 2140 2141 2142 2143 2144 2145 | /* * 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. */ | | | | 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 | /* * 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 = (ByteCode *) byteCodeObj->internalRep.otherValuePtr; TclNRExecuteByteCode(interp, byteCodePtr); code = TclNRRunCallbacks(interp, TCL_OK, rootPtr); Tcl_DecrRefCount(byteCodeObj); return code; } |
︙ | ︙ | |||
2204 2205 2206 2207 2208 2209 2210 | JumpList *freePtr, *newJump; if (nodePtr->mark == MARK_LEFT) { next = nodePtr->left; switch (nodePtr->lexeme) { case QUESTION: | | | | | | | 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 | 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; |
︙ | ︙ | |||
2327 2328 2329 2330 2331 2332 2333 | } TclFixupForwardJump(envPtr, &(jumpPtr->jump), jumpPtr->offset - jumpPtr->jump.codeOffset, 127); convert |= jumpPtr->convert; envPtr->currStackDepth = jumpPtr->depth + 1; freePtr = jumpPtr; jumpPtr = jumpPtr->next; | | | | 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 | } 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)); |
︙ | ︙ | |||
2354 2355 2356 2357 2358 2359 2360 | (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; | | | | | 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 | (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) { |
︙ | ︙ | |||
2537 2538 2539 2540 2541 2542 2543 | { int code = TCL_OK; if (objc < 3) { Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); } else { TclOpCmdClientData *occdPtr = clientData; | < | | | 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 | { 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]; |
︙ | ︙ | |||
2579 2580 2581 2582 2583 2584 2585 | nodes[2*(objc-2)-1].right = OT_LITERAL; nodes[0].right = lastAnd; nodes[lastAnd].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr); | | | | 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 | 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; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2666 2667 2668 2669 2670 2671 2672 | code = ExecConstantExprTree(interp, nodes, 0, &litObjPtrPtr); Tcl_DecrRefCount(litObjv[decrMe]); return code; } else { Tcl_Obj *const *litObjv = objv + 1; | | | 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 | 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; |
︙ | ︙ | |||
2699 2700 2701 2702 2703 2704 2705 | } } nodes[0].right = lastOp; nodes[lastOp].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjv); | | | 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 | } } nodes[0].right = lastOp; nodes[lastOp].p.parent = 0; code = ExecConstantExprTree(interp, nodes, 0, &litObjv); ckfree(nodes); return code; } } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to generic/tclCompile.c.
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 | /* * 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. */ | | | 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 | /* * 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. |
︙ | ︙ | |||
1251 1252 1253 1254 1255 1256 1257 | */ Tcl_IncrRefCount(envPtr->extCmdMapPtr->path); } } } | | | 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 | */ 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 |
︙ | ︙ | |||
1457 1458 1459 1460 1461 1462 1463 | 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; | | | 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 | 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); |
︙ | ︙ | |||
1873 1874 1875 1876 1877 1878 1879 | */ if (envPtr->codeNext == entryCodeNext) { TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr); } envPtr->numSrcBytes = p - script; | | | 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 | */ if (envPtr->codeNext == entryCodeNext) { TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr); } envPtr->numSrcBytes = p - script; ckfree(parsePtr); Tcl_DStringFree(&ds); } /* *---------------------------------------------------------------------- * * TclCompileTokens -- |
︙ | ︙ |
Changes to generic/tclDictObj.c.
︙ | ︙ | |||
2421 2422 2423 2424 2425 2426 2427 | return TCL_ERROR; } if (varc != 2) { Tcl_SetResult(interp, "must have exactly two variable names", TCL_STATIC); return TCL_ERROR; } | | | | | 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 | return TCL_ERROR; } if (varc != 2) { Tcl_SetResult(interp, "must have exactly two variable names", TCL_STATIC); 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]; |
︙ | ︙ | |||
2484 2485 2486 2487 2488 2489 2490 | */ error: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); | | | 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 | */ error: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); ckfree(searchPtr); return TCL_ERROR; } static int DictForLoopCallback( ClientData data[], Tcl_Interp *interp, |
︙ | ︙ | |||
2570 2571 2572 2573 2574 2575 2576 | */ done: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); | | | 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 | */ done: TclDecrRefCount(keyVarObj); TclDecrRefCount(valueVarObj); TclDecrRefCount(scriptObj); Tcl_DictObjDone(searchPtr); ckfree(searchPtr); return result; } /* *---------------------------------------------------------------------- * * DictSetCmd -- |
︙ | ︙ |
Changes to generic/tclEvent.c.
︙ | ︙ | |||
1028 1029 1030 1031 1032 1033 1034 | * 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 */ | < < | 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | * 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 */ TclInitAlloc(); /* Process wide mutex init */ #ifdef TCL_MEM_DEBUG TclInitDbCkalloc(); /* Process wide mutex init */ #endif TclpInitPlatform(); /* Creates signal handler(s) */ TclInitDoubleConversion(); /* Initializes constants for * converting to/from double. */ |
︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 | TclFinalizeSynchronization(); /* * Close down the thread-specific object allocator. */ | < | < | 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 | TclFinalizeSynchronization(); /* * Close down the thread-specific object allocator. */ TclFinalizeAlloc(); /* * 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 |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
167 168 169 170 171 172 173 174 | * 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 */ | > | > | | | 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 | * 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 */ int catchDepth; /* this level: they record the state when a */ int cleanup; /* new codePtr was received for NR */ Tcl_Obj *auxObjList; /* execution. */ int checkInterp; CmdFrame cmdFrame; unsigned int capacity; void * stack[1]; /* Start of the actual combined catch and obj * stacks; the struct will be expanded as * necessary */ } TEBCdata; #define TEBC_YIELD() \ TD->tosPtr = tosPtr; \ TD->pc = pc; \ TD->cleanup = cleanup; \ TclNRAddCallback(interp, TEBCresume, TD, \ INT2PTR(1), NULL, NULL) #define TEBC_DATA_DIG() \ pc = TD->pc; \ cleanup = TD->cleanup; \ tosPtr = TD->tosPtr #define PUSH_TAUX_OBJ(objPtr) \ do { \ objPtr->internalRep.twoPtrValue.ptr2 = auxObjList; \ auxObjList = objPtr; \ } while (0) |
︙ | ︙ | |||
291 292 293 294 295 296 297 | } \ goto cleanupV_pushObjResultPtr; \ } else { \ goto cleanupV; \ } \ } while (0) | < < < < < < < < < < < < < < | 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | } \ 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 |
︙ | ︙ | |||
679 680 681 682 683 684 685 | static void PrintByteCodeInfo(ByteCode *codePtr); static const char * StringForResultCode(int result); static void ValidatePcAndStackTop(ByteCode *codePtr, const unsigned char *pc, int stackTop, int stackLowerBound, int checkStack); #endif /* TCL_COMPILE_DEBUG */ static ByteCode * CompileExprObj(Tcl_Interp *interp, Tcl_Obj *objPtr); | < < < < < < < | 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 | static void PrintByteCodeInfo(ByteCode *codePtr); static const char * StringForResultCode(int result); static void ValidatePcAndStackTop(ByteCode *codePtr, const unsigned char *pc, int stackTop, int stackLowerBound, 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 |
︙ | ︙ | |||
841 842 843 844 845 846 847 | 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)); | < < < < < < < < < | 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 | 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); |
︙ | ︙ | |||
888 889 890 891 892 893 894 | * Side effects: * Storage for an ExecEnv and its contained storage (e.g. the evaluation * stack) is freed. * *---------------------------------------------------------------------- */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 | * 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. */ { /* * Delete all stacks in this exec env. */ TclDecrRefCount(eePtr->constants[0]); TclDecrRefCount(eePtr->constants[1]); if (eePtr->callbackPtr) { Tcl_Panic("Deleting execEnv with pending NRE callbacks!"); } if (eePtr->corPtr) { Tcl_Panic("Deleting execEnv with existing coroutine"); |
︙ | ︙ | |||
961 962 963 964 965 966 967 | TclFinalizeExecution(void) { Tcl_MutexLock(&execMutex); execInitialized = 0; Tcl_MutexUnlock(&execMutex); TclFinalizeAuxDataTypeTable(); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 905 906 907 908 909 910 911 912 913 914 915 916 917 918 | TclFinalizeExecution(void) { Tcl_MutexLock(&execMutex); execInitialized = 0; Tcl_MutexUnlock(&execMutex); TclFinalizeAuxDataTypeTable(); } /* *-------------------------------------------------------------- * * Tcl_ExprObj -- * * Evaluate an expression in a Tcl_Obj. |
︙ | ︙ | |||
1693 1694 1695 1696 1697 1698 1699 | Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); if (hePtr) { ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr); int redo = 0; if (invoker) { | | | 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr); if (hePtr) { ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr); int redo = 0; if (invoker) { CmdFrame *ctxPtr = ckalloc(sizeof(CmdFrame)); *ctxPtr = *invoker; if (invoker->type == TCL_LOCATION_BC) { /* * Note: Type BC => ctx.data.eval.path is not used. * ctx.data.tebc.codePtr used instead */ |
︙ | ︙ | |||
1732 1733 1734 1735 1736 1737 1738 | redo = ((eclPtr->type == TCL_LOCATION_SOURCE) && (eclPtr->start != ctxPtr->line[word])) || ((eclPtr->type == TCL_LOCATION_BC) && (ctxPtr->type == TCL_LOCATION_SOURCE)); } | | | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 | redo = ((eclPtr->type == TCL_LOCATION_SOURCE) && (eclPtr->start != ctxPtr->line[word])) || ((eclPtr->type == TCL_LOCATION_BC) && (ctxPtr->type == TCL_LOCATION_SOURCE)); } ckfree(ctxPtr); } if (redo) { goto recompileObj; } } } |
︙ | ︙ | |||
1917 1918 1919 1920 1921 1922 1923 | * * Side effects: * Almost certainly, depending on the ByteCode's instructions. * *---------------------------------------------------------------------- */ #define bcFramePtr (&TD->cmdFrame) | | | < | | < < | | | > | 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 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 | * * 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]) int TclNRExecuteByteCode( Tcl_Interp *interp, /* Token for command interpreter. */ ByteCode *codePtr) /* The bytecode sequence to interpret. */ { Interp *iPtr = (Interp *) interp; TEBCdata *TD; unsigned int size = sizeof(TEBCdata) + sizeof(void *) * (codePtr->maxStackDepth + codePtr->maxExceptDepth - 1); 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(size); TD->tosPtr = initTosPtr; TD->codePtr = codePtr; 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) |
︙ | ︙ | |||
2044 2045 2046 2047 2048 2049 2050 | /* * These macros are just meant to save some global variables that are not * used too frequently */ TEBCdata *TD = data[0]; #define auxObjList (TD->auxObjList) | | | | 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 | /* * 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. */ |
︙ | ︙ | |||
2109 2110 2111 2112 2113 2114 2115 | TclArgumentBCRelease((Tcl_Interp *) iPtr, bcFramePtr); } if (codePtr->flags & TCL_BYTECODE_RECOMPILE) { iPtr->flags |= ERR_ALREADY_LOGGED; codePtr->flags &= ~TCL_BYTECODE_RECOMPILE; } | | | 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 | 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 /* |
︙ | ︙ | |||
2249 2250 2251 2252 2253 2254 2255 | /* * 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) { | < | | | | | 1858 1859 1860 1861 1862 1863 1864 1865 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 | /* * 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; } TCL_DTRACE_INST_NEXT(); /* * These two instructions account for 26% of all instructions (according * to measurements on tclbench by Ben Vitale |
︙ | ︙ | |||
2639 2640 2641 2642 2643 2644 2645 | TclNewObj(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = (void *) CURR_DEPTH; PUSH_TAUX_OBJ(objPtr); NEXT_INST_F(1, 0, 0); case INST_EXPAND_STKTOP: { int i; | | < > > | < < | | | | < < < < > > > | > | > | | > | < < > | 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 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 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 | TclNewObj(objPtr); objPtr->internalRep.twoPtrValue.ptr1 = (void *) 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 = sizeof(TEBCdata) + sizeof(void *) * + (reqWords + codePtr->maxExceptDepth - 1); depth = tosPtr - initTosPtr; TD = ckrealloc(TD, size); tosPtr = initTosPtr + depth; TD->capacity = reqWords; } /* * 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); } /* |
︙ | ︙ | |||
2786 2787 2788 2789 2790 2791 2792 | iPtr->cmdFramePtr = bcFramePtr; if (iPtr->flags & INTERP_DEBUG_FRAME) { TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc, codePtr, bcFramePtr, pc - codePtr->codeStart); } | < < | 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 | 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: |
︙ | ︙ | |||
3012 3013 3014 3015 3016 3017 3018 | doCallPtrGetVar: /* * There are either errors or the variable is traced: call * TclPtrGetVar to process fully. */ | < < > | 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 | 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); |
︙ | ︙ | |||
3259 3260 3261 3262 3263 3264 3265 | varPtr = varPtr->value.linkPtr; } cleanup = 1; arrayPtr = NULL; part1Ptr = part2Ptr = NULL; doCallPtrSetVar: | < < > | 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 | 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); |
︙ | ︙ | |||
3523 3524 3525 3526 3527 3528 3529 | Tcl_DecrRefCount(incrPtr); TRACE_APPEND(("ERROR: %.30s\n", O2S(Tcl_GetObjResult(interp)))); goto gotError; } Tcl_DecrRefCount(incrPtr); } else { | < < > | 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 | 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; } } |
︙ | ︙ | |||
3558 3559 3560 3561 3562 3563 3564 | opnd = TclGetUInt4AtPtr(pc+1); varPtr = LOCAL(opnd); while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (ReadTraced(varPtr)) { | < < > | 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 | 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; } } /* |
︙ | ︙ | |||
3594 3595 3596 3597 3598 3599 3600 | goto doneExistArray; } } varPtr = TclLookupArrayElement(interp, NULL, part2Ptr, 0, "access", 0, 1, arrayPtr, opnd); if (varPtr) { if (ReadTraced(varPtr) || (arrayPtr && ReadTraced(arrayPtr))) { | < < > | 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 | 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: |
︙ | ︙ | |||
3627 3628 3629 3630 3631 3632 3633 | 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))) { | < < > | 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 | 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); |
︙ | ︙ | |||
3674 3675 3676 3677 3678 3679 3680 | goto slowUnsetScalar; } varPtr->value.objPtr = NULL; NEXT_INST_F(6, 0, 0); } slowUnsetScalar: | < | | 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 | 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); |
︙ | ︙ | |||
3716 3717 3718 3719 3720 3721 3722 | * Don't need to do anything here. */ NEXT_INST_F(6, 1, 0); } } slowUnsetArray: | < | < | | < < > | 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 | * 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. * ----------------------------------------------------------------- |
︙ | ︙ | |||
4020 4021 4022 4023 4024 4025 4026 | 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"))); | < < > < < > | 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 | 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); |
︙ | ︙ | |||
4808 4809 4810 4811 4812 4813 4814 | 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"))); | < < > < < > | 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 | 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. */ |
︙ | ︙ | |||
4879 4880 4881 4882 4883 4884 4885 | } case INST_RSHIFT: if (l2 < 0) { Tcl_SetResult(interp, "negative shift argument", TCL_STATIC); #if 0 | < | | 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 | } case INST_RSHIFT: if (l2 < 0) { Tcl_SetResult(interp, "negative shift argument", TCL_STATIC); #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); |
︙ | ︙ | |||
4927 4928 4929 4930 4931 4932 4933 | } case INST_LSHIFT: if (l2 < 0) { Tcl_SetResult(interp, "negative shift argument", TCL_STATIC); #if 0 | < | < < > | 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 | } case INST_LSHIFT: if (l2 < 0) { Tcl_SetResult(interp, "negative shift argument", TCL_STATIC); #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_SetResult(interp, "integer value too large to represent", TCL_STATIC); #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. |
︙ | ︙ | |||
5037 5038 5039 5040 5041 5042 5043 | 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"))); | < < > < < > | 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 | 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. |
︙ | ︙ | |||
5207 5208 5209 5210 5211 5212 5213 | 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"))); | < < > < < > | 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 | 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); |
︙ | ︙ | |||
5254 5255 5256 5257 5258 5259 5260 | 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"))); | < < > | 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 | 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: |
︙ | ︙ | |||
5300 5301 5302 5303 5304 5305 5306 | if (*pc == INST_UPLUS) { /* * ... +$NonNumeric => raise an error. */ TRACE(("\"%.20s\" => ILLEGAL TYPE %s \n", O2S(valuePtr), (valuePtr->typePtr? valuePtr->typePtr->name:"null"))); | < < > < < > < < > | 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 | 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 |
︙ | ︙ | |||
5375 5376 5377 5378 5379 5380 5381 | /* * End of numeric operator instructions. * ----------------------------------------------------------------- */ case INST_BREAK: /* | < < > < < > | 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 | /* * 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; |
︙ | ︙ | |||
5520 5521 5522 5523 5524 5525 5526 | if (value2Ptr != NULL) { TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = valuePtr; Tcl_IncrRefCount(valuePtr); } } else { | < < > | | 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 | 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++; } } |
︙ | ︙ | |||
5562 5563 5564 5565 5566 5567 5568 | 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. */ | | | | | < < > | | 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 | 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); /* |
︙ | ︙ | |||
5596 5597 5598 5599 5600 5601 5602 | case INST_PUSH_RETURN_CODE: TclNewIntObj(objResultPtr, result); TRACE(("=> %u\n", result)); NEXT_INST_F(1, 0, 1); case INST_PUSH_RETURN_OPTIONS: | < < > | 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 | 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) { |
︙ | ︙ | |||
5650 5651 5652 5653 5654 5655 5656 | } if (Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &objResultPtr) == TCL_OK) { if (objResultPtr) { TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); } | < | | 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 | } if (Tcl_DictObjGet(interp, dictPtr, OBJ_AT_TOS, &objResultPtr) == TCL_OK) { if (objResultPtr) { TRACE_APPEND(("%.30s\n", O2S(objResultPtr))); NEXT_INST_V(5, opnd+1, 1); } Tcl_ResetResult(interp); Tcl_AppendResult(interp, "key \"", TclGetString(OBJ_AT_TOS), "\" not known in dictionary", NULL); Tcl_SetErrorCode(interp, "TCL", "LOOKUP", "DICT", TclGetString(OBJ_AT_TOS), NULL); checkInterp = 1; TRACE_WITH_OBJ(("%u => ERROR ", opnd), Tcl_GetObjResult(interp)); } else { TRACE_WITH_OBJ(( "%u => ERROR reading leaf dictionary key \"%s\": ", opnd, O2S(dictPtr)), Tcl_GetObjResult(interp)); } goto gotError; |
︙ | ︙ | |||
5679 5680 5681 5682 5683 5684 5685 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u %u => ", opnd, opnd2)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { | < < > | 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 | 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) { |
︙ | ︙ | |||
5753 5754 5755 5756 5757 5758 5759 | TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); | < < > | 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 | 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; } } |
︙ | ︙ | |||
5783 5784 5785 5786 5787 5788 5789 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { | < < > | 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 | 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) { |
︙ | ︙ | |||
5889 5890 5891 5892 5893 5894 5895 | TclDecrRefCount(value2Ptr); } varPtr->value.objPtr = dictPtr; } objResultPtr = dictPtr; } else { Tcl_IncrRefCount(dictPtr); | < < > | 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 | 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; } } |
︙ | ︙ | |||
5994 5995 5996 5997 5998 5999 6000 | while (TclIsVarLink(varPtr)) { varPtr = varPtr->value.linkPtr; } TRACE(("%u => ", opnd)); if (TclIsVarDirectReadable(varPtr)) { dictPtr = varPtr->value.objPtr; } else { | < < > < | | < < > | 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 | 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) { |
︙ | ︙ | |||
6073 6074 6075 6076 6077 6078 6079 | while (TclIsVarLink(var2Ptr)) { var2Ptr = var2Ptr->value.linkPtr; } if (TclIsVarDirectReadable(var2Ptr)) { valuePtr = var2Ptr->value.objPtr; } else { | < < > < < > | 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668 5669 5670 5671 5672 5673 5674 5675 | 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; } } |
︙ | ︙ | |||
6211 6212 6213 6214 6215 6216 6217 | /* * Division by zero in an expression. Control only reaches this point * by "goto divideByZero". */ divideByZero: | < < > < | | 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 | /* * 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: |
︙ | ︙ | |||
6254 6255 6256 6257 6258 6259 6260 | 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); | < < > | | | 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 | 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 |
︙ | ︙ | |||
6307 6308 6309 6310 6311 6312 6313 | if (traceInstructions) { fprintf(stdout, " ... limit exceeded, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } | | | 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 | 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; |
︙ | ︙ | |||
6342 6343 6344 6345 6346 6347 6348 | * "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: | | | | | | 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 | * "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. |
︙ | ︙ | |||
6400 6401 6402 6403 6404 6405 6406 | CLANG_ASSERT(bcFramePtr); } iPtr->cmdFramePtr = bcFramePtr->nextPtr; if (--codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); } | | < | | 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 | CLANG_ASSERT(bcFramePtr); } iPtr->cmdFramePtr = bcFramePtr->nextPtr; if (--codePtr->refCount <= 0) { TclCleanupByteCode(codePtr); } ckfree(TD); /* free my stack */ return result; } #undef codePtr #undef iPtr #undef bcFramePtr #undef initTosPtr #undef auxObjList #undef catchDepth #undef TCONST /* *---------------------------------------------------------------------- * * ExecuteExtendedBinaryMathOp, ExecuteExtendedUnaryMathOp -- * |
︙ | ︙ |
Changes to generic/tclFCmd.c.
︙ | ︙ | |||
995 996 997 998 999 1000 1001 | * Use objStrings as a list object. */ if (Tcl_ListObjLength(interp, objStrings, &numObjStrings) != TCL_OK) { goto end; } attributeStringsAllocated = (const char **) | | | 995 996 997 998 999 1000 1001 1002 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 **) 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; } |
︙ | ︙ | |||
1106 1107 1108 1109 1110 1111 1112 | end: if (attributeStringsAllocated != NULL) { /* * Free up the array we allocated. */ | | | 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 | end: if (attributeStringsAllocated != NULL) { /* * Free up the array we allocated. */ ckfree((void *) attributeStringsAllocated); /* * We don't need this object that was passed to us any more. */ if (objStrings != NULL) { Tcl_DecrRefCount(objStrings); |
︙ | ︙ |
Changes to generic/tclFileName.c.
︙ | ︙ | |||
1418 1419 1420 1421 1422 1423 1424 | * platform. */ Tcl_ListObjLength(interp, typePtr, &length); if (length <= 0) { goto skipTypes; } | | | 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 | * 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; |
︙ | ︙ | |||
1634 1635 1636 1637 1638 1639 1640 | if (globTypes != NULL) { if (globTypes->macType != NULL) { Tcl_DecrRefCount(globTypes->macType); } if (globTypes->macCreator != NULL) { Tcl_DecrRefCount(globTypes->macCreator); } | | | 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 | 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.
︙ | ︙ | |||
925 926 927 928 929 930 931 | /* * 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; | | | | 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 | /* * 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.
︙ | ︙ | |||
948 949 950 951 952 953 954 | elemLen = strlen(elementStr); } else { elementStr = TclGetStringFromObj(origObjv[i], &elemLen); } len = Tcl_ScanCountedElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { | | | | 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 | elemLen = strlen(elementStr); } else { elementStr = TclGetStringFromObj(origObjv[i], &elemLen); } len = Tcl_ScanCountedElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { char *quotedElementStr = ckalloc((unsigned)len); len = Tcl_ConvertCountedElement(elementStr, elemLen, quotedElementStr, flags); Tcl_AppendToObj(objPtr, quotedElementStr, len); ckfree(quotedElementStr); } else { Tcl_AppendToObj(objPtr, elementStr, elemLen); } AFTER_FIRST_WORD; /* |
︙ | ︙ | |||
1002 1003 1004 1005 1006 1007 1008 | * Quote the argument if it contains spaces (Bug 942757). */ elementStr = TclGetStringFromObj(objv[i], &elemLen); len = Tcl_ScanCountedElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { | | | | 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 | * Quote the argument if it contains spaces (Bug 942757). */ elementStr = TclGetStringFromObj(objv[i], &elemLen); len = Tcl_ScanCountedElement(elementStr, elemLen, &flags); if (MAY_QUOTE_WORD && len != elemLen) { char *quotedElementStr = ckalloc((unsigned) len); len = Tcl_ConvertCountedElement(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.
︙ | ︙ | |||
31 32 33 34 35 36 37 | #} #declare 1 { # int TclAccessDeleteProc(TclAccessProc_ *proc) #} #declare 2 { # int TclAccessInsertProc(TclAccessProc_ *proc) #} | | | < > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | #} #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) |
︙ | ︙ | |||
863 864 865 866 867 868 869 | } declare 213 { Tcl_Obj *TclGetObjNameOfExecutable(void) } declare 214 { void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding) } | | | < > | | < > | 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 | } 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) } |
︙ | ︙ |
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 |
︙ | ︙ | |||
1385 1386 1387 1388 1389 1390 1391 | /* * This is a convenience macro used to initialize a thread local storage ptr. */ #define TCL_TSD_INIT(keyPtr) \ (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) | < < < < < < < | 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 | /* * 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; |
︙ | ︙ | |||
1433 1434 1435 1436 1437 1438 1439 | * The type of procedure called from the compilation hook point in * SetByteCodeFromAny. */ typedef int (CompileHookProc)(Tcl_Interp *interp, struct CompileEnv *compEnvPtr, ClientData clientData); | < < < < < < < < < < < < < | 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 | * 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. */ |
︙ | ︙ | |||
1483 1484 1485 1486 1487 1488 1489 | * 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 { | < < | 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | * 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; |
︙ | ︙ | |||
1763 1764 1765 1766 1767 1768 1769 | * Values for the selection mode, i.e the package require preferences. */ enum PkgPreferOptions { PKG_PREFER_LATEST, PKG_PREFER_STABLE }; | < < < < < < < < < < < < < < < < < < | 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 | * 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. *---------------------------------------------------------------- |
︙ | ︙ | |||
2114 2115 2116 2117 2118 2119 2120 | * 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. */ | < | 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 | * 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. */ void *pendingObjDataPtr; /* Pointer to the Cache and PendingObjData * structs for this interp's thread; see * tclObj.c and tclThreadAlloc.c */ 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. |
︙ | ︙ | |||
2346 2347 2348 2349 2350 2351 2352 | * 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. * |
︙ | ︙ | |||
2898 2899 2900 2901 2902 2903 2904 | MODULE_SCOPE Tcl_ObjCmdProc TclFileReadLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileRenameCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileTemporaryCmd; MODULE_SCOPE void TclCreateLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); | < < | 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 | MODULE_SCOPE Tcl_ObjCmdProc TclFileReadLinkCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileRenameCmd; MODULE_SCOPE Tcl_ObjCmdProc TclFileTemporaryCmd; MODULE_SCOPE void TclCreateLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); MODULE_SCOPE void TclDeleteLateExitHandler(Tcl_ExitProc *proc, ClientData clientData); 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, |
︙ | ︙ | |||
3093 3094 3095 3096 3097 3098 3099 | mp_int *bignumValue); 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); | < < | 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 | mp_int *bignumValue); 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, |
︙ | ︙ | |||
3804 3805 3806 3807 3808 3809 3810 | tclObjsFreed++ #else # define TclIncrObjsAllocated() # define TclIncrObjsFreed() #endif /* TCL_COMPILE_STATS */ # define TclAllocObjStorage(objPtr) \ | | | | 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 | 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; \ |
︙ | ︙ | |||
3842 3843 3844 3845 3846 3847 3848 | TclFreeObjStorage(objPtr); \ TclIncrObjsFreed(); \ } else { \ TclFreeObj(objPtr); \ } \ } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 | 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(); \ |
︙ | ︙ | |||
3962 3963 3964 3965 3966 3967 3968 | # define TclDecrRefCount(objPtr) \ Tcl_DbDecrRefCount(objPtr, __FILE__, __LINE__) # define TclNewListObjDirect(objc, objv) \ TclDbNewListObjDirect(objc, objv, __FILE__, __LINE__) | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 | # 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 /* * List of valid allocators. Have to respect the following convention: * - allocators that shunt TclpAlloc to malloc are below aNONE * - allocators that use zippy are above aNONE */ #define aNATIVE 0 #define aPURIFY 1 #define aNONE 2 #define aZIPPY 3 #define aMULTI 4 #if defined(TCL_ALLOCATOR) && ((TCL_ALLOCATOR < 0) || (TCL_ALLOCATOR > aMULTI)) #undef TCL_ALLOCATOR #endif #ifdef PURIFY # undef TCL_ALLOCATOR # define TCL_ALLOCATOR aPURIFY #endif #if !defined(TCL_ALLOCATOR) # if defined(USE_THREAD_ALLOC) || defined(USE_TCLALLOC) # define TCL_ALLOCATOR aZIPPY # else # define TCL_ALLOCATOR aNATIVE # endif #endif #if TCL_ALLOCATOR < aNONE /* native or purify */ # define TclpAlloc(size) ckalloc(size) # define TclpRealloc(ptr, size) ckrealloc((ptr),(size)) # define TclpFree(size) ckfree(size) #else MODULE_SCOPE char * TclpAlloc(unsigned int size); MODULE_SCOPE char * TclpRealloc(char * ptr, unsigned int size); MODULE_SCOPE void TclpFree(char * ptr); #endif #if TCL_ALLOCATOR == aPURIFY # define TclSmallAlloc() ckalloc(sizeof(Tcl_Obj)) # define TclSmallFree(ptr) ckfree(ptr) # define TclInitAlloc() # define TclFinalizeAlloc() #else MODULE_SCOPE void * TclSmallAlloc(); MODULE_SCOPE void TclSmallFree(void *ptr); MODULE_SCOPE void TclInitAlloc(void); MODULE_SCOPE void TclFinalizeAlloc(void); #endif #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 (TCL_ALLOCATOR == aPURIFY) && 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 |
︙ | ︙ | |||
4466 4467 4468 4469 4470 4471 4472 4473 | * Adapted with permission from * http://www.pixelbeat.org/programming/gcc/static_assert.html */ #define TCL_CT_ASSERT(e) \ {enum { ct_assert_value = 1/(!!(e)) };} /* | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 | * 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) *---------------------------------------------------------------- */ |
︙ | ︙ | |||
4606 4607 4608 4609 4610 4611 4612 | if (((Interp *)interp)->deferredCallbacks) { \ TclNRSpliceCallbacks(interp, ((Interp *)interp)->deferredCallbacks); \ ((Interp *)interp)->deferredCallbacks = NULL; \ } #if NRE_USE_SMALL_ALLOC #define TCLNR_ALLOC(interp, ptr) \ | | | | 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 | if (((Interp *)interp)->deferredCallbacks) { \ TclNRSpliceCallbacks(interp, ((Interp *)interp)->deferredCallbacks); \ ((Interp *)interp)->deferredCallbacks = NULL; \ } #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.
︙ | ︙ | |||
54 55 56 57 58 59 60 | /* * Exported function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ | | < | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | /* * 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 */ |
︙ | ︙ | |||
502 503 504 505 506 507 508 | /* 212 */ EXTERN void TclpFindExecutable(const char *argv0); /* 213 */ EXTERN Tcl_Obj * TclGetObjNameOfExecutable(void); /* 214 */ EXTERN void TclSetObjNameOfExecutable(Tcl_Obj *name, Tcl_Encoding encoding); | | < | < | 501 502 503 504 505 506 507 508 509 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); /* 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); |
︙ | ︙ | |||
605 606 607 608 609 610 611 | typedef struct TclIntStubs { int magic; const struct TclIntStubHooks *hooks; void (*reserved0)(void); void (*reserved1)(void); void (*reserved2)(void); | | | 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 | typedef struct TclIntStubs { int magic; const struct TclIntStubHooks *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 */ |
︙ | ︙ | |||
817 818 819 820 821 822 823 | 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 */ | | | | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | 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); |
︙ | ︙ | |||
872 873 874 875 876 877 878 | /* * Inline function declarations: */ /* Slot 0 is reserved */ /* Slot 1 is reserved */ /* Slot 2 is reserved */ | | < | 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 | /* * 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 */ |
︙ | ︙ | |||
1212 1213 1214 1215 1216 1217 1218 | /* Slot 211 is reserved */ #define TclpFindExecutable \ (tclIntStubsPtr->tclpFindExecutable) /* 212 */ #define TclGetObjNameOfExecutable \ (tclIntStubsPtr->tclGetObjNameOfExecutable) /* 213 */ #define TclSetObjNameOfExecutable \ (tclIntStubsPtr->tclSetObjNameOfExecutable) /* 214 */ | < | < | | 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 | /* 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 */ |
︙ | ︙ |
Changes to generic/tclInterp.c.
︙ | ︙ | |||
1165 1166 1167 1168 1169 1170 1171 | const char *const *argv) /* These are the additional args. */ { Tcl_Obj *slaveObjPtr, *targetObjPtr; Tcl_Obj **objv; int i; int result; | | | | 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 | 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; } /* |
︙ | ︙ | |||
1859 1860 1861 1862 1863 1864 1865 | prefc = aliasPtr->objc; prefv = &aliasPtr->objPtr; cmdc = prefc + objc - 1; if (cmdc <= ALIAS_CMDV_PREALLOC) { cmdv = cmdArr; } else { | | | 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 | 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); |
︙ | ︙ | |||
1926 1927 1928 1929 1930 1931 1932 | Tcl_Release(targetInterp); } for (i=0; i<cmdc; i++) { Tcl_DecrRefCount(cmdv[i]); } if (cmdv != cmdArr) { | | | 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 | 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/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 -- * |
︙ | ︙ | |||
2628 2629 2630 2631 2632 2633 2634 | 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. */ | | < | 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 | 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 |
︙ | ︙ | |||
2718 2719 2720 2721 2722 2723 2724 | * the trailPtr array. */ trailFront++; if (trailFront == trailSize) { int newSize = 2 * trailSize; | < | | | 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 | * 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 -- * |
︙ | ︙ | |||
3966 3967 3968 3969 3970 3971 3972 | * 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) { | < | | | 3964 3965 3966 3967 3968 3969 3970 3971 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 | * 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.
︙ | ︙ | |||
100 101 102 103 104 105 106 | void TclOODeleteContext( CallContext *contextPtr) { register Object *oPtr = contextPtr->oPtr; TclOODeleteChain(contextPtr->callPtr); | | | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | void TclOODeleteContext( CallContext *contextPtr) { register Object *oPtr = contextPtr->oPtr; TclOODeleteChain(contextPtr->callPtr); ckfree(contextPtr); DelRef(oPtr); } /* * ---------------------------------------------------------------------- * * TclOODeleteChainCache -- |
︙ | ︙ | |||
1083 1084 1085 1086 1087 1088 1089 | TclOODeleteChain(oPtr->selfCls->destructorChainPtr); } oPtr->selfCls->destructorChainPtr = callPtr; callPtr->refCount++; } returnContext: | | | 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 | 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; } |
︙ | ︙ |
Changes to generic/tclOODefineCmds.c.
︙ | ︙ | |||
451 452 453 454 455 456 457 | } if (matchedStr != NULL) { /* * Got one match, and only one match! */ | | | | 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 | } 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_AppendResult(interp, "invalid command name \"",soughtStr,"\"", NULL); return TCL_ERROR; } |
︙ | ︙ | |||
1542 1543 1544 1545 1546 1547 1548 | if (oPtr == NULL) { return TCL_ERROR; } if (!isInstanceMixin && !oPtr->classPtr) { Tcl_AppendResult(interp, "attempt to misuse API", NULL); return TCL_ERROR; } | | | 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 | if (oPtr == NULL) { return TCL_ERROR; } if (!isInstanceMixin && !oPtr->classPtr) { Tcl_AppendResult(interp, "attempt to misuse API", 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; |
︙ | ︙ | |||
1564 1565 1566 1567 1568 1569 1570 | if (isInstanceMixin) { TclOOObjectSetMixins(oPtr, objc-1, mixins); } else { TclOOClassSetMixins(interp, oPtr->classPtr, objc-1, mixins); } | | | | 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 | 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 -- |
︙ | ︙ |
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. */ |
︙ | ︙ | |||
1443 1444 1445 1446 1447 1448 1449 | FinalizeForwardCall( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **argObjs = data[0]; | | | 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 | FinalizeForwardCall( ClientData data[], Tcl_Interp *interp, int result) { Tcl_Obj **argObjs = data[0]; ckfree(argObjs); return result; } /* * ---------------------------------------------------------------------- * * DeleteForwardMethod, CloneForwardMethod -- |
︙ | ︙ | |||
1572 1573 1574 1575 1576 1577 1578 | * array of rewritten arguments. */ { Interp *iPtr = (Interp *) interp; int isRootEnsemble = (iPtr->ensembleRewrite.sourceObjs == NULL); Tcl_Obj **argObjs; unsigned len = rewriteLength + objc - toRewrite; | | | 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 | * 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 | * Table of all object types. */ static Tcl_HashTable typeTable; static int typeTableInitialized = 0; /* 0 means not yet initialized. */ TCL_DECLARE_MUTEX(tableMutex) /* * The object allocator is single threaded. This mutex is referenced by the * TclNewObj macro, however, so must be visible. */ #ifdef TCL_THREADS MODULE_SCOPE Tcl_Mutex tclObjMutex; |
︙ | ︙ | |||
471 472 473 474 475 476 477 | /* *---------------------------------------------------------------------- * * TclFinalizeObjects -- * * This function is called by Tcl_Finalize to clean up all registered | | < < < < < < < < < | 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 | /* *---------------------------------------------------------------------- * * TclFinalizeObjects -- * * This function is called by Tcl_Finalize to clean up all registered * Tcl_ObjType's * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ void TclFinalizeObjects(void) { Tcl_MutexLock(&tableMutex); if (typeTableInitialized) { Tcl_DeleteHashTable(&typeTable); typeTableInitialized = 0; } Tcl_MutexUnlock(&tableMutex); } /* *---------------------------------------------------------------------- * * TclGetContLineTable -- * |
︙ | ︙ | |||
1234 1235 1236 1237 1238 1239 1240 | return Tcl_NewObj(); } #endif /* TCL_MEM_DEBUG */ /* *---------------------------------------------------------------------- * | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 | 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. |
︙ | ︙ | |||
1400 1401 1402 1403 1404 1405 1406 | /* * 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); | < | 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 | /* * 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. */ |
︙ | ︙ |
Changes to generic/tclParse.c.
︙ | ︙ | |||
1125 1126 1127 1128 1129 1130 1131 | * Command substitution. Call Tcl_ParseCommand recursively (and * repeatedly) to parse the nested command(s), then throw away the * parse information. */ src++; numBytes--; | | | | 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 | * 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); /* |
︙ | ︙ | |||
1158 1159 1160 1161 1162 1163 1164 | if (parsePtr->interp != NULL) { Tcl_SetResult(parsePtr->interp, "missing close-bracket", TCL_STATIC); } parsePtr->errorType = TCL_PARSE_MISSING_BRACKET; parsePtr->term = tokenPtr->start; parsePtr->incomplete = 1; | | | | 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 | if (parsePtr->interp != NULL) { Tcl_SetResult(parsePtr->interp, "missing close-bracket", TCL_STATIC); } 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; |
︙ | ︙ | |||
1522 1523 1524 1525 1526 1527 1528 | * 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; | | | | | | 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 | * 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 |
︙ | ︙ | |||
2004 2005 2006 2007 2008 2009 2010 | * 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 = | | | | 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 | * 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/tclProc.c.
︙ | ︙ | |||
218 219 220 221 222 223 224 | * 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) { | | | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | * 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 |
︙ | ︙ | |||
296 297 298 299 300 301 302 | * '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; } | | | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | * '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. * |
︙ | ︙ | |||
1092 1093 1094 1095 1096 1097 1098 | const char *final = NULL; /* * Build up desired argument list for Tcl_WrongNumArgs */ numArgs = framePtr->procPtr->numArgs; | < | | 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 | 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 { #ifdef AVOID_HACKS_FOR_ITCL desiredObjs[0] = framePtr->objv[skip-1]; #else |
︙ | ︙ | |||
1131 1132 1133 1134 1135 1136 1137 | Tcl_ResetResult(interp); Tcl_WrongNumArgs(interp, numArgs+1, desiredObjs, final); for (i=0 ; i<=numArgs ; i++) { Tcl_DecrRefCount(desiredObjs[i]); } | | | 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 | 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 -- |
︙ | ︙ | |||
1445 1446 1447 1448 1449 1450 1451 | /* * Create the "compiledLocals" array. Make sure it is large enough to hold * all the procedure's compiled local variables, including its formal * parameters. */ | | | 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 | /* * 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 |
︙ | ︙ | |||
1736 1737 1738 1739 1740 1741 1742 | CallFrame *freePtr; ByteCode *codePtr; result = InitArgsAndLocals(interp, procNameObj, skip); if (result != TCL_OK) { freePtr = iPtr->framePtr; Tcl_PopCallFrame(interp); /* Pop but do not free. */ | | | | 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 | 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; |
︙ | ︙ | |||
1908 1909 1910 1911 1912 1913 1914 | * 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. */ | | | | 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 | * 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; } /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
2512 2513 2514 2515 2516 2517 2518 | * 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) { | | | 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 | * 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'. |
︙ | ︙ | |||
2576 2577 2578 2579 2580 2581 2582 | /* * 'contextPtr' is going out of scope. Release the reference that * it's holding to the source file path */ Tcl_DecrRefCount(contextPtr->data.eval.path); } | | | 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 | /* * '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); } /* * Set the namespace for this lambda: given by objv[2] understood as a * global reference, or else global per default. */ |
︙ | ︙ | |||
2713 2714 2715 2716 2717 2718 2719 | nsObjPtr = lambdaPtr->internalRep.twoPtrValue.ptr2; result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr); if (result != TCL_OK) { return TCL_ERROR; } | | | 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 | 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! * |
︙ | ︙ | |||
2764 2765 2766 2767 2768 2769 2770 | { ApplyExtraData *extraPtr = data[0]; if (extraPtr->isRootEnsemble) { ((Interp *) interp)->ensembleRewrite.sourceObjs = NULL; } | | | 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 | { 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]; /* * Initialize an array that records the number of times a variable is * assigned to by the format string. We use this to detect if a variable * is multiply assigned or left unassigned. */ |
︙ | ︙ | |||
461 462 463 464 465 466 467 | value = nspace; if (xpgSize) { nspace = xpgSize; } else { nspace += 16; /* formerly STATIC_LIST_SIZE */ } | < | | 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | 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++; } |
︙ | ︙ | |||
505 506 507 508 509 510 511 | Tcl_SetResult(interp, "variable is not assigned by any conversion specifiers", TCL_STATIC); goto error; } } | | | | 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 | Tcl_SetResult(interp, "variable is not assigned by any conversion specifiers", TCL_STATIC); goto error; } } ckfree(nassign); return TCL_OK; badIndex: if (gotXpg) { Tcl_SetResult(interp, "\"%n$\" argument index out of range", TCL_STATIC); } else { Tcl_SetResult(interp, "different numbers of variable names and field specifiers", TCL_STATIC); } error: ckfree(nassign); return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Tcl_ScanObjCmd -- |
︙ | ︙ |
Changes to generic/tclStubInit.c.
︙ | ︙ | |||
53 54 55 56 57 58 59 | static const TclIntStubs tclIntStubs = { TCL_STUB_MAGIC, 0, 0, /* 0 */ 0, /* 1 */ 0, /* 2 */ | | | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 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 */ |
︙ | ︙ | |||
265 266 267 268 269 270 271 | TclpOpenFileChannel, /* 208 */ 0, /* 209 */ 0, /* 210 */ 0, /* 211 */ TclpFindExecutable, /* 212 */ TclGetObjNameOfExecutable, /* 213 */ TclSetObjNameOfExecutable, /* 214 */ | | | | 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 | 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 */ |
︙ | ︙ |
Changes to generic/tclTest.c.
︙ | ︙ | |||
6716 6717 6718 6719 6720 6721 6722 | Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { Interp *iPtr = (Interp *) interp; static ptrdiff_t *refDepth = NULL; ptrdiff_t depth; | | < < | | | 6716 6717 6718 6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731 6732 6733 6734 6735 6736 6737 6738 6739 6740 6741 6742 6743 6744 6745 6746 6747 6748 6749 6750 6751 | 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.
︙ | ︙ | |||
1646 1647 1648 1649 1650 1651 1652 | char *commandCopy; int traceCode; /* * Copy the command characters into a new string. */ | | | | 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 | 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 -- |
︙ | ︙ | |||
2233 2234 2235 2236 2237 2238 2239 | int i; /* * This is a bit messy because we have to emulate the old trace interface, * which uses strings for everything. */ | | | | 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 | 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; } /* *---------------------------------------------------------------------- * |
︙ | ︙ |
Changes to tests/nre.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 | # can now actually measure using testnrelevels. # if {[testConstraint testnrelevels]} { namespace eval testnre { namespace path ::tcl::mathop # | | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # 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.
︙ | ︙ | |||
20 21 22 23 24 25 26 | # 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 { # | | | | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | # 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 { |
︙ | ︙ | |||
62 63 64 65 66 67 68 | } tailcall a $i } } -body { a 0 } -cleanup { rename a {} | | | | | 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 | } 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} { |
︙ | ︙ | |||
120 121 122 123 124 125 126 | namespace import ::ns::a rename a b } -body { b 0 } -cleanup { rename b {} namespace delete ::ns | | | | 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 | 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} { |
︙ | ︙ | |||
163 164 165 166 167 168 169 | namespace ensemble create -command a -unknown d } -body { a b 0 } -cleanup { rename a {} rename c {} rename d {} | | | | 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 | 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.
︙ | ︙ | |||
300 301 302 303 304 305 306 | 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 \ | | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 | 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 |
︙ | ︙ | |||
441 442 443 444 445 446 447 | $(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 \ | < | 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | $(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 \ |
︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 | 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 | < < < | | 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 | 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 tclAlloc.o: $(GENERIC_DIR)/tclAlloc.c $(CC) -c $(CC_SWITCHES) $(GENERIC_DIR)/tclAlloc.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 |
︙ | ︙ | |||
1282 1283 1284 1285 1286 1287 1288 | 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 | < < < | 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 | 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.
︙ | ︙ | |||
448 449 450 451 452 453 454 | } /* * We need to allocate and convert this before the fork so it is properly * deallocated later */ | | | | 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | } /* * 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 /* |
︙ | ︙ | |||
520 521 522 523 524 525 526 | /* * Free the mem we used for the fork */ for (i = 0; i < argc; i++) { Tcl_DStringFree(&dsArray[i]); } | | | | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | /* * 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_AppendResult(interp, "couldn't fork child process: ", Tcl_PosixError(interp), NULL); goto error; } |
︙ | ︙ |
Changes to unix/tclUnixThrd.c.
︙ | ︙ | |||
672 673 674 675 676 677 678 | sprintf(tsdPtr->nabuf, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]); return tsdPtr->nabuf; #else return inet_ntoa(addr); #endif } | | < | 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 | 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; |
︙ | ︙ | |||
713 714 715 716 717 718 719 720 721 722 723 724 725 726 | allocMutex* lockPtr = (allocMutex*) mutex; if (!lockPtr) { return; } pthread_mutex_destroy(&lockPtr->plock); free(lockPtr); } void TclpFreeAllocCache( void *ptr) { if (ptr != NULL) { /* | > | 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 | allocMutex* lockPtr = (allocMutex*) mutex; if (!lockPtr) { return; } pthread_mutex_destroy(&lockPtr->plock); free(lockPtr); } void TclpFreeAllocCache( void *ptr) { if (ptr != NULL) { /* |
︙ | ︙ | |||
756 757 758 759 760 761 762 | void TclpSetAllocCache( void *arg) { pthread_setspecific(key, arg); } | | > | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | 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) { |
︙ | ︙ |