<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"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></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>>extendedStoreBytecodePop: (in category 'stack bytecodes') -----<br>
extendedStoreBytecodePop: popBoolean<br>
"Override to use itemporary:in:put:"<br>
| descriptor variableType variableIndex value |<br>
<inline: true><br>
descriptor := self fetchByte.<br>
- self fetchNextBytecode.<br>
variableType := descriptor >> 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: 'illegal store'!<br>
<br>
Item was changed:<br>
----- Method: CogObjectRepresentationForSpur>>genImmutableCheck:slotIndex:sourceReg:scratchReg:popBoolean:needRestoreRcvr: (in category 'compile abstract instructions') -----<br>
genImmutableCheck: regHoldingObjectMutated slotIndex: index sourceReg: regHoldingValueToStore scratchReg: scratchReg popBoolean: popBoolean needRestoreRcvr: needRestoreRcvr<br>
| mutableJump fail |<br>
<var: #mutableJump type: #'AbstractInstruction *'><br>
<var: #fail type: #'AbstractInstruction *'><br>
<inline: true><br>
<option: #IMMUTABILITY><br>
"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."<br>
self assert: regHoldingObjectMutated == ReceiverResultReg.<br>
self assert: scratchReg == TempReg.<br>
self assert: regHoldingValueToStore == ClassReg.<br>
mutableJump := self genJumpMutable: ClassReg scratchReg: TempReg.<br>
<br>
"We reach this code if the object mutated is immutable."<br>
"simulatedStack state altered for the trampoline, spill top value if needed"<br>
(popBoolean or: [ cogit ssTop spilled ]) ifFalse:<br>
[ self assert: (cogit ssTop type = SSRegister and: [cogit ssTop register = ClassReg]).<br>
cogit PushR: ClassReg ].<br>
"pass the unboxed index using TempReg"<br>
cogit MoveCq: index R: TempReg.<br>
"trampoline call and mcpc to bcpc annotation."<br>
cogit CallRT: ceCannotAssignToWithIndexTrampoline.<br>
cogit annotateBytecode: cogit Label.<br>
"Top of stack is consumed by the trampoline. In case of store with non spilled value,<br>
restore ClassReg to match simulated stack state"<br>
(popBoolean or: [ cogit ssTop spilled ]) ifFalse:<br>
[cogit popR: ClassReg].<br>
"restore ReceiverResultReg state if needed"<br>
+ needRestoreRcvr ifTrue: [ cogit putSelfInReceiverResultReg ].<br>
- needRestoreRcvr ifTrue: [ self putSelfInReceiverResultReg ].<br>
fail := cogit Jump: 0.<br>
<br>
"We reach this code is the object mutated is mutable"<br>
mutableJump jmpTarget: cogit Label.<br>
<br>
^ fail!<br>
<br>
Item was changed:<br>
----- Method: InterpreterPrimitives>>primitiveGetImmutability (in category 'object access primitives') -----<br>
primitiveGetImmutability<br>
<option: #IMMUTABILITY><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>>primitiveSetImmutability (in category 'object access primitives') -----<br>
primitiveSetImmutability<br>
<option: #IMMUTABILITY><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>>doubleExtendedDoAnythingBytecode (in category 'send bytecodes') -----<br>
doubleExtendedDoAnythingBytecode<br>
"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"<br>
| byte2 byte3 opType top |<br>
byte2 := self fetchByte.<br>
byte3 := self fetchByte.<br>
opType := byte2 >> 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>
"opType = 5 is store; opType = 6 is storePop"<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>>extStoreAndPopLiteralVariableBytecode (in category 'stack bytecodes') -----<br>
extStoreAndPopLiteralVariableBytecode<br>
"236 11101100 i i i i i i i i Pop and Store Literal Variable #iiiiiiii (+ Extend A * 256)"<br>
| variableIndex value |<br>
variableIndex := self fetchByte + (extA << 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>>extStoreAndPopReceiverVariableBytecode (in category 'stack bytecodes') -----<br>
extStoreAndPopReceiverVariableBytecode<br>
"235 11101011 i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)"<br>
| variableIndex value |<br>
variableIndex := self fetchByte + (extA << 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>>extStoreLiteralVariableBytecode (in category 'stack bytecodes') -----<br>
extStoreLiteralVariableBytecode<br>
"233 11101001 i i i i i i i i Store Literal Variable #iiiiiiii (+ Extend A * 256)"<br>
| variableIndex |<br>
variableIndex := self fetchByte + (extA << 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>>extStoreReceiverVariableBytecode (in category 'stack bytecodes') -----<br>
extStoreReceiverVariableBytecode<br>
"232 11101000 i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)"<br>
| variableIndex |<br>
variableIndex := self fetchByte + (extA << 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>>extendedStoreBytecodePop: (in category 'stack bytecodes') -----<br>
extendedStoreBytecodePop: popBoolean<br>
| descriptor variableType variableIndex value |<br>
<inline: true><br>
descriptor := self fetchByte.<br>
- self fetchNextBytecode.<br>
variableType := descriptor >> 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: 'illegal store'<br>
!<br>
<br>
Item was changed:<br>
----- Method: StackInterpreter>>storeAndPopReceiverVariableBytecode (in category 'stack bytecodes') -----<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>