<div dir="ltr">Hello,<div><br></div><div>Nice job Tim with the closedPIC logic.<br><div><br></div><div>In the Sista JIT, you changed the way the type information from the closed PICs is extracted. Eliot wrote that and I don&#39;t understand it very well. I will compile a new VM and try to see if your code works. However I will do that next week as I am at Smalltalks right now.</div><div><br></div><div>By the way, what kind of machine use MIPS processor these days ? I saw the backend in mainstream VMs such as V8 so I guess the port makes sense but I am just wondering who use that.</div></div></div><div class="gmail_extra"><br><div class="gmail_quote">2015-11-11 16:28 GMT-03:00 Eliot Miranda <span dir="ltr">&lt;<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <br><div dir="ltr">Bravo Tim!  Such a nice improvement.  Thank you!</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Nov 6, 2015 at 12:08 PM,  <span dir="ltr">&lt;<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
tim Rowledge uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-tpr.1511.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMaker/VMMaker.oscog-tpr.1511.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-tpr.1511<br>
Author: tpr<br>
Time: 6 November 2015, 1:08:47.44 pm<br>
UUID: c040c1b1-b67f-45ec-973e-4ffd34322ea5<br>
Ancestors: VMMaker.oscog-eem.1510<br>
<br>
Merge in a fairly large change to closed PICs; they are no longer compiled each time we make on or extend one, but rather  copied from a prototype and updated as needed.<br>
Take a look at  <a href="http://wiki.squeak.org/squeak/6205" rel="noreferrer" target="_blank">http://wiki.squeak.org/squeak/6205</a> for some explanations.<br>
<br>
Oh, and fix the div/mod simulation so it actually works. This makes simulating the stdio reading test images actually work on ARM.<br>
<br>
Clement - there is a single Sista related change in here that may or may not break things for you ;-)<br>
<br>
=============== Diff against VMMaker.oscog-eem.1510 ===============<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;aeabiDiv:Mod: (in category &#39;simulation&#39;) -----<br>
  aeabiDiv: dividend Mod: divisor<br>
  &quot;simulate the __aeabi_idivmod call&quot;<br>
        &lt;doNotGenerate&gt;<br>
+       |result top bottom|<br>
-       |result|<br>
<br>
+       top:= dividend signedIntFromLong.<br>
+       bottom := divisor signedIntFromLong.<br>
+<br>
+       cogit processor r0: (result :=(top quo: bottom) signedIntToLong).<br>
+       cogit processor r1: (top rem: bottom) signedIntToLong.<br>
-       cogit processor r0: (result :=dividend quo: divisor).<br>
-       cogit processor r1: (dividend rem: divisor).<br>
        ^result!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;callTargetFromReturnAddress: (in category &#39;inline cacheing&#39;) -----<br>
  callTargetFromReturnAddress: callSiteReturnAddress<br>
        &quot;Answer the address that the call immediately preceding callSiteReturnAddress will jump to.&quot;<br>
        &quot;this is also used by #jumpLongTargetBeforeFollowingAddress:.&quot;<br>
        | callDistance call |<br>
        call := self instructionBeforeAddress: callSiteReturnAddress.<br>
        self assert: ((self instructionIsB: call) or: [self instructionIsBL: call]).<br>
        callDistance := self extractOffsetFromBL: call.<br>
+       ^callSiteReturnAddress + 4 &quot;this is the pc&#39;s +8 offset, - the 4 byte correction for the previous instruction address&quot; + callDistance signedIntFromLong!<br>
-       ^callSiteReturnAddress + 4 + callDistance signedIntFromLong!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;computeMaximumSize (in category &#39;generate machine code&#39;) -----<br>
  computeMaximumSize<br>
        &quot;Because we don&#39;t use Thumb, each ARM instruction has 4 bytes. Many<br>
         abstract opcodes need more than one instruction. Instructions that refer<br>
         to constants and/or literals depend on literals being stored in-line or out-of-line.<br>
<br>
         N.B.  The ^N forms are to get around the bytecode compiler&#39;s long branch<br>
         limits which are exceeded when each case jumps around the otherwise.&quot;<br>
<br>
        opcode<br>
                caseOf: {<br>
                &quot;Noops &amp; Pseudo Ops&quot;<br>
                [Label]                                 -&gt; [^0].<br>
                [Literal]                                       -&gt; [^4].<br>
                [AlignmentNops]         -&gt; [^(operands at: 0) - 4].<br>
                [Fill16]                                        -&gt; [^4].<br>
                [Fill32]                                        -&gt; [^4].<br>
                [FillFromWord]                  -&gt; [^4].<br>
                [Nop]                                   -&gt; [^4].<br>
                &quot;Control&quot;<br>
                [Call]                                  -&gt; [^4].<br>
                [CallFull]                              -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [JumpR]                                 -&gt; [^4].<br>
                [Jump]                                  -&gt; [^4].<br>
                [JumpFull]                              -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [JumpLong]                              -&gt; [^4].<br>
                [JumpZero]                              -&gt; [^4].<br>
                [JumpNonZero]                   -&gt; [^4].<br>
                [JumpNegative]                  -&gt; [^4].<br>
                [JumpNonNegative]               -&gt; [^4].<br>
                [JumpOverflow]                  -&gt; [^4].<br>
                [JumpNoOverflow]                -&gt; [^4].<br>
                [JumpCarry]                     -&gt; [^4].<br>
                [JumpNoCarry]                   -&gt; [^4].<br>
                [JumpLess]                              -&gt; [^4].<br>
                [JumpGreaterOrEqual]    -&gt; [^4].<br>
                [JumpGreater]                   -&gt; [^4].<br>
                [JumpLessOrEqual]               -&gt; [^4].<br>
                [JumpBelow]                     -&gt; [^4].<br>
                [JumpAboveOrEqual]      -&gt; [^4].<br>
                [JumpAbove]                     -&gt; [^4].<br>
                [JumpBelowOrEqual]      -&gt; [^4].<br>
                [JumpLongZero]          -&gt; [^4].<br>
                [JumpLongNonZero]       -&gt; [^4].<br>
                [JumpFPEqual]                   -&gt; [^8].<br>
                [JumpFPNotEqual]                -&gt; [^8].<br>
                [JumpFPLess]                    -&gt; [^8].<br>
                [JumpFPGreaterOrEqual]-&gt; [^8].<br>
                [JumpFPGreater]         -&gt; [^8].<br>
                [JumpFPLessOrEqual]     -&gt; [^8].<br>
                [JumpFPOrdered]         -&gt; [^8].<br>
                [JumpFPUnordered]               -&gt; [^8].<br>
                [RetN]                                  -&gt; [^(operands at: 0) = 0 ifTrue: [4] ifFalse: [8]].<br>
                [Stop]                                  -&gt; [^4].<br>
<br>
                &quot;Arithmetic&quot;<br>
                [AddCqR]                                -&gt; [^self rotateable8bitSignedImmediate: (operands at: 0)<br>
                                                                                ifTrue: [:r :i :n| 4]<br>
                                                                                ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [AndCqR]                                -&gt; [^self rotateable8bitBitwiseImmediate: (operands at: 0)<br>
                                                                                ifTrue: [:r :i :n| 4]<br>
                                                                                ifFalse:<br>
                                                                                        [self literalLoadInstructionBytes = 4<br>
                                                                                                ifTrue: [8]<br>
                                                                                                ifFalse:<br>
                                                                                                        [1 &lt;&lt; (operands at: 0) highBit = ((operands at: 0) + 1)<br>
                                                                                                                ifTrue: [8]<br>
                                                                                                                ifFalse: [self literalLoadInstructionBytes + 4]]]].<br>
                [AndCqRR]                               -&gt; [^self rotateable8bitBitwiseImmediate: (operands at: 0)<br>
                                                                                ifTrue: [:r :i :n| 4]<br>
                                                                                ifFalse:<br>
                                                                                        [self literalLoadInstructionBytes = 4<br>
                                                                                                ifTrue: [8]<br>
                                                                                                ifFalse:<br>
                                                                                                        [1 &lt;&lt; (operands at: 0) highBit = ((operands at: 0) + 1)<br>
                                                                                                                ifTrue: [8]<br>
                                                                                                                ifFalse: [self literalLoadInstructionBytes + 4]]]].<br>
                [CmpCqR]                                -&gt; [^self rotateable8bitSignedImmediate: (operands at: 0)<br>
                                                                                        ifTrue: [:r :i :n| 4]<br>
                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [OrCqR]                                 -&gt; [^self rotateable8bitImmediate: (operands at: 0)<br>
                                                                                        ifTrue: [:r :i| 4]<br>
                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [SubCqR]                                -&gt; [^self rotateable8bitSignedImmediate: (operands at: 0)<br>
                                                                                        ifTrue: [:r :i :n| 4]<br>
                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [TstCqR]                                -&gt; [^self rotateable8bitImmediate: (operands at: 0)<br>
                                                                                        ifTrue: [:r :i| 4]<br>
                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [XorCqR]                                -&gt; [^self rotateable8bitBitwiseImmediate: (operands at: 0)<br>
                                                                                ifTrue: [:r :i :n| 4]<br>
                                                                                ifFalse:<br>
                                                                                        [self literalLoadInstructionBytes = 4<br>
                                                                                                ifTrue: [8]<br>
                                                                                                ifFalse:<br>
                                                                                                        [1 &lt;&lt; (operands at: 0) highBit = ((operands at: 0) + 1)<br>
                                                                                                                ifTrue: [8]<br>
                                                                                                                ifFalse: [self literalLoadInstructionBytes + 4]]]].<br>
                [AddCwR]                                -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [AndCwR]                                -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [CmpCwR]                                -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [OrCwR]                         -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [SubCwR]                                -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [XorCwR]                                -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [AddRR]                                 -&gt; [^4].<br>
                [AndRR]                                 -&gt; [^4].<br>
                [CmpRR]                         -&gt; [^4].<br>
                [OrRR]                                  -&gt; [^4].<br>
                [XorRR]                                 -&gt; [^4].<br>
                [SubRR]                                 -&gt; [^4].<br>
                [NegateR]                               -&gt; [^4].<br>
                [LoadEffectiveAddressMwrR]<br>
                                                                        -&gt; [^self rotateable8bitImmediate: (operands at: 0)<br>
                                                                                        ifTrue: [:r :i| 4]<br>
                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
<br>
                [LogicalShiftLeftCqR]           -&gt; [^4].<br>
                [LogicalShiftRightCqR]          -&gt; [^4].<br>
                [ArithmeticShiftRightCqR]       -&gt; [^4].<br>
                [LogicalShiftLeftRR]                    -&gt; [^4].<br>
                [LogicalShiftRightRR]           -&gt; [^4].<br>
                [ArithmeticShiftRightRR]                -&gt; [^4].<br>
                [AddRdRd]                                       -&gt; [^4].<br>
                [CmpRdRd]                                       -&gt; [^4].<br>
                [SubRdRd]                                       -&gt; [^4].<br>
                [MulRdRd]                                       -&gt; [^4].<br>
                [DivRdRd]                                       -&gt; [^4].<br>
                [SqrtRd]                                        -&gt; [^4].<br>
                &quot;ARM Specific Arithmetic&quot;<br>
                [SMULL]                         -&gt; [^4].<br>
                [MSR]                                   -&gt; [^4].<br>
                [CMPSMULL]                      -&gt; [^4]. &quot;special compare for genMulR:R: usage&quot;<br>
                &quot;Data Movement&quot;<br>
                [MoveCqR]                               -&gt; [^self literalLoadInstructionBytes = 4<br>
                                                                                ifTrue: [self literalLoadInstructionBytes]<br>
                                                                                ifFalse:<br>
                                                                                        [self rotateable8bitBitwiseImmediate: (operands at: 0)<br>
                                                                                                ifTrue: [:r :i :n| 4]<br>
                                                                                                ifFalse: [self literalLoadInstructionBytes]]].<br>
                [MoveCwR]                               -&gt; [^self literalLoadInstructionBytes = 4<br>
                                                                                ifTrue: [self literalLoadInstructionBytes]<br>
                                                                                ifFalse:<br>
                                                                                        [(self inCurrentCompilation: (operands at: 0))<br>
                                                                                                ifTrue: [4]<br>
                                                                                                ifFalse: [self literalLoadInstructionBytes]]].<br>
                [MoveRR]                                -&gt; [^4].<br>
                [MoveRdRd]                              -&gt; [^4].<br>
                [MoveAwR]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 0))<br>
                                                                                                        ifTrue: [4]<br>
                                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveRAw]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 1))<br>
                                                                                                        ifTrue: [4]<br>
                                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
+               [MoveAbR]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 0))<br>
+                                                                                                       ifTrue: [4]<br>
+                                                                                                       ifFalse: [self literalLoadInstructionBytes + 4]].<br>
+               [MoveRAb]                               -&gt; [^(self isAddressRelativeToVarBase: (operands at: 1))<br>
+                                                                                                       ifTrue: [4]<br>
+                                                                                                       ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveRMwr]                      -&gt; [^self is12BitValue: (operands at: 1)<br>
                                                                                ifTrue: [:u :i| 4]<br>
                                                                                ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveRdM64r]                    -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [MoveMbrR]                              -&gt; [^self is12BitValue: (operands at: 0)<br>
                                                                                ifTrue: [:u :i| 4]<br>
                                                                                ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveRMbr]                              -&gt; [^self is12BitValue: (operands at: 1)<br>
                                                                                ifTrue: [:u :i| 4]<br>
                                                                                ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveM16rR]                     -&gt; [^self rotateable8bitImmediate: (operands at: 0)<br>
                                                                                        ifTrue: [:r :i| 4]<br>
                                                                                        ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveM64rRd]                    -&gt; [^self literalLoadInstructionBytes + 4].<br>
                [MoveMwrR]                      -&gt; [^self is12BitValue: (operands at: 0)<br>
                                                                                ifTrue: [:u :i| 4]<br>
                                                                                ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                [MoveXbrRR]                     -&gt; [^4].<br>
                [MoveRXbrR]                     -&gt; [^4].<br>
                [MoveXwrRR]                     -&gt; [^4].<br>
                [MoveRXwrR]                     -&gt; [^4].<br>
                [PopR]                                  -&gt; [^4].<br>
                [PushR]                                 -&gt; [^4].<br>
                [PushCw]                                -&gt; [^self literalLoadInstructionBytes = 4<br>
                                                                                ifTrue: [self literalLoadInstructionBytes + 4]<br>
                                                                                ifFalse:<br>
                                                                                        [(self inCurrentCompilation: (operands at: 0))<br>
                                                                                                ifTrue: [8]<br>
                                                                                                ifFalse:<br>
                                                                                                        [self rotateable8bitBitwiseImmediate: (operands at: 0)<br>
                                                                                                                ifTrue: [:r :i :n| 8]<br>
                                                                                                                ifFalse: [self literalLoadInstructionBytes + 4]]]].<br>
                [PushCq]                                -&gt; [^self literalLoadInstructionBytes = 4<br>
                                                                                ifTrue: [self literalLoadInstructionBytes + 4]<br>
                                                                                ifFalse:<br>
                                                                                        [self rotateable8bitBitwiseImmediate: (operands at: 0)<br>
                                                                                                ifTrue: [:r :i :n| 8]<br>
                                                                                                ifFalse: [self literalLoadInstructionBytes + 4]]].<br>
                [PrefetchAw]                    -&gt; [^(self isAddressRelativeToVarBase: (operands at: 0))<br>
                                                                                ifTrue: [4]<br>
                                                                                ifFalse: [self literalLoadInstructionBytes + 4]].<br>
                &quot;Conversion&quot;<br>
                [ConvertRRd]                    -&gt; [^8].<br>
                }.<br>
        ^0 &quot;to keep C compiler quiet&quot;<br>
  !<br>
<br>
Item was added:<br>
+ ----- Method: CogARMCompiler&gt;&gt;concretizeMoveAbR (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeMoveAbR<br>
+       &quot;Will get inlined into concretizeAt: switch.&quot;<br>
+       &lt;inline: true&gt;<br>
+       | srcAddr destReg instrOffset|<br>
+       srcAddr := operands at: 0.<br>
+       destReg := self concreteRegister: (operands at: 1).<br>
+       (self isAddressRelativeToVarBase: srcAddr) ifTrue:<br>
+               [self machineCodeAt: 0 put: (self ldrb: destReg rn: ConcreteVarBaseReg plus: 1 imm: srcAddr - cogit varBaseAddress).<br>
+                ^machineCodeSize := 4].<br>
+       &quot;load the address into ConcreteIPReg&quot;<br>
+       instrOffset := self moveCw: srcAddr intoR: ConcreteIPReg.<br>
+       &quot;We *could* overwrite the last instruction above with a LDR a, b, last-byte-of-srcAddr BUT that would break if we change to loading literals instead of forming long constants&quot;<br>
+       self machineCodeAt: instrOffset put: (self ldrb: destReg rn: ConcreteIPReg plus: 1 imm: 0).<br>
+       ^machineCodeSize := instrOffset + 4!<br>
<br>
Item was added:<br>
+ ----- Method: CogARMCompiler&gt;&gt;concretizeMoveRAb (in category &#39;generate machine code - concretize&#39;) -----<br>
+ concretizeMoveRAb<br>
+       &quot;Will get inlined into concretizeAt: switch.&quot;<br>
+       &quot;LEA ConcreteIPReg<br>
+       strb srcReg, [ConcreteIPReg]&quot;<br>
+       &lt;inline: true&gt;<br>
+       | srcReg destAddr instrOffset|<br>
+       srcReg := self concreteRegister: (operands at: 0).<br>
+       destAddr := operands at: 1.<br>
+       (self isAddressRelativeToVarBase: destAddr) ifTrue:<br>
+               [self machineCodeAt: 0 put: (self strb: srcReg rn: ConcreteVarBaseReg plus: 1 imm: destAddr - cogit varBaseAddress).<br>
+                ^machineCodeSize := 4].<br>
+       &quot;load the address into ConcreteIPReg&quot;<br>
+       instrOffset := self moveCw: destAddr intoR: ConcreteIPReg.<br>
+       &quot;We *could* overwrite the last instruction above with a LDR a, b, last-byte-of-srcAddr BUT that would break if we change to loading literals instead of forming long constants&quot;<br>
+       self machineCodeAt: instrOffset put: (self strb: srcReg rn: ConcreteIPReg plus: 1 imm: 0).<br>
+       ^machineCodeSize := instrOffset + 4!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;dispatchConcretize (in category &#39;generate machine code&#39;) -----<br>
  dispatchConcretize<br>
        &quot;Attempt to generate concrete machine code for the instruction at address.<br>
         This is the inner dispatch of concretizeAt: actualAddress which exists only<br>
         to get around the branch size limits in the SqueakV3 (blue book derived)<br>
         bytecode set.&quot;<br>
        &lt;returnTypeC: #void&gt;<br>
        conditionOrNil ifNotNil:<br>
                [self concretizeConditionalInstruction.<br>
                 ^self].<br>
<br>
        opcode caseOf: {<br>
                &quot;Noops &amp; Pseudo Ops&quot;<br>
                [Label]                                 -&gt; [^self concretizeLabel].<br>
                [Literal]                                       -&gt; [^self concretizeLiteral].<br>
                [AlignmentNops]         -&gt; [^self concretizeAlignmentNops].<br>
                [Fill16]                                        -&gt; [^self concretizeFill16].<br>
                [Fill32]                                        -&gt; [^self concretizeFill32].<br>
                [FillFromWord]                  -&gt; [^self concretizeFillFromWord].<br>
                [Nop]                                   -&gt; [^self concretizeNop].<br>
                &quot;Control&quot;<br>
                [Call]                                          -&gt; [^self concretizeCall]. &quot;call code within code space&quot;<br>
                [CallFull]                                      -&gt; [^self concretizeCallFull]. &quot;call code anywhere in address space&quot;<br>
                [JumpR]                                         -&gt; [^self concretizeJumpR].<br>
                [JumpFull]                                      -&gt; [^self concretizeJumpFull].&quot;jump within address space&quot;<br>
                [JumpLong]                                      -&gt; [^self concretizeConditionalJump: AL].&quot;jumps witihn code space&quot;<br>
                [JumpLongZero]                  -&gt; [^self concretizeConditionalJump: EQ].<br>
                [JumpLongNonZero]               -&gt; [^self concretizeConditionalJump: NE].<br>
                [Jump]                                          -&gt; [^self concretizeConditionalJump: AL].<br>
                [JumpZero]                                      -&gt; [^self concretizeConditionalJump: EQ].<br>
                [JumpNonZero]                           -&gt; [^self concretizeConditionalJump: NE].<br>
                [JumpNegative]                          -&gt; [^self concretizeConditionalJump: MI].<br>
                [JumpNonNegative]                       -&gt; [^self concretizeConditionalJump: PL].<br>
                [JumpOverflow]                          -&gt; [^self concretizeConditionalJump: VS].<br>
                [JumpNoOverflow]                        -&gt; [^self concretizeConditionalJump: VC].<br>
                [JumpCarry]                             -&gt; [^self concretizeConditionalJump: CS].<br>
                [JumpNoCarry]                           -&gt; [^self concretizeConditionalJump: CC].<br>
                [JumpLess]                                      -&gt; [^self concretizeConditionalJump: LT].<br>
                [JumpGreaterOrEqual]            -&gt; [^self concretizeConditionalJump: GE].<br>
                [JumpGreater]                           -&gt; [^self concretizeConditionalJump: GT].<br>
                [JumpLessOrEqual]                       -&gt; [^self concretizeConditionalJump: LE].<br>
                [JumpBelow]                             -&gt; [^self concretizeConditionalJump: CC]. &quot;unsigned lower&quot;<br>
                [JumpAboveOrEqual]              -&gt; [^self concretizeConditionalJump: CS]. &quot;unsigned greater or equal&quot;<br>
                [JumpAbove]                             -&gt; [^self concretizeConditionalJump: HI].<br>
                [JumpBelowOrEqual]              -&gt; [^self concretizeConditionalJump: LS].<br>
                [JumpFPEqual]                           -&gt; [^self concretizeFPConditionalJump: EQ].<br>
                [JumpFPNotEqual]                        -&gt; [^self concretizeFPConditionalJump: NE].<br>
                [JumpFPLess]                            -&gt; [^self concretizeFPConditionalJump: LT].<br>
                [JumpFPGreaterOrEqual]  -&gt; [^self concretizeFPConditionalJump: GE].<br>
                [JumpFPGreater]                 -&gt; [^self concretizeFPConditionalJump: GT].<br>
                [JumpFPLessOrEqual]             -&gt; [^self concretizeFPConditionalJump: LE].<br>
                [JumpFPOrdered]                 -&gt; [^self concretizeFPConditionalJump: VC].<br>
                [JumpFPUnordered]                       -&gt; [^self concretizeFPConditionalJump: VS].<br>
                [RetN]                                          -&gt; [^self concretizeRetN].<br>
                [Stop]                                          -&gt; [^self concretizeStop].<br>
                &quot;Arithmetic&quot;<br>
                [AddCqR]                                        -&gt; [^self concretizeNegateableDataOperationCqR: AddOpcode].<br>
                [AndCqR]                                        -&gt; [^self concretizeInvertibleDataOperationCqR: AndOpcode].<br>
                [AndCqRR]                                       -&gt; [^self concretizeAndCqRR].<br>
                [CmpCqR]                                        -&gt; [^self concretizeNegateableDataOperationCqR: CmpOpcode].<br>
                [OrCqR]                                         -&gt; [^self concretizeDataOperationCqR: OrOpcode].<br>
                [SubCqR]                                        -&gt; [^self concretizeSubCqR].<br>
                [TstCqR]                                        -&gt; [^self concretizeTstCqR].<br>
                [XorCqR]                                        -&gt; [^self concretizeInvertibleDataOperationCqR: XorOpcode].<br>
                [AddCwR]                                        -&gt; [^self concretizeDataOperationCwR: AddOpcode].<br>
                [AndCwR]                                        -&gt; [^self concretizeDataOperationCwR: AndOpcode].<br>
                [CmpCwR]                                        -&gt; [^self concretizeDataOperationCwR: CmpOpcode].<br>
                [OrCwR]                                 -&gt; [^self concretizeDataOperationCwR: OrOpcode].<br>
                [SubCwR]                                        -&gt; [^self concretizeDataOperationCwR: SubOpcode].<br>
                [XorCwR]                                        -&gt; [^self concretizeDataOperationCwR: XorOpcode].<br>
                [AddRR]                                         -&gt; [^self concretizeDataOperationRR: AddOpcode].<br>
                [AndRR]                                         -&gt; [^self concretizeDataOperationRR: AndOpcode].<br>
                [CmpRR]                                 -&gt; [^self concretizeDataOperationRR: CmpOpcode].<br>
                [OrRR]                                          -&gt; [^self concretizeDataOperationRR: OrOpcode].<br>
                [SubRR]                                         -&gt; [^self concretizeDataOperationRR: SubOpcode].<br>
                [XorRR]                                         -&gt; [^self concretizeDataOperationRR: XorOpcode].<br>
                [AddRdRd]                                       -&gt; [^self concretizeAddRdRd].<br>
                [CmpRdRd]                                       -&gt; [^self concretizeCmpRdRd].<br>
                [DivRdRd]                                       -&gt; [^self concretizeDivRdRd].<br>
                [MulRdRd]                                       -&gt; [^self concretizeMulRdRd].<br>
                [SubRdRd]                                       -&gt; [^self concretizeSubRdRd].<br>
                [SqrtRd]                                        -&gt; [^self concretizeSqrtRd].<br>
                [NegateR]                                               -&gt; [^self concretizeNegateR].<br>
                [LoadEffectiveAddressMwrR]      -&gt; [^self concretizeLoadEffectiveAddressMwrR].<br>
                [ArithmeticShiftRightCqR]               -&gt; [^self concretizeArithmeticShiftRightCqR].<br>
                [LogicalShiftRightCqR]                  -&gt; [^self concretizeLogicalShiftRightCqR].<br>
                [LogicalShiftLeftCqR]                   -&gt; [^self concretizeLogicalShiftLeftCqR].<br>
                [ArithmeticShiftRightRR]                        -&gt; [^self concretizeArithmeticShiftRightRR].<br>
                [LogicalShiftLeftRR]                            -&gt; [^self concretizeLogicalShiftLeftRR].<br>
                [LogicalShiftRightRR]                   -&gt; [^self concretizeLogicalShiftRightRR].<br>
                &quot;ARM Specific Arithmetic&quot;<br>
                [SMULL]                 -&gt; [^self concretizeSMULL]      .<br>
                [CMPSMULL]              -&gt; [^self concretizeCMPSMULL].<br>
                [MSR]                           -&gt; [^self concretizeMSR].<br>
                &quot;Data Movement&quot;<br>
                [MoveCqR]                       -&gt; [^self concretizeMoveCqR].<br>
                [MoveCwR]                       -&gt; [^self concretizeMoveCwR].<br>
                [MoveRR]                        -&gt; [^self concretizeMoveRR].<br>
                [MoveAwR]                       -&gt; [^self concretizeMoveAwR].<br>
                [MoveRAw]                       -&gt; [^self concretizeMoveRAw].<br>
+               [MoveAbR]                        -&gt; [^self concretizeMoveAbR].<br>
+               [MoveRAb]                       -&gt; [^self concretizeMoveRAb].<br>
                [MoveMbrR]                      -&gt; [^self concretizeMoveMbrR].<br>
                [MoveRMbr]                      -&gt; [^self concretizeMoveRMbr].<br>
                [MoveM16rR]             -&gt; [^self concretizeMoveM16rR].<br>
                [MoveM64rRd]            -&gt; [^self concretizeMoveM64rRd].<br>
                [MoveMwrR]              -&gt; [^self concretizeMoveMwrR].<br>
                [MoveXbrRR]             -&gt; [^self concretizeMoveXbrRR].<br>
                [MoveRXbrR]             -&gt; [^self concretizeMoveRXbrR].<br>
                [MoveXwrRR]             -&gt; [^self concretizeMoveXwrRR].<br>
                [MoveRXwrR]             -&gt; [^self concretizeMoveRXwrR].<br>
                [MoveRMwr]              -&gt; [^self concretizeMoveRMwr].<br>
                [MoveRdM64r]            -&gt; [^self concretizeMoveRdM64r].<br>
                [PopR]                          -&gt; [^self concretizePopR].<br>
                [PushR]                         -&gt; [^self concretizePushR].<br>
                [PushCq]                        -&gt; [^self concretizePushCq].<br>
                [PushCw]                        -&gt; [^self concretizePushCw].<br>
                [PrefetchAw]            -&gt; [^self concretizePrefetchAw].<br>
                &quot;Conversion&quot;<br>
                [ConvertRRd]            -&gt; [^self concretizeConvertRRd]}!<br>
<br>
Item was added:<br>
+ ----- Method: CogARMCompiler&gt;&gt;instructionAddressBefore: (in category &#39;inline cacheing&#39;) -----<br>
+ instructionAddressBefore: followingAddress<br>
+       &quot;Answer the instruction address immediately preceding followingAddress.&quot;<br>
+       &lt;inline: true&gt;<br>
+       ^followingAddress -4!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;instructionBeforeAddress: (in category &#39;inline cacheing&#39;) -----<br>
  instructionBeforeAddress: followingAddress<br>
        &quot;Answer the instruction immediately preceding followingAddress.&quot;<br>
        &lt;inline: true&gt;<br>
+       ^objectMemory longAt: (self instructionAddressBefore: followingAddress)!<br>
-       ^objectMemory longAt: followingAddress -4!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;loadLiteralByteSize (in category &#39;accessing&#39;) -----<br>
  loadLiteralByteSize<br>
+       &quot;Answer the byte size of a MoveCwR opcode&#39;s corresponding machine code. On ARM this is a single instruction pc-relative register load - unless we have made a mistake and not turned on the out of line literals manager&quot;<br>
+       ^4!<br>
-       &quot;Answer the byte size of a MoveCwR opcode&#39;s corresponding machine code&quot;<br>
-       ^16!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;relocateCallBeforeReturnPC:by: (in category &#39;inline cacheing&#39;) -----<br>
  relocateCallBeforeReturnPC: retpc by: delta<br>
        | instr distanceDiv4 |<br>
        self assert: delta \\ 4 = 0.<br>
        delta ~= 0 ifTrue:<br>
                [instr := self instructionBeforeAddress: retpc.<br>
                 self assert: ((self instructionIsB: instr) or: [self instructionIsBL: instr]).<br>
                 distanceDiv4 := instr bitAnd: 16rFFFFFF.<br>
                 distanceDiv4 := distanceDiv4 + (delta // 4).<br>
+                objectMemory longAt: (self instructionAddressBefore: retpc ) put: ((instr bitAnd: 16rFF000000) bitOr: (distanceDiv4 bitAnd: 16rFFFFFF))]!<br>
-                objectMemory longAt: retpc - 4 put: ((instr bitAnd: 16rFF000000) bitOr: (distanceDiv4 bitAnd: 16rFFFFFF))]!<br>
<br>
Item was added:<br>
+ ----- Method: CogARMCompiler&gt;&gt;rewriteCPICJumpAt:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCPICJumpAt: callSiteReturnAddress target: callTargetAddress<br>
+       &quot;Rewrite a jump instruction to call a different target.  This variant is used to reset the<br>
+       jumps in the prototype CPIC to suit each use,.<br>
+       Answer the extent of the code change which is used to compute the range of the icache to flush.&quot;<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+       ^self rewriteTransferAt: callSiteReturnAddress target: callTargetAddress!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;rewriteCallAt:target: (in category &#39;inline cacheing&#39;) -----<br>
  rewriteCallAt: callSiteReturnAddress target: callTargetAddress<br>
        &quot;Rewrite a call instruction to call a different target.  This variant is used to link PICs<br>
+        in ceSendMiss et al,.<br>
+       Answer the extent of the code change which is used to compute the range of the icache to flush.&quot;<br>
-        in ceSendMiss et al, and to rewrite cached primitive calls.   Answer the extent of<br>
-        the code change which is used to compute the range of the icache to flush.&quot;<br>
        &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
        &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+       ^self rewriteTransferAt: callSiteReturnAddress target: callTargetAddress!<br>
-       | callDistance call |<br>
-       &quot;self cCode: &#39;&#39;<br>
-               inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 10 to: callSiteReturnAddress - 1].&quot;<br>
-       false<br>
-               ifTrue: [self assert: callTargetAddress &gt;= cogit minCallAddress]<br>
-               ifFalse: [callTargetAddress &gt;= cogit minCallAddress ifFalse:<br>
-                                       [self error: &#39;linking callsite to invalid address&#39;]].<br>
-       callDistance := (callTargetAddress - (callSiteReturnAddress + 8 &quot;pc offset&quot;- 4 &quot;return offset&quot;)) signedIntToLong.<br>
-       self assert: (self isInImmediateJumpRange: callDistance). &quot;we don&#39;t support long call updates, yet&quot;<br>
-       call := self bl: callDistance.<br>
-       objectMemory longAt:  callSiteReturnAddress - 4 put: call.<br>
-<br>
-       self assert: (self callTargetFromReturnAddress: callSiteReturnAddress) signedIntToLong = callTargetAddress.<br>
-       &quot;self cCode: &#39;&#39;<br>
-               inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 10 to: callSiteReturnAddress - 1].&quot;<br>
-       ^4!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;rewriteCallFullAt:target: (in category &#39;inline cacheing&#39;) -----<br>
  rewriteCallFullAt: callSiteReturnAddress target: callTargetAddress<br>
        &quot;Rewrite a callFull instruction to jump to a different target.  This variant<br>
+        is used to rewrite cached primitive calls where we load the target address into ip<br>
+       and use the &#39;blx ip&#39; instruction for the actual call.<br>
+       Answer the extent of the<br>
-        is used to rewrite cached primitive calls.   Answer the extent of the<br>
         code change which is used to compute the range of the icache to flush.&quot;<br>
        &lt;inline: true&gt;<br>
        ^self<br>
                rewriteFullTransferAt: callSiteReturnAddress<br>
                target: callTargetAddress<br>
                expectedInstruction: 16rE12FFF3C!<br>
<br>
Item was changed:<br>
  ----- Method: CogARMCompiler&gt;&gt;rewriteJumpFullAt:target: (in category &#39;inline cacheing&#39;) -----<br>
  rewriteJumpFullAt: callSiteReturnAddress target: callTargetAddress<br>
        &quot;Rewrite a full jump instruction to jump to a different target.  This variant<br>
+        is used to rewrite cached primitive calls where we load the target address into ip<br>
+       and use the &#39;bx ip&#39; instruction for the actual jump.<br>
+       Answer the extent of the<br>
-        is used to rewrite cached primitive calls.   Answer the extent of the<br>
         code change which is used to compute the range of the icache to flush.&quot;<br>
        &lt;inline: true&gt;<br>
        ^self<br>
                rewriteFullTransferAt: callSiteReturnAddress<br>
                target: callTargetAddress<br>
                expectedInstruction: 16rE12FFF1C!<br>
<br>
Item was added:<br>
+ ----- Method: CogARMCompiler&gt;&gt;rewriteJumpLongAt:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteJumpLongAt: callSiteReturnAddress target: callTargetAddress<br>
+       &quot;Rewrite a jump instruction to call a different target.  This variant is used to reset the<br>
+       jumps in the prototype CPIC to suit each use,.<br>
+       Answer the extent of the code change which is used to compute the range of the icache to flush.&quot;<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+       ^self rewriteTransferAt: callSiteReturnAddress target: callTargetAddress!<br>
<br>
Item was added:<br>
+ ----- Method: CogARMCompiler&gt;&gt;rewriteTransferAt:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteTransferAt: callSiteReturnAddress target: callTargetAddress<br>
+       &quot;Rewrite a call/jump instruction to call a different target.  This variant is used to link PICs<br>
+        in ceSendMiss et al, and to rewrite call/jumps in CPICs.<br>
+       Answer the extent of<br>
+        the code change which is used to compute the range of the icache to flush.&quot;<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+       | callDistance instr |<br>
+       &quot;for debug - [cogit disassembleFrom: callSiteReturnAddress - 10 to: callSiteReturnAddress - 1].&quot;<br>
+       false<br>
+               ifTrue: [self assert: callTargetAddress &gt;= cogit minCallAddress]<br>
+               ifFalse: [callTargetAddress &gt;= cogit minCallAddress ifFalse:<br>
+                                       [self error: &#39;linking callsite to invalid address&#39;]].<br>
+<br>
+       callDistance := (callTargetAddress - (callSiteReturnAddress + 8 &quot;pc offset&quot;- 4 &quot;return offset&quot;)) signedIntToLong.<br>
+       self assert: (self isInImmediateJumpRange: callDistance). &quot;we don&#39;t support long call updates, yet&quot;<br>
+<br>
+       instr := self instructionBeforeAddress: callSiteReturnAddress.<br>
+       self assert: ((self instructionIsB: instr) or: [self instructionIsBL: instr]).<br>
+<br>
+       objectMemory longAt:  (self instructionAddressBefore: callSiteReturnAddress) put: ((instr bitAnd: 16rFF000000) bitOr: (callDistance // 4 bitAnd: 16rFFFFFF)).<br>
+<br>
+       self assert: (self callTargetFromReturnAddress: callSiteReturnAddress) signedIntToLong = callTargetAddress.<br>
+<br>
+       ^4!<br>
<br>
Item was added:<br>
+ ----- Method: CogAbstractInstruction&gt;&gt;rewriteCPICCaseAt:tag:objRef:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCPICCaseAt: followingAddress tag: newTag objRef: newObjRef target: newTarget<br>
+       &quot;rewrite the three values involved in a CPIC case. Used by the create &amp; extend cpcic methods&quot;<br>
+       self subclassResponsibility<br>
+       !<br>
<br>
Item was added:<br>
+ ----- Method: CogIA32Compiler&gt;&gt;rewriteCPICCaseAt:tag:objRef:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCPICCaseAt: followingAddress tag: newTag objRef: newObjRef target: newTarget<br>
+       &quot;rewrite the three values involved in a CPIC case. Used by the create &amp; extend cpcic methods&quot;<br>
+<br>
+       &quot;IA32 CPIC cases are<br>
+       cmpl $0x newTag, %eax<br>
+       movl $0x newObjRef, %ebx<br>
+       jz .+0x newTarget (0x00010924)<br>
+ &quot;<br>
+       &quot;rewite the tag via the first ldr&quot;<br>
+       self storeLiteral: newTag beforeFollowingAddress: (followingAddress -11).<br>
+<br>
+       &quot;write the obj ref/operand via the second ldr&quot;<br>
+       self storeLiteral: newObjRef beforeFollowingAddress: (followingAddress - 6).<br>
+<br>
+       &quot;write the jump address for the new target address&quot;<br>
+       self rewriteJumpLongAt: followingAddress target: newTarget!<br>
<br>
Item was added:<br>
+ ----- Method: CogIA32Compiler&gt;&gt;rewriteCPICJumpAt:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCPICJumpAt: callSiteReturnAddress target: callTargetAddress<br>
+       &quot;Rewrite the short jump instruction to jump to a new cpic case target. &quot;<br>
+       &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
+       &lt;var: #callTargetAddress type: #usqInt&gt;<br>
+       | callDistance |<br>
+       callDistance := (callTargetAddress - callSiteReturnAddress) signedIntToLong.<br>
+       self assert: (callDistance &lt; 256).<br>
+       objectMemory<br>
+               byteAt: callSiteReturnAddress - 1 put:  (callDistance  bitAnd: 16rFF).<br>
+       &quot;self cCode: &#39;&#39;<br>
+               inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 10 to: callSiteReturnAddress - 1].&quot;<br>
+       ^2!<br>
<br>
Item was changed:<br>
  ----- Method: CogInLineLiteralsARMCompiler&gt;&gt;rewriteInlineCacheAt:tag:target: (in category &#39;inline cacheing&#39;) -----<br>
  rewriteInlineCacheAt: callSiteReturnAddress tag: cacheTag target: callTargetAddress<br>
        &quot;Rewrite an inline cache to call a different target for a new tag.  This variant is used<br>
         to link unlinked sends in ceSend:to:numArgs: et al.  Answer the extent of the code<br>
         change which is used to compute the range of the icache to flush.&quot;<br>
        &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
        &lt;var: #callTargetAddress type: #usqInt&gt;<br>
        | call callDistance |<br>
        false<br>
                ifTrue: [self assert: callTargetAddress &gt;= cogit minCallAddress]<br>
                ifFalse: [callTargetAddress &gt;= cogit minCallAddress ifFalse:<br>
                                        [self error: &#39;linking callsite to invalid address&#39;]].<br>
        callDistance := (callTargetAddress - (callSiteReturnAddress + 8 &quot;pc offset&quot;- 4 &quot;return offset&quot;)) signedIntToLong.<br>
        self assert: (self isInImmediateJumpRange: callDistance). &quot;we don&#39;t support long call updates here&quot;<br>
        call := self bl: callDistance.<br>
+       objectMemory longAt: (self instructionAddressBefore: callSiteReturnAddress ) put: call.<br>
+       self insert32BitOperand: cacheTag into4InstructionsPreceding: (self instructionAddressBefore: callSiteReturnAddress ).<br>
-       objectMemory longAt: callSiteReturnAddress - 4 put: call.<br>
-       self insert32BitOperand: cacheTag into4InstructionsPreceding: callSiteReturnAddress - 4.<br>
        self assert: (self callTargetFromReturnAddress: callSiteReturnAddress) signedIntToLong = callTargetAddress.<br>
+       self assert: (self extract32BitOperandFrom4InstructionsPreceding: (self instructionAddressBefore: callSiteReturnAddress )) = cacheTag.<br>
-       self assert: (self extract32BitOperandFrom4InstructionsPreceding: callSiteReturnAddress - 4) = cacheTag.<br>
        &quot;self cCode: &#39;&#39;<br>
                inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 20 to: callSiteReturnAddress - 1].&quot;<br>
        ^20!<br>
<br>
Item was changed:<br>
  ----- Method: CogMethod&gt;&gt;containsAddress: (in category &#39;testing&#39;) -----<br>
  containsAddress: anAddress<br>
+       &quot;is anAddress within my bounds; not a test of addresses referred to within instructions in the method&quot;<br>
        &lt;inline: true&gt;<br>
        ^self asUnsignedInteger &lt;= anAddress asUnsignedInteger<br>
          and: [self asUnsignedInteger + self blockSize &gt;= anAddress asUnsignedInteger]!<br>
<br>
Item was changed:<br>
  ----- Method: CogMethodZone&gt;&gt;printOpenPICList (in category &#39;accessing&#39;) -----<br>
  printOpenPICList<br>
        &lt;api&gt;<br>
        | openPIC |<br>
        &lt;var: #openPIC type: #&#39;CogMethod *&#39;&gt;<br>
        openPIC := openPICList.<br>
        [openPIC == nil] whileFalse:<br>
+               [coInterpreter printCogMethod: openPIC.<br>
-               [self printCogMethod: openPIC.<br>
                 openPIC := self cCoerceSimple: openPIC nextOpenPIC to: #&#39;CogMethod *&#39;]!<br>
<br>
Item was added:<br>
+ ----- Method: CogOutOfLineLiteralsARMCompiler&gt;&gt;literalBeforeFollowingAddress: (in category &#39;inline cacheing&#39;) -----<br>
+ literalBeforeFollowingAddress: followingAddress<br>
+       &quot;Return the literal referenced by the instruction immediately preceding followingAddress.&quot;<br>
+       ^objectMemory longAt: (self pcRelativeAddressAt: (self instructionAddressBefore: followingAddress))!<br>
<br>
Item was added:<br>
+ ----- Method: CogOutOfLineLiteralsARMCompiler&gt;&gt;rewriteCPICCaseAt:tag:objRef:target: (in category &#39;inline cacheing&#39;) -----<br>
+ rewriteCPICCaseAt: followingAddress tag: newTag objRef: newObjRef target: newTarget<br>
+       &quot;rewrite the three values involved in a CPIC case. Used by the create &amp; extend cpcic methods&quot;<br>
+<br>
+       &quot;ARM CPIC cases are<br>
+       ldr TempReg, [pc relative -&gt; tag]<br>
+       cmp TempReg0, TempReg<br>
+       ldr SendNumArgs, [pc relative -&gt; obj ref]<br>
+       beq target&quot;<br>
+       &quot;rewite the tag via the first ldr&quot;<br>
+       objectMemory longAt: (self pcRelativeAddressAt: followingAddress - 16) put: newTag.<br>
+<br>
+       &quot;write the obj ref/operand via the second ldr&quot;<br>
+       objectMemory longAt: (self pcRelativeAddressAt: followingAddress - 8) put: newObjRef.<br>
+<br>
+       &quot;write the jump address for the new target address&quot;<br>
+       self rewriteJumpLongAt: followingAddress target: newTarget!<br>
<br>
Item was changed:<br>
  ----- Method: CogOutOfLineLiteralsARMCompiler&gt;&gt;rewriteFullTransferAt:target:expectedInstruction: (in category &#39;inline cacheing&#39;) -----<br>
  rewriteFullTransferAt: callSiteReturnAddress target: callTargetAddress expectedInstruction: expectedInstruction<br>
        &quot;Rewrite a CallFull or JumpFull instruction to transfer to a different target.<br>
+        This variant is used to rewrite cached primitive calls where we load the target address into ip<br>
+       and use the &#39;bx ip&#39; or &#39;blx ip&#39; instruction for the actual jump or call.<br>
+       Answer the extent<br>
-        This variant is used to rewrite cached primitive calls.   Answer the extent<br>
         of the code change which is used to compute the range of the icache to flush.&quot;<br>
        &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
        &lt;var: #callTargetAddress type: #usqInt&gt;<br>
        self assert: (self instructionBeforeAddress: callSiteReturnAddress) = expectedInstruction.<br>
        objectMemory longAt: (self pcRelativeAddressAt: callSiteReturnAddress - 8) put: callTargetAddress.<br>
        &quot;self cCode: &#39;&#39;<br>
                inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 8 to: (self pcRelativeAddressAt: callSiteReturnAddress - 8)].&quot;<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: CogOutOfLineLiteralsARMCompiler&gt;&gt;rewriteInlineCacheAt:tag:target: (in category &#39;inline cacheing&#39;) -----<br>
  rewriteInlineCacheAt: callSiteReturnAddress tag: cacheTag target: callTargetAddress<br>
        &quot;Rewrite an inline cache to call a different target for a new tag.  This variant is used<br>
         to link unlinked sends in ceSend:to:numArgs: et al.  Answer the extent of the code<br>
         change which is used to compute the range of the icache to flush.&quot;<br>
        &lt;var: #callSiteReturnAddress type: #usqInt&gt;<br>
        &lt;var: #callTargetAddress type: #usqInt&gt;<br>
        | call callDistance |<br>
        callTargetAddress &gt;= cogit minCallAddress ifFalse:<br>
                [self error: &#39;linking callsite to invalid address&#39;].<br>
        callDistance := (callTargetAddress - (callSiteReturnAddress + 8 &quot;pc offset&quot;- 4 &quot;return offset&quot;)) signedIntToLong.<br>
        self assert: (self isInImmediateJumpRange: callDistance). &quot;we don&#39;t support long call updates here&quot;<br>
        call := self bl: callDistance.<br>
        objectMemory<br>
+               longAt: (self instructionAddressBefore: callSiteReturnAddress ) put: call;<br>
-               longAt: callSiteReturnAddress - 4 put: call;<br>
                longAt: (self pcRelativeAddressAt: callSiteReturnAddress - 8) put: cacheTag.<br>
        self assert: (self inlineCacheTagAt: callSiteReturnAddress) = cacheTag.<br>
        &quot;self cCode: &#39;&#39;<br>
                inSmalltalk: [cogit disassembleFrom: callSiteReturnAddress - 8 to: (self pcRelativeAddressAt: callSiteReturnAddress - 8)].&quot;<br>
        ^4!<br>
<br>
Item was changed:<br>
  ----- Method: CogOutOfLineLiteralsARMCompiler&gt;&gt;storeLiteral:beforeFollowingAddress: (in category &#39;inline cacheing&#39;) -----<br>
  storeLiteral: literal beforeFollowingAddress: followingAddress<br>
        &quot;Rewrite the literal in the instruction immediately preceding followingAddress.&quot;<br>
+       objectMemory longAt: (self pcRelativeAddressAt: (self instructionAddressBefore: followingAddress )) put: literal!<br>
-       objectMemory longAt: (self pcRelativeAddressAt: followingAddress - 4) put: literal!<br>
<br>
Item was changed:<br>
  CogClass subclass: #Cogit<br>
+       instanceVariableNames: &#39;coInterpreter objectMemory objectRepresentation processor threadManager methodZone methodZoneBase codeBase minValidCallAddress lastNInstructions simulatedAddresses simulatedTrampolines simulatedVariableGetters simulatedVariableSetters printRegisters printInstructions compilationTrace clickConfirm breakPC breakBlock singleStep guardPageSize traceFlags traceStores breakMethod methodObj initialPC endPC methodOrBlockNumArgs inBlock needsFrame hasYoungReferent primitiveIndex backEnd literalsManager callerSavedRegMask postCompileHook methodLabel stackCheckLabel blockEntryLabel blockEntryNoContextSwitch blockNoContextSwitchOffset stackOverflowCall sendMiss missOffset entryPointMask checkedEntryAlignment uncheckedEntryAlignment cmEntryOffset entry cmNoCheckEntryOffset noCheckEntry picMNUAbort picInterpretAbort endCPICCase0 endCPICCase1 firstCPICCaseOffset cPICCaseSize cPICEndSize closedPICSize openPICSize fixups abstractOpcodes generatorTable primitiveGeneratorTable byte0 byte1 byte2 byte3 bytecodePC bytecodeSetOffset opcodeIndex numAbstractOpcodes blockStarts blockCount labelCounter cStackAlignment expectedSPAlignment expectedFPAlignment codeModified maxLitIndex ceMethodAbortTrampoline cePICAbortTrampoline ceCheckForInterruptTrampoline ceCPICMissTrampoline ceReturnToInterpreterTrampoline ceBaseFrameReturnTrampoline ceSendMustBeBooleanAddTrueTrampoline ceSendMustBeBooleanAddFalseTrampoline ceCannotResumeTrampoline ceEnterCogCodePopReceiverReg ceCallCogCodePopReceiverReg ceCallCogCodePopReceiverAndClassRegs cePrimReturnEnterCogCode cePrimReturnEnterCogCodeProfiling ceNonLocalReturnTrampoline ceFetchContextInstVarTrampoline ceStoreContextInstVarTrampoline ceEnclosingObjectTrampoline ceCaptureCStackPointers ceFlushICache ceCheckFeaturesFunction ceTraceLinkedSendTrampoline ceTraceBlockActivationTrampoline ceTraceStoreTrampoline ceGetSP ordinarySendTrampolines superSendTrampolines directedSuperSendTrampolines dynamicSuperSendTrampolines outerSendTrampolines selfSendTrampolines firstSend lastSend realCEEnterCogCodePopReceiverReg realCECallCogCodePopReceiverReg realCECallCogCodePopReceiverAndClassRegs trampolineTableIndex trampolineAddresses objectReferencesInRuntime runtimeObjectRefIndex cFramePointerInUse debugPrimCallStackOffset ceTryLockVMOwner ceUnlockVMOwner extA extB tempOop numIRCs indexOfIRC theIRCs implicitReceiverSendTrampolines cogMethodSurrogateClass cogBlockMethodSurrogateClass nsSendCacheSurrogateClass CStackPointer CFramePointer cPICPrototype cPICEndOfCodeOffset cPICEndOfCodeLabel maxCPICCases&#39;<br>
-       instanceVariableNames: &#39;coInterpreter objectMemory objectRepresentation processor threadManager methodZone methodZoneBase codeBase minValidCallAddress lastNInstructions simulatedAddresses simulatedTrampolines simulatedVariableGetters simulatedVariableSetters printRegisters printInstructions compilationTrace clickConfirm breakPC breakBlock singleStep guardPageSize traceFlags traceStores breakMethod methodObj initialPC endPC methodOrBlockNumArgs inBlock needsFrame hasYoungReferent primitiveIndex backEnd literalsManager callerSavedRegMask postCompileHook methodLabel stackCheckLabel blockEntryLabel blockEntryNoContextSwitch blockNoContextSwitchOffset stackOverflowCall sendMiss missOffset entryPointMask checkedEntryAlignment uncheckedEntryAlignment cmEntryOffset entry cmNoCheckEntryOffset noCheckEntry picMNUAbort picInterpretAbort endCPICCase0 endCPICCase1 numPICCases firstCPICCaseOffset cPICCaseSize cPICEndSize closedPICSize openPICSize fixups abstractOpcodes generatorTable primitiveGeneratorTable byte0 byte1 byte2 byte3 bytecodePC bytecodeSetOffset opcodeIndex numAbstractOpcodes blockStarts blockCount labelCounter cStackAlignment expectedSPAlignment expectedFPAlignment codeModified maxLitIndex ceMethodAbortTrampoline cePICAbortTrampoline ceCheckForInterruptTrampoline ceCPICMissTrampoline ceReturnToInterpreterTrampoline ceBaseFrameReturnTrampoline ceSendMustBeBooleanAddTrueTrampoline ceSendMustBeBooleanAddFalseTrampoline ceCannotResumeTrampoline ceEnterCogCodePopReceiverReg ceCallCogCodePopReceiverReg ceCallCogCodePopReceiverAndClassRegs cePrimReturnEnterCogCode cePrimReturnEnterCogCodeProfiling ceNonLocalReturnTrampoline ceFetchContextInstVarTrampoline ceStoreContextInstVarTrampoline ceEnclosingObjectTrampoline ceCaptureCStackPointers ceFlushICache ceCheckFeaturesFunction ceTraceLinkedSendTrampoline ceTraceBlockActivationTrampoline ceTraceStoreTrampoline ceGetSP ordinarySendTrampolines superSendTrampolines directedSuperSendTrampolines dynamicSuperSendTrampolines outerSendTrampolines selfSendTrampolines firstSend lastSend realCEEnterCogCodePopReceiverReg realCECallCogCodePopReceiverReg realCECallCogCodePopReceiverAndClassRegs trampolineTableIndex trampolineAddresses objectReferencesInRuntime runtimeObjectRefIndex cFramePointerInUse debugPrimCallStackOffset ceTryLockVMOwner ceUnlockVMOwner extA extB tempOop numIRCs indexOfIRC theIRCs implicitReceiverSendTrampolines cogMethodSurrogateClass cogBlockMethodSurrogateClass nsSendCacheSurrogateClass CStackPointer CFramePointer&#39;<br>
        classVariableNames: &#39;AltBlockCreationBytecodeSize AltFirstSpecialSelector AltNSSendIsPCAnnotated AltNumSpecialSelectors AnnotationConstantNames AnnotationShift AnnotationsWithBytecodePCs BlockCreationBytecodeSize Debug DisplacementMask DisplacementX2N EagerInstructionDecoration FirstAnnotation FirstSpecialSelector HasBytecodePC IsAbsPCReference IsAnnotationExtension IsDirectedSuperSend IsDisplacementX2N IsNSDynamicSuperSend IsNSImplicitReceiverSend IsNSSelfSend IsNSSendCall IsObjectReference IsRelativeCall IsSendCall IsSuperSend MapEnd MaxCompiledPrimitiveIndex MaxStackAllocSize MaxX2NDisplacement NSCClassTagIndex NSCEnclosingObjectIndex NSCNumArgsIndex NSCSelectorIndex NSCTargetIndex NSSendIsPCAnnotated NumObjRefsInRuntime NumOopsPerNSC NumSpecialSelectors NumTrampolines ProcessorClass&#39;<br>
        poolDictionaries: &#39;CogCompilationConstants CogMethodConstants CogRTLOpcodes VMBasicConstants VMBytecodeConstants VMObjectIndices VMStackFrameOffsets&#39;<br>
        category: &#39;VMMaker-JIT&#39;!<br>
  Cogit class<br>
        instanceVariableNames: &#39;generatorTable primitiveTable&#39;!<br>
<br>
  !Cogit commentStamp: &#39;eem 4/6/2015 15:56&#39; prior: 0!<br>
  I am the code generator for the Cog VM.  My job is to produce machine code versions of methods for faster execution and to manage inline caches for faster send performance.  I can be tested in the current image using my class-side in-image compilation facilities.  e.g. try<br>
<br>
        StackToRegisterMappingCogit genAndDis: (Integer &gt;&gt; #benchFib)<br>
<br>
  I have concrete subclasses that implement different levels of optimization:<br>
        SimpleStackBasedCogit is the simplest code generator.<br>
<br>
        StackToRegisterMappingCogit is the current production code generator  It defers pushing operands<br>
        to the stack until necessary and implements a register-based calling convention for low-arity sends.<br>
<br>
        StackToRegisterMappingCogit is an experimental code generator with support for counting<br>
        conditional branches, intended to support adaptive optimization.<br>
<br>
  coInterpreter &lt;CoInterpreterSimulator&gt;<br>
        the VM&#39;s interpreter with which I cooperate<br>
  methodZoneManager &lt;CogMethodZoneManager&gt;<br>
        the manager of the machine code zone<br>
  objectRepresentation &lt;CogObjectRepresentation&gt;<br>
        the object used to generate object accesses<br>
  processor &lt;BochsIA32Alien|?&gt;<br>
        the simulator that executes the IA32/x86 machine code I generate when simulating execution in Smalltalk<br>
  simulatedTrampolines &lt;Dictionary of Integer -&gt; MessageSend&gt;<br>
        the dictionary mapping trap jump addresses to run-time routines used to warp from simulated machine code in to the Smalltalk run-time.<br>
  simulatedVariableGetters &lt;Dictionary of Integer -&gt; MessageSend&gt;<br>
        the dictionary mapping trap read addresses to variables in run-time objects used to allow simulated machine code to read variables in the Smalltalk run-time.<br>
  simulatedVariableSetters &lt;Dictionary of Integer -&gt; MessageSend&gt;<br>
        the dictionary mapping trap write addresses to variables in run-time objects used to allow simulated machine code to write variables in the Smalltalk run-time.<br>
  printRegisters printInstructions clickConfirm &lt;Boolean&gt;<br>
        flags controlling debug printing and code simulation<br>
  breakPC &lt;Integer&gt;<br>
        machine code pc breakpoint<br>
  cFramePointer cStackPointer &lt;Integer&gt;<br>
        the variables representing the C stack &amp; frame pointers, which must change on FFI callback and return<br>
  selectorOop &lt;sqInt&gt;<br>
        the oop of the methodObj being compiled<br>
  methodObj &lt;sqInt&gt;<br>
        the bytecode method being compiled<br>
  initialPC endPC &lt;Integer&gt;<br>
        the start and end pcs of the methodObj being compiled<br>
  methodOrBlockNumArgs &lt;Integer&gt;<br>
        argument count of current method or block being compiled<br>
  needsFrame &lt;Boolean&gt;<br>
        whether methodObj or block needs a frame to execute<br>
  primitiveIndex &lt;Integer&gt;<br>
        primitive index of current method being compiled<br>
  methodLabel &lt;CogAbstractOpcode&gt;<br>
        label for the method header<br>
  blockEntryLabel &lt;CogAbstractOpcode&gt;<br>
        label for the start of the block dispatch code<br>
  stackOverflowCall &lt;CogAbstractOpcode&gt;<br>
        label for the call of ceStackOverflow in the method prolog<br>
  sendMissCall &lt;CogAbstractOpcode&gt;<br>
        label for the call of ceSICMiss in the method prolog<br>
  entryOffset &lt;Integer&gt;<br>
        offset of method entry code from start (header) of method<br>
  entry &lt;CogAbstractOpcode&gt;<br>
        label for the first instruction of the method entry code<br>
  noCheckEntryOffset &lt;Integer&gt;<br>
        offset of the start of a method proper (after the method entry code) from start (header) of method<br>
  noCheckEntry &lt;CogAbstractOpcode&gt;<br>
        label for the first instruction of start of a method proper<br>
  fixups &lt;Array of &lt;AbstractOpcode Label | nil&gt;&gt;<br>
        the labels for forward jumps that will be fixed up when reaching the relevant bytecode.  fixup shas one element per byte in methodObj&#39;s bytecode<br>
  abstractOpcodes &lt;Array of &lt;AbstractOpcode&gt;&gt;<br>
        the code generated when compiling methodObj<br>
  byte0 byte1 byte2 byte3 &lt;Integer&gt;<br>
        individual bytes of current bytecode being compiled in methodObj<br>
  bytecodePointer &lt;Integer&gt;<br>
        bytecode pc (same as Smalltalk) of the current bytecode being compiled<br>
  opcodeIndex &lt;Integer&gt;<br>
        the index of the next free entry in abstractOpcodes (this code is translated into C where OrderedCollection et al do not exist)<br>
  numAbstractOpcodes &lt;Integer&gt;<br>
        the number of elements in abstractOpcocdes<br>
  blockStarts &lt;Array of &lt;BlockStart&gt;&gt;<br>
        the starts of blocks in the current method<br>
  blockCount<br>
        the index into blockStarts as they are being noted, and hence eventually the total number of blocks in the current method<br>
  labelCounter &lt;Integer&gt;<br>
        a nicety for numbering labels not needed in the production system but probably not expensive enough to worry about<br>
  ceStackOverflowTrampoline &lt;Integer&gt;<br>
  ceSend0ArgsTrampoline &lt;Integer&gt;<br>
  ceSend1ArgsTrampoline &lt;Integer&gt;<br>
  ceSend2ArgsTrampoline &lt;Integer&gt;<br>
  ceSendNArgsTrampoline &lt;Integer&gt;<br>
  ceSendSuper0ArgsTrampoline &lt;Integer&gt;<br>
  ceSendSuper1ArgsTrampoline &lt;Integer&gt;<br>
  ceSendSuper2ArgsTrampoline &lt;Integer&gt;<br>
  ceSendSuperNArgsTrampoline &lt;Integer&gt;<br>
  ceSICMissTrampoline &lt;Integer&gt;<br>
  ceCPICMissTrampoline &lt;Integer&gt;<br>
  ceStoreCheckTrampoline &lt;Integer&gt;<br>
  ceReturnToInterpreterTrampoline &lt;Integer&gt;<br>
  ceBaseFrameReturnTrampoline &lt;Integer&gt;<br>
  ceSendMustBeBooleanTrampoline &lt;Integer&gt;<br>
  ceClosureCopyTrampoline &lt;Integer&gt;<br>
        the various trampolines (system-call-like jumps from machine code to the run-time).<br>
        See Cogit&gt;&gt;generateTrampolines for the mapping from trampoline to run-time<br>
        routine and then read the run-time routine for a funcitonal description.<br>
  ceEnterCogCodePopReceiverReg &lt;Integer&gt;<br>
        the enilopmart (jump from run-time to machine-code)<br>
  methodZoneBase &lt;Integer&gt;<br>
  !<br>
  Cogit class<br>
        instanceVariableNames: &#39;generatorTable primitiveTable&#39;!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit class&gt;&gt;declareCVarsIn: (in category &#39;translation&#39;) -----<br>
  declareCVarsIn: aCCodeGenerator<br>
        #(      &#39;coInterpreter&#39; &#39;objectMemory&#39; &#39;methodZone&#39; &#39;objectRepresentation&#39;<br>
                &#39;cogBlockMethodSurrogateClass&#39; &#39;cogMethodSurrogateClass&#39; &#39;nsSendCacheSurrogateClass&#39;<br>
                &#39;threadManager&#39; &#39;processor&#39; &#39;lastNInstructions&#39; &#39;simulatedAddresses&#39;<br>
                &#39;simulatedTrampolines&#39; &#39;simulatedVariableGetters&#39; &#39;simulatedVariableSetters&#39;<br>
                &#39;printRegisters&#39; &#39;printInstructions&#39; &#39;clickConfirm&#39; &#39;singleStep&#39;) do:<br>
                        [:simulationVariableNotNeededForRealVM|<br>
                        aCCodeGenerator removeVariable: simulationVariableNotNeededForRealVM].<br>
        NewspeakVM ifFalse:<br>
                [#(     &#39;selfSendTrampolines&#39; &#39;dynamicSuperSendTrampolines&#39;<br>
                        &#39;implicitReceiverSendTrampolines&#39; &#39;outerSendTrampolines&#39;<br>
                        &#39;ceEnclosingObjectTrampoline&#39; &#39;numIRCs&#39; &#39;indexOfIRC&#39; &#39;theIRCs&#39;) do:<br>
                                [:variableNotNeededInNormalVM|<br>
                                aCCodeGenerator removeVariable: variableNotNeededInNormalVM]].<br>
        aCCodeGenerator removeConstant: #COGMTVM. &quot;this should be defined at compile time&quot;<br>
        aCCodeGenerator<br>
                addHeaderFile:&#39;&lt;stddef.h&gt;&#39;; &quot;for e.g. offsetof&quot;<br>
                addHeaderFile:&#39;&quot;sqCogStackAlignment.h&quot;&#39;;<br>
                addHeaderFile:&#39;&quot;dispdbg.h&quot;&#39;; &quot;must precede cointerp.h &amp; cogit.h otherwise NoDbgRegParms gets screwed up&quot;<br>
                addHeaderFile:&#39;&quot;cogmethod.h&quot;&#39;.<br>
        NewspeakVM ifTrue:<br>
                [aCCodeGenerator addHeaderFile:&#39;&quot;nssendcache.h&quot;&#39;].<br>
        aCCodeGenerator<br>
                addHeaderFile:&#39;#if COGMTVM&#39;;<br>
                addHeaderFile:&#39;&quot;cointerpmt.h&quot;&#39;;<br>
                addHeaderFile:&#39;#else&#39;;<br>
                addHeaderFile:&#39;&quot;cointerp.h&quot;&#39;;<br>
                addHeaderFile:&#39;#endif&#39;;<br>
                addHeaderFile:&#39;&quot;cogit.h&quot;&#39;.<br>
        aCCodeGenerator<br>
                var: #ceGetSP<br>
                        declareC: &#39;unsigned long (*ceGetSP)(void)&#39;;<br>
                var: #ceCaptureCStackPointers<br>
                        declareC: &#39;void (*ceCaptureCStackPointers)(void)&#39;;<br>
                var: #ceEnterCogCodePopReceiverReg<br>
                        declareC: &#39;void (*ceEnterCogCodePopReceiverReg)(void)&#39;;<br>
                var: #realCEEnterCogCodePopReceiverReg<br>
                        declareC: &#39;void (*realCEEnterCogCodePopReceiverReg)(void)&#39;;<br>
                var: #ceCallCogCodePopReceiverReg<br>
                        declareC: &#39;void (*ceCallCogCodePopReceiverReg)(void)&#39;;<br>
                var: #realCECallCogCodePopReceiverReg<br>
                        declareC: &#39;void (*realCECallCogCodePopReceiverReg)(void)&#39;;<br>
                var: #ceCallCogCodePopReceiverAndClassRegs<br>
                        declareC: &#39;void (*ceCallCogCodePopReceiverAndClassRegs)(void)&#39;;<br>
                var: #realCECallCogCodePopReceiverAndClassRegs<br>
                        declareC: &#39;void (*realCECallCogCodePopReceiverAndClassRegs)(void)&#39;;<br>
                var: #ceFlushICache<br>
                        declareC: &#39;static void (*ceFlushICache)(unsigned long from, unsigned long to)&#39;;<br>
                var: #ceCheckFeaturesFunction<br>
                        declareC: &#39;static unsigned long (*ceCheckFeaturesFunction)(void)&#39;;<br>
                var: #ceTryLockVMOwner<br>
                        declareC: &#39;unsigned long (*ceTryLockVMOwner)(void)&#39;;<br>
                var: #ceUnlockVMOwner<br>
                        declareC: &#39;void (*ceUnlockVMOwner)(void)&#39;;<br>
                var: #postCompileHook<br>
                        declareC: &#39;void (*postCompileHook)(CogMethod *)&#39;;<br>
                var: #openPICList declareC: &#39;CogMethod *openPICList = 0&#39;;<br>
                var: #maxMethodBefore type: #&#39;CogBlockMethod *&#39;.<br>
        aCCodeGenerator<br>
                declareVar: &#39;aMethodLabel&#39; type: #&#39;AbstractInstruction&#39;; &quot;Has to come lexicographically before backEnd &amp; methodLabel&quot;<br>
                var: #backEnd declareC: &#39;AbstractInstruction * const backEnd = &amp;aMethodLabel&#39;;<br>
                var: #methodLabel declareC: &#39;AbstractInstruction * const methodLabel = &amp;aMethodLabel&#39;.<br>
        self declareC: #(abstractOpcodes stackCheckLabel<br>
                                        blockEntryLabel blockEntryNoContextSwitch<br>
                                        stackOverflowCall sendMiss<br>
                                        entry noCheckEntry selfSendEntry dynSuperEntry<br>
+                                       picMNUAbort picInterpretAbort  endCPICCase0 endCPICCase1 cPICEndOfCodeLabel)<br>
-                                       picMNUAbort picInterpretAbort endCPICCase0 endCPICCase1)<br>
                        as: #&#39;AbstractInstruction *&#39;<br>
                                in: aCCodeGenerator.<br>
        aCCodeGenerator<br>
                declareVar: #blockStarts type: #&#39;BlockStart *&#39;;<br>
                declareVar: #fixups type: #&#39;BytecodeFixup *&#39;.<br>
        aCCodeGenerator<br>
                var: #ordinarySendTrampolines<br>
                        declareC: &#39;sqInt ordinarySendTrampolines[NumSendTrampolines]&#39;;<br>
                var: #superSendTrampolines<br>
                        declareC: &#39;sqInt superSendTrampolines[NumSendTrampolines]&#39;;<br>
                var: #directedSuperSendTrampolines<br>
                        declareC: &#39;sqInt directedSuperSendTrampolines[NumSendTrampolines]&#39;;<br>
                var: #selfSendTrampolines<br>
                        declareC: &#39;sqInt selfSendTrampolines[NumSendTrampolines]&#39;;<br>
                var: #dynamicSuperSendTrampolines<br>
                        declareC: &#39;sqInt dynamicSuperSendTrampolines[NumSendTrampolines]&#39;;<br>
                var: #implicitReceiverSendTrampolines<br>
                        declareC: &#39;sqInt implicitReceiverSendTrampolines[NumSendTrampolines]&#39;;<br>
                var: #outerSendTrampolines<br>
                        declareC: &#39;sqInt outerSendTrampolines[NumSendTrampolines]&#39;;<br>
                var: #trampolineAddresses<br>
                        declareC: &#39;static char *trampolineAddresses[NumTrampolines*2]&#39;;<br>
                var: #objectReferencesInRuntime<br>
                        declareC: &#39;static usqInt objectReferencesInRuntime[NumObjRefsInRuntime]&#39;;<br>
                var: #labelCounter<br>
                        type: #int;<br>
                var: #traceFlags<br>
                        declareC: &#39;int traceFlags = 8 /* prim trace log on by default */&#39;;<br>
                var: #cStackAlignment<br>
                        declareC: &#39;const int cStackAlignment = STACK_ALIGN_BYTES&#39;.<br>
        aCCodeGenerator<br>
                declareVar: #CFramePointer type: #&#39;void *&#39;;<br>
                declareVar: #CStackPointer type: #&#39;void *&#39;;<br>
                declareVar: #minValidCallAddress type: #&#39;unsigned long&#39;;<br>
                declareVar: #debugPrimCallStackOffset type: #&#39;unsigned long&#39;.<br>
        aCCodeGenerator vmClass generatorTable ifNotNil:<br>
                [:bytecodeGenTable|<br>
                aCCodeGenerator<br>
                        var: #generatorTable<br>
                                declareC: &#39;static BytecodeDescriptor generatorTable[&#39;, bytecodeGenTable size, &#39;]&#39;,<br>
                                                        (self tableInitializerFor: bytecodeGenTable<br>
                                                                in: aCCodeGenerator);<br>
                        var: #primitiveGeneratorTable<br>
                                declareC: &#39;static PrimitiveDescriptor primitiveGeneratorTable[MaxCompiledPrimitiveIndex+1]&#39;,<br>
                                                        (self tableInitializerFor: aCCodeGenerator vmClass primitiveTable<br>
                                                                in: aCCodeGenerator)].<br>
        &quot;In C the abstract opcode names clash with the Smalltak generator syntactic sugar.<br>
         Most of the syntactic sugar is inlined, but alas some remains.  Rename the syntactic<br>
         sugar to avoid the clash.&quot;<br>
        (self organization listAtCategoryNamed: #&#39;abstract instructions&#39;) do:<br>
                [:s|<br>
                aCCodeGenerator addSelectorTranslation: s to: &#39;g&#39;, (aCCodeGenerator cFunctionNameFor: s)].<br>
        aCCodeGenerator addSelectorTranslation: #halt: to: &#39;haltmsg&#39;!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;addressOfEndOfCase:inCPIC: (in category &#39;in-line cacheing&#39;) -----<br>
+ addressOfEndOfCase: n inCPIC: cPIC<br>
+       &quot;calculate the end of the n&#39;th case statement - which is complicated because we have case 1 right at the top of our CPIC and then build up from the last one. Yes I know this sounds strange, but trust me - I&#39;m an Engineer, we do things backwards all the emit&quot;<br>
+<br>
- addressOfEndOfCase: n inCPIC: cPIC<br>
-       &quot;N.B. zero-relative&quot;<br>
        &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
+       self assert: (n &gt;= 1and: [n &lt;= maxCPICCases]).<br>
+       n = 1<br>
+               ifTrue: [^ cPIC asInteger + firstCPICCaseOffset]<br>
+               ifFalse: [^ cPIC asInteger + firstCPICCaseOffset + (maxCPICCases + 1 - n * cPICCaseSize)]!<br>
-       ^cPIC asInteger + firstCPICCaseOffset + (n * cPICCaseSize)!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;cPIC:HasTarget: (in category &#39;in-line cacheing&#39;) -----<br>
  cPIC: cPIC HasTarget: targetMethod<br>
+       &quot;Are any of the jumps from this CPIC to targetMethod?&quot;<br>
        &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
        &lt;var: #targetMethod type: #&#39;CogMethod *&#39;&gt;<br>
        | pc target |<br>
        target := targetMethod asUnsignedInteger + cmNoCheckEntryOffset.<br>
        pc := cPIC asInteger + firstCPICCaseOffset.<br>
+       &quot;Since this is a fast test doing simple compares we don&#39;t need to care that some<br>
+       cases have nonsense addresses in there. Just zip on through&quot;<br>
        1 to: cPIC cPICNumCases do:<br>
                [:i|<br>
+               target = (backEnd jumpLongTargetBeforeFollowingAddress: pc) ifTrue:<br>
-               target = (literalsManager cPICCase: i jumpTargetBefore: pc) ifTrue:<br>
                        [^true].<br>
                pc := pc + cPICCaseSize].<br>
        ^false!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;cPICHasForwardedClass: (in category &#39;in-line cacheing&#39;) -----<br>
+ cPICHasForwardedClass: cPIC<br>
+       &quot;The first case in a CPIC doesn&#39;t have a class reference so we need only step over actually usd subsequent cases.&quot;<br>
- cPICHasForwardedClass: cPIC<br>
-       &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
        | pc |<br>
+       &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
+       &quot;start by finding the address of the topmost case, the cPICNumCases&#39;th one&quot;<br>
+       pc := (self addressOfEndOfCase: cPIC cPICNumCases inCPIC: cPIC)<br>
+                               - backEnd jumpLongConditionalByteSize.<br>
+       2 to: cPIC cPICNumCases do:<br>
+                       [:i |  | classIndex |<br>
+                       classIndex := literalsManager classRefInClosedPICAt: pc.<br>
+                       (objectMemory isForwardedClassIndex: classIndex)<br>
+                               ifTrue: [^ true].<br>
+                       &quot;since we started at the top, we can just add the case size each time to move on to the next case&quot;<br>
+                       pc := pc + cPICCaseSize].<br>
+       ^ false!<br>
-       pc := cPIC asUnsignedInteger<br>
-               + firstCPICCaseOffset<br>
-               + cPICCaseSize<br>
-               - backEnd jumpLongConditionalByteSize.<br>
-       2 to: cPIC cPICNumCases do:<br>
-               [:i| | classIndex |<br>
-               classIndex := literalsManager classRefInClosedPICAt: pc.<br>
-               (objectMemory isForwardedClassIndex: classIndex) ifTrue:<br>
-                       [^true].<br>
-               pc := pc + cPICCaseSize].<br>
-       ^false!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;cPICHasFreedTargets: (in category &#39;in-line cacheing&#39;) -----<br>
  cPICHasFreedTargets: cPIC<br>
+       &quot;scan the CPIC for target methods that have been freed. &quot;<br>
        &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
        | pc entryPoint targetMethod |<br>
        &lt;var: #targetMethod type: #&#39;CogMethod *&#39;&gt;<br>
+<br>
-       pc := cPIC asInteger + firstCPICCaseOffset.<br>
        1 to: cPIC cPICNumCases do:<br>
                [:i|<br>
+               pc := self addressOfEndOfCase: i inCPIC: cPIC.<br>
+               entryPoint := backEnd jumpLongTargetBeforeFollowingAddress: pc.<br>
-               entryPoint := literalsManager cPICCase: i jumpTargetBefore: pc.<br>
                &quot;Find target from jump.  Ignore jumps to the interpret and MNU calls within this PIC&quot;<br>
                (cPIC containsAddress: entryPoint) ifFalse:<br>
                        [targetMethod := self cCoerceSimple: entryPoint - cmNoCheckEntryOffset to: #&#39;CogMethod *&#39;.<br>
                         self assert: (targetMethod cmType = CMMethod or: [targetMethod cmType = CMFree]).<br>
                         targetMethod cmType = CMFree ifTrue:<br>
+                               [^true]]].<br>
-                               [^true]].<br>
-               pc := pc + cPICCaseSize].<br>
        ^false!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;ceCPICMiss:receiver: (in category &#39;in-line cacheing&#39;) -----<br>
  ceCPICMiss: cPIC receiver: receiver<br>
        &quot;Code entry closed PIC miss.  A send has fallen<br>
         through a closed (finite) polymorphic inline cache.<br>
         Either extend it or patch the send site to an open PIC.<br>
         The stack looks like:<br>
                        receiver<br>
                        args<br>
          sp=&gt;  sender return address&quot;<br>
        &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
        &lt;api&gt;<br>
        | outerReturn newTargetMethodOrNil errorSelectorOrNil cacheTag result |<br>
        self cCode: &#39;&#39;<br>
                inSmalltalk:<br>
                        [cPIC isInteger ifTrue:<br>
                                [^self ceCPICMiss: (self cogMethodSurrogateAt: cPIC) receiver: receiver]].<br>
        (objectMemory isOopForwarded: receiver) ifTrue:<br>
                [^coInterpreter ceSendFromInLineCacheMiss: cPIC].<br>
        outerReturn := coInterpreter stackTop.<br>
        self deny: (backEnd inlineCacheTagAt: outerReturn) = self picAbortDiscriminatorValue.<br>
+       cPIC cPICNumCases &lt; maxCPICCases<br>
-       cPIC cPICNumCases &lt; numPICCases<br>
                ifTrue:<br>
                        [self lookup: cPIC selector<br>
                                for: receiver<br>
                                methodAndErrorSelectorInto:<br>
                                        [:method :errsel|<br>
                                        newTargetMethodOrNil := method.<br>
                                        errorSelectorOrNil := errsel]]<br>
                ifFalse: [newTargetMethodOrNil := errorSelectorOrNil := nil].<br>
        &quot;We assume lookupAndCog:for: will *not* reclaim the method zone&quot;<br>
        self assert: outerReturn = coInterpreter stackTop.<br>
        cacheTag := objectRepresentation inlineCacheTagForInstance: receiver.<br>
+       (cPIC cPICNumCases &gt;= maxCPICCases<br>
-       (cPIC cPICNumCases &gt;= numPICCases<br>
         or: [(errorSelectorOrNil notNil and: [errorSelectorOrNil ~= SelectorDoesNotUnderstand])<br>
         or: [(objectRepresentation inlineCacheTagIsYoung: cacheTag)<br>
         or: [newTargetMethodOrNil isNil<br>
         or: [objectMemory isYoung: newTargetMethodOrNil]]]]) ifTrue:<br>
                [result := self patchToOpenPICFor: cPIC selector<br>
                                        numArgs: cPIC cmNumArgs<br>
                                        receiver: receiver.<br>
                 self assert: result not. &quot;If patchToOpenPICFor:.. returns we&#39;re out of code memory&quot;<br>
                 ^coInterpreter ceSendFromInLineCacheMiss: cPIC].<br>
        &quot;Now extend the PIC with the new case.&quot;<br>
        self cogExtendPIC: cPIC<br>
                CaseNMethod: newTargetMethodOrNil<br>
                tag: cacheTag<br>
                isMNUCase: errorSelectorOrNil = SelectorDoesNotUnderstand.<br>
        &quot;Jump back into the pic at its entry in case this is an MNU.&quot;<br>
        coInterpreter<br>
                executeCogPIC: cPIC<br>
                fromLinkedSendWithReceiver: receiver<br>
                andCacheTag: (backEnd inlineCacheTagAt: outerReturn).<br>
        &quot;NOTREACHED&quot;<br>
        ^nil!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;checkValidObjectReferencesInClosedPIC: (in category &#39;garbage collection&#39;) -----<br>
  checkValidObjectReferencesInClosedPIC: cPIC<br>
        &lt;var: #cPIC type: #&#39;CogMethod *&#39;&gt;<br>
        | ok pc |<br>
        ok := true.<br>
        pc := cPIC asInteger + firstCPICCaseOffset.<br>
+<br>
+       &quot;first we check the obj ref at the beginning of the CPIC&quot;<br>
        (self checkMaybeObjRefInClosedPIC: (literalsManager objRefInClosedPICAt: pc - backEnd jumpLongByteSize)) ifFalse:<br>
                [self print: &#39;object leak in CPIC &#39;; printHex: cPIC asInteger;<br>
                        print: &#39; @ &#39;; printHex: pc - backEnd jumpLongByteSize; cr.<br>
                 ok := false].<br>
+<br>
+       &quot;Next we step over each case that is in use. We find the end address of the cPICNumCases&#39;th case and can then just step forward by the case size thereafter&quot;<br>
+       pc := self addressOfEndOfCase: cPIC cPICNumCases inCPIC: cPIC.<br>
+<br>
+       &quot;For each case we check any object reference at the end address - sizeof(conditional instruction) and then increment the end address by case size&quot;<br>
-       pc := pc + cPICCaseSize.<br>
        2 to: cPIC cPICNumCases do:<br>
                [:i|<br>
                objectRepresentation inlineCacheTagsMayBeObjects ifTrue:<br>
                        [(self checkMaybeObjRefInClosedPIC: (literalsManager classRefInClosedPICAt: pc - backEnd jumpLongConditionalByteSize)) ifFalse:<br>
                                [self print: &#39;object leak in CPIC &#39;; printHex: cPIC asInteger;<br>
                                        print: &#39; @ &#39;; printHex: pc - backEnd jumpLongConditionalByteSize - backEnd loadLiteralByteSize; cr.<br>
                                 ok := false]].<br>
                (self checkMaybeObjRefInClosedPIC: (literalsManager objRefInClosedPICAt: pc - backEnd jumpLongConditionalByteSize)) ifFalse:<br>
                        [self print: &#39;object leak in CPIC &#39;; printHex: cPIC asInteger;<br>
                                print: &#39; @ &#39;; printHex: pc - backEnd jumpLongConditionalByteSize; cr.<br>
                         ok := false].<br>
                pc := pc + cPICCaseSize].<br>
        ^ok!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit&gt;&gt;closedPICRefersToUnmarkedObject: (in category &#39;garbage collection&#39;) -----<br>
  </blockquote></div></div><br>...<br><br>[Message tronqué]  </blockquote></div><br></div>