<div dir="ltr">I forgot to put the URL, load this package:<div><br></div><div><a href="http://smalltalkhub.com/mc/ClementBera/Immutability/main">http://smalltalkhub.com/mc/ClementBera/Immutability/main</a><br></div><div><br></div><div>to try to use immutability on the Stack VM compiled with #(IMMUTABILITY true), Spur only.</div><div><br></div><div>The JIT is still crashing (I think there are problems in the bcpc to mcpc mapping in what I did I will have a look later).</div></div><div class="gmail_extra"><br><div class="gmail_quote">2016-01-18 18:29 GMT+01:00  <span dir="ltr">&lt;<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>&gt;</span>:<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-cb.1651.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMaker/VMMaker.oscog-cb.1651.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-cb.1651<br>
Author: cb<br>
Time: 18 January 2016, 6:29:12.307 pm<br>
UUID: b53b4619-89ec-4131-bc40-8740fbb218fb<br>
Ancestors: VMMaker.oscog-eem.1650<br>
<br>
In this version, the Stack VM compiled to C is fully working with Immutability ON.<br>
<br>
Load the package to try to use it.<br>
<br>
I fixed the primitive not popping enough the stack...<br>
<br>
Fixed a zip in Cogit.<br>
<br>
Important change in the stack interpreter: if the cannotAssign:withValue: callback was called, its sender pc was ahead by one due to the fetchNextBytecode before the normalSend. I postponed the fetchNextBytecode after the immutability check, which works fine in the compiled VM.<br>
<br>
I think the Simulator works fine too but I might need to fix something there.<br>
<br>
=============== Diff against VMMaker.oscog-eem.1650 ===============<br>
<br>
Item was changed:<br>
  ----- Method: CoInterpreter&gt;&gt;extendedStoreBytecodePop: (in category &#39;stack bytecodes&#39;) -----<br>
  extendedStoreBytecodePop: popBoolean<br>
        &quot;Override to use itemporary:in:put:&quot;<br>
        | descriptor variableType variableIndex value |<br>
        &lt;inline: true&gt;<br>
        descriptor := self fetchByte.<br>
-       self fetchNextBytecode.<br>
        variableType := descriptor &gt;&gt; 6 bitAnd: 3.<br>
        variableIndex := descriptor bitAnd: 63.<br>
        value := self internalStackTop.<br>
        popBoolean ifTrue: [ self internalPop: 1 ].<br>
        variableType = 0 ifTrue:<br>
+               [objectMemory storePointerImmutabilityCheck: variableIndex ofObject: self receiver withValue: value.<br>
+               ^ self fetchNextBytecode.].<br>
-               [^objectMemory storePointerImmutabilityCheck: variableIndex ofObject: self receiver withValue: value].<br>
        variableType = 1 ifTrue:<br>
+               [ self fetchNextBytecode.<br>
+               ^self itemporary: variableIndex in: localFP put: value].<br>
-               [^self itemporary: variableIndex in: localFP put: value].<br>
        variableType = 3 ifTrue:<br>
+               [self storeLiteralVariable: variableIndex withValue: value.<br>
+               ^ self fetchNextBytecode.].<br>
-               [^self storeLiteralVariable: variableIndex withValue: value].<br>
        self error: &#39;illegal store&#39;!<br>
<br>
Item was changed:<br>
  ----- Method: CogObjectRepresentationForSpur&gt;&gt;genImmutableCheck:slotIndex:sourceReg:scratchReg:popBoolean:needRestoreRcvr: (in category &#39;compile abstract instructions&#39;) -----<br>
  genImmutableCheck: regHoldingObjectMutated slotIndex: index sourceReg: regHoldingValueToStore scratchReg: scratchReg popBoolean: popBoolean needRestoreRcvr: needRestoreRcvr<br>
        | mutableJump fail |<br>
        &lt;var: #mutableJump type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;var: #fail type: #&#39;AbstractInstruction *&#39;&gt;<br>
        &lt;inline: true&gt;<br>
        &lt;option: #IMMUTABILITY&gt;<br>
        &quot;Trampoline convention:<br>
        - objectMutated passed in ReceiverResultReg<br>
        - index (unboxed) passed in TempReg<br>
        - valueToStore passed in ClassReg.<br>
        Simulated stack is flushed until simulatedStackPointer - 1, which implies full flush<br>
        if popBoolean is true, else top value may not be flushed.<br>
        We spill the top value (the value to store) for the trampoline if needed.&quot;<br>
        self assert: regHoldingObjectMutated == ReceiverResultReg.<br>
        self assert: scratchReg == TempReg.<br>
        self assert: regHoldingValueToStore == ClassReg.<br>
        mutableJump := self genJumpMutable: ClassReg scratchReg: TempReg.<br>
<br>
        &quot;We reach this code if the object mutated is immutable.&quot;<br>
        &quot;simulatedStack state altered for the trampoline, spill top value if needed&quot;<br>
        (popBoolean or: [ cogit ssTop spilled ]) ifFalse:<br>
                [ self assert: (cogit ssTop type = SSRegister and: [cogit ssTop register = ClassReg]).<br>
                  cogit PushR: ClassReg ].<br>
        &quot;pass the unboxed index using TempReg&quot;<br>
        cogit MoveCq: index R: TempReg.<br>
        &quot;trampoline call and mcpc to bcpc annotation.&quot;<br>
        cogit CallRT: ceCannotAssignToWithIndexTrampoline.<br>
        cogit annotateBytecode: cogit Label.<br>
        &quot;Top of stack is consumed by the trampoline. In case of store with non spilled value,<br>
        restore ClassReg to match simulated stack state&quot;<br>
        (popBoolean or: [ cogit ssTop spilled ]) ifFalse:<br>
                [cogit popR: ClassReg].<br>
        &quot;restore ReceiverResultReg state if needed&quot;<br>
+       needRestoreRcvr ifTrue: [ cogit putSelfInReceiverResultReg ].<br>
-       needRestoreRcvr ifTrue: [ self putSelfInReceiverResultReg ].<br>
        fail := cogit Jump: 0.<br>
<br>
        &quot;We reach this code is the object mutated is mutable&quot;<br>
        mutableJump jmpTarget: cogit Label.<br>
<br>
        ^ fail!<br>
<br>
Item was changed:<br>
  ----- Method: InterpreterPrimitives&gt;&gt;primitiveGetImmutability (in category &#39;object access primitives&#39;) -----<br>
  primitiveGetImmutability<br>
        &lt;option: #IMMUTABILITY&gt;<br>
        | rcvr bool |<br>
        rcvr := self stackValue: 0.<br>
        bool := (objectMemory isOopImmutable: rcvr)<br>
                ifTrue: [ TrueObject ]<br>
                ifFalse: [ FalseObject ].<br>
+       self pop: argumentCount + 1 thenPush: (self splObj: bool)!<br>
-       self pop: argumentCount thenPush: (self splObj: bool)!<br>
<br>
Item was changed:<br>
  ----- Method: InterpreterPrimitives&gt;&gt;primitiveSetImmutability (in category &#39;object access primitives&#39;) -----<br>
  primitiveSetImmutability<br>
        &lt;option: #IMMUTABILITY&gt;<br>
        | rcvr boolean wasImmutable |<br>
        rcvr := self stackValue: 1.<br>
        (objectMemory isImmediate: rcvr) ifTrue: [ ^ self primitiveFailFor: PrimErrInappropriate ].<br>
        boolean := self booleanValueOf: self stackTop.<br>
        self successful ifFalse:<br>
                [^self primitiveFailFor: PrimErrBadArgument].<br>
        boolean ifTrue:<br>
                [ (self canBeImmutable: rcvr) ifFalse: [ ^ self primitiveFailFor: PrimErrInappropriate ] ].<br>
        wasImmutable := (objectMemory isOopImmutable: rcvr)<br>
                ifTrue: [ TrueObject ]<br>
                ifFalse: [ FalseObject ].<br>
        objectMemory setIsImmutableOf: rcvr to: boolean.<br>
+       self pop: argumentCount + 1 thenPush: (self splObj: wasImmutable)!<br>
-       self pop: argumentCount thenPush: (self splObj: wasImmutable)!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter&gt;&gt;doubleExtendedDoAnythingBytecode (in category &#39;send bytecodes&#39;) -----<br>
  doubleExtendedDoAnythingBytecode<br>
        &quot;Replaces the Blue Book double-extended send [132], in which the first byte was wasted on 8 bits of argument count.<br>
        Here we use 3 bits for the operation sub-type (opType),  and the remaining 5 bits for argument count where needed.<br>
        The last byte give access to 256 instVars or literals.<br>
        See also secondExtendedSendBytecode&quot;<br>
        | byte2 byte3 opType top |<br>
        byte2 := self fetchByte.<br>
        byte3 := self fetchByte.<br>
        opType := byte2 &gt;&gt; 5.<br>
        opType = 0 ifTrue:<br>
                [messageSelector := self literal: byte3.<br>
                 argumentCount := byte2 bitAnd: 31.<br>
                 ^self normalSend].<br>
        opType = 1 ifTrue:<br>
                [messageSelector := self literal: byte3.<br>
                 argumentCount := byte2 bitAnd: 31.<br>
                 ^self superclassSend].<br>
+       opType = 2 ifTrue: [self fetchNextBytecode. ^self pushMaybeContextReceiverVariable: byte3].<br>
+       opType = 3 ifTrue: [self fetchNextBytecode. ^self pushLiteralConstant: byte3].<br>
+       opType = 4 ifTrue: [self fetchNextBytecode. ^self pushLiteralVariable: byte3].<br>
-       self fetchNextBytecode.<br>
-       opType = 2 ifTrue: [^self pushMaybeContextReceiverVariable: byte3].<br>
-       opType = 3 ifTrue: [^self pushLiteralConstant: byte3].<br>
-       opType = 4 ifTrue: [^self pushLiteralVariable: byte3].<br>
        top := self internalStackTop.<br>
        opType = 7 ifTrue:<br>
                [self storeLiteralVariable: byte3 withValue: top.<br>
+                ^self fetchNextBytecode].<br>
-                ^self].<br>
        &quot;opType = 5 is store; opType = 6 is storePop&quot;<br>
        opType = 6 ifTrue:<br>
                [self internalPop: 1].<br>
+       self storeMaybeContextReceiverVariable: byte3 withValue: top.<br>
+       self fetchNextBytecode!<br>
-       self storeMaybeContextReceiverVariable: byte3 withValue: top!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter&gt;&gt;extStoreAndPopLiteralVariableBytecode (in category &#39;stack bytecodes&#39;) -----<br>
  extStoreAndPopLiteralVariableBytecode<br>
        &quot;236            11101100        i i i i i i i i Pop and Store Literal Variable #iiiiiiii (+ Extend A * 256)&quot;<br>
        | variableIndex value |<br>
        variableIndex := self fetchByte + (extA &lt;&lt; 8).<br>
-       self fetchNextBytecode.<br>
        value := self internalStackTop.<br>
        self internalPop: 1.<br>
        extA := 0.<br>
+       self storeLiteralVariable: variableIndex withValue: value.<br>
+       self fetchNextBytecode.!<br>
-       self storeLiteralVariable: variableIndex withValue: value!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter&gt;&gt;extStoreAndPopReceiverVariableBytecode (in category &#39;stack bytecodes&#39;) -----<br>
  extStoreAndPopReceiverVariableBytecode<br>
        &quot;235            11101011        i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)&quot;<br>
        | variableIndex value |<br>
        variableIndex := self fetchByte + (extA &lt;&lt; 8).<br>
-       self fetchNextBytecode.<br>
        extA := 0.<br>
        value := self internalStackTop.<br>
        self internalPop: 1.<br>
+       self storeMaybeContextReceiverVariable: variableIndex withValue: value.<br>
+       self fetchNextBytecode.!<br>
-       self storeMaybeContextReceiverVariable: variableIndex withValue: value!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter&gt;&gt;extStoreLiteralVariableBytecode (in category &#39;stack bytecodes&#39;) -----<br>
  extStoreLiteralVariableBytecode<br>
        &quot;233            11101001        i i i i i i i i Store Literal Variable #iiiiiiii (+ Extend A * 256)&quot;<br>
        | variableIndex |<br>
        variableIndex := self fetchByte + (extA &lt;&lt; 8).<br>
-       self fetchNextBytecode.<br>
        extA := 0.<br>
+       self storeLiteralVariable: variableIndex withValue: self internalStackTop.<br>
+       self fetchNextBytecode.!<br>
-       self storeLiteralVariable: variableIndex withValue: self internalStackTop!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter&gt;&gt;extStoreReceiverVariableBytecode (in category &#39;stack bytecodes&#39;) -----<br>
  extStoreReceiverVariableBytecode<br>
        &quot;232            11101000        i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)&quot;<br>
        | variableIndex |<br>
        variableIndex := self fetchByte + (extA &lt;&lt; 8).<br>
-       self fetchNextBytecode.<br>
        extA := 0.<br>
+       self storeMaybeContextReceiverVariable: variableIndex withValue: self internalStackTop.<br>
+       self fetchNextBytecode.!<br>
-       self storeMaybeContextReceiverVariable: variableIndex withValue: self internalStackTop!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter&gt;&gt;extendedStoreBytecodePop: (in category &#39;stack bytecodes&#39;) -----<br>
  extendedStoreBytecodePop: popBoolean<br>
        | descriptor variableType variableIndex value |<br>
        &lt;inline: true&gt;<br>
        descriptor := self fetchByte.<br>
-       self fetchNextBytecode.<br>
        variableType := descriptor &gt;&gt; 6 bitAnd: 3.<br>
        variableIndex := descriptor bitAnd: 63.<br>
        value := self internalStackTop.<br>
        popBoolean ifTrue: [ self internalPop: 1 ].<br>
        variableType = 0 ifTrue:<br>
+               [objectMemory storePointerImmutabilityCheck: variableIndex ofObject: self receiver withValue: value.<br>
+               ^ self fetchNextBytecode].<br>
-               [^objectMemory storePointerImmutabilityCheck: variableIndex ofObject: self receiver withValue: value].<br>
        variableType = 1 ifTrue:<br>
+               [ self fetchNextBytecode.<br>
+               ^self temporary: variableIndex in: localFP put: value].<br>
-               [^self temporary: variableIndex in: localFP put: value].<br>
        variableType = 3 ifTrue:<br>
+               [self storeLiteralVariable: variableIndex withValue: value.<br>
+               ^ self fetchNextBytecode].<br>
-               [^self storeLiteralVariable: variableIndex withValue: value].<br>
        self error: &#39;illegal store&#39;<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter&gt;&gt;storeAndPopReceiverVariableBytecode (in category &#39;stack bytecodes&#39;) -----<br>
  storeAndPopReceiverVariableBytecode<br>
        | rcvr top instVarIndex |<br>
        rcvr := self receiver.<br>
        top := self internalStackTop.<br>
        instVarIndex := currentBytecode bitAnd: 7.<br>
        self internalPop: 1.<br>
-       self fetchNextBytecode.<br>
        objectMemory<br>
                storePointerImmutabilityCheck: instVarIndex<br>
                ofObject: rcvr<br>
+               withValue: top.<br>
+       self fetchNextBytecode.!<br>
-               withValue: top!<br>
<br>
</blockquote></div><br></div>