<div dir="ltr">Hi Clément, Hi Tim F,<div><br></div><div>    forgive me.  I managed to find the energy to fix the duff's device code.  I did so by a) making sayer that the image you supplied worked for the case of the 11 slot SqNumberParser that gets instantiated many times, and b) by using the following to look at all the cases:</div><div><br></div><div><div>| classes method |</div><div>classes := (9 to: 16) collect: [:n| Smalltalk allClasses detect: [:c| c instSize = n]].</div><div>method := AssemblerMethod new.</div><div>method</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">    </span>importMethodClass: #Object;</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">    </span>selector: #instantiate;</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>signFlag: true;</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">        </span>numArgs: 0.</div><div>classes do: [:c| method literal: c].</div><div>classes do: [:c| method pushConstant: c; callInlinePrimitive: 1011].</div><div>method</div><div><span class="gmail-Apple-tab-span" style="white-space:pre"> </span>pushConsArrayWithElements: 8;</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">  </span>methodReturnTop.</div><div>SistaCogit </div><div><span class="gmail-Apple-tab-span" style="white-space:pre">    </span>genAndDis: method assemble</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">     </span>options: #(ObjectMemory Spur32BitCoMemoryManager</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                               </span>MULTIPLEBYTECODESETS true</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                              </span>SistaVM true</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                           </span>bytecodeTableInitializer initializeBytecodeTableForSqueakV3PlusClosuresSistaV1Hybrid)</div></div><div><br></div><div>Clément, you should be able to run the method and get an Array of classes  here's the code its generating.  I especially like that register allocation is working nicely with the results only being spilled once needed to do another allocation.</div><div><br></div><div>The first case is a 9 slot object, making 1 1/8 trips through the 8-element loop</div><div><div>00001861: movl %ds:0x8001c=#freeStart, %esi<span class="gmail-Apple-tab-span" style="white-space:pre">                                       allocate the object to %esi</span></div><div>00001867: movl $0x01001b9f, %eax</div><div>0000186c: movl %eax, %ds:(%esi)<span class="gmail-Apple-tab-span" style="white-space:pre">                                                      store least significant half of header</span></div><div>0000186e: movl $0x09000000, %eax</div><div>00001873: movl %eax, %ds:0x4(%esi)<span class="gmail-Apple-tab-span" style="white-space:pre">                                                        store most significant half of header</span></div><div>00001876: leal %ds:0x30(%esi), %eax</div><div>00001879: movl %eax, %ds:0x8001c=#freeStart<span class="gmail-Apple-tab-span" style="white-space:pre">                                     update freeStart to point to the start of the next object</span></div><div>0000187e: movl $0x00100000=nil, %edi</div><div>00001883: subl $0x00000014, %esi<span class="gmail-Apple-tab-span" style="white-space:pre">                                                   offset result for entry into the last instruction of loop</span></div><div>00001886: subl $0x00000004, %eax</div><div>00001889: jmp .+0x00000014 (0x0000189f=instantiate@9F)</div><div>0000188b: movl %edi, %ds:(%esi)</div><div>0000188d: movl %edi, %ds:0x4(%esi)</div><div>00001890: movl %edi, %ds:0x8(%esi)</div><div>00001893: movl %edi, %ds:0xc(%esi)</div><div>00001896: movl %edi, %ds:0x10(%esi)</div><div>00001899: movl %edi, %ds:0x14(%esi)</div><div>0000189c: movl %edi, %ds:0x18(%esi)</div><div>=>00189f: movl %edi, %ds:0x1c(%esi)</div><div>000018a2: addl $0x00000020, %esi<span style="white-space:pre">                                                     increment result for next iteration of loop</span></div><div>000018a5: cmpl %eax, %esi</div><div>000018a7: jb .+0xffffffe2 (0x0000188b=instantiate@8B)<span style="white-space:pre">                      jump to beginning of loop if not done</span></div><div>000018a9: subl $0x0000002c, %esi<span style="white-space:pre">                                                 offset updated result to point back to start of object</span></div><div><br></div><div>000018ac: movl %ds:0x8001c=#freeStart, %ebx</div><div>000018b2: movl $0x01001ba3, %eax</div><div>000018b7: movl %eax, %ds:(%ebx)</div><div>000018b9: movl $0x0a000000, %eax</div><div>000018be: movl %eax, %ds:0x4(%ebx)</div><div>000018c1: leal %ds:0x30(%ebx), %eax</div><div>000018c4: movl %eax, %ds:0x8001c=#freeStart</div><div>000018c9: movl $0x00100000=nil, %edi</div><div>000018ce: subl $0x00000010, %ebx</div><div>000018d1: jmp .+0x00000011 (0x000018e4=instantiate@E4)</div><div>000018d3: movl %edi, %ds:(%ebx)</div><div>000018d5: movl %edi, %ds:0x4(%ebx)</div><div>000018d8: movl %edi, %ds:0x8(%ebx)</div><div>000018db: movl %edi, %ds:0xc(%ebx)</div><div>000018de: movl %edi, %ds:0x10(%ebx)</div><div>000018e1: movl %edi, %ds:0x14(%ebx)</div><div>000018e4: movl %edi, %ds:0x18(%ebx)</div><div>000018e7: movl %edi, %ds:0x1c(%ebx)</div><div>000018ea: addl $0x00000020, %ebx</div><div>000018ed: cmpl %eax, %ebx</div><div>000018ef: jb .+0xffffffe2 (0x000018d3=instantiate@D3)</div><div>000018f1: subl $0x00000030, %ebx</div><div><br></div><div>000018f4: movl %ds:0x8001c=#freeStart, %ecx</div><div>000018fa: movl $0x01001b9e, %eax</div><div>000018ff: movl %eax, %ds:(%ecx)</div><div>00001901: movl $0x0b000000, %eax</div><div>00001906: movl %eax, %ds:0x4(%ecx)</div><div>00001909: leal %ds:0x38(%ecx), %eax</div><div>0000190c: movl %eax, %ds:0x8001c=#freeStart</div><div>00001911: movl $0x00100000=nil, %edi</div><div>00001916: subl $0x0000000c, %ecx</div><div>00001919: subl $0x00000004, %eax</div><div>0000191c: jmp .+0x0000000e (0x0000192c=instantiate@12C)</div><div>0000191e: movl %edi, %ds:(%ecx)</div><div>00001920: movl %edi, %ds:0x4(%ecx)</div><div>00001923: movl %edi, %ds:0x8(%ecx)</div><div>00001926: movl %edi, %ds:0xc(%ecx)</div><div>00001929: movl %edi, %ds:0x10(%ecx)</div><div>0000192c: movl %edi, %ds:0x14(%ecx)</div><div>0000192f: movl %edi, %ds:0x18(%ecx)</div><div>00001932: movl %edi, %ds:0x1c(%ecx)</div><div>00001935: addl $0x00000020, %ecx</div><div>00001938: cmpl %eax, %ecx</div><div>0000193a: jb .+0xffffffe2 (0x0000191e=instantiate@11E)</div><div>0000193c: subl $0x00000034, %ecx</div><div><br></div><div>0000193f: movl %ds:0x8001c=#freeStart, %edx</div><div>00001945: movl $0x0100179a, %eax</div><div>0000194a: movl %eax, %ds:(%edx)</div><div>0000194c: movl $0x0c000000, %eax</div><div>00001951: movl %eax, %ds:0x4(%edx)</div><div>00001954: leal %ds:0x38(%edx), %eax</div><div>00001957: movl %eax, %ds:0x8001c=#freeStart</div><div>0000195c: movl $0x00100000=nil, %edi</div><div>00001961: subl $0x00000008, %edx</div><div>00001964: jmp .+0x0000000b (0x00001971=instantiate@171)</div><div>00001966: movl %edi, %ds:(%edx)</div><div>00001968: movl %edi, %ds:0x4(%edx)</div><div>0000196b: movl %edi, %ds:0x8(%edx)</div><div>0000196e: movl %edi, %ds:0xc(%edx)</div><div>00001971: movl %edi, %ds:0x10(%edx)</div><div>00001974: movl %edi, %ds:0x14(%edx)</div><div>00001977: movl %edi, %ds:0x18(%edx)</div><div>0000197a: movl %edi, %ds:0x1c(%edx)</div><div>0000197d: addl $0x00000020, %edx</div><div>00001980: cmpl %eax, %edx</div><div>00001982: jb .+0xffffffe2 (0x00001966=instantiate@166)</div><div>00001984: subl $0x00000038, %edx</div><div>00001987: pushl %esi</div><div><br></div><div>00001988: movl %ds:0x8001c=#freeStart, %esi</div><div>0000198e: movl $0x0100155c, %eax</div><div>00001993: movl %eax, %ds:(%esi)</div><div>00001995: movl $0x0d000000, %eax</div><div>0000199a: movl %eax, %ds:0x4(%esi)</div><div>0000199d: leal %ds:0x40(%esi), %eax</div><div>000019a0: movl %eax, %ds:0x8001c=#freeStart</div><div>000019a5: movl $0x00100000=nil, %edi</div><div>000019aa: subl $0x00000004, %esi</div><div>000019ad: subl $0x00000004, %eax</div><div>000019b0: jmp .+0x00000008 (0x000019ba=instantiate@1BA)</div><div>000019b2: movl %edi, %ds:(%esi)</div><div>000019b4: movl %edi, %ds:0x4(%esi)</div><div>000019b7: movl %edi, %ds:0x8(%esi)</div><div>000019ba: movl %edi, %ds:0xc(%esi)</div><div>000019bd: movl %edi, %ds:0x10(%esi)</div><div>000019c0: movl %edi, %ds:0x14(%esi)</div><div>000019c3: movl %edi, %ds:0x18(%esi)</div><div>000019c6: movl %edi, %ds:0x1c(%esi)</div><div>000019c9: addl $0x00000020, %esi</div><div>000019cc: cmpl %eax, %esi</div><div>000019ce: jb .+0xffffffe2 (0x000019b2=instantiate@1B2)</div><div>000019d0: subl $0x0000003c, %esi</div><div>000019d3: pushl %ebx</div><div><br></div><div>000019d4: movl %ds:0x8001c=#freeStart, %ebx</div><div>000019da: movl $0x01000668, %eax</div><div>000019df: movl %eax, %ds:(%ebx)</div><div>000019e1: movl $0x0e000000, %eax</div><div>000019e6: movl %eax, %ds:0x4(%ebx)</div><div>000019e9: leal %ds:0x40(%ebx), %eax</div><div>000019ec: movl %eax, %ds:0x8001c=#freeStart</div><div>000019f1: movl $0x00100000=nil, %edi</div><div>000019f6: jmp .+0x00000005 (0x000019fd=instantiate@1FD)</div><div>000019f8: movl %edi, %ds:(%ebx)</div><div>000019fa: movl %edi, %ds:0x4(%ebx)</div><div>000019fd: movl %edi, %ds:0x8(%ebx)</div><div>00001a00: movl %edi, %ds:0xc(%ebx)</div><div>00001a03: movl %edi, %ds:0x10(%ebx)</div><div>00001a06: movl %edi, %ds:0x14(%ebx)</div><div>00001a09: movl %edi, %ds:0x18(%ebx)</div><div>00001a0c: movl %edi, %ds:0x1c(%ebx)</div><div>00001a0f: addl $0x00000020, %ebx</div><div>00001a12: cmpl %eax, %ebx</div><div>00001a14: jb .+0xffffffe2 (0x000019f8=instantiate@1F8)</div><div>00001a16: subl $0x00000040, %ebx</div><div>00001a19: pushl %ecx</div><div><br></div><div>00001a1a: movl %ds:0x8001c=#freeStart, %ecx</div><div>00001a20: movl $0x01001bd3, %eax</div><div>00001a25: movl %eax, %ds:(%ecx)</div><div>00001a27: movl $0x0f000000, %eax</div><div>00001a2c: movl %eax, %ds:0x4(%ecx)</div><div>00001a2f: leal %ds:0x48(%ecx), %eax</div><div>00001a32: movl %eax, %ds:0x8001c=#freeStart</div><div>00001a37: movl $0x00100000=nil, %edi</div><div>00001a3c: addl $0x00000004, %ecx</div><div>00001a3f: subl $0x00000004, %eax</div><div>00001a42: jmp .+0x00000002 (0x00001a46=instantiate@246)</div><div>00001a44: movl %edi, %ds:(%ecx)</div><div>00001a46: movl %edi, %ds:0x4(%ecx)</div><div>00001a49: movl %edi, %ds:0x8(%ecx)</div><div>00001a4c: movl %edi, %ds:0xc(%ecx)</div><div>00001a4f: movl %edi, %ds:0x10(%ecx)</div><div>00001a52: movl %edi, %ds:0x14(%ecx)</div><div>00001a55: movl %edi, %ds:0x18(%ecx)</div><div>00001a58: movl %edi, %ds:0x1c(%ecx)</div><div>00001a5b: addl $0x00000020, %ecx</div><div>00001a5e: cmpl %eax, %ecx</div><div>00001a60: jb .+0xffffffe2 (0x00001a44=instantiate@244)</div><div>00001a62: subl $0x00000044, %ecx</div><div>00001a65: pushl %edx</div><div><br></div><div>The final case is a 16 slot object, making 2 trips through the 8-element loop<br></div><div>00001a66: movl %ds:0x8001c=#freeStart, %edx</div><div>00001a6c: movl $0x01001bd0, %eax</div><div>00001a71: movl %eax, %ds:(%edx)</div><div>00001a73: movl $0x10000000, %eax</div><div>00001a78: movl %eax, %ds:0x4(%edx)</div><div>00001a7b: leal %ds:0x48(%edx), %eax</div><div>00001a7e: movl %eax, %ds:0x8001c=#freeStart</div><div>00001a83: movl $0x00100000=nil, %edi</div><div>00001a88: addl $0x00000008, %edx<span style="white-space:pre">                                   offset result to skip header</span></div><div>00001a8b: movl %edi, %ds:(%edx)</div><div>00001a8d: movl %edi, %ds:0x4(%edx)</div><div>00001a90: movl %edi, %ds:0x8(%edx)</div><div>00001a93: movl %edi, %ds:0xc(%edx)</div><div>00001a96: movl %edi, %ds:0x10(%edx)</div><div>00001a99: movl %edi, %ds:0x14(%edx)</div><div>00001a9c: movl %edi, %ds:0x18(%edx)</div><div>00001a9f: movl %edi, %ds:0x1c(%edx)</div><div>00001aa2: addl $0x00000020, %edx</div><div>00001aa5: cmpl %eax, %edx</div><div>00001aa7: jb .+0xffffffe2 (0x00001a8b=instantiate@28B)</div><div>00001aa9: subl $0x00000048, %edx<span style="white-space:pre">                                     offset updated result to point back to start of object</span></div><div><br></div><div>And this pushes the remaining results and cones an 8 element array with the results</div><div>00001aac: pushl %esi</div><div>00001aad: pushl %ebx</div><div>00001aae: pushl %ecx</div><div>00001aaf: pushl %edx</div><div>00001ab0: movl %ds:0x8001c=#freeStart, %edx</div><div>00001ab6: movl $0x02000033, %eax</div><div>00001abb: movl %eax, %ds:(%edx)</div><div>00001abd: movl $0x08000000, %eax</div><div>00001ac2: movl %eax, %ds:0x4(%edx)</div><div>00001ac5: leal %ds:0x28(%edx), %eax</div><div>00001ac8: movl %eax, %ds:0x8001c=#freeStart</div><div>00001acd: cmpl $0x00060000='scavengeThreshold', %eax</div><div>00001ad2: jb .+0x00000005 (0x00001ad9=instantiate@2D9)</div><div>00001ad4: call .+0xfffff1df (0x00000cb8=ceScheduleScavengeTrampoline)</div><div>IsRelativeCall:</div><div>00001ad9: popl %eax</div><div>00001ada: movl %eax, %ds:0x24(%edx)</div><div>00001add: popl %eax</div><div>00001ade: movl %eax, %ds:0x20(%edx)</div><div>00001ae1: popl %eax</div><div>00001ae2: movl %eax, %ds:0x1c(%edx)</div><div>00001ae5: popl %eax</div><div>00001ae6: movl %eax, %ds:0x18(%edx)</div><div>00001ae9: popl %eax</div><div>00001aea: movl %eax, %ds:0x14(%edx)</div><div>00001aed: popl %eax</div><div>00001aee: movl %eax, %ds:0x10(%edx)</div><div>00001af1: popl %eax</div><div>00001af2: movl %eax, %ds:0xc(%edx)</div><div>00001af5: popl %eax</div><div>00001af6: movl %eax, %ds:0x8(%edx)</div><div><br></div><div>00001af9: movl %ebp, %esp</div><div>00001afb: popl %ebp</div><div>00001afc: ret $0x0004</div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jun 9, 2017 at 8:11 PM,  <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br>Eliot Miranda uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2240.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/<wbr>VMMaker/VMMaker.oscog-eem.<wbr>2240.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-eem.2240<br>
Author: eem<br>
Time: 9 June 2017, 8:10:37.386604 pm<br>
UUID: b7a78631-1fbc-42e2-a0e2-<wbr>0a950a5db06e<br>
Ancestors: VMMaker.oscog-eem.2239<br>
<br>
Fix (I think) genGetInstanceOfFixedClass:<wbr>into:initializingIf: for duff's device instance creation, and restore its use in genUnaryInlinePrimitive:.<br>
<br>
Clément, I think I got it right.  I tested the generated code worked correctly for the 11 slot case and then did in-image compilation for a set of classes with slot sizes 9 thorugh 32 and the code looks good.  I hope you don't mind.<br>
<br>
=============== Diff against VMMaker.oscog-eem.2239 ===============<br>
<br>
Item was changed:<br>
+ ----- Method: CogObjectRepresentationForSpur<wbr>>>genGetInstanceOf:into:<wbr>initializingIf: (in category 'inline primitive support') -----<br>
- ----- Method: CogObjectRepresentationForSpur<wbr>>>genGetInstanceOf:into:<wbr>initializingIf: (in category 'bytecode generator support') -----<br>
  genGetInstanceOf: classObj into: destReg initializingIf: initializeInstance<br>
        "Create an instance of classObj and assign it to destReg, initializing the instance<br>
         if initializeInstance is true with nil or 0 as appropriate This is for inline primitives.<br>
         Assume there is sufficient space in new space to complete the operation.<br>
         Answer zero on success."<br>
        | classIndex classFormat header slots |<br>
        ((objectMemory isNonImmediate: classObj)<br>
         and: [(coInterpreter objCouldBeClassObj: classObj)<br>
         and: [(classIndex := objectMemory rawHashBitsOf: classObj) ~= 0<br>
         and: [(objectMemory isFixedSizePointerFormat: (objectMemory instSpecOfClassFormat: (classFormat := objectMemory formatOfClass: classObj)))<br>
         and: [(slots := objectMemory fixedFieldsOfClassFormat: classFormat) < objectMemory numSlotsMask]]]]) ifFalse:<br>
                [^UnimplementedOperation].<br>
