lists.squeakfoundation.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Vm-dev
November 2016
----- 2024 -----
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
vm-dev@lists.squeakfoundation.org
34 participants
155 discussions
Start a n
N
ew thread
[OpenSmalltalk/opensmalltalk-vm] dfe6cf: Minor improvement
by GitHub
24 Nov '16
24 Nov '16
Branch: refs/heads/Cog Home:
https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: dfe6cf8cbfc04982ffecd4e92768700f31eea2c2
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/dfe6cf8cbfc04982ff…
Author: Fabio Niephaus <code(a)fniephaus.com> Date: 2016-11-24 (Thu, 24 Nov 2016) Changed paths: M .travis_build.sh Log Message: ----------- Minor improvement
1
0
0
0
[OpenSmalltalk/opensmalltalk-vm] 6513b4: Bundle ht and itimer VMs separately
by GitHub
24 Nov '16
24 Nov '16
Branch: refs/heads/Cog Home:
https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 6513b463cd10bf1d56beba3de42facdfb17a5d12
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/6513b463cd10bf1d56…
Author: Fabio Niephaus <code(a)fniephaus.com> Date: 2016-11-24 (Thu, 24 Nov 2016) Changed paths: M .travis_build.sh Log Message: ----------- Bundle ht and itimer VMs separately and improve .travis_build.sh
1
0
0
0
[OpenSmalltalk/opensmalltalk-vm] ece41e: Use unique Travis fold name
by GitHub
24 Nov '16
24 Nov '16
Branch: refs/heads/Cog Home:
https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: ece41e78a438b7129aa18ba2423bda70ef12c57c
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/ece41e78a438b7129a…
Author: Fabio Niephaus <code(a)fniephaus.com> Date: 2016-11-24 (Thu, 24 Nov 2016) Changed paths: M .travis_build.sh Log Message: ----------- Use unique Travis fold name
1
0
0
0
[OpenSmalltalk/opensmalltalk-vm] 293bbf: Also build VM with itimerheartbeat if available
by GitHub
24 Nov '16
24 Nov '16
Branch: refs/heads/Cog Home:
https://github.com/OpenSmalltalk/opensmalltalk-vm
Commit: 293bbf9134efccb9a0b1d4d8a4c3190b02a34cb0
https://github.com/OpenSmalltalk/opensmalltalk-vm/commit/293bbf9134efccb9a0…
Author: Fabio Niephaus <code(a)fniephaus.com> Date: 2016-11-24 (Thu, 24 Nov 2016) Changed paths: M .travis_build.sh Log Message: ----------- Also build VM with itimerheartbeat if available
1
0
0
0
VM Maker: VMMaker.oscog-cb.2003.mcz
by commits@source.squeak.org
24 Nov '16
24 Nov '16
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!
1
0
0
0
[VM-dev] Does reflective call (#perform:) jitted?
by Denis Kudriashov
24 Nov '16
24 Nov '16
Hello. I have another question on special cases for jitter. Do VM has a kind of PIC for reflective calls like #perform:? In addition to receiver class it could also check selector from argument.
4
7
0
0
VM Maker: VMMaker.oscog-eem.2002.mcz
by commits@source.squeak.org
24 Nov '16
24 Nov '16
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2002.mcz
==================== Summary ==================== Name: VMMaker.oscog-eem.2002 Author: eem Time: 23 November 2016, 5:45:22.404678 pm UUID: 326c4e54-4578-420d-948e-e5e58a1fa993 Ancestors: VMMaker.oscog-eem.2001 RegisterAllocatingCogit Get the 64-bit system as far as the second \\ send in IdentityDictionary>>#scanFor:. Set a simStackEntry's liveRegister in popToReg: and storeToReg: in addition to in genStorePop:TemporaryVariable:. When setting liveRegister: in this way, look through the simStack for any and all copies of the entry having its liveRegister set, and set their liveRegister to match. When ensuring that ensureReceiverResultRegContainsSelf, nuke any liveRegister in non-self stack entries that is equal ReceiverResultReg. Make inlined genSpecialSelectorArithmetic keep register values live around the uncommon send by cloning the simStack after generating inline code and reconciling the register state after the send. liveRegister must be taken into account when asking for a simStackEntry's registerMask to arrange that flushing/spilling occurs. Print the optStatus as well as the simStack when tracing the simStack. =============== Diff against VMMaker.oscog-eem.2001 =============== Item was changed: CogSSBytecodeFixup subclass: #CogRASSBytecodeFixup instanceVariableNames: 'cogit mergeSimStack' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-JIT'! + + !CogRASSBytecodeFixup commentStamp: 'eem 11/22/2016 08:44' prior: 0! + A CogRASSBytecodeFixup extends CogSSBytecodeFixup with state to merge the stack at control-flow joins, preserving register contents. By holding onto the entire stack state a CogRASSBytecodeFixup allows RegisterAllocatingCogit to merge individual stack entries, instead of merely spilling to the same height. + + Instance Variables + cogit: <RegisterAllocatingCogit> + mergeSimStack: <Array of: CogRegisterAllocatingSimStackEntry> + + cogit + - the JIT compiler + + mergeSimStack + - the state of the stack at the jump to this fixup! Item was changed: ----- Method: CogRegisterAllocatingSimStackEntry>>ensureSpilledAt:from: (in category 'compile abstract instructions') ----- ensureSpilledAt: baseOffset from: baseRegister - | inst | - <var: #inst type: #'AbstractInstruction *'> spilled ifTrue: [type = SSSpill ifTrue: [self assert: (offset = baseOffset and: [register = baseRegister]). + liveRegister := NoReg. ^self]]. self assert: type ~= SSSpill. cogit traceSpill: self. type = SSConstant ifTrue: + [cogit genPushConstant: constant] - [inst := cogit genPushConstant: constant] ifFalse: [type = SSBaseOffset ifTrue: + [liveRegister = NoReg - [ liveRegister = NoReg ifTrue: [cogit MoveMw: offset r: register R: TempReg. + cogit PushR: TempReg] + ifFalse: [cogit PushR: liveRegister]] - inst := cogit PushR: TempReg ] - ifFalse: [ inst := cogit PushR: liveRegister]] ifFalse: [self assert: type = SSRegister. + cogit PushR: register]. - inst := cogit PushR: register]. type := SSSpill. offset := baseOffset. register := baseRegister]. + liveRegister := NoReg. + spilled := true! - spilled := true.! Item was added: + ----- Method: CogRegisterAllocatingSimStackEntry>>isSameEntryAs: (in category 'comparing') ----- + isSameEntryAs: ssEntry + ^type = ssEntry type + and: [((type = SSBaseOffset or: [type == SSSpill]) and: [offset = ssEntry offset and: [register = ssEntry register]]) + or: [(type = SSRegister and: [register = ssEntry register]) + or: [(type = SSConstant and: [constant = ssEntry constant])]]]! Item was added: + ----- Method: CogRegisterAllocatingSimStackEntry>>noteLiveRegisterIn: (in category 'compile abstract instructions') ----- + noteLiveRegisterIn: simStackEntry + "Copy the liveRegister state in simStackEntry into the receiver if it is the same value at a different location on the stack." + <inline: true> + self flag: 'should this also apply to SSConstant entries assigned to registers?'. + (self ~~ simStackEntry + and: [type = simStackEntry type + and: [type = SSBaseOffset + and: [register = simStackEntry register and: [offset = simStackEntry offset]]]]) ifTrue: + [liveRegister := simStackEntry liveRegister]! Item was added: + ----- Method: CogRegisterAllocatingSimStackEntry>>offset (in category 'accessing') ----- + offset + "Answer the value of offset" + self assert: (type = SSBaseOffset or: [type = SSSpill]). + ^offset! Item was changed: ----- Method: CogRegisterAllocatingSimStackEntry>>popToReg: (in category 'compile abstract instructions') ----- popToReg: reg | inst | <var: #inst type: #'AbstractInstruction *'> liveRegister ~= NoReg ifTrue: [inst := reg ~= liveRegister ifTrue: [cogit MoveR: liveRegister R: reg] ifFalse: [cogit Label] ] ifFalse: [spilled ifTrue: [inst := cogit PopR: reg] ifFalse: [type caseOf: { [SSBaseOffset] -> [inst := cogit MoveMw: offset r: register R: reg]. [SSConstant] -> [inst := cogit genMoveConstant: constant R: reg]. [SSRegister] -> [inst := reg ~= register ifTrue: [cogit MoveR: register R: reg] ifFalse: [cogit Label]] }]]. + reg ~= TempReg ifTrue: + [liveRegister := reg. + cogit observeLiveRegisterIn: self]! - reg ~= TempReg ifTrue: [ liveRegister := reg ]! Item was added: + ----- Method: CogRegisterAllocatingSimStackEntry>>reconcileWith: (in category 'compile abstract instructions') ----- + reconcileWith: simStackEntry + <var: #simStackEntry type: #'SimStackEntry *'> + type = SSConstant ifTrue: + [cogit AddCw: BytesPerWord R: SPReg. + ^self]. + liveRegister ~= NoReg ifTrue: + [simStackEntry popToReg: liveRegister. + ^self]. + type = SSRegister ifTrue: + [simStackEntry popToReg: register. + ^self]. + self halt! Item was added: + ----- Method: CogRegisterAllocatingSimStackEntry>>register (in category 'accessing') ----- + register + "Answer the value of register" + self assert: (type = SSBaseOffset or: [type = SSRegister or: [type = SSSpill]]). + ^register! Item was added: + ----- Method: CogRegisterAllocatingSimStackEntry>>registerMask (in category 'accessing') ----- + registerMask + "Answer a bit mask for the receiver's register, if any." + liveRegister ~= NoReg ifTrue: + [^cogit registerMaskFor: liveRegister]. + ^super registerMask! Item was added: + ----- Method: CogRegisterAllocatingSimStackEntry>>registerOrNone (in category 'accessing') ----- + registerOrNone + liveRegister ~= NoReg ifTrue: + [^liveRegister]. + ^super registerOrNone! Item was changed: ----- Method: CogRegisterAllocatingSimStackEntry>>storeToReg: (in category 'compile abstract instructions') ----- storeToReg: reg | inst | <var: #inst type: #'AbstractInstruction *'> liveRegister ~= NoReg ifTrue: [inst := reg ~= liveRegister ifTrue: [cogit MoveR: liveRegister R: reg] ifFalse: [cogit Label]] ifFalse: [type caseOf: { [SSBaseOffset] -> [inst := cogit MoveMw: offset r: register R: reg]. [SSSpill] -> [inst := cogit MoveMw: offset r: register R: reg]. [SSConstant] -> [inst := cogit genMoveConstant: constant R: reg]. [SSRegister] -> [inst := reg ~= register ifTrue: [cogit MoveR: register R: reg] ifFalse: [cogit Label]] }]. + reg ~= TempReg ifTrue: + [liveRegister := reg. + cogit observeLiveRegisterIn: self]! - reg ~= TempReg ifTrue: [ liveRegister := reg ]! Item was changed: CogBytecodeFixup subclass: #CogSSBytecodeFixup instanceVariableNames: 'simStackPtr simNativeStackPtr simNativeStackSize' classVariableNames: 'NeedsMergeFixupFlag NeedsNonMergeFixupFlag UnknownSimStackPtrFlag' poolDictionaries: '' category: 'VMMaker-JIT'! + !CogSSBytecodeFixup commentStamp: 'eem 11/22/2016 08:39' prior: 0! - !CogSSBytecodeFixup commentStamp: 'eem 1/20/2011 13:03' prior: 0! A CogSSBytecodeFixup extends CogBytecodeFixup with state to merge the stack at control-flow joins. At a join the code generator must ensure that the stack is spilled to the same point along both branches and that the simStackPtr is correct. Instance Variables simStackPtr: <Integer> simStackPtr + - the simStackPtr at the jump to this fixup. It should either agree with the incoming fixup if control continues, or replace the simStackPtr if control doesn't continue (the incomming control flow ended with a return)! - - the simStackPtr at the jump to this fixup. It should either agree with the incoming fixup if control continues, or replace the simStackPtr if contrl doesn't continue (the incomming control flow ended with a return)! Item was changed: ----- Method: Cogit>>compilationTrace: (in category 'simulation only') ----- compilationTrace: anInteger + " 1 = method/block compilation + 2 = bytecode descriptor. + 4 = simStack & optStatus + 8 = spill - "1 = compilation - 2 = bytecode descriptor. - 4 = simStack. - 8 = spill 16 = merge + 32 = fixup" - 32 = fixup" compilationTrace := anInteger! Item was changed: ----- Method: Cogit>>exclude: (in category 'simulation only') ----- exclude: aMethodObj "For debugging, allow excluding methods based on selector or methodClass. Answer if the mehtod should be excluded." <inline: true> self cCode: [] inSmalltalk: "for debugging, allow excluding methods based on selector or methodClass" [self class initializationOptions at: #DoNotJIT ifPresent: [:excluded| (excluded anySatisfy: [:exclude| aMethodObj = exclude]) ifTrue: + [coInterpreter transcript + ensureCr; nextPutAll: 'EXCLUDING '; + nextPutAll: aMethodObj; nextPutAll: ' (compiled block)'; + cr; flush. - [coInterpreter transcript nextPutAll: 'EXCLUDING '; nextPutAll: aMethodObj; nextPutAll: ' (compiled block)'; cr; flush. ^true]]. (compilationTrace anyMask: 1) ifTrue: [| methodClass | methodClass := coInterpreter nameOfClass: (coInterpreter methodClassOf: aMethodObj). coInterpreter transcript + ensureCr; nextPutAll: 'compiling compiled block in '; nextPutAll: methodClass; cr; flush]]. ^false! Item was changed: ----- Method: Cogit>>exclude:selector: (in category 'simulation only') ----- exclude: aMethodObj selector: aSelectorOop "For debugging, allow excluding methods based on selector or methodClass. Answer if the mehtod should be excluded." <inline: true> self cCode: [] inSmalltalk: [| methodClass selector | self class initializationOptions at: #DoNotJIT ifPresent: [:excluded| methodClass := coInterpreter nameOfClass: (coInterpreter methodClassOf: aMethodObj). selector := coInterpreter stringOf: aSelectorOop. (excluded anySatisfy: [:exclude| selector = exclude or: [methodClass = exclude]]) ifTrue: [coInterpreter transcript + ensureCr; nextPutAll: 'EXCLUDING '; + nextPutAll: methodClass; nextPutAll: '>>#'; nextPutAll: selector; - nextPutAll: 'EXCLUDING '; - nextPutAll: methodClass; - nextPutAll: '>>#'; - nextPutAll: selector; cr; flush. ^true]]. (compilationTrace anyMask: 1) ifTrue: [methodClass := coInterpreter nameOfClass: (coInterpreter methodClassOf: aMethodObj). selector := coInterpreter stringOf: aSelectorOop. selector isEmpty ifTrue: [selector := coInterpreter stringOf: (coInterpreter maybeSelectorOfMethod: aMethodObj)]. coInterpreter transcript + ensureCr; nextPutAll: 'compiling '; + nextPutAll: methodClass; nextPutAll: '>>#'; nextPutAll: selector; - nextPutAll: 'compiling '; - nextPutAll: methodClass; - nextPutAll: '>>#'; - nextPutAll: selector; cr; flush]]. ^false! Item was changed: ----- Method: CurrentImageCoInterpreterFacade>>stringOf: (in category 'accessing') ----- stringOf: anOop + ^(self lookupAddress: anOop) asString! - ^self lookupAddress: anOop! Item was changed: StackToRegisterMappingCogit subclass: #RegisterAllocatingCogit + instanceVariableNames: 'numFixups mergeSimStacksBase nextFixup scratchSimStack scratchSpillBase' - instanceVariableNames: 'numFixups mergeSimStacksBase nextFixup' classVariableNames: '' poolDictionaries: '' category: 'VMMaker-JIT'! !RegisterAllocatingCogit commentStamp: 'cb 4/15/2016 14:58' prior: 0! RegisterAllocatingCogit is an optimizing code generator that is specialized in register allocation.. On the contrary to StackToRegisterMappingCogit, RegisterAllocatingCogit keeps at each control flow merge point the state of the simulated stack to merge into and not only an integer fixup. Each branch and jump record the current state of the simulated stack, and each fixup is responsible for merging this state into the saved simulated stack. ! Item was added: + ----- Method: RegisterAllocatingCogit class>>declareCVarsIn: (in category 'C translation') ----- + declareCVarsIn: aCodeGen + aCodeGen var: #scratchSimStack type: #'CogSimStackEntry *'! Item was added: + ----- Method: RegisterAllocatingCogit>>copySimStackToScratch: (in category 'bytecode generator support') ----- + copySimStackToScratch: spillBase + <inline: true> + self cCode: [self mem: scratchSimStack cp: simStack y: self simStackSlots * (self sizeof: CogSimStackEntry)] + inSmalltalk: [0 to: simStackPtr do: + [:i| + scratchSimStack at: i put: (simStack at: i) copy]]. + scratchSpillBase := spillBase! Item was added: + ----- Method: RegisterAllocatingCogit>>ensureReceiverResultRegContainsSelf (in category 'bytecode generator support') ----- + ensureReceiverResultRegContainsSelf + super ensureReceiverResultRegContainsSelf. + 0 to: simStackPtr do: + [:i| + (simSelf isSameEntryAs: (self simStackAt: i)) + ifTrue: [(self simStackAt: i) liveRegister: ReceiverResultReg] + ifFalse: + [(self simStackAt: i) liveRegister = ReceiverResultReg ifTrue: + [(self simStackAt: i) liveRegister: NoReg]]]. + simSelf liveRegister: ReceiverResultReg! Item was added: + ----- Method: RegisterAllocatingCogit>>existsInstVarRefBeforeSendOrReturn (in category 'bytecode generator support') ----- + existsInstVarRefBeforeSendOrReturn + "Answer if the current bytecode is followed by an inst var ref before the next full send." + | pc nExts descriptor | + pc := bytecodePC. + nExts := 0. + [pc <= endPC] whileTrue: + [descriptor := self generatorAt: pc. + (descriptor isMapped + or: [descriptor isBranchTrue + or: [descriptor isBranchFalse + or: [descriptor spanFunction notNil]]]) ifTrue: + [^false]. + descriptor isInstVarRef ifTrue: + [^true]. + nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [0]. + pc := self nextBytecodePCFor: descriptor at: pc exts: nExts in: methodObj]. + ^false! Item was changed: ----- Method: RegisterAllocatingCogit>>flushLiveRegistersForCRunTimeCall (in category 'bytecode generator support') ----- flushLiveRegistersForCRunTimeCall <inline: true> + | reg | + self assert: simSelf type = SSBaseOffset. + reg := simSelf liveRegister. + (reg ~= NoReg and: [(self isCallerSavedReg: reg)]) ifTrue: + [simSelf liveRegister: NoReg]. 0 to: simStackPtr do: + [:i| - [:i| | reg | self assert: (self simStackAt: i) type = (i <= methodOrBlockNumTemps ifTrue: [SSBaseOffset] ifFalse: [SSSpill]). reg := (self simStackAt: i) liveRegister. (reg ~= NoReg and: [(self isCallerSavedReg: reg)]) ifTrue: [(self simStackAt: i) liveRegister: NoReg]]! Item was added: + ----- Method: RegisterAllocatingCogit>>flushLiveRegistersForSend (in category 'bytecode generator support') ----- + flushLiveRegistersForSend + <inline: true> + self assert: simSelf type = SSBaseOffset. + simSelf liveRegister: NoReg. + 0 to: simStackPtr do: + [:i| + self assert: ((self simStackAt: i) spilled + and: [((self simStackAt: i) type = SSBaseOffset + or: [i >= methodOrBlockNumTemps + and: (self simStackAt: i) type = SSSpill]) + and: [(self simStackAt: i) register = FPReg + and: [(self simStackAt: i) offset = (self frameOffsetOfTemporary: i)]]]). + (self simStackAt: i) liveRegister: NoReg]! Item was removed: - ----- Method: RegisterAllocatingCogit>>flushLiveRegistersForSend: (in category 'bytecode generator support') ----- - flushLiveRegistersForSend: numArgs - <inline: true> - simSelf liveRegister: NoReg. - 0 to: simStackPtr - numArgs - 1 do: - [:i| - self assert: (self simStackAt: i) type = (i < methodOrBlockNumTemps - ifTrue: [SSBaseOffset] - ifFalse: [SSSpill]). - (self simStackAt: i) liveRegister: NoReg]! Item was added: + ----- Method: RegisterAllocatingCogit>>frameOffsetOfLastTemp (in category 'bytecode generator support') ----- + frameOffsetOfLastTemp + ^self frameOffsetOfTemporary: methodOrBlockNumTemps! Item was changed: ----- Method: RegisterAllocatingCogit>>genMarshalledSend:numArgs:sendTable: (in category 'bytecode generator support') ----- genMarshalledSend: selectorIndex numArgs: numArgs sendTable: sendTable + self flushLiveRegistersForSend. - self flushLiveRegistersForSend: numArgs. ^super genMarshalledSend: selectorIndex numArgs: numArgs sendTable: sendTable! Item was added: + ----- Method: RegisterAllocatingCogit>>genSpecialSelectorArithmetic (in category 'bytecode generators') ----- + genSpecialSelectorArithmetic + | primDescriptor rcvrIsConst argIsConst rcvrIsInt argIsInt rcvrInt argInt result + jumpNotSmallInts jumpContinue index rcvrReg argReg | + <var: #jumpContinue type: #'AbstractInstruction *'> + <var: #primDescriptor type: #'BytecodeDescriptor *'> + <var: #jumpNotSmallInts type: #'AbstractInstruction *'> + primDescriptor := self generatorAt: byte0. + argIsInt := (argIsConst := self ssTop type = SSConstant) + and: [objectMemory isIntegerObject: (argInt := self ssTop constant)]. + rcvrIsInt := (rcvrIsConst := (self ssValue: 1) type = SSConstant) + and: [objectMemory isIntegerObject: (rcvrInt := (self ssValue: 1) constant)]. + + (argIsInt and: [rcvrIsInt]) ifTrue: + [rcvrInt := objectMemory integerValueOf: rcvrInt. + argInt := objectMemory integerValueOf: argInt. + primDescriptor opcode caseOf: { + [AddRR] -> [result := rcvrInt + argInt]. + [SubRR] -> [result := rcvrInt - argInt]. + [AndRR] -> [result := rcvrInt bitAnd: argInt]. + [OrRR] -> [result := rcvrInt bitOr: argInt] }. + (objectMemory isIntegerValue: result) ifTrue: + ["Must annotate the bytecode for correct pc mapping." + ^self ssPop: 2; ssPushAnnotatedConstant: (objectMemory integerObjectOf: result)]. + ^self genSpecialSelectorSend]. + + "If there's any constant involved other than a SmallInteger don't attempt to inline." + ((rcvrIsConst and: [rcvrIsInt not]) + or: [argIsConst and: [argIsInt not]]) ifTrue: + [^self genSpecialSelectorSend]. + + "If we know nothing about the types then better not to inline as the inline cache and + primitive code is not terribly slow so wasting time on duplicating tag tests is pointless." + (argIsInt or: [rcvrIsInt]) ifFalse: + [^self genSpecialSelectorSend]. + + argIsInt + ifTrue: + [rcvrReg := self allocateRegForStackEntryAt: 1. + (self ssValue: 1) popToReg: rcvrReg. + self MoveR: rcvrReg R: TempReg] + ifFalse: + [self allocateRegForStackTopTwoEntriesInto: [:rTop :rNext| argReg := rTop. rcvrReg := rNext]. + self ssTop popToReg: argReg. + (self ssValue: 1) popToReg: rcvrReg. + self MoveR: argReg R: TempReg]. + self ssPop: 2. + jumpNotSmallInts := (argIsInt or: [rcvrIsInt]) + ifTrue: [objectRepresentation genJumpNotSmallIntegerInScratchReg: TempReg] + ifFalse: [objectRepresentation genJumpNotSmallIntegersIn: rcvrReg andScratch: TempReg scratch: ClassReg]. + primDescriptor opcode caseOf: { + [AddRR] -> [argIsInt + ifTrue: + [self AddCq: argInt - ConstZero R: rcvrReg. + jumpContinue := self JumpNoOverflow: 0. + "overflow; must undo the damage before continuing" + self SubCq: argInt - ConstZero R: rcvrReg] + ifFalse: + [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: rcvrReg. + self AddR: argReg R: rcvrReg. + jumpContinue := self JumpNoOverflow: 0. + "overflow; must undo the damage before continuing" + rcvrIsInt + ifTrue: [self MoveCq: rcvrInt R: rcvrReg] + ifFalse: + [self SubR: argReg R: rcvrReg. + objectRepresentation genSetSmallIntegerTagsIn: rcvrReg]]]. + [SubRR] -> [argIsInt + ifTrue: + [self SubCq: argInt - ConstZero R: rcvrReg. + jumpContinue := self JumpNoOverflow: 0. + "overflow; must undo the damage before continuing" + self AddCq: argInt - ConstZero R: rcvrReg] + ifFalse: + [objectRepresentation genRemoveSmallIntegerTagsInScratchReg: argReg. + self SubR: argReg R: rcvrReg. + jumpContinue := self JumpNoOverflow: 0. + "overflow; must undo the damage before continuing" + self AddR: argReg R: rcvrReg. + objectRepresentation genSetSmallIntegerTagsIn: argReg]]. + [AndRR] -> [argIsInt + ifTrue: [self AndCq: argInt R: rcvrReg] + ifFalse: [self AndR: argReg R: rcvrReg]. + jumpContinue := self Jump: 0]. + [OrRR] -> [argIsInt + ifTrue: [self OrCq: argInt R: rcvrReg] + ifFalse: [self OrR: argReg R: rcvrReg]. + jumpContinue := self Jump: 0] }. + jumpNotSmallInts jmpTarget: self Label. + self ssPushRegister: rcvrReg. + self copySimStackToScratch: (simSpillBase min: simStackPtr - 1). + self ssPop: 1. + self ssFlushTo: simStackPtr. + self deny: rcvrReg = Arg0Reg. + argIsInt + ifTrue: [self MoveCq: argInt R: Arg0Reg] + ifFalse: [argReg ~= Arg0Reg ifTrue: [self MoveR: argReg R: Arg0Reg]]. + rcvrReg ~= ReceiverResultReg ifTrue: [self MoveR: rcvrReg R: ReceiverResultReg]. + index := byte0 - self firstSpecialSelectorBytecodeOffset. + self genMarshalledSend: index negated - 1 numArgs: 1 sendTable: ordinarySendTrampolines. + self reconcileRegisterStateForJoinAfterSpecialSelectorSend. + jumpContinue jmpTarget: self Label. + ^0! Item was changed: ----- Method: RegisterAllocatingCogit>>genStorePop:TemporaryVariable: (in category 'bytecode generator support') ----- genStorePop: popBoolean TemporaryVariable: tempIndex "Override so that if a register other than TempReg is allocated, the temp is marked as being live in that register." | reg | self ssFlushUpThroughTemporaryVariable: tempIndex. reg := self ssStorePop: popBoolean toPreferredReg: TempReg. self MoveR: reg Mw: (self frameOffsetOfTemporary: tempIndex) r: FPReg. reg ~= TempReg ifTrue: + [(self simStackAt: tempIndex) liveRegister: reg. + self observeLiveRegisterIn: (self simStackAt: tempIndex)]. - [(self simStackAt: tempIndex) liveRegister: reg]. ^0! Item was added: + ----- Method: RegisterAllocatingCogit>>initializeCodeZoneFrom:upTo: (in category 'initialization') ----- + initializeCodeZoneFrom: startAddress upTo: endAddress + scratchSimStack := self cCode: [self malloc: self simStackSlots * (self sizeof: CogSimStackEntry)] + inSmalltalk: [CArrayAccessor on: ((1 to: self simStackSlots) collect: [:ign| CogRegisterAllocatingSimStackEntry new])]. + super initializeCodeZoneFrom: startAddress upTo: endAddress! Item was added: + ----- Method: RegisterAllocatingCogit>>observeLiveRegisterIn: (in category 'bytecode generator support') ----- + observeLiveRegisterIn: simStackEntry + "Copy the liveRegister in simStackEntry into all corresponding stack entries." + <var: #simStackEntry type: #'SimStackEntry *'> + simStackPtr to: 0 by: -1 do: + [:i| + (self simStackAt: i) noteLiveRegisterIn: simStackEntry]! Item was added: + ----- Method: RegisterAllocatingCogit>>reconcileRegisterStateForJoinAfterSpecialSelectorSend (in category 'bytecode generators') ----- + reconcileRegisterStateForJoinAfterSpecialSelectorSend + "When the control flow from the inlined special selector code (e.g. add or comparison) + joins the control flow from the send, taken when the inlined code fails, we should decide + whether to reload any registers known to contain useful values or mark them as dead." + + "If ReceiverResultReg is live along the inlined path, and is used before the next full send, + reload it on the uncommon path." + optStatus isReceiverResultRegLive ifTrue: + [self existsInstVarRefBeforeSendOrReturn + ifTrue: [optStatus ssEntry storeToReg: ReceiverResultReg] + ifFalse: [optStatus isReceiverResultRegLive: false]]. + + "Restore the simStack to that in scratchSimStack, + popping any spilled state back into allocated registers." + simSpillBase := scratchSpillBase. + simStackPtr to: simSpillBase + 1 by: -1 do: + [:i| + self assert: (i = simStackPtr + ifTrue: [(self simStackAt: i) type = SSRegister] + ifFalse: [(self simStackAt: i) spilled]). + (self addressOf: (scratchSimStack at: i)) reconcileWith: (self simStackAt: i). + simStack + at: i + put: (self + cCode: [scratchSimStack at: i] + inSmalltalk: [(scratchSimStack at: i) copy])]! Item was changed: ----- Method: RegisterAllocatingCogit>>simStack:at: (in category 'simulation stack') ----- simStack: stack at: index <cmacro: '(stack,index) ((stack) + (index))'> + <returnTypeC: #'SimStackEntry *'> - <returnTypeC: #'CogSimStackEntry *'> ^self addressOf: (stack at: index)! Item was changed: ----- Method: RegisterAllocatingCogit>>ssFlushFrom:upThroughRegister: (in category 'simulation stack') ----- ssFlushFrom: start upThroughRegister: reg "Any occurrences on the stack of the register must be flushed, and hence any values colder than them stack." + <var: #desc type: #'SimStackEntry *'> - <var: #desc type: #'CogSimStackEntry *'> self ssFlushFrom: start upThrough: [ :desc | desc type = SSRegister and: [ desc register = reg ] ]! Item was changed: ----- Method: RegisterAllocatingCogit>>ssStorePop:toPreferredReg: (in category 'simulation stack') ----- ssStorePop: popBoolean toPreferredReg: preferredReg "Store or pop the top simulated stack entry to a register. Use preferredReg if the entry is not itself a register. Answer the actual register the result ends up in." | actualReg | actualReg := preferredReg. self ssTop type = SSRegister ifTrue: [self assert: (self ssTop liveRegister = NoReg or: [self ssTop liveRegister = self ssTop register]). + self assert: self ssTop spilled not. + actualReg := self ssTop register]. - self assert: self ssTop spilled not]. self ssTop liveRegister ~= NoReg ifTrue: [actualReg := self ssTop liveRegister]. self ssStorePop: popBoolean toReg: actualReg. "generates nothing if ssTop is already in actualReg" ^ actualReg! Item was added: + ----- Method: StackToRegisterMappingCogit>>printOptStatus (in category 'simulation only') ----- + printOptStatus + <doNotGenerate> + coInterpreter transcript ensureCr; nextPutAll: 'opt: '. + (optStatus isReceiverResultRegLive ~~ true + and: [optStatus ssEntry isNil]) ifTrue: + [coInterpreter transcript nextPutAll: 'none']. + optStatus printStateOn: coInterpreter transcript. + coInterpreter transcript cr; flush! Item was changed: ----- Method: StackToRegisterMappingCogit>>ssFlushTo:nativeFlushTo: (in category 'simulation stack') ----- ssFlushTo: index nativeFlushTo: nativeIndex + LowcodeVM ifTrue: + [self ssNativeFlushTo: nativeIndex]. + 0 to: methodOrBlockNumTemps - 1 do: + [:i| self assert: (self simStackAt: i) type = SSBaseOffset]. - LowcodeVM ifTrue: [ - self ssNativeFlushTo: nativeIndex. - ]. methodOrBlockNumTemps to: simSpillBase - 1 do: [:i| self assert: (self simStackAt: i) spilled]. simSpillBase <= index ifTrue: + [(simSpillBase max: methodOrBlockNumTemps) to: index do: - [(simSpillBase max: 0) to: index do: [:i| self assert: needsFrame. (self simStackAt: i) ensureSpilledAt: (self frameOffsetOfTemporary: i) from: FPReg]. simSpillBase := index + 1]! Item was changed: ----- Method: StackToRegisterMappingCogit>>traceSimStack (in category 'simulation only') ----- traceSimStack <cmacro: '() 0'> (compilationTrace anyMask: 4) ifTrue: + [self printOptStatus; printSimStack]! - [self printSimStack]!
1
0
0
0
[VM-dev] Does doesNotUnderstand:/cannotInterprer: jitted?
by Denis Kudriashov
23 Nov '16
23 Nov '16
Hello. What happens when message lookup not found method for given message? Will #doesNotUnderstand: or #cannotInterpret: be added to PIC?
5
13
0
0
Re: [Vm-dev] New Smalltalk Build HUB for Pharo, Gemstone, Squeak, ...
by Eliot Miranda
23 Nov '16
23 Nov '16
Hi Fabio, are the builds available yet, and where? If they're not available yet, what's the ETA? I'm impatient because I want to update the image building scripts in opensmalltalk/vm/image to download an up-to-date VM. Forgive me :-) On Sat, Nov 19, 2016 at 3:33 PM, Smalltalk <groups-noreply(a)linkedin.com> wrote: > Built, initiated by excellent Fabio Niephaus, senior student at HPI (Hasso > Plattner Institute, Potsdam near Berlin)
https://github.com/hpi-swa/
> smalltalkCI Never saw a guy doing highly complex tasks in such a speed. > > > > [image: LinkedIn] > <
https://www.linkedin.com/comm/nhome/?midToken=AQE_sEaUTrp0Mg&trk=eml-b2_ane…
> > > > Groups > > > > > What's new in your group > > > > > [image: Smalltalk] > <
https://www.linkedin.com/comm/groups/100141/100141-6204615610501074947?midT…
> > > > Smalltalk > > > New Smalltalk Build HUB for Pharo, Gemstone, Squeak, ... > <
https://www.linkedin.com/comm/groups/100141/100141-6204615610501074947?midT…
> > > > By Guido Stepken > > > Built, initiated by excellent Fabio Niephaus, senior student at HPI (Hasso > Plattner Institute, Potsdam near Berlin)... > > > > > View Discussion > <
https://www.linkedin.com/comm/groups/100141/100141-6204615610501074947?midT…
> > > > > > > You are receiving Groups Digest emails. Unsubscribe > <
https://www.linkedin.com/e/v2?e=4v7dw-ivpinqco-y8&t=lun&midToken=AQE_sEaUTr…
> > This email was intended for Eliot Miranda (Cog Smalltalk/Newspeak Virtual > Machine Author. Dynamic language systems architect and implementor.). Learn > why we included this. > <
https://www.linkedin.com/e/v2?e=4v7dw-ivpinqco-y8&a=customerServiceUrl&midT…
> > If you need assistance or have questions, please contact LinkedIn > Customer Service > <
https://www.linkedin.com/e/v2?e=4v7dw-ivpinqco-y8&a=customerServiceUrl&midT…
> > . > > > © 2016 LinkedIn Corporation, 2029 Stierlin Court, Mountain View CA 94043. > LinkedIn and the LinkedIn logo are registered trademarks of LinkedIn. > > > > > -- _,,,^..^,,,_ best, Eliot
2
1
0
0
VM Maker: VMMaker.oscog-eem.2001.mcz
by commits@source.squeak.org
22 Nov '16
22 Nov '16
Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2001.mcz
==================== Summary ==================== Name: VMMaker.oscog-eem.2001 Author: eem Time: 21 November 2016, 5:22:12.864973 pm UUID: 2c3cb42e-09ea-444f-b1b4-84bfa0cdd9d9 Ancestors: VMMaker.oscog-nice.2000 RegisterAllocatingCogit Get the 64-bit system as far as the isInMemory send in SmalltalkImage>>#send:toClassesNamedIn:with:. Main change is to not merge following a return (there is no mergeSimStack at a fixup). Fix several asserts checking the spill state of the stack. Reorder the compilationTrace flags and add tracing of compilation in cog:selector: and cogFullBlockMethod:numCopied:. Improve printing of constasnts in the sim stack entry classes. =============== Diff against VMMaker.oscog-nice.2000 =============== Item was changed: ----- Method: CogRegisterAllocatingSimStackEntry>>printStateOn: (in category 'printing') ----- printStateOn: aStream <doNotGenerate> "Smalltalk-side only" type isInteger ifFalse: [^self]. aStream nextPut: $(. type caseOf: { [SSBaseOffset] -> [aStream nextPutAll: 'bo '; nextPutAll: (cogit backEnd nameForRegister: register). offset negative ifFalse: [aStream nextPut: $+]. aStream print: offset]. [SSConstant] -> [aStream nextPutAll: 'const '; + nextPutAll: (cogit coInterpreter shortPrint: constant)]. - print: constant]. [SSRegister] -> [aStream nextPutAll: 'reg '; nextPutAll: (cogit backEnd nameForRegister: register)]. [SSSpill] -> [aStream nextPutAll: 'spill @ '; nextPutAll: (cogit backEnd nameForRegister: register). offset negative ifFalse: [aStream nextPut: $+]. aStream print: offset] }. (spilled and: [type ~= SSSpill]) ifTrue: [aStream nextPutAll: ' (spilled)']. liveRegister ~= NoReg ifTrue: [aStream nextPutAll: ' (live: '; nextPutAll: (cogit backEnd nameForRegister: liveRegister); nextPut: $)]. bcptr ifNotNil: [aStream space; nextPut: ${; print: bcptr; nextPut: $}]. aStream nextPut: $)! Item was changed: ----- Method: CogSimStackEntry>>printStateOn: (in category 'printing') ----- printStateOn: aStream <doNotGenerate> "Smalltalk-side only" type isInteger ifFalse: [^self]. aStream nextPut: $(. type caseOf: { [SSBaseOffset] -> [aStream nextPutAll: 'bo '; nextPutAll: (cogit backEnd nameForRegister: register). offset negative ifFalse: [aStream nextPut: $+]. aStream print: offset]. [SSConstant] -> [aStream nextPutAll: 'const '; + nextPutAll: (cogit coInterpreter shortPrint: constant)]. - print: constant]. [SSRegister] -> [aStream nextPutAll: 'reg '; nextPutAll: (cogit backEnd nameForRegister: register)]. [SSSpill] -> [aStream nextPutAll: 'spill @ '; nextPutAll: (cogit backEnd nameForRegister: register). offset negative ifFalse: [aStream nextPut: $+]. aStream print: offset] }. (spilled and: [type ~= SSSpill]) ifTrue: [aStream nextPutAll: ' (spilled)']. bcptr ifNotNil: [aStream space; nextPut: ${; print: bcptr; nextPut: $}]. aStream nextPut: $)! Item was changed: ----- Method: Cogit>>cogFullBlockMethod:numCopied: (in category 'jit - api') ----- cogFullBlockMethod: aMethodObj numCopied: numCopied "Attempt to produce a machine code method for the bytecode method object aMethodObj. N.B. If there is no code memory available do *NOT* attempt to reclaim the method zone. Certain clients (e.g. ceSICMiss:) depend on the zone remaining constant across method generation." <api> <option: #SistaV1BytecodeSet> <returnTypeC: #'CogMethod *'> | cogMethod | <var: #cogMethod type: #'CogMethod *'> + (self exclude: aMethodObj) ifTrue: + [^nil]. - self cCode: [] inSmalltalk: "for debugging, allow excluding methods based on selector or methodClass" - [self class initializationOptions - at: #DoNotJIT - ifPresent: - [:excluded| - (excluded anySatisfy: [:exclude| aMethodObj = exclude]) ifTrue: - [coInterpreter transcript nextPutAll: 'EXCLUDING '; nextPutAll: aMethodObj; nextPutAll: ' (compiled block)'; cr; flush. - ^nil]]]. self deny: (coInterpreter methodHasCogMethod: aMethodObj). self assert: (objectMemory isOopCompiledMethod: (coInterpreter ultimateLiteralOf: aMethodObj)). aMethodObj = breakMethod ifTrue: [self halt: 'Compilation of breakMethod']. "If the generators for the alternate bytecode set are missing then interpret." (coInterpreter methodUsesAlternateBytecodeSet: aMethodObj) ifTrue: [(self numElementsIn: generatorTable) <= 256 ifTrue: [^nil]. bytecodeSetOffset := 256] ifFalse: [bytecodeSetOffset := 0]. objectRepresentation ensureNoForwardedLiteralsIn: aMethodObj. methodObj := aMethodObj. methodHeader := objectMemory methodHeaderOf: aMethodObj. cogMethod := self compileCogFullBlockMethod: numCopied. (cogMethod asInteger between: MaxNegativeErrorCode and: -1) ifTrue: [cogMethod asInteger = InsufficientCodeSpace ifTrue: [coInterpreter callForCogCompiledCodeCompaction]. self maybeFreeCounters. "Right now no errors should be reported, so nothing more to do." "self reportError: (self cCoerceSimple: cogMethod to: #sqInt)." ^nil]. "self cCode: '' inSmalltalk: [coInterpreter printCogMethod: cogMethod. ""coInterpreter symbolicMethod: aMethodObj."" self assertValidMethodMap: cogMethod." "self disassembleMethod: cogMethod." "printInstructions := clickConfirm := true""]." ^cogMethod! Item was changed: ----- Method: Cogit>>compilationTrace: (in category 'simulation only') ----- compilationTrace: anInteger + "1 = compilation + 2 = bytecode descriptor. + 4 = simStack. + 8 = spill + 16 = merge + 32 = fixup" compilationTrace := anInteger! Item was added: + ----- Method: Cogit>>exclude: (in category 'simulation only') ----- + exclude: aMethodObj + "For debugging, allow excluding methods based on selector or methodClass. Answer if the mehtod should be excluded." + <inline: true> + self cCode: [] inSmalltalk: "for debugging, allow excluding methods based on selector or methodClass" + [self class initializationOptions + at: #DoNotJIT + ifPresent: + [:excluded| + (excluded anySatisfy: [:exclude| aMethodObj = exclude]) ifTrue: + [coInterpreter transcript nextPutAll: 'EXCLUDING '; nextPutAll: aMethodObj; nextPutAll: ' (compiled block)'; cr; flush. + ^true]]. + (compilationTrace anyMask: 1) ifTrue: + [| methodClass | + methodClass := coInterpreter nameOfClass: (coInterpreter methodClassOf: aMethodObj). + coInterpreter transcript + nextPutAll: 'compiling compiled block in '; + nextPutAll: methodClass; + cr; flush]]. + ^false! Item was changed: ----- Method: Cogit>>exclude:selector: (in category 'simulation only') ----- exclude: aMethodObj selector: aSelectorOop "For debugging, allow excluding methods based on selector or methodClass. Answer if the mehtod should be excluded." <inline: true> + self cCode: [] inSmalltalk: + [| methodClass selector | + self class initializationOptions + at: #DoNotJIT + ifPresent: + [:excluded| + methodClass := coInterpreter nameOfClass: (coInterpreter methodClassOf: aMethodObj). + selector := coInterpreter stringOf: aSelectorOop. + (excluded anySatisfy: [:exclude| selector = exclude or: [methodClass = exclude]]) ifTrue: + [coInterpreter transcript + nextPutAll: 'EXCLUDING '; + nextPutAll: methodClass; + nextPutAll: '>>#'; + nextPutAll: selector; + cr; flush. + ^true]]. + (compilationTrace anyMask: 1) ifTrue: + [methodClass := coInterpreter nameOfClass: (coInterpreter methodClassOf: aMethodObj). + selector := coInterpreter stringOf: aSelectorOop. + selector isEmpty ifTrue: + [selector := coInterpreter stringOf: (coInterpreter maybeSelectorOfMethod: aMethodObj)]. + coInterpreter transcript + nextPutAll: 'compiling '; + nextPutAll: methodClass; + nextPutAll: '>>#'; + nextPutAll: selector; + cr; flush]]. + ^false! - ^self - cCode: [false] - inSmalltalk: - [self class initializationOptions - at: #DoNotJIT - ifPresent: - [:excluded| | methodClass selector | - methodClass := coInterpreter nameOfClass: (coInterpreter methodClassOf: aMethodObj). - selector := coInterpreter stringOf: aSelectorOop. - (excluded anySatisfy: [:exclude| selector = exclude or: [methodClass = exclude]]) ifTrue: - [coInterpreter transcript nextPutAll: 'EXCLUDING '; nextPutAll: methodClass; nextPutAll: '>>#'; nextPutAll: selector; cr; flush. - ^true]]. - ^false]! Item was added: + ----- Method: CurrentImageCoInterpreterFacade>>nameOfClass: (in category 'accessing') ----- + nameOfClass: objOop + ^(objectMap keyAtValue: objOop) name! Item was added: + ----- Method: CurrentImageCoInterpreterFacade>>primNumberExternalCall (in category 'accessing') ----- + primNumberExternalCall + ^coInterpreter primNumberExternalCall! Item was added: + ----- Method: CurrentImageCoInterpreterFacade>>shortPrint: (in category 'accessing') ----- + shortPrint: oop + ^(objectMemory isImmediate: oop) + ifTrue: [coInterpreter shortPrint: oop] + ifFalse: [(objectMap keyAtValue: oop) printString]! Item was removed: - ----- Method: RegisterAllocatingCogit>>flushLiveRegistersForSend (in category 'bytecode generator support') ----- - flushLiveRegistersForSend - <inline: true> - 0 to: simStackPtr do: - [:i| - self assert: (self simStackAt: i) type = (i <= methodOrBlockNumTemps - ifTrue: [SSBaseOffset] - ifFalse: [SSSpill]). - (self simStackAt: i) liveRegister: NoReg]! Item was added: + ----- Method: RegisterAllocatingCogit>>flushLiveRegistersForSend: (in category 'bytecode generator support') ----- + flushLiveRegistersForSend: numArgs + <inline: true> + simSelf liveRegister: NoReg. + 0 to: simStackPtr - numArgs - 1 do: + [:i| + self assert: (self simStackAt: i) type = (i < methodOrBlockNumTemps + ifTrue: [SSBaseOffset] + ifFalse: [SSSpill]). + (self simStackAt: i) liveRegister: NoReg]! Item was changed: ----- Method: RegisterAllocatingCogit>>genMarshalledSend:numArgs:sendTable: (in category 'bytecode generator support') ----- genMarshalledSend: selectorIndex numArgs: numArgs sendTable: sendTable + self flushLiveRegistersForSend: numArgs. - self flushLiveRegistersForSend. ^super genMarshalledSend: selectorIndex numArgs: numArgs sendTable: sendTable! Item was changed: ----- Method: RegisterAllocatingCogit>>restoreSimStackAtMergePoint: (in category 'simulation stack') ----- restoreSimStackAtMergePoint: fixup <inline: true> + "All the execution paths reaching a merge point expect everything to be spilled + on stack and the optStatus is unknown. If the merge point follows a return, it + isn't a merge, but a sdkip past a return. If it is a real merge point then throw + away all simStack and optStatus optimization state." + fixup mergeSimStack ifNotNil: + [simSpillBase := methodOrBlockNumTemps. + optStatus isReceiverResultRegLive: false. + 0 to: simStackPtr do: + [:i| + self cCode: [simStack at: i put: (fixup mergeSimStack at: i)] + inSmalltalk: [(simStack at: i) copyFrom: (fixup mergeSimStack at: i)]]]. + ^0! - "All the execution paths reaching a merge point expect everything to be - spilled on stack and the optStatus is unknown. Throw away all simStack and - optStatus optimization state." - simSpillBase := methodOrBlockNumTemps. - optStatus isReceiverResultRegLive: false. - 0 to: simStackPtr do: - [:i| - self cCode: [simStack at: i put: (fixup mergeSimStack at: i)] - inSmalltalk: [(simStack at: i) copyFrom: (fixup mergeSimStack at: i)]]. - ^ 0! Item was changed: ----- Method: RegisterAllocatingCogit>>setMergeSimStackOf: (in category 'bytecode generator support') ----- setMergeSimStackOf: fixup <var: #fixup type: #'BytecodeFixup *'> + self assert: nextFixup <= numFixups. - self assert: nextFixup < numFixups. self moveSimStackConstantsToRegisters. self cCode: [fixup mergeSimStack: mergeSimStacksBase + (nextFixup * self simStackSlots * (self sizeof: CogSimStackEntry))]. nextFixup := nextFixup + 1. self cCode: [self mem: fixup mergeSimStack cp: simStack y: self simStackSlots * (self sizeof: CogSimStackEntry)] inSmalltalk: [fixup mergeSimStack: self copySimStack]! Item was changed: ----- Method: StackToRegisterMappingCogit>>traceDescriptor: (in category 'simulation only') ----- traceDescriptor: descriptor <cmacro: '(ign) 0'> (compilationTrace anyMask: 2) ifTrue: [coInterpreter transcript cr; print: bytecodePC; space; nextPutAll: descriptor generator; flush]! Item was changed: ----- Method: StackToRegisterMappingCogit>>traceFixup: (in category 'simulation only') ----- traceFixup: fixup <cmacro: '(ign) 0'> | index | + (compilationTrace anyMask: 32) ifTrue: - (compilationTrace anyMask: 8) ifTrue: [index := (fixups object identityIndexOf: fixup) - 1. coInterpreter transcript ensureCr; print: bytecodePC; nextPutAll: ' -> '; print: index; nextPut: $/; print: index + initialPC; nextPut: $:; space. fixup printStateOn: coInterpreter transcript. coInterpreter transcript cr; flush]! Item was changed: ----- Method: StackToRegisterMappingCogit>>traceMerge: (in category 'simulation only') ----- traceMerge: fixup <cmacro: '(ign) 0'> | index | + (compilationTrace anyMask: 16) ifTrue: - (compilationTrace anyMask: 4) ifTrue: [index := (fixups object identityIndexOf: fixup) - 1. coInterpreter transcript ensureCr; print: index; nextPut: $/; print: index + initialPC; nextPut: $:; space. fixup printStateOn: coInterpreter transcript. coInterpreter transcript cr; flush]! Item was changed: ----- Method: StackToRegisterMappingCogit>>traceSimStack (in category 'simulation only') ----- traceSimStack <cmacro: '() 0'> + (compilationTrace anyMask: 4) ifTrue: - (compilationTrace anyMask: 1) ifTrue: [self printSimStack]! Item was changed: ----- Method: StackToRegisterMappingCogit>>traceSpill: (in category 'simulation only') ----- traceSpill: simStackEntry <cmacro: '(ign) 0'> + (compilationTrace anyMask: 8) ifTrue: - (compilationTrace anyMask: 2) ifTrue: [coInterpreter transcript cr; print: bytecodePC; space; print: simStackEntry; flush]!
1
0
0
0
← Newer
1
2
3
4
5
6
7
8
...
16
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Results per page:
10
25
50
100
200