[Vm-dev] VM Maker: VMMaker.oscog-cb.2003.mcz
commits at source.squeak.org
commits at source.squeak.org
Thu Nov 24 12:44:57 UTC 2016
ClementBera uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-cb.2003.mcz
==================== Summary ====================
Name: VMMaker.oscog-cb.2003
Author: cb
Time: 24 November 2016, 1:44:37.073343 pm
UUID: 9951550e-3f78-457d-a373-2485d63d5abd
Ancestors: VMMaker.oscog-eem.2002
Made #~~ a special selector instead of #blockCopy:.
If the bytecode compiler compiles #~~ using the special selector bytecode, then the pointer comparison with #~~ is inlined as it is with #==.
This leads #~~ to have the same performance as #==. It also means #~~ is not a primitive call, as #==.
I believe this is important for system consistency.
To integrate that in the Squeak / Pharo image, one needs to add #~~ instead of #blockCopy: in the special selector array and add Object>>#~~ as primitive 169 if not already the case.
I compiled both Sista and non Sista VMs with Spur and ensure everything is correct. I "guess" the V3 and Newspeak VMs are correct too.
=============== Diff against VMMaker.oscog-eem.2002 ===============
Item was added:
+ ----- Method: CogObjectRepresentationForSpur>>genInlinedIdenticalOrNotIfGuts: (in category 'compile abstract instructions') -----
+ genInlinedIdenticalOrNotIfGuts: orNot
+ <inline: true>
+ ^ cogit genForwardersInlinedIdenticalOrNotIf: orNot!
Item was removed:
- ----- Method: CogObjectRepresentationForSpur>>genSpecialSelectorEqualsEqualsGuts (in category 'compile abstract instructions') -----
- genSpecialSelectorEqualsEqualsGuts
- < inline: true >
- ^ cogit genSpecialSelectorEqualsEqualsWithForwarders!
Item was added:
+ ----- Method: CogObjectRepresentationForSqueakV3>>genInlinedIdenticalOrNotIf: (in category 'compile abstract instructions') -----
+ genInlinedIdenticalOrNotIf: orNot
+ <inline: true>
+ ^ cogit genVanillaInlinedIdenticalOrNotIf: orNot!
Item was removed:
- ----- Method: CogObjectRepresentationForSqueakV3>>genSpecialSelectorEqualsEqualsGuts (in category 'compile abstract instructions') -----
- genSpecialSelectorEqualsEqualsGuts
- < inline: true >
- ^ cogit genVanillaSpecialSelectorEqualsEquals!
Item was changed:
----- Method: SimpleStackBasedCogit class>>initializeBytecodeTableForNewspeakV4 (in category 'class initialization') -----
initializeBytecodeTableForNewspeakV4
"SimpleStackBasedCogit initializeBytecodeTableForNewspeakV4"
NSSendIsPCAnnotated := false. "IsNSSendCall used by SendAbsentImplicit"
FirstSpecialSelector := 80.
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"
(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 genExtPushPseudoVariableOrOuterBytecode)
(1 78 78 genPushConstantZeroBytecode)
(1 79 79 genPushConstantOneBytecode)
(1 80 101 genSpecialSelectorSend isMapped) "#+ #- #< #> #<= #>= #= #~= #* #/ #\\ #@ #bitShift: #// #bitAnd: #bitOr: #at: #at:put: #size #next #nextPut: #atEnd"
(1 102 102 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 103 103 genSpecialSelectorClass needsFrameNever: notMapped 0) "not mapped because it is directly inlined (for now)"
+ (1 104 104 genSpecialSelectorNotEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
+ (1 105 111 genSpecialSelectorSend isMapped) "#value #value: #do: #new #new: #x #y"
- (1 104 111 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
(1 112 127 genSendLiteralSelector0ArgsBytecode isMapped)
(1 128 143 genSendLiteralSelector1ArgBytecode isMapped)
(1 144 159 genSendLiteralSelector2ArgsBytecode isMapped)
(1 160 175 genSendAbsentImplicit0ArgsBytecode isMapped hasIRC)
(1 176 183 genStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability needsFrameIfImmutability: -1)
(1 184 191 genStoreAndPopTemporaryVariableBytecode)
(1 192 199 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 200 207 genShortJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 208 215 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 216 216 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 217 217 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 218 218 genExtReturnTopFromBlock return needsFrameNever: -1)
(1 219 219 duplicateTopBytecode needsFrameNever: 1)
(1 220 220 genPopStackBytecode needsFrameNever: -1)
(1 221 221 genExtNopBytecode needsFrameNever: 0)
(1 222 223 unknownBytecode)
"2 byte bytecodes"
(2 224 224 extABytecode extension)
(2 225 225 extBBytecode extension)
(2 226 226 genExtPushReceiverVariableBytecode isInstVarRef)
(2 227 227 genExtPushLiteralVariableBytecode needsFrameNever: 1)
(2 228 228 genExtPushLiteralBytecode needsFrameNever: 1)
(2 229 229 genExtPushIntegerBytecode needsFrameNever: 1)
(2 230 230 genLongPushTemporaryVariableBytecode)
(2 231 231 genPushNewArrayBytecode)
(2 232 232 genExtStoreReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 233 233 genExtStoreLiteralVariableBytecode isMappedIfImmutability)
(2 234 234 genLongStoreTemporaryVariableBytecode)
(2 235 235 genExtStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 236 236 genExtStoreAndPopLiteralVariableBytecode isMappedIfImmutability)
(2 237 237 genLongStoreAndPopTemporaryVariableBytecode)
(2 238 238 genExtSendBytecode isMapped)
(2 239 239 genExtSendSuperBytecode isMapped)
(2 240 240 genExtSendAbsentImplicitBytecode isMapped hasIRC)
(2 241 241 genExtSendAbsentDynamicSuperBytecode isMapped hasIRC)
(2 242 242 genExtUnconditionalJump branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
(2 243 243 genExtJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 244 244 genExtJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 245 245 genExtSendAbsentSelfBytecode isMapped hasIRC)
(2 246 248 unknownBytecode)
"3 byte bytecodes"
(3 249 249 genCallPrimitiveBytecode)
(3 250 250 genPushRemoteTempLongBytecode)
(3 251 251 genStoreRemoteTempLongBytecode)
(3 252 252 genStoreAndPopRemoteTempLongBytecode)
(3 253 253 genExtPushClosureBytecode block v4:Block:Code:Size:)
(3 254 254 genExtSendAbsentOuterBytecode isMapped hasIRC)
(3 255 255 unknownBytecode))!
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 120 genSpecialSelectorNotEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
+ (1 121 127 genSpecialSelectorSend isMapped) "#value #value: #do: #new #new: #x #y"
- (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 unknownBytecode)
(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 genSistaExtStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 241 241 genSistaExtStoreAndPopLiteralVariableBytecode isMappedIfImmutability)
(2 242 242 genLongStoreAndPopTemporaryVariableBytecode)
(2 243 243 genSistaExtStoreReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 244 244 genSistaExtStoreLiteralVariableBytecode isMappedIfImmutability)
(2 245 245 genLongStoreTemporaryVariableBytecode)
(2 246 247 unknownBytecode)
"3 byte bytecodes"
(3 248 248 genCallPrimitiveBytecode)
(3 249 249 genExtPushFullClosureBytecode)
(3 250 250 genExtPushClosureBytecode block v4:Block:Code:Size:)
(3 251 251 genExtPushRemoteTempOrInstVarLongBytecode)
(3 252 252 genExtStoreRemoteTempOrInstVarLongBytecode isMappedIfImmutability)
(3 253 253 genExtStoreAndPopRemoteTempOrInstVarLongBytecode isMappedIfImmutability)
(3 254 254 genExtJumpIfNotInstanceOfBehaviorsBytecode)
(3 255 255 unknownBytecode))!
Item was changed:
----- Method: SimpleStackBasedCogit class>>initializeBytecodeTableForSqueakV3PlusClosures (in category 'class initialization') -----
initializeBytecodeTableForSqueakV3PlusClosures
"SimpleStackBasedCogit initializeBytecodeTableForSqueakV3PlusClosures"
FirstSpecialSelector := 176.
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 0 15 genPushReceiverVariableBytecode isInstVarRef)
(1 16 31 genPushTemporaryVariableBytecode)
(1 32 63 genPushLiteralConstantBytecode needsFrameNever: 1)
(1 64 95 genPushLiteralVariableBytecode needsFrameNever: 1)
(1 96 103 genStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability needsFrameIfImmutability: -1)
(1 104 111 genStoreAndPopTemporaryVariableBytecode)
(1 112 112 genPushReceiverBytecode)
(1 113 113 genPushConstantTrueBytecode needsFrameNever: 1)
(1 114 114 genPushConstantFalseBytecode needsFrameNever: 1)
(1 115 115 genPushConstantNilBytecode needsFrameNever: 1)
(1 116 119 genPushQuickIntegerConstantBytecode needsFrameNever: 1)
"method returns in blocks need a frame because of nonlocalReturn:through:"
(1 120 120 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 121 121 genReturnTrue return needsFrameIfInBlock: isMappedInBlock 0)
(1 122 122 genReturnFalse return needsFrameIfInBlock: isMappedInBlock 0)
(1 123 123 genReturnNil return needsFrameIfInBlock: isMappedInBlock 0)
(1 124 124 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 125 125 genReturnTopFromBlock return needsFrameNever: -1)
(1 126 127 unknownBytecode)
(2 128 128 extendedPushBytecode isInstVarRef) "well, maybe inst var ref"
(2 129 129 extendedStoreBytecode isInstVarRef isMappedIfImmutability) "well, maybe inst var ref"
(2 130 130 extendedStoreAndPopBytecode isInstVarRef isMappedIfImmutability) "well, maybe inst var ref"
(2 131 131 genExtendedSendBytecode isMapped)
(3 132 132 doubleExtendedDoAnythingBytecode isInstVarRef isMapped) "well, maybe inst var ref"
(2 133 133 genExtendedSuperBytecode isMapped)
(2 134 134 genSecondExtendedSendBytecode isMapped)
(1 135 135 genPopStackBytecode needsFrameNever: -1)
(1 136 136 duplicateTopBytecode needsFrameNever: 1)
(1 137 137 genPushActiveContextBytecode)
(2 138 138 genPushNewArrayBytecode)),
((initializationOptions at: #SpurObjectMemory ifAbsent: [false])
ifTrue: [#((3 139 139 genCallPrimitiveBytecode))]
ifFalse: [#((1 139 139 unknownBytecode))]),
#(
(3 140 140 genPushRemoteTempLongBytecode)
(3 141 141 genStoreRemoteTempLongBytecode)
(3 142 142 genStoreAndPopRemoteTempLongBytecode)
(4 143 143 genPushClosureCopyCopiedValuesBytecode block v3:Block:Code:Size:)
(1 144 151 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 152 159 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(2 160 163 genLongUnconditionalBackwardJump branch isMapped "because of interrupt check"
v3:Long:Branch:Distance:)
(2 164 167 genLongUnconditionalForwardJump branch v3:Long:Branch:Distance:)
(2 168 171 genLongJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:LongForward:Branch:Distance:)
(2 172 175 genLongJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:LongForward:Branch:Distance:)
(1 176 197 genSpecialSelectorSend isMapped)
(1 198 198 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 199 199 genSpecialSelectorClass needsFrameNever: notMapped 0) "not mapped because it is directly inlined (for now)"
+ (1 200 200 genSpecialSelectorNotEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
+ (1 201 207 genSpecialSelectorSend isMapped)
- (1 200 207 genSpecialSelectorSend isMapped)
(1 208 223 genSendLiteralSelector0ArgsBytecode isMapped)
(1 224 239 genSendLiteralSelector1ArgBytecode isMapped)
(1 240 255 genSendLiteralSelector2ArgsBytecode isMapped))!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genInlinedIdenticalOrNotIf: (in category 'bytecode generator support') -----
+ genInlinedIdenticalOrNotIf: orNot
+ | jumpNotEqual jumpPush |
+ <var: #jumpNotEqual type: #'AbstractInstruction *'>
+ <var: #jumpPush type: #'AbstractInstruction *'>
+ self PopR: Arg0Reg.
+ objectRepresentation
+ genEnsureOopInRegNotForwarded: Arg0Reg
+ scratchReg: TempReg.
+ self MoveMw: 0 r: SPReg R: ClassReg.
+ objectRepresentation
+ genEnsureOopInRegNotForwarded: ClassReg
+ scratchReg: TempReg.
+ self CmpR: Arg0Reg R: ClassReg.
+ jumpNotEqual := self genConditionalBranch: (orNot ifTrue: [JumpZero] ifFalse: [JumpZero]) operand: 0.
+ self annotate: (self genMoveTrueR: Arg0Reg)
+ objRef: objectMemory trueObject.
+ jumpPush := self Jump: 0.
+ jumpNotEqual jmpTarget: (self genMoveFalseR: Arg0Reg).
+ jumpPush jmpTarget: (self MoveR: Arg0Reg Mw: 0 r: SPReg).
+ ^0!
Item was changed:
----- Method: SimpleStackBasedCogit>>genSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
genSpecialSelectorEqualsEquals
+ ^ self genInlinedIdenticalOrNotIf: false!
- | jumpNotEqual jumpPush |
- <var: #jumpNotEqual type: #'AbstractInstruction *'>
- <var: #jumpPush type: #'AbstractInstruction *'>
- self PopR: Arg0Reg.
- objectRepresentation
- genEnsureOopInRegNotForwarded: Arg0Reg
- scratchReg: TempReg.
- self MoveMw: 0 r: SPReg R: ClassReg.
- objectRepresentation
- genEnsureOopInRegNotForwarded: ClassReg
- scratchReg: TempReg.
- self CmpR: Arg0Reg R: ClassReg.
- jumpNotEqual := self JumpNonZero: 0.
- self annotate: (self genMoveTrueR: Arg0Reg)
- objRef: objectMemory trueObject.
- jumpPush := self Jump: 0.
- jumpNotEqual jmpTarget: (self genMoveFalseR: Arg0Reg).
- jumpPush jmpTarget: (self MoveR: Arg0Reg Mw: 0 r: SPReg).
- ^0!
Item was added:
+ ----- Method: SimpleStackBasedCogit>>genSpecialSelectorNotEqualsEquals (in category 'bytecode generators') -----
+ genSpecialSelectorNotEqualsEquals
+ ^ self genInlinedIdenticalOrNotIf: true!
Item was added:
+ ----- Method: SistaCogit>>genForwardersInlinedIdenticalOrNotIf: (in category 'bytecode generators') -----
+ genForwardersInlinedIdenticalOrNotIf: orNot
+ "Override to count inlined branches if followed by a conditional branch.
+ We borrow the following conditional branch's counter and when about to
+ inline the comparison we decrement the counter (without writing it back)
+ and if it trips simply abort the inlining, falling back to the normal send which
+ will then continue to the conditional branch which will trip and enter the abort."
+ | nextPC postBranchPC targetBytecodePC branchDescriptor counterReg fixup jumpEqual jumpNotEqual
+ counterAddress countTripped unforwardArg unforwardRcvr argReg rcvrReg regMask |
+ <var: #fixup type: #'BytecodeFixup *'>
+ <var: #countTripped type: #'AbstractInstruction *'>
+ <var: #label type: #'AbstractInstruction *'>
+ <var: #branchDescriptor type: #'BytecodeDescriptor *'>
+ <var: #jumpEqual type: #'AbstractInstruction *'>
+ <var: #jumpNotEqual type: #'AbstractInstruction *'>
+
+ ((coInterpreter isOptimizedMethod: methodObj) or: [needsFrame not]) ifTrue:
+ [^super genForwardersInlinedIdenticalOrNotIf: orNot].
+
+ regMask := 0.
+
+ self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target |
+ branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
+
+ unforwardRcvr := (objectRepresentation isUnannotatableConstant: (self ssValue: 1)) not.
+ unforwardArg := (objectRepresentation isUnannotatableConstant: self ssTop) not.
+
+ "If an operand is an annotable constant, it may be forwarded, so we need to store it into a
+ register so the forwarder check can jump back to the comparison after unforwarding the constant.
+ However, if one of the operand is an unnanotable constant, does not allocate a register for it
+ (machine code will use operations on constants)."
+ rcvrReg:= argReg := NoReg.
+ self
+ allocateEqualsEqualsRegistersArgNeedsReg: unforwardArg
+ rcvrNeedsReg: unforwardRcvr
+ into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ].
+
+ argReg ~= NoReg ifTrue: [ regMask := self registerMaskFor: argReg ].
+ rcvrReg ~= NoReg ifTrue: [ regMask := regMask bitOr: (self registerMaskFor: rcvrReg) ].
+
+ "Only interested in inlining if followed by a conditional branch."
+ (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
+ [^ self
+ genIdenticalNoBranchArgIsConstant: unforwardArg not
+ rcvrIsConstant: unforwardRcvr not
+ argReg: argReg
+ rcvrReg: rcvrReg
+ orNotIf: orNot].
+
+ "If branching the stack must be flushed for the merge"
+ self ssFlushTo: simStackPtr - 2.
+
+ unforwardArg ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg ].
+ unforwardRcvr ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg ].
+
+ counterReg := self allocateRegNotConflictingWith: regMask.
+ self
+ genExecutionCountLogicInto: [ :cAddress :countTripBranch |
+ counterAddress := cAddress.
+ countTripped := countTripBranch ]
+ counterReg: counterReg.
+
+ self assert: (unforwardArg or: [ unforwardRcvr ]).
+ self genCmpArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg.
+ self ssPop: 2.
+
+ "We could use (branchDescriptor isBranchTrue xor: orNot) to simplify this."
+ orNot
+ ifFalse: [branchDescriptor isBranchTrue
+ ifTrue:
+ [ fixup := (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger ]
+ ifFalse: "branchDescriptor is branchFalse"
+ [ fixup := (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger ]]
+ ifTrue: [branchDescriptor isBranchTrue
+ ifFalse: "branchDescriptor is branchFalse"
+ [ fixup := (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger ]
+ ifTrue:
+ [ fixup := (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger ]].
+
+ self genFallsThroughCountLogicCounterReg: counterReg counterAddress: counterAddress.
+ self Jump: fixup.
+
+ countTripped jmpTarget: self Label.
+
+ "inlined version of #== ignoring the branchDescriptor if the counter trips to have normal state for the optimizer"
+ self ssPop: -2.
+ self genCmpArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg.
+ self ssPop: 2.
+
+ "This code necessarily directly falls through the jumpIf: code which pops the top of the stack into TempReg.
+ We therefore directly assign the result to TempReg to save one move instruction"
+ jumpEqual := orNot ifFalse: [self JumpZero: 0] ifTrue: [self JumpNonZero: 0].
+ self genMoveFalseR: TempReg.
+ jumpNotEqual := self Jump: 0.
+ jumpEqual jmpTarget: (self genMoveTrueR: TempReg).
+ jumpNotEqual jmpTarget: self Label.
+ self ssPushRegister: TempReg.
+
+ (self fixupAt: nextPC - initialPC) notAFixup ifTrue: [ branchReachedOnlyForCounterTrip := true ].
+
+ ^ 0!
Item was removed:
- ----- Method: SistaCogit>>genSpecialSelectorEqualsEqualsWithForwarders (in category 'bytecode generators') -----
- genSpecialSelectorEqualsEqualsWithForwarders
- "Override to count inlined branches if followed by a conditional branch.
- We borrow the following conditional branch's counter and when about to
- inline the comparison we decrement the counter (without writing it back)
- and if it trips simply abort the inlining, falling back to the normal send which
- will then continue to the conditional branch which will trip and enter the abort."
- | nextPC postBranchPC targetBytecodePC branchDescriptor counterReg fixup jumpEqual jumpNotEqual
- counterAddress countTripped unforwardArg unforwardRcvr argReg rcvrReg regMask |
- <var: #fixup type: #'BytecodeFixup *'>
- <var: #countTripped type: #'AbstractInstruction *'>
- <var: #label type: #'AbstractInstruction *'>
- <var: #branchDescriptor type: #'BytecodeDescriptor *'>
- <var: #jumpEqual type: #'AbstractInstruction *'>
- <var: #jumpNotEqual type: #'AbstractInstruction *'>
-
- ((coInterpreter isOptimizedMethod: methodObj) or: [needsFrame not]) ifTrue:
- [^super genSpecialSelectorEqualsEqualsWithForwarders].
-
- regMask := 0.
-
- self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target |
- branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
-
- unforwardRcvr := (objectRepresentation isUnannotatableConstant: (self ssValue: 1)) not.
- unforwardArg := (objectRepresentation isUnannotatableConstant: self ssTop) not.
-
- "If an operand is an annotable constant, it may be forwarded, so we need to store it into a
- register so the forwarder check can jump back to the comparison after unforwarding the constant.
- However, if one of the operand is an unnanotable constant, does not allocate a register for it
- (machine code will use operations on constants)."
- rcvrReg:= argReg := NoReg.
- self
- allocateEqualsEqualsRegistersArgNeedsReg: unforwardArg
- rcvrNeedsReg: unforwardRcvr
- into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ].
-
- argReg ~= NoReg ifTrue: [ regMask := self registerMaskFor: argReg ].
- rcvrReg ~= NoReg ifTrue: [ regMask := regMask bitOr: (self registerMaskFor: rcvrReg) ].
-
- "Only interested in inlining if followed by a conditional branch."
- (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
- [^ self genEqualsEqualsNoBranchArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg].
-
- "If branching the stack must be flushed for the merge"
- self ssFlushTo: simStackPtr - 2.
-
- unforwardArg ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg ].
- unforwardRcvr ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: rcvrReg scratchReg: TempReg ].
-
- counterReg := self allocateRegNotConflictingWith: regMask.
- self
- genExecutionCountLogicInto: [ :cAddress :countTripBranch |
- counterAddress := cAddress.
- countTripped := countTripBranch ]
- counterReg: counterReg.
-
- self assert: (unforwardArg or: [ unforwardRcvr ]).
-
- self genEqualsEqualsComparisonArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg.
-
- self ssPop: 2.
-
- branchDescriptor isBranchTrue
- ifTrue:
- [ fixup := self ensureNonMergeFixupAt: postBranchPC - initialPC.
- self JumpZero: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger. ]
- ifFalse:
- [ fixup := self ensureNonMergeFixupAt: targetBytecodePC - initialPC.
- self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger. ].
-
- self genFallsThroughCountLogicCounterReg: counterReg counterAddress: counterAddress.
- self Jump: fixup.
-
- countTripped jmpTarget: self Label.
-
- "inlined version of #== ignoring the branchDescriptor if the counter trips to have normal state for the optimizer"
- self ssPop: -2.
- self genEqualsEqualsComparisonArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg.
- self ssPop: 2.
-
- "This code necessarily directly falls through the jumpIf: code which pops the top of the stack into TempReg.
- We therefore directly assign the result to TempReg to save one move instruction"
- jumpEqual := self JumpZero: 0.
- self genMoveFalseR: TempReg.
- jumpNotEqual := self Jump: 0.
- jumpEqual jmpTarget: (self genMoveTrueR: TempReg).
- jumpNotEqual jmpTarget: self Label.
- self ssPushRegister: TempReg.
-
- (self fixupAt: nextPC - initialPC) notAFixup ifTrue: [ branchReachedOnlyForCounterTrip := true ].
-
- ^ 0!
Item was changed:
----- Method: StackInterpreter class>>initializeBytecodeTableForNewspeakV4 (in category 'initialization') -----
initializeBytecodeTableForNewspeakV4
"StackInterpreter initializeBytecodeTableForNewspeakV4"
"Note: This table will be used to generate a C switch statement."
initializationOptions at: #NewsqueakV4BytecodeSet put: (NewsqueakV4BytecodeSet := true).
BytecodeTable := Array new: 256.
BytecodeEncoderClassName := #EncoderForNewsqueakV4.
BytecodeSetHasExtensions := true.
LongStoreBytecode := 234.
self table: BytecodeTable from:
#( "1 byte bytecodes"
( 0 15 pushReceiverVariableBytecode)
( 16 31 pushLiteralVariable16CasesBytecode)
( 32 63 pushLiteralConstantBytecode)
( 64 75 pushTemporaryVariableBytecode)
( 76 pushReceiverBytecode)
( 77 extPushPseudoVariableOrOuterBytecode)
( 78 pushConstantZeroBytecode)
( 79 pushConstantOneBytecode)
( 80 bytecodePrimAdd)
( 81 bytecodePrimSubtract)
( 82 bytecodePrimLessThanV4) "for booleanCheatV4:"
( 83 bytecodePrimGreaterThanV4) "for booleanCheatV4:"
( 84 bytecodePrimLessOrEqualV4) "for booleanCheatV4:"
( 85 bytecodePrimGreaterOrEqualV4) "for booleanCheatV4:"
( 86 bytecodePrimEqualV4) "for booleanCheatV4:"
( 87 bytecodePrimNotEqualV4) "for booleanCheatV4:"
( 88 bytecodePrimMultiply)
( 89 bytecodePrimDivide)
( 90 bytecodePrimMod)
( 91 bytecodePrimMakePoint)
( 92 bytecodePrimBitShift)
( 93 bytecodePrimDiv)
( 94 bytecodePrimBitAnd)
( 95 bytecodePrimBitOr)
( 96 bytecodePrimAt)
( 97 bytecodePrimAtPut)
( 98 bytecodePrimSize)
( 99 bytecodePrimNext)
(100 bytecodePrimNextPut)
(101 bytecodePrimAtEnd)
(102 bytecodePrimIdenticalV4) "for booleanCheatV4:"
(103 bytecodePrimClass)
+ (104 bytecodePrimNotIdenticalV4) "was blockCopy:"
- (104 bytecodePrimSpecialSelector24) "was blockCopy:"
(105 bytecodePrimValue)
(106 bytecodePrimValueWithArg)
(107 bytecodePrimDo)
(108 bytecodePrimNew)
(109 bytecodePrimNewWithArg)
(110 bytecodePrimPointX)
(111 bytecodePrimPointY)
(112 127 sendLiteralSelector0ArgsBytecode)
(128 143 sendLiteralSelector1ArgBytecode)
(144 159 sendLiteralSelector2ArgsBytecode)
(160 175 sendAbsentImplicit0ArgsBytecode)
(176 183 storeAndPopReceiverVariableBytecode)
(184 191 storeAndPopTemporaryVariableBytecode)
(192 199 shortUnconditionalJump)
(200 207 shortConditionalJumpTrue)
(208 215 shortConditionalJumpFalse)
(216 returnReceiver)
(217 returnTopFromMethod)
(218 extReturnTopFromBlock)
(219 duplicateTopBytecode)
(220 popStackBytecode)
(221 extNopBytecode)
(222 223 unknownBytecode)
"2 byte bytecodes"
(224 extABytecode)
(225 extBBytecode)
(226 extPushReceiverVariableBytecode)
(227 extPushLiteralVariableBytecode)
(228 extPushLiteralBytecode)
(229 extPushIntegerBytecode)
(230 longPushTemporaryVariableBytecode)
(231 pushNewArrayBytecode)
(232 extStoreReceiverVariableBytecode)
(233 extStoreLiteralVariableBytecode)
(234 longStoreTemporaryVariableBytecode)
(235 extStoreAndPopReceiverVariableBytecode)
(236 extStoreAndPopLiteralVariableBytecode)
(237 longStoreAndPopTemporaryVariableBytecode)
(238 extSendBytecode)
(239 extSendSuperBytecode)
(240 extSendAbsentImplicitBytecode)
(241 extSendAbsentDynamicSuperBytecode)
(242 extUnconditionalJump)
(243 extJumpIfTrue)
(244 extJumpIfFalse)
(245 extSendAbsentSelfBytecode)
(246 248 unknownBytecode)
"3 byte bytecodes"
(249 callPrimitiveBytecode)
(250 pushRemoteTempLongBytecode)
(251 storeRemoteTempLongBytecode)
(252 storeAndPopRemoteTempLongBytecode)
(253 extPushClosureBytecode)
(254 extSendAbsentOuterBytecode)
(255 unknownBytecode)
)!
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."
initializationOptions at: #SistaV1BytecodeSet put: (SistaV1BytecodeSet := true).
BytecodeTable := Array new: 256.
BytecodeEncoderClassName := #EncoderForSistaV1.
BytecodeSetHasDirectedSuperSend := true.
BytecodeSetHasExtensions := true.
LongStoreBytecode := 245.
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 bytecodePrimNotIdenticalSistaV1) "was blockCopy:"
- (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 unknownBytecode)
(231 pushNewArrayBytecode)
(232 extPushIntegerBytecode)
(233 extPushCharacterBytecode)
(234 extSendBytecode)
(235 extSendSuperBytecode)
(236 unknownBytecode)
(237 extUnconditionalJump)
(238 extJumpIfTrue)
(239 extJumpIfFalse)
(240 extSistaStoreAndPopReceiverVariableBytecode)
(241 extSistaStoreAndPopLiteralVariableBytecode)
(242 longStoreAndPopTemporaryVariableBytecode)
(243 extSistaStoreReceiverVariableBytecode)
(244 extSistaStoreLiteralVariableBytecode)
(245 longStoreTemporaryVariableBytecode)
(246 247 unknownBytecode)
"3 byte bytecodes"
(248 callPrimitiveBytecode)
(249 extPushFullClosureBytecode)
(250 extPushClosureBytecode)
(251 extPushRemoteTempOrInstVarLongBytecode)
(252 extStoreRemoteTempOrInstVarLongBytecode)
(253 extStoreAndPopRemoteTempOrInstVarLongBytecode)
(254 extJumpIfNotInstanceOfBehaviorsBytecode)
(255 unknownBytecode)
)!
Item was changed:
----- Method: StackInterpreter class>>initializeBytecodeTableForSqueakV3PlusClosures (in category 'initialization') -----
initializeBytecodeTableForSqueakV3PlusClosures
"StackInterpreter initializeBytecodeTableForSqueakV3PlusClosures"
"Note: This table will be used to generate a C switch statement."
initializationOptions at: #SqueakV3PlusClosuresBytecodeSet put: (SqueakV3PlusClosuresBytecodeSet := true).
BytecodeTable := Array new: 256.
BytecodeEncoderClassName := #EncoderForV3PlusClosures.
LongStoreBytecode := 129.
self table: BytecodeTable from:
#(
( 0 15 pushReceiverVariableBytecode)
( 16 31 pushTemporaryVariableBytecode)
( 32 63 pushLiteralConstantBytecode)
( 64 95 pushLiteralVariableBytecode)
( 96 103 storeAndPopReceiverVariableBytecode)
(104 111 storeAndPopTemporaryVariableBytecode)
(112 pushReceiverBytecode)
(113 pushConstantTrueBytecode)
(114 pushConstantFalseBytecode)
(115 pushConstantNilBytecode)
(116 pushConstantMinusOneBytecode)
(117 pushConstantZeroBytecode)
(118 pushConstantOneBytecode)
(119 pushConstantTwoBytecode)
(120 returnReceiver)
(121 returnTrue)
(122 returnFalse)
(123 returnNil)
(124 returnTopFromMethod)
(125 returnTopFromBlock)
(126 127 unknownBytecode)
(128 extendedPushBytecode)
(129 extendedStoreBytecode)
(130 extendedStoreAndPopBytecode)
(131 singleExtendedSendBytecode)
(132 doubleExtendedDoAnythingBytecode)
(133 singleExtendedSuperBytecode)
(134 secondExtendedSendBytecode)
(135 popStackBytecode)
(136 duplicateTopBytecode)
(137 pushActiveContextBytecode)
(138 pushNewArrayBytecode)),
((initializationOptions at: #SpurObjectMemory ifAbsent: [false])
ifTrue: [#((139 callPrimitiveBytecode))] "V3PlusClosures on Spur"
ifFalse: [#((139 unknownBytecode))]), "V3PlusClosures on V3"
#(
(140 pushRemoteTempLongBytecode)
(141 storeRemoteTempLongBytecode)
(142 storeAndPopRemoteTempLongBytecode)
(143 pushClosureCopyCopiedValuesBytecode)
(144 151 shortUnconditionalJump)
(152 159 shortConditionalJumpFalse)
(160 167 longUnconditionalJump)
(168 171 longJumpIfTrue)
(172 175 longJumpIfFalse)
"176-191 were sendArithmeticSelectorBytecode"
(176 bytecodePrimAdd)
(177 bytecodePrimSubtract)
(178 bytecodePrimLessThan)
(179 bytecodePrimGreaterThan)
(180 bytecodePrimLessOrEqual)
(181 bytecodePrimGreaterOrEqual)
(182 bytecodePrimEqual)
(183 bytecodePrimNotEqual)
(184 bytecodePrimMultiply)
(185 bytecodePrimDivide)
(186 bytecodePrimMod)
(187 bytecodePrimMakePoint)
(188 bytecodePrimBitShift)
(189 bytecodePrimDiv)
(190 bytecodePrimBitAnd)
(191 bytecodePrimBitOr)
"192-207 were sendCommonSelectorBytecode"
(192 bytecodePrimAt)
(193 bytecodePrimAtPut)
(194 bytecodePrimSize)
(195 bytecodePrimNext)
(196 bytecodePrimNextPut)
(197 bytecodePrimAtEnd)
(198 bytecodePrimIdentical)
(199 bytecodePrimClass)
+ (200 bytecodePrimNotIdentical) "was bytecodePrimSpecialSelector24 / blockCopy"
- (200 bytecodePrimSpecialSelector24)
(201 bytecodePrimValue)
(202 bytecodePrimValueWithArg)
(203 bytecodePrimDo)
(204 bytecodePrimNew)
(205 bytecodePrimNewWithArg)
(206 bytecodePrimPointX)
(207 bytecodePrimPointY)
(208 223 sendLiteralSelector0ArgsBytecode)
(224 239 sendLiteralSelector1ArgBytecode)
(240 255 sendLiteralSelector2ArgsBytecode)
)!
Item was added:
+ ----- Method: StackInterpreter>>bytecodePrimNotIdentical (in category 'common selector sends') -----
+ bytecodePrimNotIdentical
+ | rcvr arg |
+ rcvr := self internalStackValue: 1.
+ (objectMemory isOopForwarded: rcvr) ifTrue:
+ [rcvr := self handleSpecialSelectorSendFaultFor: rcvr].
+ arg := self internalStackValue: 0.
+ (objectMemory isOopForwarded: arg) ifTrue:
+ [arg := self handleSpecialSelectorSendFaultFor: arg].
+ self booleanCheat: rcvr ~= arg!
Item was added:
+ ----- Method: StackInterpreter>>bytecodePrimNotIdenticalSistaV1 (in category 'common selector sends') -----
+ bytecodePrimNotIdenticalSistaV1
+ | rcvr arg |
+ rcvr := self internalStackValue: 1.
+ arg := self internalStackValue: 0.
+ (objectMemory isOopForwarded: rcvr) ifTrue:
+ [rcvr := self handleSpecialSelectorSendFaultFor: rcvr].
+ (objectMemory isOopForwarded: arg) ifTrue:
+ [arg := self handleSpecialSelectorSendFaultFor: arg].
+ self booleanCheatSistaV1: rcvr ~= arg!
Item was added:
+ ----- Method: StackInterpreter>>bytecodePrimNotIdenticalV4 (in category 'common selector sends') -----
+ bytecodePrimNotIdenticalV4
+ | rcvr arg |
+ rcvr := self internalStackValue: 1.
+ arg := self internalStackValue: 0.
+ (objectMemory isOopForwarded: rcvr) ifTrue:
+ [rcvr := self handleSpecialSelectorSendFaultFor: rcvr].
+ (objectMemory isOopForwarded: arg) ifTrue:
+ [arg := self handleSpecialSelectorSendFaultFor: arg].
+ self booleanCheatV4: rcvr ~= arg!
Item was changed:
----- Method: StackToRegisterMappingCogit class>>initializeBytecodeTableForNewspeakV4 (in category 'class initialization') -----
initializeBytecodeTableForNewspeakV4
"StackToRegisterMappingCogit initializeBytecodeTableForNewspeakV4"
numPushNilsFunction := #v4:Num:Push:Nils:.
pushNilSizeFunction := #v4PushNilSize:numInitialNils:.
NSSendIsPCAnnotated := true. "IsNSSendCall used by SendAbsentImplicit"
FirstSpecialSelector := 80.
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"
(1 0 15 genPushReceiverVariableBytecode isInstVarRef needsFrameNever: 1)
(1 16 31 genPushLiteralVariable16CasesBytecode needsFrameNever: 1)
(1 32 63 genPushLiteralConstantBytecode needsFrameNever: 1)
(1 64 75 genPushTemporaryVariableBytecode needsFrameIfMod16GENumArgs: 1)
(1 76 76 genPushReceiverBytecode needsFrameNever: 1)
(1 77 77 genExtPushPseudoVariableOrOuterBytecode needsFrameIfExtBGT2: 1)
(1 78 78 genPushConstantZeroBytecode needsFrameNever: 1)
(1 79 79 genPushConstantOneBytecode needsFrameNever: 1)
(1 80 80 genSpecialSelectorArithmetic isMapped AddRR)
(1 81 81 genSpecialSelectorArithmetic isMapped SubRR)
(1 82 82 genSpecialSelectorComparison isMapped JumpLess)
(1 83 83 genSpecialSelectorComparison isMapped JumpGreater)
(1 84 84 genSpecialSelectorComparison isMapped JumpLessOrEqual)
(1 85 85 genSpecialSelectorComparison isMapped JumpGreaterOrEqual)
(1 86 86 genSpecialSelectorComparison isMapped JumpZero)
(1 87 87 genSpecialSelectorComparison isMapped JumpNonZero)
(1 88 93 genSpecialSelectorSend isMapped) " #* #/ #\\ #@ #bitShift: //"
(1 94 94 genSpecialSelectorArithmetic isMapped AndRR)
(1 95 95 genSpecialSelectorArithmetic isMapped OrRR)
(1 96 101 genSpecialSelectorSend isMapped) "#at: #at:put: #size #next #nextPut: #atEnd"
(1 102 102 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 103 103 genSpecialSelectorClass needsFrameIfStackGreaterThanOne: notMapped 0) "not mapped because it is directly inlined (for now)"
+ (1 104 104 genSpecialSelectorNotEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
+ (1 105 111 genSpecialSelectorSend isMapped) " #value #value: #do: #new #new: #x #y"
- (1 104 111 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
(1 112 127 genSendLiteralSelector0ArgsBytecode isMapped)
(1 128 143 genSendLiteralSelector1ArgBytecode isMapped)
(1 144 159 genSendLiteralSelector2ArgsBytecode isMapped)
(1 160 175 genSendAbsentImplicit0ArgsBytecode isMapped hasIRC)
(1 176 183 genStoreAndPopReceiverVariableBytecode isInstVarRef is1ByteInstVarStore isMappedIfImmutability needsFrameIfImmutability: -1)
(1 184 191 genStoreAndPopTemporaryVariableBytecode)
(1 192 199 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 200 207 genShortJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 208 215 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(1 216 216 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 217 217 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 218 218 genExtReturnTopFromBlock return needsFrameNever: -1)
(1 219 219 duplicateTopBytecode needsFrameNever: 1)
(1 220 220 genPopStackBytecode needsFrameNever: -1)
(1 221 221 genExtNopBytecode needsFrameNever: 0)
(1 222 223 unknownBytecode)
"2 byte bytecodes"
(2 224 224 extABytecode extension needsFrameNever: 0)
(2 225 225 extBBytecode extension needsFrameNever: 0)
(2 226 226 genExtPushReceiverVariableBytecode isInstVarRef)
(2 227 227 genExtPushLiteralVariableBytecode needsFrameNever: 1)
(2 228 228 genExtPushLiteralBytecode needsFrameNever: 1)
(2 229 229 genExtPushIntegerBytecode needsFrameNever: 1)
(2 230 230 genLongPushTemporaryVariableBytecode)
(2 231 231 genPushNewArrayBytecode)
(2 232 232 genExtStoreReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 233 233 genExtStoreLiteralVariableBytecode isMappedIfImmutability)
(2 234 234 genLongStoreTemporaryVariableBytecode)
(2 235 235 genExtStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 236 236 genExtStoreAndPopLiteralVariableBytecode isMappedIfImmutability)
(2 237 237 genLongStoreAndPopTemporaryVariableBytecode)
(2 238 238 genExtSendBytecode isMapped)
(2 239 239 genExtSendSuperBytecode isMapped)
(2 240 240 genExtSendAbsentImplicitBytecode isMapped hasIRC)
(2 241 241 genExtSendAbsentDynamicSuperBytecode isMapped hasIRC)
(2 242 242 genExtUnconditionalJump branch isMapped "because of interrupt check" v4:Long:Branch:Distance:)
(2 243 243 genExtJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 244 244 genExtJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean" v4:Long:Branch:Distance:)
(2 245 245 genExtSendAbsentSelfBytecode isMapped hasIRC)
(2 246 248 unknownBytecode)
"3 byte bytecodes"
(3 249 249 genCallPrimitiveBytecode)
(3 250 250 genPushRemoteTempLongBytecode)
(3 251 251 genStoreRemoteTempLongBytecode)
(3 252 252 genStoreAndPopRemoteTempLongBytecode)
(3 253 253 genExtPushClosureBytecode block v4:Block:Code:Size:)
(3 254 254 genExtSendAbsentOuterBytecode isMapped hasIRC)
(3 255 255 unknownBytecode))!
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 120 genSpecialSelectorNotEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
+ (1 121 127 genSpecialSelectorSend isMapped) "#value #value: #do: #new #new: #x #y"
- (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 is1ByteInstVarStore 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 unknownBytecode)
(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 genSistaExtStoreAndPopReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 241 241 genSistaExtStoreAndPopLiteralVariableBytecode isMappedIfImmutability)
(2 242 242 genLongStoreAndPopTemporaryVariableBytecode)
(2 243 243 genSistaExtStoreReceiverVariableBytecode isInstVarRef isMappedIfImmutability)
(2 244 244 genSistaExtStoreLiteralVariableBytecode isMappedIfImmutability)
(2 245 245 genLongStoreTemporaryVariableBytecode)
(2 246 247 unknownBytecode)
"3 byte bytecodes"
(3 248 248 genCallPrimitiveBytecode)
(3 249 249 genExtPushFullClosureBytecode)
(3 250 250 genExtPushClosureBytecode block v4:Block:Code:Size:)
(3 251 251 genExtPushRemoteTempOrInstVarLongBytecode)
(3 252 252 genExtStoreRemoteTempOrInstVarLongBytecode isMappedIfImmutability)
(3 253 253 genExtStoreAndPopRemoteTempOrInstVarLongBytecode isMappedIfImmutability)
(3 254 254 genExtJumpIfNotInstanceOfBehaviorsBytecode branch v4:Long:BranchIfNotInstanceOf:Distance:)
(3 255 255 unknownBytecode))!
Item was changed:
----- Method: StackToRegisterMappingCogit class>>initializeBytecodeTableForSqueakV3PlusClosures (in category 'class initialization') -----
initializeBytecodeTableForSqueakV3PlusClosures
"StackToRegisterMappingCogit initializeBytecodeTableForSqueakV3PlusClosures"
numPushNilsFunction := #v3:Num:Push:Nils:.
pushNilSizeFunction := #v3PushNilSize:numInitialNils:.
FirstSpecialSelector := 176.
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 0 15 genPushReceiverVariableBytecode isInstVarRef needsFrameNever: 1)
(1 16 31 genPushTemporaryVariableBytecode needsFrameIfMod16GENumArgs: 1)
(1 32 63 genPushLiteralConstantBytecode needsFrameNever: 1)
(1 64 95 genPushLiteralVariableBytecode needsFrameNever: 1)
(1 96 103 genStoreAndPopReceiverVariableBytecode isInstVarRef is1ByteInstVarStore isMappedIfImmutability needsFrameIfImmutability: -1)
(1 104 111 genStoreAndPopTemporaryVariableBytecode)
(1 112 112 genPushReceiverBytecode needsFrameNever: 1)
(1 113 113 genPushConstantTrueBytecode needsFrameNever: 1)
(1 114 114 genPushConstantFalseBytecode needsFrameNever: 1)
(1 115 115 genPushConstantNilBytecode needsFrameNever: 1)
(1 116 119 genPushQuickIntegerConstantBytecode needsFrameNever: 1)
"method returns in blocks need a frame because of nonlocalReturn:through:"
(1 120 120 genReturnReceiver return needsFrameIfInBlock: isMappedInBlock 0)
(1 121 121 genReturnTrue return needsFrameIfInBlock: isMappedInBlock 0)
(1 122 122 genReturnFalse return needsFrameIfInBlock: isMappedInBlock 0)
(1 123 123 genReturnNil return needsFrameIfInBlock: isMappedInBlock 0)
(1 124 124 genReturnTopFromMethod return needsFrameIfInBlock: isMappedInBlock -1)
(1 125 125 genReturnTopFromBlock return needsFrameNever: -1)
(1 126 127 unknownBytecode)
(2 128 128 extendedPushBytecode isInstVarRef) "well, maybe inst var ref"
(2 129 129 extendedStoreBytecode isInstVarRef isMappedIfImmutability) "well, maybe inst var ref"
(2 130 130 extendedStoreAndPopBytecode isInstVarRef isMappedIfImmutability) "well, maybe inst var ref"
(2 131 131 genExtendedSendBytecode isMapped)
(3 132 132 doubleExtendedDoAnythingBytecode isMapped) "well, maybe inst var ref"
(2 133 133 genExtendedSuperBytecode isInstVarRef isMapped)
(2 134 134 genSecondExtendedSendBytecode isMapped)
(1 135 135 genPopStackBytecode needsFrameNever: -1)
(1 136 136 duplicateTopBytecode needsFrameNever: 1)
(1 137 137 genPushActiveContextBytecode)
(2 138 138 genPushNewArrayBytecode)),
((initializationOptions at: #SpurObjectMemory ifAbsent: [false])
ifTrue: [#((3 139 139 genCallPrimitiveBytecode))]
ifFalse: [#((1 139 139 unknownBytecode))]),
#(
(3 140 140 genPushRemoteTempLongBytecode)
(3 141 141 genStoreRemoteTempLongBytecode)
(3 142 142 genStoreAndPopRemoteTempLongBytecode)
(4 143 143 genPushClosureCopyCopiedValuesBytecode block v3:Block:Code:Size:)
(1 144 151 genShortUnconditionalJump branch v3:ShortForward:Branch:Distance:)
(1 152 159 genShortJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:ShortForward:Branch:Distance:)
(2 160 163 genLongUnconditionalBackwardJump branch isMapped "because of interrupt check"
v3:Long:Branch:Distance:)
(2 164 167 genLongUnconditionalForwardJump branch v3:Long:Branch:Distance:)
(2 168 171 genLongJumpIfTrue branch isBranchTrue isMapped "because of mustBeBoolean"
v3:LongForward:Branch:Distance:)
(2 172 175 genLongJumpIfFalse branch isBranchFalse isMapped "because of mustBeBoolean"
v3:LongForward:Branch:Distance:)
(1 176 176 genSpecialSelectorArithmetic isMapped AddRR)
(1 177 177 genSpecialSelectorArithmetic isMapped SubRR)
(1 178 178 genSpecialSelectorComparison isMapped JumpLess)
(1 179 179 genSpecialSelectorComparison isMapped JumpGreater)
(1 180 180 genSpecialSelectorComparison isMapped JumpLessOrEqual)
(1 181 181 genSpecialSelectorComparison isMapped JumpGreaterOrEqual)
(1 182 182 genSpecialSelectorComparison isMapped JumpZero)
(1 183 183 genSpecialSelectorComparison isMapped JumpNonZero)
(1 184 189 genSpecialSelectorSend isMapped) " #* #/ #\\ #@ #bitShift: //"
(1 190 190 genSpecialSelectorArithmetic isMapped AndRR)
(1 191 191 genSpecialSelectorArithmetic isMapped OrRR)
(1 192 197 genSpecialSelectorSend isMapped) "#at: #at:put: #size #next #nextPut: #atEnd"
(1 198 198 genSpecialSelectorEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
(1 199 199 genSpecialSelectorClass needsFrameIfStackGreaterThanOne: notMapped 0) "not mapped because it is directly inlined (for now)"
+ (1 200 200 genSpecialSelectorNotEqualsEquals needsFrameNever: notMapped -1) "not mapped because it is directly inlined (for now)"
+ (1 201 207 genSpecialSelectorSend isMapped) " #value #value: #do: #new #new: #x #y"
- (1 200 207 genSpecialSelectorSend isMapped) "#blockCopy: #value #value: #do: #new #new: #x #y"
(1 208 223 genSendLiteralSelector0ArgsBytecode isMapped)
(1 224 239 genSendLiteralSelector1ArgBytecode isMapped)
(1 240 255 genSendLiteralSelector2ArgsBytecode isMapped))!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genCmpArgIsConstant:rcvrIsConstant:argReg:rcvrReg: (in category 'bytecode generator support') -----
+ genCmpArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrReg
+ "Generates the Cmp instruction for the top two ssStack values.
+ ssTop is called the argument and ssValue: 1 is called the receiver.
+ 0 or 1 value on ssStack is a constant (but not 2). If a value is a constant, then noReg is passed as argReg or rcvrReg.
+ The instruction is different if one of the operands is a constant.
+ In the case of the v3 memory manager, the constant could be annotable."
+ <inline: true>
+ self assert: (argReg ~= NoReg or: [rcvrReg ~= NoReg]).
+ argIsConstant
+ ifTrue: [ self genCmpConstant: self ssTop constant R: rcvrReg ]
+ ifFalse: [ rcvrIsConstant
+ ifTrue: [ self genCmpConstant: (self ssValue: 1) constant R: argReg ]
+ ifFalse: [ self CmpR: argReg R: rcvrReg ] ].!
Item was removed:
- ----- Method: StackToRegisterMappingCogit>>genEqualsEqualsComparisonArgIsConstant:rcvrIsConstant:argReg:rcvrReg: (in category 'bytecode generator support') -----
- genEqualsEqualsComparisonArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrReg
- "Generates the Cmp instruction for #==. The instruction is different if one of the operands is a constant.
- In the case of the v3 memory manager, the constant could be annotable."
- <inline: true>
- argIsConstant
- ifTrue: [ self genCmpConstant: self ssTop constant R: rcvrReg ]
- ifFalse: [ rcvrIsConstant
- ifTrue: [ self genCmpConstant: (self ssValue: 1) constant R: argReg ]
- ifFalse: [ self CmpR: argReg R: rcvrReg ] ].!
Item was removed:
- ----- Method: StackToRegisterMappingCogit>>genEqualsEqualsNoBranchArgIsConstant:rcvrIsConstant:argReg:rcvrReg: (in category 'bytecode generator support') -----
- genEqualsEqualsNoBranchArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrRegOrNone
- "Generates the machine code for #== in the case where the instruction is not followed by a branch"
- | label jumpEqual jumpNotEqual resultReg |
- <var: #label type: #'AbstractInstruction *'>
- <var: #jumpEqual type: #'AbstractInstruction *'>
- <var: #jumpNotEqual type: #'AbstractInstruction *'>
- label := self Label.
- self genEqualsEqualsComparisonArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrRegOrNone.
- self ssPop: 2.
- resultReg := rcvrRegOrNone = NoReg ifTrue: [argReg] ifFalse: [rcvrRegOrNone].
- jumpEqual := self JumpZero: 0.
- argIsConstant ifFalse:
- [objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg jumpBackTo: label].
- rcvrIsConstant ifFalse:
- [objectRepresentation genEnsureOopInRegNotForwarded: rcvrRegOrNone scratchReg: TempReg jumpBackTo: label].
- self genMoveFalseR: resultReg.
- jumpNotEqual := self Jump: 0.
- jumpEqual jmpTarget: (self genMoveTrueR: resultReg).
- jumpNotEqual jmpTarget: self Label.
- self ssPushRegister: resultReg.
- ^0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genForwardersInlinedIdenticalOrNotIf: (in category 'bytecode generators') -----
+ genForwardersInlinedIdenticalOrNotIf: orNot
+ | nextPC branchDescriptor unforwardRcvr argReg targetBytecodePC
+ unforwardArg rcvrReg postBranchPC label fixup |
+ <var: #branchDescriptor type: #'BytecodeDescriptor *'>
+ <var: #label type: #'AbstractInstruction *'>
+
+ self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target |
+ branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
+
+ "If an operand is an annotable constant, it may be forwarded, so we need to store it into a
+ register so the forwarder check can jump back to the comparison after unforwarding the constant.
+ However, if one of the operand is an unnanotable constant, does not allocate a register for it
+ (machine code will use operations on constants) and does not generate forwarder checks."
+ unforwardRcvr := (objectRepresentation isUnannotatableConstant: (self ssValue: 1)) not.
+ unforwardArg := (objectRepresentation isUnannotatableConstant: self ssTop) not.
+
+ self
+ allocateEqualsEqualsRegistersArgNeedsReg: unforwardArg
+ rcvrNeedsReg: unforwardRcvr
+ into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ].
+
+ "If not followed by a branch, resolve to true or false."
+ (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
+ [^ self
+ genIdenticalNoBranchArgIsConstant: unforwardArg not
+ rcvrIsConstant: unforwardRcvr not
+ argReg: argReg
+ rcvrReg: rcvrReg
+ orNotIf: orNot].
+
+ "If branching the stack must be flushed for the merge"
+ self ssFlushTo: simStackPtr - 2.
+
+ label := self Label.
+ self genCmpArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg.
+ self ssPop: 2.
+
+ "Further since there is a following conditional jump bytecode, define
+ non-merge fixups and leave the cond bytecode to set the mergeness."
+ (self fixupAt: nextPC - initialPC) notAFixup
+ ifTrue: "The next instruction is dead. we can skip it."
+ [deadCode := true.
+ self ensureFixupAt: targetBytecodePC - initialPC.
+ self ensureFixupAt: postBranchPC - initialPC]
+ ifFalse:
+ [self ssPushConstant: objectMemory trueObject]. "dummy value"
+
+ self assert: (unforwardArg or: [unforwardRcvr]).
+ "We could use (branchDescriptor isBranchTrue xor: orNot) to simplify this."
+ orNot
+ ifFalse: [branchDescriptor isBranchTrue
+ ifTrue:
+ [ fixup := (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger ]
+ ifFalse: "branchDescriptor is branchFalse"
+ [ fixup := (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger ]]
+ ifTrue: [branchDescriptor isBranchTrue
+ ifFalse: "branchDescriptor is branchFalse"
+ [ fixup := (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger ]
+ ifTrue:
+ [ fixup := (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+ self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger ]].
+
+ "The forwarders checks need to jump back to the comparison (label) if a forwarder is found, else
+ jump forward either to the next forwarder check or to the postBranch or branch target (fixup)."
+ unforwardArg ifTrue:
+ [ unforwardRcvr
+ ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg jumpBackTo: label ]
+ ifFalse: [ objectRepresentation
+ genEnsureOopInRegNotForwarded: argReg
+ scratchReg: TempReg
+ ifForwarder: label
+ ifNotForwarder: fixup ] ].
+ unforwardRcvr ifTrue:
+ [ objectRepresentation
+ genEnsureOopInRegNotForwarded: rcvrReg
+ scratchReg: TempReg
+ ifForwarder: label
+ ifNotForwarder: fixup ].
+
+ "Not reached, execution flow have jumped to fixup"
+
+ ^0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genIdenticalNoBranchArgIsConstant:rcvrIsConstant:argReg:rcvrReg:orNotIf: (in category 'bytecode generator support') -----
+ genIdenticalNoBranchArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrRegOrNone orNotIf: orNot
+ "Generates the machine code for #== in the case where the instruction is not followed by a branch"
+ | label jumpEqual jumpNotEqual resultReg |
+ <var: #label type: #'AbstractInstruction *'>
+ <var: #jumpEqual type: #'AbstractInstruction *'>
+ <var: #jumpNotEqual type: #'AbstractInstruction *'>
+ label := self Label.
+ self genCmpArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrRegOrNone.
+ self ssPop: 2.
+ resultReg := rcvrRegOrNone = NoReg ifTrue: [argReg] ifFalse: [rcvrRegOrNone].
+ jumpEqual := self JumpZero: 0.
+ argIsConstant ifFalse:
+ [objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg jumpBackTo: label].
+ rcvrIsConstant ifFalse:
+ [objectRepresentation genEnsureOopInRegNotForwarded: rcvrRegOrNone scratchReg: TempReg jumpBackTo: label].
+ orNot ifFalse: [self genMoveFalseR: resultReg] ifTrue: [self genMoveTrueR: resultReg].
+ jumpNotEqual := self Jump: 0.
+ jumpEqual jmpTarget: (orNot ifFalse: [self genMoveTrueR: resultReg] ifTrue: [self genMoveFalseR: resultReg]).
+ jumpNotEqual jmpTarget: self Label.
+ self ssPushRegister: resultReg.
+ ^0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genInlinedIdenticalOrNotIf: (in category 'bytecode generators') -----
+ genInlinedIdenticalOrNotIf: orNot
+ "Decompose code generation for #== into a common constant-folding version,
+ followed by a double dispatch throguh the objectRepresentation to a version
+ that doesn't deal with forwarders and a version that does."
+ | primDescriptor result |
+ <var: #primDescriptor type: #'BytecodeDescriptor *'>
+ primDescriptor := self generatorAt: byte0.
+
+ ((objectRepresentation isUnannotatableConstant: self ssTop)
+ and: [ objectRepresentation isUnannotatableConstant: (self ssValue: 1) ]) ifTrue:
+ [self assert: primDescriptor isMapped not.
+ result := (orNot
+ ifFalse: [self ssTop constant = (self ssValue: 1) constant]
+ ifTrue: [self ssTop constant ~= (self ssValue: 1) constant])
+ ifTrue: [objectMemory trueObject]
+ ifFalse: [objectMemory falseObject].
+ self ssPop: 2.
+ ^self ssPushConstant: result].
+
+ ^objectRepresentation genInlinedIdenticalOrNotIfGuts: orNot!
Item was removed:
- ----- Method: StackToRegisterMappingCogit>>genSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
- genSpecialSelectorEqualsEquals
- "Decompose code generation for #== into a common constant-folding version,
- followed by a double dispatch throguh the objectRepresentation to a version
- that doesn't deal with forwarders and a version that does."
- | primDescriptor result |
- <var: #primDescriptor type: #'BytecodeDescriptor *'>
- primDescriptor := self generatorAt: byte0.
-
- ((objectRepresentation isUnannotatableConstant: self ssTop)
- and: [ objectRepresentation isUnannotatableConstant: (self ssValue: 1) ]) ifTrue:
- [self assert: primDescriptor isMapped not.
- result := self ssTop constant = (self ssValue: 1) constant
- ifTrue: [objectMemory trueObject]
- ifFalse: [objectMemory falseObject].
- self ssPop: 2.
- ^self ssPushConstant: result].
-
- ^objectRepresentation genSpecialSelectorEqualsEqualsGuts!
Item was removed:
- ----- Method: StackToRegisterMappingCogit>>genSpecialSelectorEqualsEqualsWithForwarders (in category 'bytecode generators') -----
- genSpecialSelectorEqualsEqualsWithForwarders
- | nextPC branchDescriptor unforwardRcvr argReg targetBytecodePC
- unforwardArg rcvrReg postBranchPC label fixup |
- <var: #branchDescriptor type: #'BytecodeDescriptor *'>
- <var: #label type: #'AbstractInstruction *'>
-
- self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target |
- branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
-
- "If an operand is an annotable constant, it may be forwarded, so we need to store it into a
- register so the forwarder check can jump back to the comparison after unforwarding the constant.
- However, if one of the operand is an unnanotable constant, does not allocate a register for it
- (machine code will use operations on constants) and does not generate forwarder checks."
- unforwardRcvr := (objectRepresentation isUnannotatableConstant: (self ssValue: 1)) not.
- unforwardArg := (objectRepresentation isUnannotatableConstant: self ssTop) not.
-
- self
- allocateEqualsEqualsRegistersArgNeedsReg: unforwardArg
- rcvrNeedsReg: unforwardRcvr
- into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ].
-
- "If not followed by a branch, resolve to true or false."
- (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
- [^ self genEqualsEqualsNoBranchArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg].
-
- "If branching the stack must be flushed for the merge"
- self ssFlushTo: simStackPtr - 2.
-
- label := self Label.
- self genEqualsEqualsComparisonArgIsConstant: unforwardArg not rcvrIsConstant: unforwardRcvr not argReg: argReg rcvrReg: rcvrReg.
- self ssPop: 2.
-
- "Further since there is a following conditional jump bytecode, define
- non-merge fixups and leave the cond bytecode to set the mergeness."
- (self fixupAt: nextPC - initialPC) notAFixup
- ifTrue: "The next instruction is dead. we can skip it."
- [deadCode := true.
- self ensureFixupAt: targetBytecodePC - initialPC.
- self ensureFixupAt: postBranchPC - initialPC]
- ifFalse:
- [self ssPushConstant: objectMemory trueObject]. "dummy value"
-
- self assert: (unforwardArg or: [ unforwardRcvr ]).
- branchDescriptor isBranchTrue
- ifTrue:
- [ fixup := (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger.
- self JumpZero: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger ]
- ifFalse: "branchDescriptor is branchFalse"
- [ fixup := (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
- self JumpZero: (self ensureNonMergeFixupAt: postBranchPC - initialPC) asUnsignedInteger ].
-
- "The forwarders checks need to jump back to the comparison (label) if a forwarder is found, else
- jump forward either to the next forwarder check or to the postBranch or branch target (fixup)."
- unforwardArg ifTrue:
- [ unforwardRcvr
- ifTrue: [ objectRepresentation genEnsureOopInRegNotForwarded: argReg scratchReg: TempReg jumpBackTo: label ]
- ifFalse: [ objectRepresentation
- genEnsureOopInRegNotForwarded: argReg
- scratchReg: TempReg
- ifForwarder: label
- ifNotForwarder: fixup ] ].
- unforwardRcvr ifTrue:
- [ objectRepresentation
- genEnsureOopInRegNotForwarded: rcvrReg
- scratchReg: TempReg
- ifForwarder: label
- ifNotForwarder: fixup ].
-
- "Not reached, execution flow have jumped to fixup"
-
- ^0!
Item was added:
+ ----- Method: StackToRegisterMappingCogit>>genVanillaInlinedIdenticalOrNotIf: (in category 'bytecode generators') -----
+ genVanillaInlinedIdenticalOrNotIf: orNot
+ | nextPC postBranchPC targetBytecodePC branchDescriptor
+ rcvrReg argReg argIsConstant rcvrIsConstant |
+ <var: #branchDescriptor type: #'BytecodeDescriptor *'>
+
+ self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target |
+ branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
+
+ argIsConstant := self ssTop type = SSConstant.
+ "They can't be both constants to use correct machine opcodes.
+ However annotable constants can't be resolved statically, hence we need to careful."
+ rcvrIsConstant := argIsConstant not and: [(self ssValue: 1) type = SSConstant].
+
+ self
+ allocateEqualsEqualsRegistersArgNeedsReg: argIsConstant not
+ rcvrNeedsReg: rcvrIsConstant not
+ into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ].
+
+ "If not followed by a branch, resolve to true or false."
+ (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
+ [^ self
+ genIdenticalNoBranchArgIsConstant: argIsConstant
+ rcvrIsConstant: rcvrIsConstant
+ argReg: argReg
+ rcvrReg: rcvrReg
+ orNotIf: orNot].
+
+ "If branching the stack must be flushed for the merge"
+ self ssFlushTo: simStackPtr - 2.
+
+ self genCmpArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrReg.
+ self ssPop: 2.
+
+ "Further since there is a following conditional jump bytecode, define
+ non-merge fixups and leave the cond bytecode to set the mergeness."
+ (self fixupAt: nextPC - initialPC) notAFixup
+ ifTrue: "The next instruction is dead. we can skip it."
+ [deadCode := true.
+ self ensureFixupAt: targetBytecodePC - initialPC.
+ self ensureFixupAt: postBranchPC - initialPC]
+ ifFalse:
+ [self ssPushConstant: objectMemory trueObject]. "dummy value"
+
+ "We could simplify this with a xor:"
+ self genConditionalBranch: (orNot
+ ifFalse: [branchDescriptor isBranchTrue ifTrue: [JumpZero] ifFalse: [JumpNonZero]]
+ ifTrue: [branchDescriptor isBranchTrue ifTrue: [JumpNonZero] ifFalse: [JumpZero]])
+ operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
+
+ "If the branch is dead, then we can just fall through postBranchPC (only a nop in-between), else
+ we need to jump over the code of the branch"
+ deadCode ifFalse: [self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC)].
+ ^0!
Item was removed:
- ----- Method: StackToRegisterMappingCogit>>genVanillaSpecialSelectorEqualsEquals (in category 'bytecode generators') -----
- genVanillaSpecialSelectorEqualsEquals
- | nextPC postBranchPC targetBytecodePC branchDescriptor
- rcvrReg argReg argIsConstant rcvrIsConstant |
- <var: #branchDescriptor type: #'BytecodeDescriptor *'>
-
- self extractMaybeBranchDescriptorInto: [ :descr :next :postBranch :target |
- branchDescriptor := descr. nextPC := next. postBranchPC := postBranch. targetBytecodePC := target ].
-
- argIsConstant := self ssTop type = SSConstant.
- "they can't be both constants because we do not have instructions manipulating two constants,
- if this is the case, which can happen due to annotable constants that can be moved in memory
- with become and therefore can't resolve #== at compilation time, still write the rcvr into a
- register as if it was not a constant. It's uncommon anyway."
- rcvrIsConstant := argIsConstant not and: [(self ssValue: 1) type = SSConstant].
-
- self
- allocateEqualsEqualsRegistersArgNeedsReg: argIsConstant not
- rcvrNeedsReg: rcvrIsConstant not
- into: [ :rcvr :arg | rcvrReg:= rcvr. argReg := arg ].
-
- "If not followed by a branch, resolve to true or false."
- (branchDescriptor isBranchTrue or: [branchDescriptor isBranchFalse]) ifFalse:
- [ ^ self genEqualsEqualsNoBranchArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrReg].
-
- "If branching the stack must be flushed for the merge"
- self ssFlushTo: simStackPtr - 2.
-
- self genEqualsEqualsComparisonArgIsConstant: argIsConstant rcvrIsConstant: rcvrIsConstant argReg: argReg rcvrReg: rcvrReg.
- self ssPop: 2.
-
- "Further since there is a following conditional jump bytecode, define
- non-merge fixups and leave the cond bytecode to set the mergeness."
- (self fixupAt: nextPC - initialPC) notAFixup
- ifTrue: "The next instruction is dead. we can skip it."
- [deadCode := true.
- self ensureFixupAt: targetBytecodePC - initialPC.
- self ensureFixupAt: postBranchPC - initialPC]
- ifFalse:
- [self ssPushConstant: objectMemory trueObject]. "dummy value"
-
- self genConditionalBranch: (branchDescriptor isBranchTrue ifTrue: [JumpZero] ifFalse: [JumpNonZero])
- operand: (self ensureNonMergeFixupAt: targetBytecodePC - initialPC) asUnsignedInteger.
-
- "If the branch is dead, then we can just fall through postBranchPC (only a nop in-between), else
- we need to jump over the code of the branch"
- deadCode ifFalse: [self Jump: (self ensureNonMergeFixupAt: postBranchPC - initialPC)].
- ^0!
More information about the Vm-dev
mailing list