<br>
        self deny: destReg = TempReg.<br>
<br>
        header := objectMemory<br>
                                        headerForSlots: slots<br>
                                        format: (objectMemory instSpecOfClassFormat: classFormat)<br>
                                        classIndex: classIndex.<br>
<br>
        cogit MoveAw: objectMemory freeStartAddress R: destReg.<br>
        self genStoreHeader: header intoNewInstance: destReg using: TempReg.<br>
        cogit<br>
                LoadEffectiveAddressMw: (objectMemory smallObjectBytesForSlots: slots) r: destReg R: TempReg;<br>
                MoveR: TempReg Aw: objectMemory freeStartAddress.<br>
        (initializeInstance and: [slots > 0]) ifTrue:<br>
                [cogit genMoveConstant: objectMemory nilObject R: TempReg.<br>
                 0 to: slots - 1 do:<br>
                        [:i| cogit MoveR: TempReg<br>
                                        Mw: i * objectMemory wordSize + objectMemory baseHeaderSize<br>
                                        r: destReg]].<br>
        ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: CogObjectRepresentationForSpur<wbr>>>genGetInstanceOfFixedClass:<wbr>into:initializingIf: (in category 'inline primitive support') -----<br>
- ----- Method: CogObjectRepresentationForSpur<wbr>>>genGetInstanceOfFixedClass:<wbr>into:initializingIf: (in category 'bytecode generator support') -----<br>
  genGetInstanceOfFixedClass: classObj into: destReg initializingIf: initializeInstance<br>
        "Create an instance of classObj and assign it to destReg, initializing the instance<br>
         if initializeInstance is true with nil or 0 as appropriate This is for inline primitives.<br>
         Assume there is sufficient space in new space to complete the operation.<br>
         Answer zero on success."<br>
        | classIndex classFormat header slots branch constReg inst loop delta loopCount slotsPerIteration |<br>
        ((objectMemory isNonImmediate: classObj)<br>
         and: [(coInterpreter objCouldBeClassObj: classObj)<br>
         and: [(classIndex := objectMemory rawHashBitsOf: classObj) ~= 0<br>
         and: [(objectMemory isFixedSizePointerFormat: (objectMemory instSpecOfClassFormat: (classFormat := objectMemory formatOfClass: classObj)))<br>
         and: [(slots := objectMemory fixedFieldsOfClassFormat: classFormat) < objectMemory numSlotsMask]]]]) ifFalse:<br>
                [^UnimplementedOperation].<br>
