<body><div id="__MailbirdStyleContent" style="font-size: 10pt;font-family: Arial;color: #000000">
Hi Levente.<div><br></div><div>> <span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px">And when MC calculates the next update number, it doesn't take into </span><span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px">account what's in your package cache. It only looks up the remote </span><span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px">repositories and calculates the next number based on those.</span></div><div><span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px"><br></span></div><div><span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px">No worries. We should also consider the package cache in MCWorkingCopy >> #uniqueVersionName.</span></div><div><span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px"><br></span></div><div><span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px">Best,</span></div><div><span style="font-family: Arial, Helvetica, sans-serif;font-size: 13px">Marcel</span></div><div class="mb_sig"></div><blockquote class="history_container" type="cite" style="border-left-style:solid;border-width:1px; margin-top:20px; margin-left:0px;padding-left:10px;">
<p style="color: #AAAAAA; margin-top: 10px;">Am 16.06.2020 13:25:08 schrieb Levente Uzonyi <leves@caesar.elte.hu>:</p><div style="font-family:Arial,Helvetica,sans-serif">Hi All,<br><br>On Tue, 16 Jun 2020, commits@source.squeak.org wrote:<br><br>> Marcel Taeumel uploaded a new version of Collections to project The Trunk:<br>> http://source.squeak.org/trunk/Collections-mt.898.mcz<br>><br>> ==================== Summary ====================<br>><br>> Name: Collections-mt.898<br>> Author: mt<br>> Time: 16 June 2020, 8:55:38.416917 am<br>> UUID: 89207449-befb-f84f-83a0-ff0d727d40bc<br>> Ancestors: Collections-mt.896, Collections-ul.897<br>><br>> Merges ancestry. <br>><br>> Does somebody know where to find Collections-ul.896?<br><br>Well, that's not the actual Collections-ul.897 I intended to push to <br>the Inbox/Trunk. It contains my experiments with primitive 158, but does <br>not use the primitive yet (the pragmas are commented out).<br>Fortunately, the code is backwards compatible. It introduces minor <br>slowdown because it uses the fallback code (which is the "old" primitive) <br>instead of primitive 158 for string comparison.<br><br>The reason why I mistakenly uploaded it is because MC silently ignores <br>your commit when a file with the same name exists.<br>And when MC calculates the next update number, it doesn't take into <br>account what's in your package cache. It only looks up the remote <br>repositories and calculates the next number based on those.<br>After "saving" it also shows the window with your freshly "saved" <br>version open, so you can easily copy "it" to any repository you want to.<br><br>Since I already had Collections-ul.897 in my package cache, my version <br>with only the WeakIdentityDictionary and the removal of ByteArray >> <br>#atAllPut: got lost.<br><br>Back to primitive 158, there is a bug in either the jitted variant of the <br>primitive or the jit engine I was trying to track down. But I couldn't <br>find out how to set a breakpoint in jitted code with gdb, nor did I want <br>to build the bochs plugin, so I simply gave up.<br>If someone has the time and tools ready to debug it, here's a recipe to <br>trigger the error:<br>1. Make sure your image has been saved as the bug might cause corruption.<br>2. Uncomment the primitive pragmas in String >> #compareWith: and String <br>>> #compareWith:collated:<br>3. Run ClosureCompilerTest >> #testDecompiledDoitMethodTempNames which <br>will fail: the primitive will return a non-zero value even though the two <br>compared strings are equal.<br>4. Don't save your image, it might have been corrupted.<br><br>I couldn't write a script to reproduce the bug, hence the testcase.<br>The bug is so hard to trigger, you won't notice string comparison being <br>broken: your image will keep running.<br>When the testcase fails, the primitive's return value suggests that the <br>jitted code probably sees one of the strings shorter than it actually is.<br>The non-jitted version of the primitive works fine.<br><br><br>Levente<br><br>><br>> =============== Diff against Collections-mt.896 ===============<br>><br>> Item was removed:<br>> - ----- Method: ByteArray>>atAllPut: (in category 'accessing') -----<br>> - atAllPut: value<br>> - "Fill the receiver with the given value"<br>> - <br>> - <primitive: 145=""><br>> - super atAllPut: value!<br>><br>> Item was changed:<br>> ----- Method: String>>< (in="" category="" 'comparing')=""><br>> <><br>> "Answer whether the receiver sorts before aString.<br>> The collation order is simple ascii (with case differences)."<br>> <br>> + ^(self compareWith: aString) <><br>> - ^ (self compare: self with: aString collated: AsciiOrder) = 1!<br>><br>> Item was changed:<br>> ----- Method: String>><= (in="" category="" 'comparing')=""></=><br>> <=></=><br>> "Answer whether the receiver sorts before or equal to aString.<br>> The collation order is simple ascii (with case differences)."<br>> <br>> + ^(self compareWith: aString) <=></=><br>> - ^ (self compare: self with: aString collated: AsciiOrder) <=></=><br>><br>> Item was changed:<br>> ----- Method: String>>= (in category 'comparing') -----<br>> = aString<br>> "Answer whether the receiver sorts equally as aString.<br>> The collation order is simple ascii (with case differences)."<br>><br>> self == aString ifTrue: [ ^true ].<br>> aString isString ifFalse: [ ^false ].<br>> self size = aString size ifFalse: [ ^false ].<br>> + ^ (self compareWith: aString) = 0!<br>> - ^ (self compare: self with: aString collated: AsciiOrder) = 2!<br>><br>> Item was changed:<br>> ----- Method: String>>> (in category 'comparing') -----<br>> > aString<br>> "Answer whether the receiver sorts after aString.<br>> The collation order is simple ascii (with case differences)."<br>> <br>> + ^(self compareWith: aString) > 0!<br>> - ^ (self compare: self with: aString collated: AsciiOrder) = 3!<br>><br>> Item was changed:<br>> ----- Method: String>>>= (in category 'comparing') -----<br>> >= aString<br>> "Answer whether the receiver sorts after or equal to aString.<br>> The collation order is simple ascii (with case differences)."<br>> <br>> + ^(self compareWith: aString) >= 0!<br>> - ^ (self compare: self with: aString collated: AsciiOrder) >= 2!<br>><br>> Item was changed:<br>> ----- Method: String>>compare:caseSensitive: (in category 'comparing') -----<br>> compare: aString caseSensitive: aBool<br>> "Answer a comparison code telling how the receiver sorts relative to aString:<br>> 1 - before<br>> 2 - equal<br>> 3 - after.<br>> "<br>> | map |<br>> map := aBool ifTrue:[CaseSensitiveOrder] ifFalse:[CaseInsensitiveOrder].<br>> + ^(self compareWith: aString collated: map) + 2!<br>> - ^self compare: self with: aString collated: map!<br>><br>> Item was added:<br>> + ----- Method: String>>compareWith: (in category 'comparing') -----<br>> + compareWith: aString<br>> + <br>> + "<primitive: 158="">"<br>> + ^(self compare: self with: aString collated: AsciiOrder) - 2!<br>><br>> Item was added:<br>> + ----- Method: String>>compareWith:collated: (in category 'comparing') -----<br>> + compareWith: aString collated: collation<br>> + <br>> + "<primitive: 158="">"<br>> + ^(self compare: self with: aString collated: collation) - 2!<br>><br>> Item was removed:<br>> - ----- Method: WeakIdentityDictionary>>cleanupIndex: (in category 'private') -----<br>> - cleanupIndex: anInteger<br>> - array at: anInteger put: vacuum.<br>> - tally := tally - 1.<br>> - self fixCollisionsFrom: anInteger.!<br>><br>> Item was changed:<br>> ----- Method: WeakIdentityDictionary>>fixCollisionsFrom: (in category 'private') -----<br>> fixCollisionsFrom: start<br>> "The element at start has been removed and replaced by vacuum.<br>> This method moves forward from there, relocating any entries<br>> that had been placed below due to collisions with this one."<br>><br>> | element index |<br>> index := start.<br>> [ (element := array at: (index := index \\ array size + 1)) == vacuum ] whileFalse: [<br>> element<br>> ifNil:<br>> [ "The binding at this slot was reclaimed - finish the cleanup"<br>> array at: index put: vacuum.<br>> tally := tally - 1 ]<br>> ifNotNil:<br>> [| newIndex |<br>> + (newIndex := self scanFor: element key) = index ifFalse: [<br>> - (newIndex := self scanWithoutGarbagingFor: element key) = index ifFalse: [<br>> array<br>> at: newIndex put: element;<br>> at: index put: vacuum ] ] ]!<br>><br>> Item was changed:<br>> ----- Method: WeakIdentityDictionary>>removeKey:ifAbsent: (in category 'removing') -----<br>> removeKey: key ifAbsent: aBlock<br>> "Remove key (and its associated value) from the receiver. If key is not in<br>> the receiver, answer the result of evaluating aBlock. Otherwise, answer<br>> the value externally named by key."<br>><br>> | index association |<br>> index := self scanFor: key.<br>> (association := (array at: index)) == vacuum ifTrue: [ ^aBlock value ].<br>> + array at: index put: vacuum.<br>> + tally := tally - 1.<br>> + self fixCollisionsFrom: index.<br>> - self cleanupIndex: index.<br>> ^association value!<br>><br>> Item was changed:<br>> ----- Method: WeakIdentityDictionary>>scanFor: (in category 'private') -----<br>> scanFor: anObject<br>> "Scan the array for the first slot containing either<br>> - a vacuum object indicating an empty slot<br>> - or a binding whose key matches anObject.<br>> + Answer the index of that slot or raise an error if no slot is found which should never happen."<br>> - Answer the index of that slot or raise an error if no slot is found.<br>> - When garbage collected slots are encountered, perform a clean-up."<br>> <br>> + | index start size |<br>> + index := start := anObject scaledIdentityHash \\ (size := array size) + 1.<br>> + [ <br>> + (array at: index) ifNotNil: [ :element |<br>> + (element == vacuum or: [ element key == anObject ])<br>> + ifTrue: [ ^index ] ].<br>> + (index := index \\ size + 1) = start ] whileFalse.<br>> - | index start rescan | <br>> - [<br>> - rescan := false.<br>> - index := start := anObject scaledIdentityHash \\ array size + 1.<br>> - [ <br>> - (array at: index) <br>> - ifNil:<br>> - ["Object at this slot has been garbage collected.<br>> - A rescan is necessary because fixing collisions<br>> - might have moved the target before current index."<br>> - self cleanupIndex: index.<br>> - rescan := true]<br>> - ifNotNil:<br>> - [:element | (element == vacuum or: [ element key == anObject ])<br>> - ifTrue: [ ^index ].<br>> - (index := index \\ array size + 1) = start ] ] whileFalse.<br>> - rescan ] whileTrue.<br>> self errorNoFreeSpace!<br>><br>> Item was changed:<br>> ----- Method: WeakIdentityDictionary>>scanForEmptySlotFor: (in category 'private') -----<br>> scanForEmptySlotFor: anObject<br>> + "Scan the array for the first empty slot marked by vacuum object or nil.<br>> + Answer the index of that slot or raise an error if no slot is found, which should never happen."<br>> - "Scan the array for the first empty slot marked by vacuum object.<br>> - Answer the index of that slot or raise an error if no slot is found.<br>> - Ignore the slots that have been garbage collected (those containing nil)."<br>><br>> | index start |<br>> index := start := anObject scaledIdentityHash \\ array size + 1.<br>> [ <br>> + | element |<br>> + ((element := array at: index) == vacuum or: [ element == nil ]) ifTrue: [ ^index ].<br>> - (array at: index) <br>> - ifNotNil:<br>> - [:element | element == vacuum ifTrue: [ ^index ] ].<br>> (index := index \\ array size + 1) = start ] whileFalse.<br>> self errorNoFreeSpace!<br>><br>> Item was removed:<br>> - ----- Method: WeakIdentityDictionary>>scanWithoutGarbagingFor: (in category 'private') -----<br>> - scanWithoutGarbagingFor: anObject<br>> - "Scan the array for the first slot containing either<br>> - - a vacuum object indicating an empty slot<br>> - - or a binding whose key matches anObject.<br>> - Answer the index of that slot or raise an error if no slot is found.<br>> - Ignore the slots that have been garbage collected (those containing nil)"<br>> - <br>> - | index start | <br>> - index := start := anObject scaledIdentityHash \\ array size + 1.<br>> - [ <br>> - (array at: index) <br>> - ifNotNil:<br>> - [:element | (element == vacuum or: [ element key == anObject ])<br>> - ifTrue: [ ^index ] ].<br>> - (index := index \\ array size + 1) = start ] whileFalse.<br>> - self errorNoFreeSpace!<br><br></primitive:></primitive:></primitive:></div></blockquote>
</div></body>