WeakArray.st
branchjv
changeset 18630 a74d669db937
parent 18608 7d521f25267c
parent 18627 1bd1d3f92fcc
child 19559 d35a89d5c0ec
equal deleted inserted replaced
18617:fbfd2d411738 18630:a74d669db937
       
     1 "{ Encoding: utf8 }"
       
     2 
     1 "
     3 "
     2  COPYRIGHT (c) 1991 by Claus Gittinger
     4  COPYRIGHT (c) 1991 by Claus Gittinger
     3 	      All Rights Reserved
     5 	      All Rights Reserved
     4 
     6 
     5  This software is furnished under a license and may be used
     7  This software is furnished under a license and may be used
   505 !WeakArray methodsFor:'enumerating'!
   507 !WeakArray methodsFor:'enumerating'!
   506 
   508 
   507 do:aBlock
   509 do:aBlock
   508     "evaluate the argument, aBlock for each element in the collection.
   510     "evaluate the argument, aBlock for each element in the collection.
   509      - reimplemented for IGC readBarrier.
   511      - reimplemented for IGC readBarrier.
   510      You dont have to understand this."
   512      You don't have to understand this."
   511 
   513 
   512     |element|
   514     |element|
   513 
   515 
   514 %{
   516 %{
   515     REGISTER int index;
   517     REGISTER int index;
   519     index = __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
   521     index = __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
   520     nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
   522     nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
   521 
   523 
   522     if (__isBlockLike(aBlock)
   524     if (__isBlockLike(aBlock)
   523      && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) {
   525      && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) {
   524 	{
   526         {
   525 	    /*
   527             /*
   526 	     * the most common case: a static compiled block, with home on the stack ...
   528              * the most common case: a static compiled block, with home on the stack ...
   527 	     */
   529              */
   528 	    REGISTER OBJFUNC codeVal;
   530             REGISTER OBJFUNC codeVal;
   529 
   531 
   530 	    if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
   532             if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
   531 	     && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC)))) {
   533              && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC)))) {
   532 
   534 
   533 #ifdef NEW_BLOCK_CALL
   535 #ifdef NEW_BLOCK_CALL
   534 #               define BLOCK_ARG        aBlock
   536 #               define BLOCK_ARG        aBlock
   535 #else
   537 #else
   536 #               define BLOCK_ARG        rHome
   538 #               define BLOCK_ARG        rHome
   537 		REGISTER OBJ rHome;
   539                 REGISTER OBJ rHome;
   538 
   540 
   539 		rHome = __BlockInstPtr(aBlock)->b_home;
   541                 rHome = __BlockInstPtr(aBlock)->b_home;
   540 		if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
   542                 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
   541 #endif
   543 #endif
   542 		{
   544                 {
   543 		    for (; index < nIndex; index++) {
   545                     for (; index < nIndex; index++) {
   544 			if (InterruptPending != nil) __interruptL(@line);
   546                         if (InterruptPending != nil) __interruptL(@line);
   545 
   547 
   546 			element = __InstPtr(self)->i_instvars[index];
   548                         element = __InstPtr(self)->i_instvars[index];
   547 			if (__isNonNilObject(element)) {
   549                         if (__isNonNilObject(element)) {
   548 			    element = __WEAK_READ__(self, element);
   550                             element = __WEAK_READ__(self, element);
   549 #ifdef WEAK_DEBUG
   551 #ifdef WEAK_DEBUG
   550 			    if (! __ISVALIDOBJECT(element)) {
   552                             if (! __ISVALIDOBJECT(element)) {
   551 				fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   553                                 fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   552 				__dumpObject__(element, __LINE__);
   554                                 __dumpObject__(element, __LINE__);
   553 				element = nil;
   555                                 element = nil;
   554 			    }
   556                             }
   555 #endif
   557 #endif
   556 			}
   558                         }
   557 			(*codeVal)(BLOCK_ARG, element);
   559                         (*codeVal)(BLOCK_ARG, element);
   558 		    }
   560                     }
   559 		    RETURN (self);
   561                     RETURN (self);
   560 		}
   562                 }
   561 	    }
   563             }
   562 	}
   564         }
   563 
   565 
   564 	/*
   566         /*
   565 	 * sorry, must check code-pointer in the loop
   567          * sorry, must check code-pointer in the loop
   566 	 * it could be recompiled or flushed
   568          * it could be recompiled or flushed
   567 	 */
   569          */
   568 #       undef BLOCK_ARG
   570 #       undef BLOCK_ARG
   569 #ifdef NEW_BLOCK_CALL
   571 #ifdef NEW_BLOCK_CALL
   570 #       define BLOCK_ARG        aBlock
   572 #       define BLOCK_ARG        aBlock
   571 #       define IBLOCK_ARG       nil
   573 #       define IBLOCK_ARG       nil
   572 #else
   574 #else
   573 #       define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
   575 #       define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
   574 #       define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
   576 #       define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
   575 #endif
   577 #endif
   576 
   578 
   577 	for (; index < nIndex; index++) {
   579         for (; index < nIndex; index++) {
   578 	    REGISTER OBJFUNC codeVal;
   580             REGISTER OBJFUNC codeVal;
   579 
   581 
   580 	    if (InterruptPending != nil) __interruptL(@line);
   582             if (InterruptPending != nil) __interruptL(@line);
   581 
   583 
   582 	    element = __InstPtr(self)->i_instvars[index];
   584             element = __InstPtr(self)->i_instvars[index];
   583 	    if (__isNonNilObject(element)) {
   585             if (__isNonNilObject(element)) {
   584 		element = __WEAK_READ__(self, element);
   586                 element = __WEAK_READ__(self, element);
   585 #ifdef WEAK_DEBUG
   587 #ifdef WEAK_DEBUG
   586 		if (! __ISVALIDOBJECT(element)) {
   588                 if (! __ISVALIDOBJECT(element)) {
   587 		    fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   589                     fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   588 		    __dumpObject__(element, __LINE__);
   590                     __dumpObject__(element, __LINE__);
   589 		    element = nil;
   591                     element = nil;
   590 		}
   592                 }
   591 #endif
   593 #endif
   592 	    }
   594             }
   593 	    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
   595             if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
   594 		(*codeVal)(BLOCK_ARG, element);
   596                 (*codeVal)(BLOCK_ARG, element);
   595 	    } else {
   597             } else {
   596 		if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
   598                 if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
   597 		    /*
   599                     /*
   598 		     * arg is a compiled block with bytecode -
   600                      * arg is a compiled block with bytecode -
   599 		     * directly call interpreter without going through Block>>value
   601                      * directly call interpreter without going through Block>>value
   600 		     */
   602                      */
   601 #ifdef PASS_ARG_POINTER
   603 #ifdef PASS_ARG_POINTER
   602 		    __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &element);
   604                     __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &element);
   603 #else
   605 #else
   604 		    __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, element);
   606                     __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, element);
   605 #endif
   607 #endif
   606 		} else {
   608                 } else {
   607 		    /*
   609                     /*
   608 		     * arg is something else - call it with #value
   610                      * arg is something else - call it with #value
   609 		     */
   611                      */
   610 		    (*val.ilc_func)(aBlock, @symbol(value:), nil, &val, element);
   612                     (*val.ilc_func)(aBlock, @symbol(value:), nil, &val, element);
   611 		}
   613                 }
   612 	    }
   614             }
   613 	}
   615         }
   614 	RETURN (self);
   616         RETURN (self);
   615 
   617 
   616 #       undef BLOCK_ARG
   618 #       undef BLOCK_ARG
   617 #       undef IBLOCK_ARG
   619 #       undef IBLOCK_ARG
   618 
   620 
   619     }
   621     }
   620 
   622 
   621     /*
   623     /*
   622      * not a block - send it #value:
   624      * not a block - send it #value:
   623      */
   625      */
   624     for (; index < nIndex; index++) {
   626     for (; index < nIndex; index++) {
   625 	if (InterruptPending != nil) __interruptL(@line);
   627         if (InterruptPending != nil) __interruptL(@line);
   626 
   628 
   627 	element = __InstPtr(self)->i_instvars[index];
   629         element = __InstPtr(self)->i_instvars[index];
   628 	if (__isNonNilObject(element)) {
   630         if (__isNonNilObject(element)) {
   629 	    element = __WEAK_READ__(self, element);
   631             element = __WEAK_READ__(self, element);
   630 #ifdef WEAK_DEBUG
   632 #ifdef WEAK_DEBUG
   631 	    if (! __ISVALIDOBJECT(element)) {
   633             if (! __ISVALIDOBJECT(element)) {
   632 		fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   634                 fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   633 		__dumpObject__(element, __LINE__);
   635                 __dumpObject__(element, __LINE__);
   634 		element = nil;
   636                 element = nil;
   635 	    }
   637             }
   636 #endif
   638 #endif
   637 	}
   639         }
   638 	(*val.ilc_func)(aBlock,
   640         (*val.ilc_func)(aBlock,
   639 			    @symbol(value:),
   641                             @symbol(value:),
   640 			    nil, &val,
   642                             nil, &val,
   641 			    element);
   643                             element);
   642     }
   644     }
   643     RETURN (self);
   645     RETURN (self);
   644 %}.
   646 %}.
   645     ^ super do:[:each |
   647     ^ super do:[:each |
   646 	each ~~ nil ifTrue:[aBlock value:each]
   648         each ~~ nil ifTrue:[aBlock value:each]
   647       ]
   649       ]
       
   650 
       
   651     "Modified: / 23-07-2015 / 15:35:24 / cg"
   648 !
   652 !
   649 
   653 
   650 forAllDeadIndicesDo:aBlock
   654 forAllDeadIndicesDo:aBlock
   651     "evaluate the argument, aBlock for all indices where elements have been
   655     "evaluate the argument, aBlock for all indices where elements have been
   652      replaced by zero (due to a collected object).
   656      replaced by zero (due to a collected object).
   845 	each ~~ nil ifTrue:[aBlock value:each]
   849 	each ~~ nil ifTrue:[aBlock value:each]
   846       ]
   850       ]
   847 !
   851 !
   848 
   852 
   849 validElementsDo:aBlock
   853 validElementsDo:aBlock
   850     "evaluate the argument, aBlock for each non-nil/non-zero element"
   854     "evaluate the argument, aBlock for each non-nil/non-evacuated element"
   851 
   855 
   852     |element|
   856     |element|
   853 %{
   857 %{
   854     REGISTER int index;
   858     REGISTER int index;
   855     int nIndex;
   859     int nIndex;
   857 
   861 
   858     index = __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
   862     index = __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars);
   859     nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
   863     nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
   860     if (__isBlockLike(aBlock)
   864     if (__isBlockLike(aBlock)
   861      && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) {
   865      && (__BlockInstPtr(aBlock)->b_nargs == __mkSmallInteger(1))) {
   862 	{
   866         {
   863 	    /*
   867             /*
   864 	     * the most common case: a static compiled block, with home on the stack ...
   868              * the most common case: a static compiled block, with home on the stack ...
   865 	     */
   869              */
   866 	    REGISTER OBJFUNC codeVal;
   870             REGISTER OBJFUNC codeVal;
   867 
   871 
   868 	    if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
   872             if (((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
   869 	     && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC)))) {
   873              && (! ((INT)(__BlockInstPtr(aBlock)->b_flags) & __MASKSMALLINT(F_DYNAMIC)))) {
   870 
   874 
   871 #ifdef NEW_BLOCK_CALL
   875 #ifdef NEW_BLOCK_CALL
   872 #               define BLOCK_ARG        aBlock
   876 #               define BLOCK_ARG        aBlock
   873 #else
   877 #else
   874 #               define BLOCK_ARG        rHome
   878 #               define BLOCK_ARG        rHome
   875 		REGISTER OBJ rHome;
   879                 REGISTER OBJ rHome;
   876 
   880 
   877 		rHome = __BlockInstPtr(aBlock)->b_home;
   881                 rHome = __BlockInstPtr(aBlock)->b_home;
   878 		if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
   882                 if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
   879 #endif
   883 #endif
   880 		{
   884                 {
   881 		    for (; index < nIndex; index++) {
   885                     for (; index < nIndex; index++) {
   882 			element = __InstPtr(self)->i_instvars[index];
   886                         element = __InstPtr(self)->i_instvars[index];
   883 			if (element && (element != __mkSmallInteger(0))) {
   887                         if (__isNonNilObject(element)) {
   884 			    if (InterruptPending != nil) {
   888                             if (InterruptPending != nil) {
   885 				__interruptL(@line);
   889                                 __interruptL(@line);
   886 				element = __InstPtr(self)->i_instvars[index];
   890                                 element = __InstPtr(self)->i_instvars[index];
   887 			    }
   891                             }
   888 
   892 
   889 			    if (__isNonNilObject(element)) {
   893                             if (__isNonNilObject(element)) {
   890 				element = __WEAK_READ__(self, element);
   894                                 element = __WEAK_READ__(self, element);
   891 #ifdef WEAK_DEBUG
   895 #ifdef WEAK_DEBUG
   892 				if (! __ISVALIDOBJECT(element)) {
   896                                 if (! __ISVALIDOBJECT(element)) {
   893 				    fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   897                                     fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   894 				    __dumpObject__(element, __LINE__);
   898                                     __dumpObject__(element, __LINE__);
   895 				    element = nil;
   899                                     element = nil;
   896 				}
   900                                 }
   897 #endif
   901 #endif
   898 			    }
   902                                 if (__isNonNilObject(element)) {
   899 			    if (element && (element != __mkSmallInteger(0))) {
   903                                     (*codeVal)(BLOCK_ARG, element);
   900 				(*codeVal)(BLOCK_ARG, element);
   904                                 }
   901 			    }
   905                             }
   902 			}
   906                         }
   903 		    }
   907                     }
   904 		    RETURN (self);
   908                     RETURN (self);
   905 		}
   909                 }
   906 	    }
   910             }
   907 	}
   911         }
   908 
   912 
   909 	/*
   913         /*
   910 	 * sorry, must check code-pointer in the loop
   914          * sorry, must check code-pointer in the loop
   911 	 * it could be recompiled or flushed
   915          * it could be recompiled or flushed
   912 	 */
   916          */
   913 #       undef BLOCK_ARG
   917 #       undef BLOCK_ARG
   914 #ifdef NEW_BLOCK_CALL
   918 #ifdef NEW_BLOCK_CALL
   915 #       define BLOCK_ARG        aBlock
   919 #       define BLOCK_ARG        aBlock
   916 #       define IBLOCK_ARG       nil
   920 #       define IBLOCK_ARG       nil
   917 #else
   921 #else
   918 #       define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
   922 #       define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
   919 #       define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
   923 #       define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
   920 #endif
   924 #endif
   921 
   925 
   922 	for (; index < nIndex; index++) {
   926         for (; index < nIndex; index++) {
   923 	    REGISTER OBJFUNC codeVal;
   927             REGISTER OBJFUNC codeVal;
   924 
   928 
   925 	    element = __InstPtr(self)->i_instvars[index];
   929             element = __InstPtr(self)->i_instvars[index];
   926 	    if (element && (element != __mkSmallInteger(0))) {
   930             if (__isNonNilObject(element)) {
   927 		if (InterruptPending != nil) {
   931                 if (InterruptPending != nil) {
   928 		    __interruptL(@line);
   932                     __interruptL(@line);
   929 		    element = __InstPtr(self)->i_instvars[index];
   933                     element = __InstPtr(self)->i_instvars[index];
   930 		}
   934                 }
   931 		if (__isNonNilObject(element)) {
   935                 if (__isNonNilObject(element)) {
   932 		    element = __WEAK_READ__(self, element);
   936                     element = __WEAK_READ__(self, element);
   933 #ifdef WEAK_DEBUG
   937 #ifdef WEAK_DEBUG
   934 		    if (! __ISVALIDOBJECT(element)) {
   938                     if (! __ISVALIDOBJECT(element)) {
   935 			fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   939                         fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   936 			__dumpObject__(element, __LINE__);
   940                         __dumpObject__(element, __LINE__);
   937 			element = nil;
   941                         element = nil;
   938 		    }
   942                     }
   939 #endif
   943 #endif
   940 		}
   944                     if (__isNonNilObject(element)) {
   941 		if (element && (element != __mkSmallInteger(0))) {
   945                         if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
   942 		    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
   946                             (*codeVal)(BLOCK_ARG, element);
   943 			(*codeVal)(BLOCK_ARG, element);
   947                         } else {
   944 		    } else {
   948                             if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
   945 			if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
   949                                 /*
   946 			    /*
   950                                  * arg is a compiled block with bytecode -
   947 			     * arg is a compiled block with bytecode -
   951                                  * directly call interpreter without going through Block>>value
   948 			     * directly call interpreter without going through Block>>value
   952                                  */
   949 			     */
       
   950 #ifdef PASS_ARG_POINTER
   953 #ifdef PASS_ARG_POINTER
   951 			    __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &element);
   954                                 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &element);
   952 #else
   955 #else
   953 			    __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, element);
   956                                 __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, element);
   954 #endif
   957 #endif
   955 			} else {
   958                             } else {
   956 			    /*
   959                                 /*
   957 			     * arg is something else - call it with #value
   960                                  * arg is something else - call it with #value
   958 			     */
   961                                  */
   959 			    (*val.ilc_func)(aBlock, @symbol(value:), nil, &val, element);
   962                                 (*val.ilc_func)(aBlock, @symbol(value:), nil, &val, element);
   960 			}
   963                             }
   961 		    }
   964                         }
   962 		}
   965                     }
   963 	    }
   966                 }
   964 	}
   967             }
   965 	RETURN (self);
   968         }
       
   969         RETURN (self);
   966 
   970 
   967 #       undef BLOCK_ARG
   971 #       undef BLOCK_ARG
   968 #       undef IBLOCK_ARG
   972 #       undef IBLOCK_ARG
   969     }
   973     }
   970 
   974 
   971     /*
   975     /*
   972      * not a block - send it #value:
   976      * not a block - send it #value:
   973      */
   977      */
   974     for (; index < nIndex; index++) {
   978     for (; index < nIndex; index++) {
   975 	element = __InstPtr(self)->i_instvars[index];
   979         element = __InstPtr(self)->i_instvars[index];
   976 	if (element && (element != __mkSmallInteger(0))) {
   980         if (__isNonNilObject(element)) {
   977 	    if (InterruptPending != nil) {
   981             if (InterruptPending != nil) {
   978 		__interruptL(@line);
   982                 __interruptL(@line);
   979 		element = __InstPtr(self)->i_instvars[index];
   983                 element = __InstPtr(self)->i_instvars[index];
   980 	    }
   984             }
   981 	    if (__isNonNilObject(element)) {
   985             if (__isNonNilObject(element)) {
   982 		element = __WEAK_READ__(self, element);
   986                 element = __WEAK_READ__(self, element);
   983 #ifdef WEAK_DEBUG
   987 #ifdef WEAK_DEBUG
   984 		if (! __ISVALIDOBJECT(element)) {
   988                 if (! __ISVALIDOBJECT(element)) {
   985 		    fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   989                     fprintf(stderr, "****** OOPS - invalid Weak-Read\n");
   986 		    __dumpObject__(element, __LINE__);
   990                     __dumpObject__(element, __LINE__);
   987 		    element = nil;
   991                     element = nil;
   988 		}
   992                 }
   989 #endif
   993 #endif
   990 	    }
   994                 if (__isNonNilObject(element)) {
   991 	    if (element && (element != __mkSmallInteger(0))) {
   995                     (*val.ilc_func)(aBlock,
   992 		(*val.ilc_func)(aBlock,
   996                                     @symbol(value:),
   993 				    @symbol(value:),
   997                                     nil, &val,
   994 				    nil, &val,
   998                                     element);
   995 				    element);
   999                 }
   996 	    }
  1000             }
   997 	}
  1001         }
   998     }
  1002     }
   999     RETURN (self);
  1003     RETURN (self);
  1000 %}.
  1004 %}.
  1001     ^ super do:[:each |
  1005     ^ super do:[:each |
  1002 	(each ~~ nil and:[each ~~ 0]) ifTrue:[aBlock value:each]
  1006         (each ~~ nil and:[each class ~~ SmallInteger]) ifTrue:[aBlock value:each]
  1003       ]
  1007       ]
  1004 
  1008 
       
  1009     "Modified: / 23-07-2015 / 15:32:44 / cg"
  1005 ! !
  1010 ! !
  1006 
  1011 
  1007 !WeakArray methodsFor:'notification'!
  1012 !WeakArray methodsFor:'notification'!
  1008 
  1013 
  1009 lostPointer
  1014 lostPointer