<br>
        header := objectMemory<br>
                                        headerForSlots: slots<br>
                                        format: (objectMemory instSpecOfClassFormat: classFormat)<br>
                                        classIndex: classIndex.<br>
<br>
        cogit MoveAw: objectMemory freeStartAddress R: destReg.<br>
        self genStoreHeader: header intoNewInstance: destReg using: TempReg.<br>
        cogit<br>
                LoadEffectiveAddressMw: (objectMemory smallObjectBytesForSlots: slots) r: destReg R: TempReg;<br>
                MoveR: TempReg Aw: objectMemory freeStartAddress.<br>
        (initializeInstance and: [slots > 0]) ifFalse:<br>
                [^0].<br>
+       slots <= (slotsPerIteration := 8) ifTrue: "slotsPerIteration must be even; see cogit SubCq: objectMemory bytesPerOop R: TempReg below"<br>
-       slots <= (slotsPerIteration := 8) ifTrue: "slotsPerIteration must be a power of two. see bitAnd: below"<br>
                [cogit genMoveConstant: objectMemory nilObject R: TempReg.<br>
                 0 to: slots - 1 do:<br>
                        [:i| cogit MoveR: TempReg<br>
                                        Mw: i * objectMemory wordSize + objectMemory baseHeaderSize<br>
                                        r: destReg].<br>
                ^0].<br>
