[Vm-dev] VM Maker: VMMaker.oscog-eem.2099.mcz
Clément Bera
bera.clement at gmail.com
Wed Jan 18 09:17:12 UTC 2017
Hi,
When I compile from this version I have a start-up crash in Pharo.
I suspect changes in primitiveStringReplace ...
Segmentation fault Wed Jan 18 10:10:24 2017
[...]
Smalltalk stack dump:
0xbff11834 M Array(SequenceableCollection)>mergeFirst:middle:last:into:by:
0x47c0138: a(n) Array
0xbff11864 M Array(SequenceableCollection)>mergeSortFrom:to:src:dst:by:
0x47c0068: a(n) Array
0xbff11894 M Array(SequenceableCollection)>mergeSortFrom:to:src:dst:by:
0x47c0068: a(n) Array
0xbff118cc I Array(SequenceableCollection)>mergeSortFrom:to:src:dst:by:
0x47c0068: a(n) Array
0xbff11900 I Array(SequenceableCollection)>mergeSortFrom:to:by: 0x47c0068:
a(n) Array
[...]
0x5356da0 s WorldMorph>doOneCycle
0x5356d40 s WorldMorph class>doOneCycle
0x876f890 s [] in MorphicUIManager>spawnNewProcess
0x876fa20 s [] in FullBlockClosure>newProcess
Most recent primitives
new:
basicNew
value:
at:
at:
[...]
replaceFrom:to:with:startingAt:
replaceFrom:to:with:startingAt:
replaceFrom:to:with:startingAt:
replaceFrom:to:with:startingAt:
stack page bytes 4096 available headroom 2788 minimum unused headroom 68
(Segmentation fault)
Abort trap: 6
On Tue, Jan 17, 2017 at 7:04 PM, <commits at source.squeak.org> wrote:
>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2099.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.2099
> Author: eem
> Time: 17 January 2017, 10:03:25.012123 am
> UUID: 08323ffb-7df4-498c-a5b0-8a4e6d295352
> Ancestors: VMMaker.oscog-eem.2098
>
> StackToRegisterMappingCogits:
> Clean-up after the branch following changes:
> Make extractMaybeBranchDescriptorInto: fulfil its contract when it
> doesn't find a following branch (directly or indirectly).
> Simplify the various gen*InlinedIdenticalOrNotIf: to eliminate the
> duplication using #== to compare orNot with the branch.
>
> =============== Diff against VMMaker.oscog-eem.2098 ===============
>
> Item was changed:
> ----- Method: RegisterAllocatingCogit>>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].
>
> 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 deny: deadCode]. "push dummy value below"
>
> self assert: (unforwardArg or: [unforwardRcvr]).
> + orNot == branchDescriptor isBranchTrue "orNot is true for ~~"
> + 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 ].
> - "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 ]].
>
> deadCode ifFalse:
> [self ssPushConstant: objectMemory trueObject]. "dummy
> value"
> "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 changed:
> ----- Method: RegisterAllocatingCogit>>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].
>
> 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 deny: deadCode]. "push dummy value below"
>
> + self genConditionalBranch: (orNot == branchDescriptor isBranchTrue
> ifTrue: [JumpNonZero] ifFalse: [JumpZero])
> - "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).
> self ssPushConstant: objectMemory trueObject]. "dummy
> value"
> ^0!
>
> Item was changed:
> ----- 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.
>
> + orNot == branchDescriptor isBranchTrue "orNot is true for ~~"
> + ifFalse:
> + [ 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 ].
> - "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 changed:
> ----- Method: SistaRegisterAllocatingCogit>>
> 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].
>
> 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.
>
> + orNot == branchDescriptor isBranchTrue "orNot is true for ~~"
> + ifFalse:
> + [ 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 ].
> - "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 changed:
> ----- Method: StackToRegisterMappingCogit>>
> extractMaybeBranchDescriptorInto: (in category 'bytecode generator
> support') -----
> extractMaybeBranchDescriptorInto: fourArgBlock
> "Looks one instruction ahead of the current bytecodePC and answers
> its bytecode descriptor and its pc.
> + If the instruction found is a branch, also answers the pc after
> the branch and the pc targeted by the branch.
> + For convenience, avoiding duplication in the senders, it follows
> those two pcs to their eventual targets."
> - If the instruction found is a branch, also answers the pc after
> the branch and the pc targeted by the branch."
> | primDescriptor nextPC nExts branchDescriptor targetBytecodePC
> postBranchPC |
> <inline: true>
> <var: #primDescriptor type: #'BytecodeDescriptor *'>
> <var: #branchDescriptor type: #'BytecodeDescriptor *'>
>
> primDescriptor := self generatorAt: byte0.
>
> nextPC := bytecodePC + primDescriptor numBytes.
> nExts := 0.
> [[branchDescriptor := self generatorAt: (objectMemory fetchByte:
> nextPC ofObject: methodObj) + bytecodeSetOffset.
> branchDescriptor isExtension] whileTrue:
> [nExts := nExts + 1.
> nextPC := nextPC + branchDescriptor numBytes].
> branchDescriptor isUnconditionalBranch]
> whileTrue:
> [nextPC := self eventualTargetOf: nextPC
>
> + branchDescriptor numBytes
>
> + (self spanFor: branchDescriptor at: nextPC exts: nExts in:
> methodObj)].
>
> targetBytecodePC := postBranchPC := 0.
>
> (branchDescriptor isBranchTrue or: [branchDescriptor
> isBranchFalse])
> ifTrue:
> [targetBytecodePC := self eventualTargetOf: nextPC
>
> + branchDescriptor numBytes
>
> + (self spanFor: branchDescriptor at:
> nextPC exts: nExts in: methodObj).
> postBranchPC := self eventualTargetOf: nextPC +
> branchDescriptor numBytes]
> ifFalse:
> + [nextPC := bytecodePC + primDescriptor numBytes].
> - [branchDescriptor isReturn ifFalse:
> - [postBranchPC := self eventualTargetOf:
> nextPC + branchDescriptor numBytes.
> - nextPC := self eventualTargetOf:
> bytecodePC + primDescriptor numBytes]].
>
> fourArgBlock value: branchDescriptor value: nextPC value:
> postBranchPC value: targetBytecodePC!
>
> Item was changed:
> ----- 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 deny: deadCode]. "push dummy value below"
>
> self assert: (unforwardArg or: [unforwardRcvr]).
> + orNot == branchDescriptor isBranchTrue "orNot is true for ~~"
> + ifFalse:
> + [ 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 ].
> - "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 ]].
>
> deadCode ifFalse:
> [self ssPushConstant: objectMemory trueObject]. "dummy
> value"
>
> "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 changed:
> ----- 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 deny: deadCode]. "push dummy value below"
>
> + self genConditionalBranch: (orNot == branchDescriptor isBranchTrue
> ifTrue: [JumpNonZero] ifFalse: [JumpZero])
> - "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).
> self ssPushConstant: objectMemory trueObject]. "dummy
> value"
> ^0!
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20170118/721c5feb/attachment-0001.html>
More information about the Vm-dev
mailing list