<div dir="ltr">Hi Levente,<div class="gmail_extra"><br><div class="gmail_quote">On Sat, Dec 3, 2016 at 10:33 AM, Levente Uzonyi <span dir="ltr"><<a href="mailto:leves@caesar.elte.hu" target="_blank">leves@caesar.elte.hu</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Eliot,<br>
<br>
Does this mean that using a temporary has become quicker than sending #size on Spur VMs?<br>
On non-Spur Cog the latter used to take less time, which was why I didn't use another temporary variable.</blockquote><div><br></div><div>There is /no way/ a single instruction to read a temporary is slower than the tens of instructions needed to derive the size of an Array.  There must have been something wrong with your measurements.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="HOEnZb"><font color="#888888"><br>
<br>
Levente</font></span><div class="HOEnZb"><div class="h5"><br>
<br>
On Sat, 3 Dec 2016, <a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a> wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Eliot Miranda uploaded a new version of Collections to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Collections-eem.724.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/trunk<wbr>/Collections-eem.724.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Collections-eem.724<br>
Author: eem<br>
Time: 3 December 2016, 9:30:36.13835 am<br>
UUID: 83cb6b85-2b47-4c92-a953-e3787a<wbr>19d53b<br>
Ancestors: Collections-eem.723<br>
<br>
The various scanFor: and scanForEmptySlotFor: implementations only need to access the size of their array once.<br>
<br>
Fix protocol for an #=<br>
<br>
=============== Diff against Collections-eem.723 ===============<br>
<br>
Item was changed:<br>
 ----- Method: Dictionary>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject hash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject hash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [ anObject = element key ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: HashedCollection>>scanForEmpty<wbr>SlotFor: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject hash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject hash \\ array size + 1.<br>
        [<br>
                (array at: index) ifNil: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: IdentityDictionary>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size | +  index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start | -       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [ element key == anObject ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: IdentityDictionary>>scanForEmp<wbr>tySlotFor: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                (array at: index) ifNil: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: IdentitySet>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [ element enclosedSetElement == anObject ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: IdentitySet>>scanForEmptySlotF<wbr>or: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                (array at: index) ifNil: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: KeyedIdentitySet>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [ (keyBlock value: element enclosedSetElement) == anObject ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: KeyedIdentitySet>>scanForEmpty<wbr>SlotFor: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                (array at: index) ifNil: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: KeyedSet>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject hash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject hash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [ (keyBlock value: element enclosedSetElement) = anObject ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: PluggableDictionary>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
-       | index start |<br>
        index := start := (hashBlock<br>
                ifNil: [ anObject hash ]<br>
+               ifNotNil: [ hashBlock value: anObject ]) \\ (size := array size) + 1.<br>
-               ifNotNil: [ hashBlock value: anObject ]) \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [<br>
                        equalBlock<br>
                                ifNil: [ element key = anObject ]<br>
                                ifNotNil: [ equalBlock value: element key value: anObject ] ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: PluggableDictionary>>scanForEm<wbr>ptySlotFor: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
-       | index start |<br>
        index := start := (hashBlock<br>
                ifNil: [ anObject hash ]<br>
+               ifNotNil: [ hashBlock value: anObject ]) \\ (size := array size) + 1.<br>
-               ifNotNil: [ hashBlock value: anObject ]) \\ array size + 1.<br>
        [<br>
                (array at: index) ifNil: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
+ ----- Method: PluggableSet>>= (in category 'comparing') -----<br>
- ----- Method: PluggableSet>>= (in category 'as yet unclassified') -----<br>
 = anObject<br>
        "Two sets are equal if<br>
         (a) they are the same 'kind' of thing.<br>
         (b) they have the same set of keys.<br>
         (c) for each (common) key, they have the same value"<br>
<br>
        self == anObject ifTrue: [ ^true ].<br>
        self species == anObject species ifFalse: [ ^false ].<br>
        hashBlock = anObject hashBlock ifFalse: [ ^false ].<br>
        equalBlock = anObject equalBlock ifFalse: [ ^false ].<br>
        self size = anObject size ifFalse: [ ^false ].<br>
        ^self allSatisfy: [ :each | anObject includes: each ]!<br>
<br>
Item was changed:<br>
 ----- Method: PluggableSet>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
-       | index start |<br>
        index := start := (hashBlock<br>
                ifNil: [ anObject hash ]<br>
+               ifNotNil: [ hashBlock value: anObject ]) \\ (size := array size) + 1.<br>
-               ifNotNil: [ hashBlock value: anObject ]) \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [<br>
                        equalBlock<br>
                                ifNil: [ element enclosedSetElement = anObject ]<br>
                                ifNotNil: [ equalBlock value: element enclosedSetElement value: anObject ] ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: PluggableSet>>scanForEmptySlot<wbr>For: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
-       | index start |<br>
        index := start := (hashBlock<br>
                ifNil: [ anObject hash ]<br>
+               ifNotNil: [ hashBlock value: anObject ]) \\ (size := array size) + 1.<br>
-               ifNotNil: [ hashBlock value: anObject ]) \\ array size + 1.<br>
        [<br>
                (array at: index) ifNil: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: Set>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject hash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject hash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [ anObject = element enclosedSetElement ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: WeakIdentityKeyDictionary>>sca<wbr>nFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == nil or: [ element key == anObject ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: WeakIdentityKeyDictionary>>sca<wbr>nForEmptySlotFor: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject scaledIdentityHash \\ array size + 1.<br>
        [<br>
                (array at: index) ifNil: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: WeakSet>>scanFor: (in category 'private') -----<br>
 scanFor: anObject<br>
        "Scan the key array for the first slot containing either flag (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or raise an error if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject hash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject hash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == flag or: [ element enclosedSetElement = anObject ])<br>
                        ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
<br>
Item was changed:<br>
 ----- Method: WeakSet>>scanForEmptySlotFor: (in category 'private') -----<br>
 scanForEmptySlotFor: anObject<br>
        "Scan the key array for the first slot containing an empty slot (indicated by flag or a nil). Answer the index of that slot. This method will be overridden in various subclasses that have different interpretations for matching elements."<br>
<br>
+       | index start size |<br>
+       index := start := anObject hash \\ (size := array size) + 1.<br>
-       | index start |<br>
-       index := start := anObject hash \\ array size + 1.<br>
        [<br>
                | element |<br>
                ((element := array at: index) == flag or: [ element == nil ]) ifTrue: [ ^index ].<br>
+               (index := index \\ size + 1) = start ] whileFalse.<br>
-               (index := index \\ array size + 1) = start ] whileFalse.<br>
        self errorNoFreeSpace!<br>
</blockquote>
<br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div>
</div></div>