+       "self halt: 'genGetInstanceOfFixedClass:..<wbr>. ', slots asInteger."<br>
        constReg := cogit allocateRegNotConflictingWith: destReg.<br>
        cogit genMoveConstant: objectMemory nilObject R: constReg.<br>
<br>
        slots \\ slotsPerIteration ~= 0<br>
+               ifTrue: "delta maps the offset at the loop entryPoint onto destReg + objectMemory baseHeaderSize"<br>
+                       [delta := (slotsPerIteration - (slots \\ slotsPerIteration) * objectMemory bytesPerOop) - objectMemory baseHeaderSize.<br>
+                        delta > 0 ifTrue: [cogit SubCq: delta R: destReg].<br>
+                        delta < 0 ifTrue: [cogit AddCq: delta negated R: destReg].<br>
+                        "now delta maps (loopCount * slotsPerIteration * objectMemory bytesPerOop) + objectMemory baseHeaderSize - delta to the start of the object"<br>
+                        delta := delta + objectMemory baseHeaderSize.<br>
+                        (objectMemory bytesPerOop < objectMemory baseHeaderSize<br>
+                         and: [slots \\ 2 = 1]) ifTrue: "if end of loop is not at start of next object, adjust loop limit in TempReg to point to last field filled."<br>
+                               [cogit SubCq: objectMemory bytesPerOop R: TempReg].<br>
-               ifTrue:<br>
-                       [delta := objectMemory baseHeaderSize - ((slotsPerIteration - (slots \\ slotsPerIteration) bitAnd: slotsPerIteration - 1) * objectMemory bytesPerOop).<br>
-                        delta ~= 0 ifTrue:<br>
-                               [cogit AddCq: delta R: destReg].<br>
                         branch := cogit Jump: 0]<br>
                ifFalse:<br>
+                       [delta := 0.<br>
-                       [delta := objectMemory baseHeaderSize.<br>
                         cogit AddCq: objectMemory baseHeaderSize R: destReg].<br>
+       "loopCount is number of times through the increment of destReg."<br>
        loopCount := slots + slotsPerIteration - 1 // slotsPerIteration.<br>
        self assert: loopCount > 1.<br>
        loop := cogit Label.<br>
        0 to: 7 do:<br>
                [:i|<br>
                inst := cogit MoveR: constReg Mw: i * objectMemory bytesPerOop r: destReg.<br>
                slotsPerIteration - (slots \\ slotsPerIteration) = i ifTrue:<br>
                        [branch jmpTarget: inst]].<br>
-       "N.B. We get away with comparing against TempReg, which points to the start of the next<br>
-        object, not necessarily immediately after the last slot, because if the size is a multiple of 8,<br>
-        TempReg will point after the last slot, and if the size is not a multiple of 8 then the add of<br>
-        slotsPerIteration * objectMemory bytesPerOop will put destReg beyond TempReg any way."<br>
        cogit<br>
                AddCq: slotsPerIteration * objectMemory bytesPerOop R: destReg;<br>
                CmpR: TempReg R: destReg;<br>
                JumpBelow: loop;<br>
+               SubCq: (loopCount * slotsPerIteration * objectMemory bytesPerOop) + objectMemory baseHeaderSize - delta R: destReg.<br>
-               SubCq: delta + (loopCount * slotsPerIteration * objectMemory bytesPerOop) R: destReg.<br>
        ^0!<br>
<br>
Item was changed:<br>
+ ----- Method: CogObjectRepresentationForSpur<wbr>>>genSetGCNeeded (in category 'inline primitive support') -----<br>
- ----- Method: CogObjectRepresentationForSpur<wbr>>>genSetGCNeeded (in category 'bytecode generator support') -----<br>
  genSetGCNeeded<br>
        <inline: true><br>
        cogit<br>
                MoveCq: 1 R: TempReg;<br>
                MoveR: TempReg Aw: coInterpreter needGCFlagAddress!<br>
<br>
Item was changed:<br>
  ----- Method: SistaCogit>><wbr>genUnaryInlinePrimitive: (in category 'inline primitive generators') -----<br>
  genUnaryInlinePrimitive: prim<br>
        "Unary inline primitives."<br>
        "SistaV1: 248           11111000        iiiiiiii                mjjjjjjj                Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.<br>
         See EncoderForSistaV1's class comment and StackInterpreter>>#<wbr>unaryInlinePrimitive:"<br>
        | rcvrReg resultReg |<br>
        rcvrReg := self allocateRegForStackEntryAt: 0.<br>
        resultReg := self allocateRegNotConflictingWith: (self registerMaskFor: rcvrReg).<br>
        prim<br>
                caseOf: {<br>
                                        "00             unchecked class"<br>
                        [1] ->  "01             unchecked pointer numSlots"<br>
                                [self ssTop popToReg: rcvrReg.<br>
                                 self ssPop: 1.<br>
                                 objectRepresentation<br>
                                        genGetNumSlotsOf: rcvrReg into: resultReg;<br>
                                        genConvertIntegerToSmallIntege<wbr>rInReg: resultReg].<br>
                                        "02             unchecked pointer basicSize"<br>
                        [3] ->  "03             unchecked byte numBytes"<br>
                                [self ssTop popToReg: rcvrReg.<br>
                                 self ssPop: 1.<br>
                                 objectRepresentation<br>
                                        genGetNumBytesOf: rcvrReg into: resultReg;<br>
                                        genConvertIntegerToSmallIntege<wbr>rInReg: resultReg].<br>
                                        "04             unchecked short16Type format numShorts"<br>
                                        "05             unchecked word32Type format numWords"<br>
                                        "06             unchecked doubleWord64Type format numDoubleWords"<br>
                        [11] -> "11             unchecked fixed pointer basicNew"<br>
                                [self ssTop type ~= SSConstant ifTrue:<br>
                                        [^EncounteredUnknownBytecode].<br>
                                 (objectRepresentation<br>
+                                       genGetInstanceOfFixedClass: self ssTop constant<br>
-                                       genGetInstanceOf: self ssTop constant<br>
                                                into: resultReg<br>
+                                                       initializingIf: self extBSpecifiesInitializeInstanc<wbr>e) ~= 0 ifTrue:<br>
-                                               initializingIf: self extBSpecifiesInitializeInstanc<wbr>e) ~= 0 ifTrue:<br>
                                        [^ShouldNotJIT]. "e.g. bad class"<br>
                                 self ssPop: 1] .<br>
                        [20] -> "20     identityHash"<br>
                                [objectRepresentation genGetIdentityHash: rcvrReg resultReg: resultReg.<br>
                                 self ssPop: 1] .<br>
                                        "21             identityHash (SmallInteger)"<br>
                                        "22             identityHash (Character)"<br>
                                        "23             identityHash (SmallFloat64)"<br>
                                        "24             identityHash (Behavior)"<br>
                                        "30     immediateAsInteger (Character)<br>
                                         31     immediateAsInteger (SmallFloat64)<br>
                                         35             immediateAsFloat          (SmallInteger)        "<br>
                        [30] -><br>
                                [self ssTop popToReg: resultReg.<br>
                                 objectRepresentation genConvertCharacterToSmallInte<wbr>gerInReg: resultReg.<br>
                                 self ssPop: 1].<br>
                        [35] -><br>
                                [self assert: self processorHasDoublePrecisionFlo<wbr>atingPointSupport.<br>
                                self MoveR: rcvrReg R: TempReg.<br>
                                self genConvertSmallIntegerToIntege<wbr>rInReg: TempReg.<br>
                                self ConvertR: TempReg Rd: DPFPReg0.<br>
                                self flag: #TODO. "Should never fail"<br>
                                self<br>
                                        genAllocFloatValue: DPFPReg0<br>
                                        into: resultReg<br>
                                        scratchReg: TempReg<br>
                                        scratchReg: NoReg. "scratch2 for V3 only"]<br>
                                  }<br>
<br>
                otherwise:<br>
                        [^EncounteredUnknownBytecode].<br>
        extB := 0.<br>
        numExtB := 0.<br>
        self ssPushRegister: resultReg.<br>
        ^0!<br>
<br>
<br></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>