Tcl Source Code

Check-in [cc113f7cfe]
Login

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

Overview
Comment:Disable all the special case code in place to prevent allocation of a List struct for empty lists as much as possible. The value of this avoidance is not clear to me. Hoping it can be demonstrated (or refuted) with both variants side by side in the code history tree.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | dgp-list-simplify
Files: files | file ages | folders
SHA1: cc113f7cfe3d0410d4b24e6498b2209c3e0c8719
User & Date: dgp 2011-05-05 18:00:54
Context
2011-05-09
13:26
A different technique to more precisely identify the optimization case. check-in: 3b589e9ee8 user: dgp tags: dgp-list-simplify
2011-05-05
18:00
Disable all the special case code in place to prevent allocation of a List struct for empty lists as... check-in: cc113f7cfe user: dgp tags: dgp-list-simplify
16:53
Tolerate NULL interps more completely. check-in: e7adc1255d user: dgp tags: core-8-5-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclListObj.c.

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
    Tcl_Obj ***objvPtr)		/* Where to store the pointer to an array of
				 * pointers to the list's objects. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;

	/*
	 * Don't get the string version of a dictionary; that transformation
	 * is not lossy, but is expensive.
	 */

	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    *objcPtr = 0;
	    *objvPtr = NULL;
	    return TCL_OK;
	}

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }
    listRepPtr = ListRepPtr(listPtr);
    *objcPtr = listRepPtr->elemCount;







|















|







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
    Tcl_Obj ***objvPtr)		/* Where to store the pointer to an array of
				 * pointers to the list's objects. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;
#if 0
	/*
	 * Don't get the string version of a dictionary; that transformation
	 * is not lossy, but is expensive.
	 */

	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    *objcPtr = 0;
	    *objvPtr = NULL;
	    return TCL_OK;
	}
#endif
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }
    listRepPtr = ListRepPtr(listPtr);
    *objcPtr = listRepPtr->elemCount;
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
    int numElems, numRequired, newMax, newSize, i;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement");
    }
    if (listPtr->typePtr != &tclListType) {
	int result, length;

	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    Tcl_SetListObj(listPtr, 1, &objPtr);
	    return TCL_OK;
	}

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);







|









|







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
    int numElems, numRequired, newMax, newSize, i;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement");
    }
    if (listPtr->typePtr != &tclListType) {
	int result, length;
#if 0
	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    Tcl_SetListObj(listPtr, 1, &objPtr);
	    return TCL_OK;
	}
#endif
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);
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
    register int index,		/* Index of element to return. */
    Tcl_Obj **objPtrPtr)	/* The resulting Tcl_Obj* is stored here. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;

	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    *objPtrPtr = NULL;
	    return TCL_OK;
	}

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);







|









|







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
    register int index,		/* Index of element to return. */
    Tcl_Obj **objPtrPtr)	/* The resulting Tcl_Obj* is stored here. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;
#if 0
	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    *objPtrPtr = NULL;
	    return TCL_OK;
	}
#endif
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);
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
    register Tcl_Obj *listPtr,	/* List object whose #elements to return. */
    register int *intPtr)	/* The resulting int is stored here. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;

	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	    /*
	     * It's tempting to just report 2*length as the list length
	     * of this dict, but arguably that's false since the max sizes
	     * for dicts and lists are not the same, so some dicts don't
	     * actually convert to lists, and it's good to get that error
	     * back from the SetListFromAny() call below instead of a false
	     * indication we can treat the value as a list.  ([llength $val]
	     * often used as a "listiness" test)
	     */
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    *intPtr = 0;
	    return TCL_OK;
	}

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);







|


















|







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
    register Tcl_Obj *listPtr,	/* List object whose #elements to return. */
    register int *intPtr)	/* The resulting int is stored here. */
{
    register List *listRepPtr;

    if (listPtr->typePtr != &tclListType) {
	int result, length;
#if 0
	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	    /*
	     * It's tempting to just report 2*length as the list length
	     * of this dict, but arguably that's false since the max sizes
	     * for dicts and lists are not the same, so some dicts don't
	     * actually convert to lists, and it's good to get that error
	     * back from the SetListFromAny() call below instead of a false
	     * indication we can treat the value as a list.  ([llength $val]
	     * often used as a "listiness" test)
	     */
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    *intPtr = 0;
	    return TCL_OK;
	}
#endif
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);
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
    int numElems, numRequired, numAfterLast, start, i, j, isShared;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
    }
    if (listPtr->typePtr != &tclListType) {
	int length;

	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    if (objc) {
		Tcl_SetListObj(listPtr, objc, NULL);
	    } else {
		return TCL_OK;
	    }
	} else {

	    int result = SetListFromAny(interp, listPtr);

	    if (result != TCL_OK) {
		return result;
	    }

	}

    }

    /*
     * Note that when count == 0 and objc == 0, this routine is logically a
     * no-op, removing and adding no elements to the list. However, by flowing
     * through this routine anyway, we get the important side effect that the
     * resulting listPtr is a list in canoncial form. This is important.







|












>





>

>







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
    int numElems, numRequired, numAfterLast, start, i, j, isShared;

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
    }
    if (listPtr->typePtr != &tclListType) {
	int length;
#if 0
	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    if (objc) {
		Tcl_SetListObj(listPtr, objc, NULL);
	    } else {
		return TCL_OK;
	    }
	} else {
#endif
	    int result = SetListFromAny(interp, listPtr);

	    if (result != TCL_OK) {
		return result;
	    }
#if 0
	}
#endif
    }

    /*
     * Note that when count == 0 and objc == 0, this routine is logically a
     * no-op, removing and adding no elements to the list. However, by flowing
     * through this routine anyway, we get the important side effect that the
     * resulting listPtr is a list in canoncial form. This is important.
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
     */

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "TclListObjSetElement");
    }
    if (listPtr->typePtr != &tclListType) {
	int length, result;

	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("list index out of range", -1));
	    }
	    return TCL_ERROR;
	}

	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);







|












>







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
     */

    if (Tcl_IsShared(listPtr)) {
	Tcl_Panic("%s called with shared object", "TclListObjSetElement");
    }
    if (listPtr->typePtr != &tclListType) {
	int length, result;
#if 0
	if (listPtr->typePtr == &tclDictType) {
	    (void) Tcl_DictObjSize(NULL, listPtr, &length);
	} else {
	    (void) TclGetStringFromObj(listPtr, &length);
	}
	if (!length) {
	    if (interp != NULL) {
		Tcl_SetObjResult(interp,
			Tcl_NewStringObj("list index out of range", -1));
	    }
	    return TCL_ERROR;
	}
#endif
	result = SetListFromAny(interp, listPtr);
	if (result != TCL_OK) {
	    return result;
	}
    }

    listRepPtr = ListRepPtr(listPtr);