<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Florin,</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 31, 2020 at 7:30 AM Florin Mateoc <<a href="mailto:florin.mateoc@gmail.com">florin.mateoc@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"> <div dir="ltr"><div>Hi,</div><div><br></div><div>I had some unexpected results while looking at some primitives in the system, and I wanted to ask if they are expected/intentional:</div><div><br></div><div>1. 'ab' instVarAt: 1    =>    97    (and 'ab' instVarAt: 2    =>    98)</div><div>    I would have thought that #instVarAt: has pointer granularity, so I am curious if the observed behavior is an accident or intentional (and maybe even used somewhere)</div></div></blockquote><div><br></div><div>Since a ByteString's indexed inst vars are bytes this is as expected.  What would you have expected?  Smalltalk-80 has always behaved this way.</div><div><br></div><div>There is a little more to this story.  In Spur, instVarAt:[put:] is actually implemented by a new primitive slotAt:[put:].  Why?</div><div><br></div><div>Spur has a lazy become scheme which means that become is implemented by morphing objects into forwarders to copies of objects.  So if a become: b, then the system allocated copies of a and b, say a' and b', and morphs a into a forwarder to b', and b into a forwarder to a'.  Forwarders are followed lazily, either when a message is sent to a forwarder or when a primitive encounters a forwarder somewhere within the objects it consumes.  When a primitive fails the VM scans the input arguments to a depth specific to the primitive and if it finds references to forwarders, fixes them up to point to the targets of the forwarders, and retries the primitive.  The old implementation of instVarAt:[put:] had primities that failed for indexes beyond the named instance variables, and handled indexed inst vars in primitive failure code:</div><div><br></div><div>Object>>instVarAt: index </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">     </span>"Primitive. Answer a fixed variable in an object. The numbering of the </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">  </span>variables corresponds to the named instance variables. Fail if the index </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">     </span>is not an Integer or is not the index of a fixed variable. Essential. See </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">    </span>Object documentation whatIsAPrimitive."</div><div><br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">  </span><primitive: 73></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">  </span>"Access beyond fixed variables."</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">     </span>^self basicAt: index - self class instSize</div><div><br></div><div><span style="white-space:pre">Chris Muller uses instVarAt:[put:] on large arrays in his Magma database.  He was noticing a severe slow down in Magma on Spur because instVarAt:[put:] was failing, the entire Array was being scanned for forwarders, and then the primitive actually failed and the basicAt:put: ran.</span></div><div><span style="white-space:pre"><br></span></div><div><span style="white-space:pre">The solution to this was to replace primitives 73 & 74 with the new slotAt:[put:] primitives 173 & 174.  Now the primitive does not fail, and performance is restored (and much improved because Spur is faster).</span></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><br></div><div>2. | o | o := Object new. (WeakArray with: o) pointsTo: o    =>    true</div><div>    I thought the main use case for #pointsTo: was to find hard references (e.g. for chasing memory leaks). The current behavior actually makes that use case a little more difficult to implement, since you have to special case weak references. When would one be interested in finding weak references?</div></div></blockquote><div><br></div><div>I can't answer this.  The design decision was made a whole ago.  It would be easy to add pointsStronglyTo: and implement that correctly.  Remember that references from named inst vars of weak objects are strong references. Only references from indexed inst vars of weak objects are weak.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>3. The comment and the primitive used in #ensure: and #ifCurtailed: are the same, but the primitive failure code is different - the one for #ifCurtailed seems buggy, it never evaluates the argument<br></div></div></blockquote><div><br></div><div>Ah, this is a neat hack.  The primitive numbers are not actually primitives,  These primitives always fail, and the blocks are evaluated with the valueNoContextSwitch send in the method body.  Instead the primitive numbers are used by the VM to mark the activations of ensure: and ifCurtailed: as unwind-protect frames.  This was one of Andreas' neatest hacks (am I right in thinking this was Andreas Raab's scheme?), in that he added unwind-protect without needing e.g. another status bit in the CompiledMethod header.  He could just use the primitive number that was already there.</div><div><br></div><div>As far as ifCurtailed: not evaluating its argument, that is its semantics.  ensure: always evaluates its argument, after evaluating its body.  ifCurtailed: only evaluates its argument if a non-local return or exception return is taken and the normal return path is not taken.  See Context>>#resume:through: which runs the ensure: & ifCurtailed: blocks.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div></div><div>None of the above are critical, but I am curious about them.<br></div><div>Thank you in advance for any clarifications,</div><div><br></div><div>Florin<br></div></div>
</blockquote></div><br clear="all"><div>HTH</div><div dir="ltr" class="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></div>