[Vm-dev] VM Maker: VMMaker.oscog-nice.1763.mcz
commits at source.squeak.org
commits at source.squeak.org
Tue Apr 5 18:22:02 UTC 2016
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1763.mcz
==================== Summary ====================
Name: VMMaker.oscog-nice.1763
Author: nice
Time: 5 April 2016, 8:19:42.268 pm
UUID: 30469988-b81f-45e0-927c-bb7b9585656f
Ancestors: VMMaker.oscog-nice.1760, VMMaker.oscog-cb.1762
merge VMMaker.oscog-nice.1760 (LargeIntegers changes), and VMMaker.oscog-cb.1762 (JIT changes).
Warning: this requires revision 3668 of SVN http://squeakvm.org/svn/squeak/branches/Cog
=============== Diff against VMMaker.oscog-nice.1760 ===============
Item was changed:
----- Method: SimpleStackBasedCogit class>>initializeBytecodeTableForSistaV1 (in category 'class initialization') -----
initializeBytecodeTableForSistaV1
"SimpleStackBasedCogit initializeBytecodeTableForSistaV1"
BytecodeSetHasDirectedSuperSend := true.
FirstSpecialSelector := 96.
NumSpecialSelectors := 32.
self flag:
'Special selector send class must be inlined to agree with the interpreter, which
inlines class. If class is sent to e.g. a general instance of ProtoObject then unless
class is inlined there will be an MNU. It must be that the Cointerpreter and Cogit
have identical semantics. We get away with not hardwiring the other special
selectors either because in the Cointerpreter they are not inlined or because they
are inlined only to instances of classes for which there will always be a method.'.
self generatorTableFrom: #(
"1 byte bytecodes"
"pushes"
(1 0 15 genPushReceiverVariableBytecode isInstVarRef)
(1 16 31 genPushLiteralVariable16CasesBytecode needsFrameNever: 1)
(1 32 63 genPushLiteralConstantBytecode needsFrameNever: 1)
(1 64 75 genPushTemporaryVariableBytecode)
(1 76 76 genPushReceiverBytecode)
(1 77 77 genPushConstantTrueBytecode needsFrameNever: 1)
(1 78 78 genPushConstantFalseBytecode needsFrameNever: 1)
(1 79 79 genPushConstantNilBytecode needsFrameNever: 1)
(1 80 80 genPushConstantZeroBytecode needsFrameNever: 1)
(1 81 81 genPushConstantOneBytecode needsFrameNever: 1)
(1 82 82 genExtPushPseudoVariable)
(1 83 83 duplicateTopBytecode needsFrameNever: 1)
(1 84 87 unknownBytecode)
"returns"
(1 88 88 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 89 89 genReturnTrue return needsFrameIfInBlock: isMappedInBlock 0)
(1 90 90 genReturnFalse return needsFrameIfInBlock: isMappedInBlock 0)
(1 91 91 genReturnNil return needsFrameIfInBlock: isMappedInBlock 0)
(1 92 92 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 93 93 genReturnNilFromBlock return needsFrameNever: -1)
(1 94 94 genReturnTopFromBlock return needsFrameNever: -1)
(1 95 95 genExtNopBytecode needsFrameNever: 0)
"sends"
(1 96 117 genSpecialSelectorSend isMapped) "#+ #- #< #> #<= #>= #= #~= #* #/ #\\ #@ #bitShift: #// #bitAnd: #bitOr: #at: #at:put: #size #next #nextPut: #atEnd"
(1 118 118 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 119 119 genSpecialSelectorClass needsFrameNever: notMapped 0) "not mapped because it is directly inlined (for now)"
(1 120 127 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
(1 128 143 genSendLiteralSelector0ArgsBytecode isMapped)
(1 144 159 genSendLiteralSelector1ArgBytecode isMapped)
(1 160 175 genSendLiteralSelector2ArgsBytecode isMapped)
"jumps"
(1 176 183 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 184 191 genShortJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 192 199 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
"stores"
(1 200 207 genStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability needsFrameIfImmutability: -1)
(1 208 215 genStoreAndPopTemporaryVariableBytecode)
(1 216 216 genPopStackBytecode needsFrameNever: -1)
(1 217 217 genUnconditionalTrapBytecode isMapped)
(1 218 223 unknownBytecode)
"2 byte bytecodes"
(2 224 224 extABytecode extension)
(2 225 225 extBBytecode extension)
"pushes"
(2 226 226 genExtPushReceiverVariableBytecode isInstVarRef) "Needs a frame for context inst var access"
(2 227 227 genExtPushLiteralVariableBytecode needsFrameNever: 1)
(2 228 228 genExtPushLiteralBytecode needsFrameNever: 1)
(2 229 229 genLongPushTemporaryVariableBytecode)
(2 230 230 genPushClosureTempsBytecode)
(2 231 231 genPushNewArrayBytecode)
(2 232 232 genExtPushIntegerBytecode needsFrameNever: 1)
(2 233 233 genExtPushCharacterBytecode needsFrameNever: 1)
"returns"
"sends"
(2 234 234 genExtSendBytecode isMapped)
(2 235 235 genExtSendSuperBytecode isMapped)
"sista bytecodes"
(2 236 236 unknownBytecode)
"jumps"
(2 237 237 genExtUnconditionalJump branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
(2 238 238 genExtJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 239 239 genExtJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
"stores"
(2 240 240 genExtStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 241 241 genExtStoreAndPopLiteralVariableBytecode isMappedIfImmutability)
(2 242 242 genLongStoreAndPopTemporaryVariableBytecode)
(2 243 243 genExtStoreReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 244 244 genExtStoreLiteralVariableBytecode isMappedIfImmutability)
(2 245 245 genLongStoreTemporaryVariableBytecode)
(2 246 247 unknownBytecode)
"3 byte bytecodes"
(3 248 248 genCallPrimitiveBytecode)
(3 249 249 unknownBytecode) "reserved for Push Float"
(3 250 250 genExtPushClosureBytecode block v4:Block:Code:Size:)
+ (3 251 251 genExtPushRemoteTempOrRemoteInstVarLongBytecode)
+ (3 252 252 genExtStoreRemoteTempOrRemoteInstVarLongBytecode)
+ (3 253 253 genExtStoreAndPopRemoteTempOrRemoteInstVarLongBytecode)
- (3 251 251 genPushRemoteTempLongBytecode)
- (3 252 252 genStoreRemoteTempLongBytecode)
- (3 253 253 genStoreAndPopRemoteTempLongBytecode)
(3 254 254 genExtJumpIfNotInstanceOfBehaviorsOrPopBytecode)
(3 255 255 unknownBytecode))!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genExtPushRemoteTempOrRemoteInstVarLongBytecode (in category 'bytecode generators') -----
+ genExtPushRemoteTempOrRemoteInstVarLongBytecode
+ ^ (byte2 noMask: 1 << 7)
+ ifTrue: [ self genPushRemoteTempLongBytecode ]
+ ifFalse: [ self genExtPushRemoteInstVarLongBytecode ]!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genExtStoreAndPopRemoteTempOrRemoteInstVarLongBytecode (in category 'bytecode generators') -----
+ genExtStoreAndPopRemoteTempOrRemoteInstVarLongBytecode
+ | index |
+ index := byte1 + (extA << 8).
+ extA := 0.
+ ^ (byte2 noMask: 1 << 7)
+ ifTrue: [ self genStorePop: true RemoteTemp: byte1 At: byte2 ]
+ ifFalse: [ self genStorePop: true RemoteInstVar: index At: byte2 - (1 << 7) ]!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genExtStoreRemoteTempOrRemoteInstVarLongBytecode (in category 'bytecode generators') -----
+ genExtStoreRemoteTempOrRemoteInstVarLongBytecode
+ | index |
+ index := byte1 + (extA << 8).
+ extA := 0.
+ ^ (byte2 noMask: 1 << 7)
+ ifTrue: [ self genStorePop: false RemoteTemp: byte1 At: byte2 ]
+ ifFalse: [ self genStorePop: false RemoteInstVar: index At: byte2 - (1 << 7) ]!
Item was changed:
----- Method: SimpleStackBasedCogit>>genJumpIf:to: (in category 'bytecode generator support') -----
genJumpIf: boolean to: targetBytecodePC
<inline: false>
"Cunning trick by LPD. If true and false are contiguous subtract the smaller.
Correct result is either 0 or the distance between them. If result is not 0 or
their distance send mustBeBoolean."
| ok |
<var: #ok type: #'AbstractInstruction *'>
self assert: (objectMemory objectAfter: objectMemory falseObject) = objectMemory trueObject.
self PopR: TempReg.
self annotate: (self SubCw: boolean R: TempReg) objRef: boolean.
self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
self CmpCq: (boolean == objectMemory falseObject
ifTrue: [objectMemory trueObject - objectMemory falseObject]
ifFalse: [objectMemory falseObject - objectMemory trueObject])
R: TempReg.
ok := self JumpZero: 0.
self CallRT: (boolean == objectMemory falseObject
ifTrue: [ceSendMustBeBooleanAddFalseTrampoline]
ifFalse: [ceSendMustBeBooleanAddTrueTrampoline]).
ok jmpTarget: (self annotateBytecode: self Label).
+ extA := 0. "ignores the flag"
^0!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genPushRemoteInstVarLongBytecode (in category 'bytecode generators') -----
+ genPushRemoteInstVarLongBytecode
+ | index |
+ index := byte1 + (extA << 8).
+ extA := 0.
+ self MoveMw: (self frameOffsetOfTemporary: byte2 - (1 << 7)) r: FPReg R: ClassReg.
+ objectRepresentation
+ genEnsureOopInRegNotForwarded: ClassReg
+ scratchReg: TempReg.
+ objectRepresentation
+ genLoadSlot: index
+ sourceReg: ClassReg
+ destReg: TempReg.
+ self PushR: TempReg.
+ ^0!
Item was changed:
----- Method: SimpleStackBasedCogit>>genPushRemoteTempLongBytecode (in category 'bytecode generators') -----
genPushRemoteTempLongBytecode
+ extA := 0.
self MoveMw: (self frameOffsetOfTemporary: byte2) r: FPReg R: ClassReg.
objectRepresentation
genLoadSlot: byte1
sourceReg: ClassReg
destReg: TempReg.
self PushR: TempReg.
^0!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genPushRemoteTempOrRemoteInstVarLongBytecode (in category 'bytecode generators') -----
+ genPushRemoteTempOrRemoteInstVarLongBytecode
+ ^ (byte2 noMask: 1 << 7)
+ ifTrue: [ self genPushRemoteTempLongBytecode ]
+ ifFalse: [ self genPushRemoteInstVarLongBytecode ]!
Item was changed:
----- Method: SimpleStackBasedCogit>>genStorePop:LiteralVariable: (in category 'bytecode generator support') -----
genStorePop: popBoolean LiteralVariable: litVarIndex
<inline: false>
| association |
"The only reason we assert needsFrame here is that in a frameless method
ReceiverResultReg must and does contain only self, but the ceStoreCheck
trampoline expects the target of the store to be in ReceiverResultReg. So
in a frameless method we would have a conflict between the receiver and
the literal store, unless we we smart enough to realise that ReceiverResultReg
was unused after the literal variable store, unlikely given that methods
return self by default."
+ extB := 0. "do the store check anyway"
self assert: needsFrame.
association := self getLiteral: litVarIndex.
self genMoveConstant: association R: ReceiverResultReg.
objectRepresentation
genEnsureObjInRegNotForwarded: ReceiverResultReg
scratchReg: TempReg.
popBoolean
ifTrue: [self PopR: ClassReg]
ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
self
genStoreSourceReg: ClassReg
slotIndex: ValueIndex
destReg: ReceiverResultReg
scratchReg: TempReg
inFrame: needsFrame.
^0!
Item was changed:
----- Method: SimpleStackBasedCogit>>genStorePop:MaybeContextReceiverVariable: (in category 'bytecode generator support') -----
genStorePop: popBoolean MaybeContextReceiverVariable: slotIndex
<inline: false>
| jmpSingle jmpDone |
<var: #jmpSingle type: #'AbstractInstruction *'>
<var: #jmpDone type: #'AbstractInstruction *'>
"The reason we need a frame here is that assigning to an inst var of a context may
involve wholesale reorganization of stack pages, and the only way to preserve the
execution state of an activation in that case is if it has a frame."
+ extB := 0. "do the store check anyway"
self assert: needsFrame.
self putSelfInReceiverResultReg.
objectRepresentation
genLoadSlot: SenderIndex
sourceReg: ReceiverResultReg
destReg: TempReg.
self MoveMw: 0 r: SPReg R: ClassReg.
jmpSingle := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.
self MoveCq: slotIndex R: SendNumArgsReg.
self CallRT: ceStoreContextInstVarTrampoline.
jmpDone := self Jump: 0.
jmpSingle jmpTarget: self Label.
popBoolean ifTrue:
[self AddCq: objectMemory wordSize R: SPReg].
self
genStoreSourceReg: ClassReg
slotIndex: slotIndex
destReg: ReceiverResultReg
scratchReg: TempReg
inFrame: needsFrame.
jmpDone jmpTarget: self Label.
^0!
Item was changed:
----- Method: SimpleStackBasedCogit>>genStorePop:ReceiverVariable: (in category 'bytecode generator support') -----
genStorePop: popBoolean ReceiverVariable: slotIndex
<inline: false>
+ extB := 0. "do the store check anyway"
needsFrame ifTrue:
[self putSelfInReceiverResultReg].
popBoolean
ifTrue: [self PopR: ClassReg]
ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
self
genStoreSourceReg: ClassReg
slotIndex: slotIndex
destReg: ReceiverResultReg
scratchReg: TempReg
inFrame: needsFrame.
^0!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genStorePop:RemoteInstVar:At: (in category 'bytecode generator support') -----
+ genStorePop: popBoolean RemoteInstVar: slotIndex At: objectIndex
+ <inline: false>
+ "The only reason we assert needsFrame here is that in a frameless method
+ ReceiverResultReg must and does contain only self, but the ceStoreCheck
+ trampoline expects the target of the store to be in ReceiverResultReg. So
+ in a frameless method we would have a conflict between the receiver and
+ the temote temp store, unless we we smart enough to realise that
+ ReceiverResultReg was unused after the literal variable store, unlikely given
+ that methods return self by default."
+ extB := 0. "do the store check anyway"
+ self assert: needsFrame.
+ popBoolean
+ ifTrue: [self PopR: ClassReg]
+ ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
+ self MoveMw: (self frameOffsetOfTemporary: objectIndex) r: FPReg R: ReceiverResultReg.
+ objectRepresentation
+ genEnsureOopInRegNotForwarded: ReceiverResultReg
+ scratchReg: TempReg.
+ ^objectRepresentation
+ genStoreSourceReg: ClassReg
+ slotIndex: slotIndex
+ destReg: ReceiverResultReg
+ scratchReg: TempReg
+ inFrame: needsFrame!
Item was changed:
----- Method: SimpleStackBasedCogit>>genStorePop:RemoteTemp:At: (in category 'bytecode generator support') -----
genStorePop: popBoolean RemoteTemp: slotIndex At: remoteTempIndex
<inline: false>
"The only reason we assert needsFrame here is that in a frameless method
ReceiverResultReg must and does contain only self, but the ceStoreCheck
trampoline expects the target of the store to be in ReceiverResultReg. So
in a frameless method we would have a conflict between the receiver and
the temote temp store, unless we we smart enough to realise that
ReceiverResultReg was unused after the literal variable store, unlikely given
that methods return self by default."
+ extB := 0. "do the store check anyway"
self assert: needsFrame.
popBoolean
ifTrue: [self PopR: ClassReg]
ifFalse: [self MoveMw: 0 r: SPReg R: ClassReg].
self MoveMw: (self frameOffsetOfTemporary: remoteTempIndex) r: FPReg R: ReceiverResultReg.
^objectRepresentation
genStoreSourceReg: ClassReg
slotIndex: slotIndex
destReg: ReceiverResultReg
scratchReg: TempReg
inFrame: needsFrame!
Item was changed:
----- Method: SistaStackToRegisterMappingCogit>>genCounterTripOnlyJumpIf:to: (in category 'bytecode generator support') -----
genCounterTripOnlyJumpIf: boolean to: targetBytecodePC
"Specific version if the branch is only reached while falling through if the counter trips after an inlined #== branch. We do not regenerate the counter logic in this case to avoid 24 bytes instructions."
<var: #ok type: #'AbstractInstruction *'>
<var: #mustBeBooleanTrampoline type: #'AbstractInstruction *'>
| ok mustBeBooleanTrampoline |
+ extA := 0. "reset it, we don't care if MBB not needed as we need the trampoline anyway"
+
self ssFlushTo: simStackPtr - 1.
self ssTop popToReg: TempReg.
self ssPop: 1.
counterIndex := counterIndex + 1. "counters are increased / decreased in the inlined branch"
"We need SendNumArgsReg because of the mustBeBooleanTrampoline"
self ssAllocateRequiredReg: SendNumArgsReg.
self MoveCq: 1 R: SendNumArgsReg.
"The first time this is reached, it calls necessarily the counter trip for the trampoline because SendNumArgsReg is non zero"
mustBeBooleanTrampoline := self CallRT: (boolean == objectMemory falseObject
ifTrue: [ceSendMustBeBooleanAddFalseTrampoline]
ifFalse: [ceSendMustBeBooleanAddTrueTrampoline]).
self annotateBytecode: self Label.
"Cunning trick by LPD. If true and false are contiguous subtract the smaller.
Correct result is either 0 or the distance between them. If result is not 0 or
their distance send mustBeBoolean."
self assert: (objectMemory objectAfter: objectMemory falseObject) = objectMemory trueObject.
self annotate: (self SubCw: boolean R: TempReg) objRef: boolean.
self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
self CmpCq: (boolean == objectMemory falseObject
ifTrue: [objectMemory trueObject - objectMemory falseObject]
ifFalse: [objectMemory falseObject - objectMemory trueObject])
R: TempReg.
ok := self JumpZero: 0.
self MoveCq: 0 R: SendNumArgsReg. "if counterReg is 0 this is a mustBeBoolean, not a counter trip."
self Jump: mustBeBooleanTrampoline.
ok jmpTarget: self Label.
^0!
Item was changed:
----- Method: SistaStackToRegisterMappingCogit>>genJumpIf:to: (in category 'bytecode generator support') -----
genJumpIf: boolean to: targetBytecodePC
"The heart of performance counting in Sista. Conditional branches are 6 times less
frequent than sends and can provide basic block frequencies (send counters can't).
Each conditional has a 32-bit counter split into an upper 16 bits counting executions
and a lower half counting untaken executions of the branch. Executing the branch
decrements the upper half, tripping if the count goes negative. Not taking the branch
decrements the lower half. N.B. We *do not* eliminate dead branches (true ifTrue:/true ifFalse:)
so that scanning for send and branch data is simplified and that branch data is correct."
<inline: false>
+ | ok counterAddress countTripped retry nextDescriptor nextPC |
- | ok counterAddress countTripped retry |
<var: #ok type: #'AbstractInstruction *'>
<var: #retry type: #'AbstractInstruction *'>
<var: #countTripped type: #'AbstractInstruction *'>
+ <var: #nextDescriptor type: #'AbstractInstruction *'>
(coInterpreter isOptimizedMethod: methodObj) ifTrue: [ ^ super genJumpIf: boolean to: targetBytecodePC ].
branchReachedOnlyForCounterTrip ifTrue:
[ branchReachedOnlyForCounterTrip := false.
^ self genCounterTripOnlyJumpIf: boolean to: targetBytecodePC ].
+
+ boolean ifFalse:
+ [ "detection of and: / or:"
+ nextPC := bytecodePC + (self generatorAt: byte0) numBytes.
+ nextDescriptor := self generatorAt: (objectMemory fetchByte: nextPC ofObject: methodObj) + bytecodeSetOffset.
+ nextDescriptor generator == #genPushConstantTrueBytecode ifTrue: [ ^ super genJumpIf: boolean to: targetBytecodePC ].
+ nextDescriptor := self generatorAt: (objectMemory fetchByte: targetBytecodePC ofObject: methodObj) + bytecodeSetOffset.
+ nextDescriptor generator == #genPushConstantFalseBytecode ifTrue: [ ^ super genJumpIf: boolean to: targetBytecodePC ]. ].
+ extA := 0. "reset it, we don't care if MBB not needed as we need the trampoline anyway"
+
self ssFlushTo: simStackPtr - 1.
self ssTop popToReg: TempReg.
self ssPop: 1.
"We need SendNumArgsReg because of the mustBeBooleanTrampoline"
self ssAllocateRequiredReg: SendNumArgsReg.
retry := self Label.
self
genExecutionCountLogicInto: [ :cAddress :countTripBranch |
counterAddress := cAddress.
countTripped := countTripBranch ]
counterReg: SendNumArgsReg.
counterIndex := counterIndex + 1.
"Cunning trick by LPD. If true and false are contiguous subtract the smaller.
Correct result is either 0 or the distance between them. If result is not 0 or
their distance send mustBeBoolean."
self assert: (objectMemory objectAfter: objectMemory falseObject) = objectMemory trueObject.
self annotate: (self SubCw: boolean R: TempReg) objRef: boolean.
self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
self genFallsThroughCountLogicCounterReg: SendNumArgsReg counterAddress: counterAddress.
self CmpCq: (boolean == objectMemory falseObject
ifTrue: [objectMemory trueObject - objectMemory falseObject]
ifFalse: [objectMemory falseObject - objectMemory trueObject])
R: TempReg.
ok := self JumpZero: 0.
self MoveCq: 0 R: SendNumArgsReg. "if counterReg is 0 this is a mustBeBoolean, not a counter trip."
countTripped jmpTarget:
(self CallRT: (boolean == objectMemory falseObject
ifTrue: [ceSendMustBeBooleanAddFalseTrampoline]
ifFalse: [ceSendMustBeBooleanAddTrueTrampoline])).
"If we're in an image which hasn't got the Sista code loaded then the ceCounterTripped:
trampoline will return directly to machine code, returning the boolean. So the code should
jump back to the retry point. The trampoline makes sure that TempReg has been reloaded."
self annotateBytecode: self Label.
self Jump: retry.
ok jmpTarget: self Label.
^0!
Item was changed:
----- Method: StackInterpreter class>>initializeBytecodeTableForSistaV1 (in category 'initialization') -----
initializeBytecodeTableForSistaV1
"See e.g. the cass comment for EncoderForSistaV1"
"StackInterpreter initializeBytecodeTableForSistaV1"
"Note: This table will be used to generate a C switch statement."
BytecodeTable := Array new: 256.
BytecodeEncoderClassName := #EncoderForSistaV1.
BytecodeSetHasDirectedSuperSend := true.
self table: BytecodeTable from:
#( "1 byte bytecodes"
( 0 15 pushReceiverVariableBytecode)
( 16 31 pushLiteralVariable16CasesBytecode)
( 32 63 pushLiteralConstantBytecode)
( 64 75 pushTemporaryVariableBytecode)
( 76 pushReceiverBytecode)
( 77 pushConstantTrueBytecode)
( 78 pushConstantFalseBytecode)
( 79 pushConstantNilBytecode)
( 80 pushConstantZeroBytecode)
( 81 pushConstantOneBytecode)
( 82 extPushPseudoVariable)
( 83 duplicateTopBytecode)
( 84 87 unknownBytecode)
( 88 returnReceiver)
( 89 returnTrue)
( 90 returnFalse)
( 91 returnNil)
( 92 returnTopFromMethod)
( 93 returnNilFromBlock)
( 94 returnTopFromBlock)
( 95 extNopBytecode)
( 96 bytecodePrimAdd)
( 97 bytecodePrimSubtract)
( 98 bytecodePrimLessThanSistaV1) "for booleanCheatSistaV1:"
( 99 bytecodePrimGreaterThanSistaV1) "for booleanCheatSistaV1:"
(100 bytecodePrimLessOrEqualSistaV1) "for booleanCheatSistaV1:"
(101 bytecodePrimGreaterOrEqualSistaV1) "for booleanCheatSistaV1:"
(102 bytecodePrimEqualSistaV1) "for booleanCheatSistaV1:"
(103 bytecodePrimNotEqualSistaV1) "for booleanCheatSistaV1:"
(104 bytecodePrimMultiply)
(105 bytecodePrimDivide)
(106 bytecodePrimMod)
(107 bytecodePrimMakePoint)
(108 bytecodePrimBitShift)
(109 bytecodePrimDiv)
(110 bytecodePrimBitAnd)
(111 bytecodePrimBitOr)
(112 bytecodePrimAt)
(113 bytecodePrimAtPut)
(114 bytecodePrimSize)
(115 bytecodePrimNext) "i.e. a 0 arg special selector"
(116 bytecodePrimNextPut) "i.e. a 1 arg special selector"
(117 bytecodePrimAtEnd)
(118 bytecodePrimIdenticalSistaV1) "for booleanCheatSistaV1:"
(119 bytecodePrimClass)
(120 bytecodePrimSpecialSelector24) "was blockCopy:"
(121 bytecodePrimValue)
(122 bytecodePrimValueWithArg)
(123 bytecodePrimDo) "i.e. a 1 arg special selector"
(124 bytecodePrimNew) "i.e. a 0 arg special selector"
(125 bytecodePrimNewWithArg) "i.e. a 1 arg special selector"
(126 bytecodePrimPointX) "i.e. a 0 arg special selector"
(127 bytecodePrimPointY) "i.e. a 0 arg special selector"
(128 143 sendLiteralSelector0ArgsBytecode)
(144 159 sendLiteralSelector1ArgBytecode)
(160 175 sendLiteralSelector2ArgsBytecode)
(176 183 shortUnconditionalJump)
(184 191 shortConditionalJumpTrue)
(192 199 shortConditionalJumpFalse)
(200 207 storeAndPopReceiverVariableBytecode)
(208 215 storeAndPopTemporaryVariableBytecode)
(216 popStackBytecode)
(217 unconditionnalTrapBytecode)
(218 223 unknownBytecode)
"2 byte bytecodes"
(224 extABytecode)
(225 extBBytecode)
(226 extPushReceiverVariableBytecode)
(227 extPushLiteralVariableBytecode)
(228 extPushLiteralBytecode)
(229 longPushTemporaryVariableBytecode)
(230 pushClosureTempsBytecode)
(231 pushNewArrayBytecode)
(232 extPushIntegerBytecode)
(233 extPushCharacterBytecode)
(234 extSendBytecode)
(235 extSendSuperBytecode)
(236 unknownBytecode)
(237 extUnconditionalJump)
(238 extJumpIfTrue)
(239 extJumpIfFalse)
(240 extStoreAndPopReceiverVariableBytecode)
(241 extStoreAndPopLiteralVariableBytecode)
(242 longStoreAndPopTemporaryVariableBytecode)
(243 extStoreReceiverVariableBytecode)
(244 extStoreLiteralVariableBytecode)
(245 longStoreTemporaryVariableBytecode)
(246 247 unknownBytecode)
"3 byte bytecodes"
(248 callPrimitiveBytecode)
(249 unknownBytecode) "reserved for Push Float"
(250 extPushClosureBytecode)
+ (251 extPushRemoteTempOrRemoteInstVarLongBytecode)
+ (252 extStoreRemoteTempOrRemoteInstVarLongBytecode)
+ (253 extStoreAndPopRemoteTempOrRemoteInstVarLongBytecode)
- (251 pushRemoteTempLongBytecode)
- (252 storeRemoteTempLongBytecode)
- (253 storeAndPopRemoteTempLongBytecode)
(254 extJumpIfNotInstanceOfBehaviorsOrPopBytecode)
(255 unknownBytecode)
)!
Item was added:
+ ----- Method: StackInterpreter>>extPushRemoteInstVar:inObjectAt: (in category 'stack bytecodes') -----
+ extPushRemoteInstVar: byte1 inObjectAt: objectIndex
+ | instVarIndex object |
+ instVarIndex := byte1 + (extA << 8).
+ extA := 0.
+ object := self temporary: objectIndex in: localFP.
+ (objectMemory isForwarded: object) ifTrue:
+ [object := objectMemory followForwarded: object].
+ self internalPush: (objectMemory fetchPointer: instVarIndex ofObject: object).!
Item was added:
+ ----- Method: StackInterpreter>>extPushRemoteTempOrRemoteInstVarLongBytecode (in category 'stack bytecodes') -----
+ extPushRemoteTempOrRemoteInstVarLongBytecode
+ | byte1 byte2 |
+ byte1 := self fetchByte.
+ byte2 := self fetchByte.
+ self fetchNextBytecode.
+ (byte2 noMask: 1 << 7)
+ ifTrue:
+ [ self pushRemoteTemp: byte1 inVectorAt: byte2 ]
+ ifFalse:
+ [ self extPushRemoteInstVar: byte1 inObjectAt: byte2 - (1 << 7) ]
+ !
Item was added:
+ ----- Method: StackInterpreter>>extStoreAndPopRemoteTempOrRemoteInstVarLongBytecode (in category 'stack bytecodes') -----
+ extStoreAndPopRemoteTempOrRemoteInstVarLongBytecode
+ | byte1 byte2 |
+ byte1 := self fetchByte.
+ byte2 := self fetchByte.
+ self fetchNextBytecode.
+ (byte2 noMask: 1 << 7)
+ ifTrue:
+ [ self storeRemoteTemp: byte1 inVectorAt: byte2.
+ self internalPop: 1 ]
+ ifFalse:
+ [ self extStoreRemoteInstVar: byte1 inObjectAt: byte2 - (1 << 7).
+ self internalPop: 1 ]
+ !
Item was added:
+ ----- Method: StackInterpreter>>extStoreRemoteInstVar:inObjectAt: (in category 'stack bytecodes') -----
+ extStoreRemoteInstVar: byte1 inObjectAt: objectIndex
+ | instVarIndex object |
+ instVarIndex := byte1 + (extA << 8).
+ extA := 0.
+ object := self temporary: objectIndex in: localFP.
+ (objectMemory isForwarded: object) ifTrue:
+ [object := objectMemory followForwarded: object].
+ objectMemory storePointerImmutabilityCheck: instVarIndex ofObject: object withValue: self internalStackTop!
Item was added:
+ ----- Method: StackInterpreter>>extStoreRemoteTempOrRemoteInstVarLongBytecode (in category 'stack bytecodes') -----
+ extStoreRemoteTempOrRemoteInstVarLongBytecode
+ | byte1 byte2 |
+ byte1 := self fetchByte.
+ byte2 := self fetchByte.
+ self fetchNextBytecode.
+ (byte2 noMask: 1 << 7)
+ ifTrue:
+ [ self storeRemoteTemp: byte1 inVectorAt: byte2 ]
+ ifFalse:
+ [ self extStoreRemoteInstVar: byte1 inObjectAt: byte2 - (1 << 7) ]
+ !
Item was changed:
----- Method: StackToRegisterMappingCogit class>>initializeBytecodeTableForSistaV1 (in category 'class initialization') -----
initializeBytecodeTableForSistaV1
"StackToRegisterMappingCogit initializeBytecodeTableForSistaV1"
numPushNilsFunction := #sistaV1:Num:Push:Nils:.
pushNilSizeFunction := #sistaV1PushNilSize:numInitialNils:.
BytecodeSetHasDirectedSuperSend := true.
FirstSpecialSelector := 96.
NumSpecialSelectors := 32.
self flag:
'Special selector send class must be inlined to agree with the interpreter, which
inlines class. If class is sent to e.g. a general instance of ProtoObject then unless
class is inlined there will be an MNU. It must be that the Cointerpreter and Cogit
have identical semantics. We get away with not hardwiring the other special
selectors either because in the Cointerpreter they are not inlined or because they
are inlined only to instances of classes for which there will always be a method.'.
self generatorTableFrom: #(
"1 byte bytecodes"
"pushes"
(1 0 15 genPushReceiverVariableBytecode isInstVarRef needsFrameNever: 1)
(1 16 31 genPushLitVarDirSup16CasesBytecode needsFrameNever: 1)
(1 32 63 genPushLiteralConstantBytecode needsFrameNever: 1)
(1 64 75 genPushTemporaryVariableBytecode needsFrameIfMod16GENumArgs: 1)
(1 76 76 genPushReceiverBytecode needsFrameNever: 1)
(1 77 77 genPushConstantTrueBytecode needsFrameNever: 1)
(1 78 78 genPushConstantFalseBytecode needsFrameNever: 1)
(1 79 79 genPushConstantNilBytecode needsFrameNever: 1)
(1 80 80 genPushConstantZeroBytecode needsFrameNever: 1)
(1 81 81 genPushConstantOneBytecode needsFrameNever: 1)
(1 82 82 genExtPushPseudoVariable)
(1 83 83 duplicateTopBytecode needsFrameNever: 1)
(1 84 87 unknownBytecode)
"returns"
(1 88 88 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 89 89 genReturnTrue return needsFrameIfInBlock: isMappedInBlock 0)
(1 90 90 genReturnFalse return needsFrameIfInBlock: isMappedInBlock 0)
(1 91 91 genReturnNil return needsFrameIfInBlock: isMappedInBlock 0)
(1 92 92 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 93 93 genReturnNilFromBlock return needsFrameNever: -1)
(1 94 94 genReturnTopFromBlock return needsFrameNever: -1)
(1 95 95 genExtNopBytecode needsFrameNever: 0)
"sends"
(1 96 96 genSpecialSelectorArithmetic isMapped AddRR)
(1 97 97 genSpecialSelectorArithmetic isMapped SubRR)
(1 98 98 genSpecialSelectorComparison isMapped JumpLess)
(1 99 99 genSpecialSelectorComparison isMapped JumpGreater)
(1 100 100 genSpecialSelectorComparison isMapped JumpLessOrEqual)
(1 101 101 genSpecialSelectorComparison isMapped JumpGreaterOrEqual)
(1 102 102 genSpecialSelectorComparison isMapped JumpZero)
(1 103 103 genSpecialSelectorComparison isMapped JumpNonZero)
(1 104 109 genSpecialSelectorSend isMapped) " #* #/ #\\ #@ #bitShift: //"
(1 110 110 genSpecialSelectorArithmetic isMapped AndRR)
(1 111 111 genSpecialSelectorArithmetic isMapped OrRR)
(1 112 117 genSpecialSelectorSend isMapped) "#at: #at:put: #size #next #nextPut: #atEnd"
(1 118 118 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 119 119 genSpecialSelectorClass needsFrameIfStackGreaterThanOne: notMapped 0) "not mapped because it is directly inlined (for now)"
(1 120 127 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
(1 128 143 genSendLiteralSelector0ArgsBytecode isMapped)
(1 144 159 genSendLiteralSelector1ArgBytecode isMapped)
(1 160 175 genSendLiteralSelector2ArgsBytecode isMapped)
"jumps"
(1 176 183 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 184 191 genShortJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 192 199 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 200 207 genStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability needsFrameIfImmutability: -1)
(1 208 215 genStoreAndPopTemporaryVariableBytecode)
(1 216 216 genPopStackBytecode needsFrameNever: -1)
(1 217 217 genUnconditionalTrapBytecode isMapped)
(1 218 223 unknownBytecode)
"2 byte bytecodes"
(2 224 224 extABytecode extension)
(2 225 225 extBBytecode extension)
"pushes"
(2 226 226 genExtPushReceiverVariableBytecode isInstVarRef) "Needs a frame for context inst var access"
(2 227 227 genExtPushLitVarDirSupBytecode needsFrameNever: 1)
(2 228 228 genExtPushLiteralBytecode needsFrameNever: 1)
(2 229 229 genLongPushTemporaryVariableBytecode)
(2 230 230 genPushClosureTempsBytecode)
(2 231 231 genPushNewArrayBytecode)
(2 232 232 genExtPushIntegerBytecode needsFrameNever: 1)
(2 233 233 genExtPushCharacterBytecode needsFrameNever: 1)
"returns"
"sends"
(2 234 234 genExtSendBytecode isMapped)
(2 235 235 genExtSendSuperBytecode isMapped)
"sista bytecodes"
(2 236 236 unknownBytecode)
"jumps"
(2 237 237 genExtUnconditionalJump branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
(2 238 238 genExtJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 239 239 genExtJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
"stores"
(2 240 240 genExtStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 241 241 genExtStoreAndPopLiteralVariableBytecode isMappedIfImmutability)
(2 242 242 genLongStoreAndPopTemporaryVariableBytecode)
(2 243 243 genExtStoreReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 244 244 genExtStoreLiteralVariableBytecode isMappedIfImmutability)
(2 245 245 genLongStoreTemporaryVariableBytecode)
(2 246 247 unknownBytecode)
"3 byte bytecodes"
(3 248 248 genCallPrimitiveBytecode)
(3 249 249 unknownBytecode) "reserved for Push Float"
(3 250 250 genExtPushClosureBytecode block v4:Block:Code:Size:)
+ (3 251 251 genExtPushRemoteTempOrRemoteInstVarLongBytecode)
+ (3 252 252 genExtStoreRemoteTempOrRemoteInstVarLongBytecode)
+ (3 253 253 genExtStoreAndPopRemoteTempOrRemoteInstVarLongBytecode)
- (3 251 251 genPushRemoteTempLongBytecode)
- (3 252 252 genStoreRemoteTempLongBytecode)
- (3 253 253 genStoreAndPopRemoteTempLongBytecode)
(3 254 254 genExtJumpIfNotInstanceOfBehaviorsOrPopBytecode branch v4:Long:BranchIfNotInstanceOf:Distance:)
(3 255 255 unknownBytecode))!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genImmutabilityCheckStorePop:LiteralVariable: (in category 'bytecode generator support') -----
genImmutabilityCheckStorePop: popBoolean LiteralVariable: litVarIndex
<inline: true>
| association needStoreCheck |
"The only reason we assert needsFrame here is that in a frameless method
ReceiverResultReg must and does contain only self, but the ceStoreCheck
trampoline expects the target of the store to be in ReceiverResultReg. So
in a frameless method we would have a conflict between the receiver and
the literal store, unless we we smart enough to realise that ReceiverResultReg
was unused after the literal variable store, unlikely given that methods
return self by default."
self assert: needsFrame.
"N.B. No need to check the stack for references because we generate code for
literal variable loads that stores the result in a register, deferring only the register push."
+ needStoreCheck := self ssTopNeedsStoreCheck.
- needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
association := self getLiteral: litVarIndex.
optStatus isReceiverResultRegLive: false.
self ssAllocateRequiredReg: ReceiverResultReg. "for store trampoline call in genStoreSourceReg: has to be ReceiverResultReg"
self genMoveConstant: association R: ReceiverResultReg.
objectRepresentation genEnsureObjInRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
self ssAllocateRequiredReg: ClassReg.
self ssStoreAndReplacePop: popBoolean toReg: ClassReg.
self ssFlushTo: simStackPtr.
objectRepresentation
genStoreWithImmutabilityCheckSourceReg: ClassReg
slotIndex: ValueIndex
destReg: ReceiverResultReg
scratchReg: TempReg
needsStoreCheck: needStoreCheck
needRestoreRcvr: false.
^ 0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genImmutabilityCheckStorePop:MaybeContextReceiverVariable: (in category 'bytecode generator support') -----
genImmutabilityCheckStorePop: popBoolean MaybeContextReceiverVariable: slotIndex
<inline: true>
| jmpSingle jmpDone needStoreCheck |
<var: #jmpSingle type: #'AbstractInstruction *'>
<var: #jmpDone type: #'AbstractInstruction *'>
"The reason we need a frame here is that assigning to an inst var of a context may
involve wholesale reorganization of stack pages, and the only way to preserve the
execution state of an activation in that case is if it has a frame."
self assert: needsFrame.
+ needStoreCheck := self ssTopNeedsStoreCheck.
- needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
"Note that ReceiverResultReg remains live after both
ceStoreContextInstVarTrampoline and ceStoreCheckTrampoline."
self ensureReceiverResultRegContainsSelf.
self ssPop: 1.
self ssAllocateCallReg: ClassReg and: SendNumArgsReg. "for ceStoreContextInstVarTrampoline"
self ssPush: 1.
objectRepresentation
genLoadSlot: SenderIndex
sourceReg: ReceiverResultReg
destReg: TempReg.
self ssStoreAndReplacePop: popBoolean toReg: ClassReg.
"stack is flushed except maybe ssTop if popBoolean is false.
ssTop is a SSregister in this case due to #ssStoreAndReplacePop:
to avoid a second indirect read / annotation in case of SSConstant
or SSBaseRegister"
self ssFlushTo: simStackPtr.
jmpSingle := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.
self MoveCq: slotIndex R: SendNumArgsReg.
self CallRT: ceStoreContextInstVarTrampoline.
jmpDone := self Jump: 0.
jmpSingle jmpTarget: self Label.
objectRepresentation
genStoreWithImmutabilityCheckSourceReg: ClassReg
slotIndex: slotIndex
destReg: ReceiverResultReg
scratchReg: TempReg
needsStoreCheck: needStoreCheck
needRestoreRcvr: true.
jmpDone jmpTarget: self Label.
^0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genImmutabilityCheckStorePop:ReceiverVariable: (in category 'bytecode generator support') -----
genImmutabilityCheckStorePop: popBoolean ReceiverVariable: slotIndex
<inline: true>
| needStoreCheck |
self assert: needsFrame.
+ needStoreCheck := self ssTopNeedsStoreCheck.
- needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
"Note that ReceiverResultReg remains live after the trampoline."
self ensureReceiverResultRegContainsSelf.
self ssAllocateRequiredReg: ClassReg.
self ssStoreAndReplacePop: popBoolean toReg: ClassReg.
self ssFlushTo: simStackPtr.
objectRepresentation
genStoreWithImmutabilityCheckSourceReg: ClassReg
slotIndex: slotIndex
destReg: ReceiverResultReg
scratchReg: TempReg
needsStoreCheck: needStoreCheck
needRestoreRcvr: true.
^ 0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genImmutabilityCheckStorePop:RemoteInstVar:At: (in category 'bytecode generator support') -----
+ genImmutabilityCheckStorePop: popBoolean RemoteInstVar: slotIndex At: objectIndex
+ <inline: true>
+ | needStoreCheck |
+ self assert: needsFrame.
+ needStoreCheck := self ssTopNeedsStoreCheck.
+
+ self ssAllocateRequiredReg: ReceiverResultReg.
+ optStatus isReceiverResultRegLive: false.
+ self MoveMw: (self frameOffsetOfTemporary: objectIndex) r: FPReg R: ReceiverResultReg.
+
+ self ssAllocateRequiredReg: ClassReg.
+ self ssStoreAndReplacePop: popBoolean toReg: ClassReg.
+ self ssFlushTo: simStackPtr.
+
+ objectRepresentation
+ genEnsureOopInRegNotForwarded: ReceiverResultReg
+ scratchReg: TempReg.
+
+ objectRepresentation
+ genStoreWithImmutabilityCheckSourceReg: ClassReg
+ slotIndex: slotIndex
+ destReg: ReceiverResultReg
+ scratchReg: TempReg
+ needsStoreCheck: needStoreCheck
+ needRestoreRcvr: false.
+ ^ 0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genJumpIf:to: (in category 'bytecode generator support') -----
genJumpIf: boolean to: targetBytecodePC
<inline: false>
| desc fixup ok |
<var: #desc type: #'CogSimStackEntry *'>
<var: #fixup type: #'BytecodeFixup *'>
<var: #ok type: #'AbstractInstruction *'>
self ssFlushTo: simStackPtr - 1.
desc := self ssTop.
self ssPop: 1.
(desc type == SSConstant
and: [desc constant = objectMemory trueObject or: [desc constant = objectMemory falseObject]]) ifTrue:
["Must arrange there's a fixup at the target whether it is jumped to or
not so that the simStackPtr can be kept correct."
fixup := self ensureFixupAt: targetBytecodePC - initialPC.
"Must enter any annotatedConstants into the map"
desc annotateUse ifTrue:
[self annotateBytecode: (self prevInstIsPCAnnotated
ifTrue: [self Nop]
ifFalse: [self Label])].
"Must annotate the bytecode for correct pc mapping."
self annotateBytecode: (desc constant = boolean
ifTrue: [self Jump: fixup]
ifFalse: [self prevInstIsPCAnnotated
ifTrue: [self Nop]
ifFalse: [self Label]]).
^0].
desc popToReg: TempReg.
+
"Cunning trick by LPD. If true and false are contiguous subtract the smaller.
Correct result is either 0 or the distance between them. If result is not 0 or
their distance send mustBeBoolean."
self assert: (objectMemory objectAfter: objectMemory falseObject) = objectMemory trueObject.
self annotate: (self SubCw: boolean R: TempReg) objRef: boolean.
self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
+
+ (extA anyMask: 1) ifTrue: [ extA := 0. ^ 0 ].
+ self assert: extA = 0.
+
self CmpCq: (boolean == objectMemory falseObject
ifTrue: [objectMemory trueObject - objectMemory falseObject]
ifFalse: [objectMemory falseObject - objectMemory trueObject])
R: TempReg.
ok := self JumpZero: 0.
self CallRT: (boolean == objectMemory falseObject
ifTrue: [ceSendMustBeBooleanAddFalseTrampoline]
ifFalse: [ceSendMustBeBooleanAddTrueTrampoline]).
ok jmpTarget: (self annotateBytecode: self Label).
^0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genPushRemoteInstVarLongBytecode (in category 'bytecode generators') -----
+ genPushRemoteInstVarLongBytecode
+ | tempVectReg remoteTempReg |
+ tempVectReg := self allocateRegNotConflictingWith: 0.
+ self MoveMw: (self frameOffsetOfTemporary: byte2 - (1 << 7)) r: FPReg R: tempVectReg.
+ objectRepresentation
+ genEnsureOopInRegNotForwarded: tempVectReg
+ scratchReg: TempReg.
+ remoteTempReg := self availableRegOrNoneNotConflictingWith: (self registerMaskFor: tempVectReg).
+ remoteTempReg = NoReg ifTrue: [remoteTempReg := tempVectReg].
+ objectRepresentation
+ genLoadSlot: byte1
+ sourceReg: tempVectReg
+ destReg: remoteTempReg.
+ ^self ssPushRegister: remoteTempReg!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genStorePop:RemoteInstVar:At: (in category 'bytecode generator support') -----
+ genStorePop: popBoolean RemoteInstVar: slotIndex At: objectIndex
+ <inline: false>
+ self
+ cppIf: IMMUTABILITY
+ ifTrue: [ ^ self genImmutabilityCheckStorePop: popBoolean RemoteInstVar: slotIndex At: objectIndex ]
+ ifFalse: [ ^ self genVanillaStorePop: popBoolean RemoteInstVar: slotIndex At: objectIndex ]
+ !
Item was changed:
----- Method: StackToRegisterMappingCogit>>genVanillaStorePop:LiteralVariable: (in category 'bytecode generator support') -----
genVanillaStorePop: popBoolean LiteralVariable: litVarIndex
<inline: true>
| topReg association needStoreCheck |
"The only reason we assert needsFrame here is that in a frameless method
ReceiverResultReg must and does contain only self, but the ceStoreCheck
trampoline expects the target of the store to be in ReceiverResultReg. So
in a frameless method we would have a conflict between the receiver and
the literal store, unless we we smart enough to realise that ReceiverResultReg
was unused after the literal variable store, unlikely given that methods
return self by default."
self assert: needsFrame.
"N.B. No need to check the stack for references because we generate code for
literal variable loads that stores the result in a register, deferring only the register push."
+ needStoreCheck := self ssTopNeedsStoreCheck.
- needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
association := self getLiteral: litVarIndex.
optStatus isReceiverResultRegLive: false.
self ssAllocateRequiredReg: ReceiverResultReg. "for ceStoreCheck call in genStoreSourceReg: has to be ReceiverResultReg"
self genMoveConstant: association R: ReceiverResultReg.
objectRepresentation genEnsureObjInRegNotForwarded: ReceiverResultReg scratchReg: TempReg.
topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: ReceiverResultReg).
self ssStorePop: popBoolean toReg: topReg.
objectRepresentation
genStoreSourceReg: topReg
slotIndex: ValueIndex
destReg: ReceiverResultReg
scratchReg: TempReg
inFrame: needsFrame
needsStoreCheck: needStoreCheck.
^ 0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genVanillaStorePop:MaybeContextReceiverVariable: (in category 'bytecode generator support') -----
genVanillaStorePop: popBoolean MaybeContextReceiverVariable: slotIndex
<inline: true>
| jmpSingle jmpDone needStoreCheck |
<var: #jmpSingle type: #'AbstractInstruction *'>
<var: #jmpDone type: #'AbstractInstruction *'>
"The reason we need a frame here is that assigning to an inst var of a context may
involve wholesale reorganization of stack pages, and the only way to preserve the
execution state of an activation in that case is if it has a frame."
self assert: needsFrame.
self ssFlushUpThroughReceiverVariable: slotIndex.
+ needStoreCheck := self ssTopNeedsStoreCheck.
- needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
"Note that ReceiverResultReg remains live after both
ceStoreContextInstVarTrampoline and ceStoreCheckTrampoline."
self ensureReceiverResultRegContainsSelf.
self ssPop: 1.
self ssAllocateCallReg: ClassReg and: SendNumArgsReg. "for ceStoreContextInstVarTrampoline"
self ssPush: 1.
objectRepresentation
genLoadSlot: SenderIndex
sourceReg: ReceiverResultReg
destReg: TempReg.
self ssStorePop: popBoolean toReg: ClassReg.
jmpSingle := objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg.
self MoveCq: slotIndex R: SendNumArgsReg.
self CallRT: ceStoreContextInstVarTrampoline.
jmpDone := self Jump: 0.
jmpSingle jmpTarget: self Label.
objectRepresentation
genStoreSourceReg: ClassReg
slotIndex: slotIndex
destReg: ReceiverResultReg
scratchReg: TempReg
inFrame: true
needsStoreCheck: needStoreCheck.
jmpDone jmpTarget: self Label.
^0!
Item was changed:
----- Method: StackToRegisterMappingCogit>>genVanillaStorePop:ReceiverVariable: (in category 'bytecode generator support') -----
genVanillaStorePop: popBoolean ReceiverVariable: slotIndex
<inline: true>
| topReg needStoreCheck |
self ssFlushUpThroughReceiverVariable: slotIndex.
+ needStoreCheck := self ssTopNeedsStoreCheck.
- needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
"Note that ReceiverResultReg remains live after ceStoreCheckTrampoline."
self ensureReceiverResultRegContainsSelf.
topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: ReceiverResultReg).
self ssStorePop: popBoolean toReg: topReg.
objectRepresentation
genStoreSourceReg: topReg
slotIndex: slotIndex
destReg: ReceiverResultReg
scratchReg: TempReg
inFrame: needsFrame
needsStoreCheck: needStoreCheck.
^ 0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genVanillaStorePop:RemoteInstVar:At: (in category 'bytecode generator support') -----
+ genVanillaStorePop: popBoolean RemoteInstVar: slotIndex At: objectIndex
+ <inline: false>
+ | topReg needStoreCheck |
+ "The only reason we assert needsFrame here is that in a frameless method
+ ReceiverResultReg must and does contain only self, but the ceStoreCheck
+ trampoline expects the target of the store to be in ReceiverResultReg. So
+ in a frameless method we would have a conflict between the receiver and
+ the temote temp store, unless we we smart enough to realise that
+ ReceiverResultReg was unused after the literal variable store, unlikely given
+ that methods return self by default."
+ self assert: needsFrame.
+ "N.B. No need to check the stack for references because we generate code for
+ remote temp loads that stores the result in a register, deferring only the register push."
+ needStoreCheck := (objectRepresentation isUnannotatableConstant: self ssTop) not.
+ topReg := self allocateRegForStackEntryAt: 0 notConflictingWith: (self registerMaskFor: ReceiverResultReg).
+ self ssAllocateRequiredReg: ReceiverResultReg.
+ optStatus isReceiverResultRegLive: false.
+ self ssStorePop: popBoolean toReg: topReg.
+ self MoveMw: (self frameOffsetOfTemporary: objectIndex) r: FPReg R: ReceiverResultReg.
+ objectRepresentation
+ genEnsureOopInRegNotForwarded: ReceiverResultReg
+ scratchReg: TempReg.
+ ^objectRepresentation
+ genStoreSourceReg: topReg
+ slotIndex: slotIndex
+ destReg: ReceiverResultReg
+ scratchReg: TempReg
+ inFrame: needsFrame
+ needsStoreCheck: needStoreCheck!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>ssTopNeedsStoreCheck (in category 'bytecode generator support') -----
+ ssTopNeedsStoreCheck
+ <inline: true>
+ | needsStoreCheck |
+ needsStoreCheck := (extB noMask: 1) and: [ (objectRepresentation isUnannotatableConstant: self ssTop) not ].
+ extB := 0.
+ ^ needsStoreCheck!
More information about the Vm-dev
mailing list