[Vm-dev] VM Maker: VMMaker.oscog-eem.2020.mcz
Esteban Lorenzano
estebanlm at gmail.com
Sat Dec 3 10:46:58 UTC 2016
This change introduced a problem when generating sources… now I have an error:
'Local variable 'bytecodePC' may mask global when inlining recordBcpc:’
cheers,
Esteban
> On 2 Dec 2016, at 18:00, 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.2020.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.2020
> Author: eem
> Time: 2 December 2016, 8:59:35.572375 am
> UUID: f53bedb4-3a2d-42ed-bf04-56ed996e7aa0
> Ancestors: VMMaker.oscog-eem.2019
>
> RegisterAllocatingCogit:
> Give sensible names to the three reconciliation methods in CogRegisterAllocatingSimStackEntry. Be sure to use registerOrNone, not just liveRegister.
> Refactor mergeCurrentSimStackWith: for clarity.
> Have restoreSimStackAtMergePoint: maintain optStatus.
>
> Execution gets as far as a stack imbalance in a send from Dictionary>noCheckNoGrowFillFrom: during EventSensor startUp:.
>
> =============== Diff against VMMaker.oscog-eem.2019 ===============
>
> Item was added:
> + ----- Method: CogRegisterAllocatingSimStackEntry>>reconcileBackwardsWith: (in category 'compile abstract instructions') -----
> + reconcileBackwardsWith: targetEntry
> + "Make the state of the receiver, a stack entry at a backward jump,
> + the same as the corresponding simStackEntry at the target of the jump"
> + <var: #targetEntry type: #'targetEntry *'>
> + | targetReg |
> + (targetReg := targetEntry registerOrNone) = NoReg ifTrue:
> + [^self].
> + targetEntry type = SSConstant ifTrue:
> + [self assert: (type = SSConstant and: [constant = targetEntry constant]).
> + ^self].
> + liveRegister ~= NoReg ifTrue:
> + [liveRegister ~= targetReg ifTrue:
> + [cogit MoveR: liveRegister R: targetReg].
> + ^self].
> + type caseOf: {
> + [SSBaseOffset] -> [cogit MoveMw: offset r: register R: targetReg].
> + [SSSpill] -> [cogit MoveMw: offset r: register R: targetReg].
> + [SSConstant] -> [cogit genMoveConstant: constant R: targetReg].
> + [SSRegister] -> [register ~= targetReg ifTrue:
> + [cogit MoveR: register R: targetReg]] }!
>
> Item was added:
> + ----- Method: CogRegisterAllocatingSimStackEntry>>reconcileForwardsWith: (in category 'compile abstract instructions') -----
> + reconcileForwardsWith: targetEntry
> + "Make the state of the receiver, a stack entry at the end of a basic block,
> + the same as the corresponding simStackEntry at the target of a preceding
> + jump to the beginning of the next basic block."
> + <var: #targetEntry type: #'targetEntry *'>
> + | targetReg |
> + (targetReg := targetEntry registerOrNone) = NoReg ifTrue:
> + [self assert: (self isSameEntryAs: targetEntry).
> + ^self].
> + liveRegister ~= NoReg ifTrue:
> + [liveRegister ~= targetReg ifTrue:
> + [cogit MoveR: liveRegister R: targetReg].
> + (spilled and: [targetEntry spilled not]) ifTrue:
> + [cogit AddCq: objectRepresentation wordSize R: SPReg].
> + ^self].
> + spilled
> + ifTrue:
> + [targetEntry spilled ifTrue:
> + [cogit PopR: targetReg. "KISS; generate the least number of instructions..."
> + ^self]]
> + ifFalse:
> + [self deny: targetEntry spilled].
> + type caseOf: {
> + [SSBaseOffset] -> [cogit MoveMw: offset r: register R: targetReg].
> + [SSSpill] -> [cogit MoveMw: offset r: register R: targetReg].
> + [SSConstant] -> [cogit genMoveConstant: constant R: targetReg].
> + [SSRegister] -> [register ~= targetReg ifTrue:
> + [cogit MoveR: register R: targetReg]] }!
>
> Item was changed:
> ----- Method: CogRegisterAllocatingSimStackEntry>>reconcilePoppingWith: (in category 'compile abstract instructions') -----
> reconcilePoppingWith: targetEntry
> "Make the state of a targetEntry, a stack entry following a non-inlined special selector
> send, the same as the corresponding entry (the receiver) along the inlined path."
> <var: #targetEntry type: #'targetEntry *'>
> + | targetReg |
> targetEntry spilled ifTrue:
> [self assert: (self isSameEntryAs: targetEntry).
> + (targetReg := targetEntry registerOrNone) = NoReg ifTrue:
> - targetEntry liveRegister = NoReg ifTrue:
> [^self].
> type caseOf: {
> + [SSBaseOffset] -> [cogit MoveMw: offset r: register R: targetReg].
> + [SSSpill] -> [cogit MoveMw: offset r: register R: targetReg].
> + [SSConstant] -> [cogit genMoveConstant: constant R: targetReg].
> + [SSRegister] -> [targetReg ~= register ifTrue:
> + [cogit MoveR: register R: targetReg]] }.
> - [SSBaseOffset] -> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - [SSSpill] -> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - [SSConstant] -> [cogit genMoveConstant: constant R: targetEntry liveRegister].
> - [SSRegister] -> [targetEntry liveRegister ~= register ifTrue:
> - [cogit MoveR: register R: targetEntry liveRegister]] }.
> ^self].
> targetEntry type = SSConstant ifTrue:
> + [self assert: (targetEntry registerOrNone) = NoReg.
> + cogit AddCq: objectRepresentation wordSize R: SPReg.
> - [cogit AddCw: BytesPerWord R: SPReg.
> ^self].
> + (targetReg := targetEntry registerOrNone) ~= NoReg ifTrue:
> + [cogit PopR: targetReg.
> - targetEntry registerOrNone ~= NoReg ifTrue:
> - [cogit PopR: targetEntry registerOrNone.
> ^self].
> self halt!
>
> Item was removed:
> - ----- Method: CogRegisterAllocatingSimStackEntry>>reconcileWith: (in category 'compile abstract instructions') -----
> - reconcileWith: targetEntry
> - "Make the state of the receiver, a stack entry at a backward jump,
> - the same as the corresponding simStackEntry at the target of the jump"
> - <var: #targetEntry type: #'targetEntry *'>
> - targetEntry liveRegister = NoReg ifTrue:
> - [^self].
> - targetEntry type = SSConstant ifTrue:
> - [self assert: (type = SSConstant and: [constant = targetEntry constant]).
> - ^self].
> - liveRegister ~= NoReg ifTrue:
> - [liveRegister ~= targetEntry liveRegister ifTrue:
> - [cogit MoveR: liveRegister R: targetEntry liveRegister].
> - ^self].
> - type caseOf: {
> - [SSBaseOffset] -> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - [SSSpill] -> [cogit MoveMw: offset r: register R: targetEntry liveRegister].
> - [SSConstant] -> [cogit genMoveConstant: constant R: targetEntry liveRegister].
> - [SSRegister] -> [register ~= targetEntry liveRegister ifTrue:
> - [cogit MoveR: register R: targetEntry liveRegister]] }!
>
> Item was changed:
> ----- Method: RegisterAllocatingCogit>>mergeCurrentSimStackWith: (in category 'bytecode generator support') -----
> mergeCurrentSimStackWith: mergeSimStack
> <var: #mergeSimStack type: #'SimStackEntry *'>
> "At a merge point the cogit expects the stack to be in the same state as mergeSimStack.
> mergeSimStack is the state as of some jump forward to this point. So make simStack agree
> with mergeSimStack (it is, um, problematic to plant code at the jump).
> Values may have to be assigned to registers. Registers may have to be swapped.
> The state of optStatus must agree."
> + | currentEntry targetEntry |
> - | currentRegsMask mergeRegsMask potentialConflictRegMask conflictingRegsMask
> - currentRegMask mergeRegMask currentEntry targetEntry |
> <var: #currentEntry type: #'SimStackEntry *'>
> <var: #targetEntry type: #'SimStackEntry *'>
> mergeSimStack ifNil: [^self].
> + "Assignments amongst the registers must be made in order to avoid overwriting.
> + If necessary exchange registers amongst simStack's entries to resolve any conflicts."
> + self resolveRegisterOrderConflictsBetweenCurrentSimStackAnd: mergeSimStack.
> - currentRegsMask := mergeRegsMask := potentialConflictRegMask := 0.
> - 0 to: simStackPtr do:
> - [:i|
> - currentRegMask := (currentEntry := self simStack: simStack at: i) registerMaskOrNone.
> - mergeRegMask := (targetEntry := self simStack: mergeSimStack at: i) registerMaskOrNone.
> - currentRegMask = mergeRegMask
> - ifTrue:
> - [self assert: (currentEntry isSameEntryAs: targetEntry)]
> - ifFalse: "This checks for a potential conflict..."
> - [(currentRegMask ~= 0 or: [mergeRegMask ~= 0]) ifTrue:
> - [potentialConflictRegMask := potentialConflictRegMask bitOr: (currentRegMask bitOr: mergeRegMask)]].
> - currentRegsMask := currentRegsMask bitOr: currentRegMask.
> - mergeRegsMask := mergeRegsMask bitOr: mergeRegMask].
> - conflictingRegsMask := potentialConflictRegMask bitAnd: (currentRegsMask bitAnd: mergeRegsMask).
> - "One simple algorithm is to spill everything if there are any conflicts and then pop back.
> - But this is terrible :-( Can we do better? Yes... Consider the following two simStacks
> - target: 0: | rA | __ | rB | rC | rD | <- sp
> - current: 0: | __ | __ | rD | rA | rC | <- sp
> - If we were to assign in a naive order, 0 through sp rA would be overwritten before its value in current[3] is written to rC,
> - and rC would be overwritten before its value in current[4] is written to rD. But if we swap the registers in current so that
> - they respect the reverse ordering in target we can assign directly:
> - swap current[3] & current[4]
> - 0: | __ | __ | rD | rC | rA | <- sp
> - now do the assignment in the order target[0] := current[0], target[1] := current[1], ... target[4] := current[4],
> - i.e. rA := current[0]; rB := rD; (rC := rC); (rD := rD)."
> - conflictingRegsMask ~= 0 ifTrue:
> - [(self isAPowerOfTwo: conflictingRegsMask) "Multiple conflicts mean we have to sort"
> - ifFalse: [self swapCurrentRegistersInMask: currentRegsMask accordingToRegisterOrderIn: mergeSimStack]
> - ifTrue: [self assignToTempRegConflictingRegisterIn: conflictingRegsMask]].
> self assert: (self conflcitsResolvedBetweenSimStackAnd: mergeSimStack).
> simStackPtr to: 0 by: -1 do:
> [:i|
> + currentEntry := self simStack: simStack at: i.
> + targetEntry := self simStack: mergeSimStack at: i.
> + currentEntry reconcileForwardsWith: targetEntry.
> + "Note, we could update the simStack and spillBase here but that is done in restoreSimStackAtMergePoint:
> + spilled ifFalse:
> + [simSpillBase := i - 1].
> + simStack
> + at: i
> + put: (self
> + cCode: [mergeSimStack at: i]
> + inSmalltalk: [(mergeSimStack at: i) copy])"]!
> - currentRegMask := (currentEntry := self simStack: simStack at: i) registerMaskOrNone.
> - mergeRegMask := (targetEntry := self simStack: mergeSimStack at: i) registerMaskOrNone.
> - mergeRegMask ~= 0
> - ifTrue:
> - [currentRegMask ~= mergeRegMask
> - ifTrue:
> - [currentEntry reconcilePoppingWith: targetEntry.
> - simStack
> - at: i
> - put: (self
> - cCode: [mergeSimStack at: i]
> - inSmalltalk: [(mergeSimStack at: i) copy])]
> - ifFalse:
> - [self assert: (currentEntry isSameEntryAs: targetEntry)]]
> - ifFalse:
> - [self assert: (currentRegMask = 0 or: [currentEntry spilled]).
> - self assert: (currentEntry isSameEntryAs: targetEntry) "really? here to check"]]!
>
> Item was changed:
> ----- Method: RegisterAllocatingCogit>>reconcileRegisterStateForBackwardJoin: (in category 'bytecode generator support') -----
> reconcileRegisterStateForBackwardJoin: fixup
> <var: #fixup type: #'SSBytecodeFixup *'>
> | fixupSimStack |
> <var: #fixupSimStack type: #'SimStackEntry *'>
> self assert: (optStatus ssEntry isSameEntryAs: simSelf).
> fixup isReceiverResultRegSelf ifTrue:
> [optStatus isReceiverResultRegLive ifFalse:
> [optStatus ssEntry storeToReg: ReceiverResultReg]].
> fixupSimStack := fixup mergeSimStack.
> simStackPtr to: 0 by: -1 do:
> [:i|
> self assert: (self simStackAt: i) spilled.
> + (self simStackAt: i) reconcileBackwardsWith: (fixupSimStack at: i)]!
> - (self simStackAt: i) reconcileWith: (fixupSimStack at: i)]!
>
> Item was added:
> + ----- Method: RegisterAllocatingCogit>>resolveRegisterOrderConflictsBetweenCurrentSimStackAnd: (in category 'bytecode generator support') -----
> + resolveRegisterOrderConflictsBetweenCurrentSimStackAnd: mergeSimStack
> + <var: #mergeSimStack type: #'SimStackEntry *'>
> + "One simple algorithm is to spill everything if there are any conflicts and then pop back.
> + But this is terrible :-( Can we do better? Yes... Consider the following two simStacks
> + target: 0: | rA | __ | rB | rC | rD | <- sp
> + current: 0: | __ | __ | rD | rA | rC | <- sp
> + If we were to assign in a naive order, 0 through sp rA would be overwritten before its value in current[3] is written to rC,
> + and rC would be overwritten before its value in current[4] is written to rD. But if we swap the registers in current so that
> + they respect the reverse ordering in target we can assign directly:
> + swap current[3] & current[4]
> + 0: | __ | __ | rD | rC | rA | <- sp
> + now do the assignment in the order target[0] := current[0], target[1] := current[1], ... target[4] := current[4],
> + i.e. rA := current[0]; rB := rD; (rC := rC); (rD := rD).
> +
> + So find any conflicts, and if there are any, swap registers in the simStack to resolve them.
> + The trivial case of a single conflict is resolved by assigning that conflict to TempReg.
> + "
> + | currentRegsMask mergeRegsMask potentialConflictRegMask conflictingRegsMask
> + currentRegMask mergeRegMask currentEntry targetEntry |
> + <var: #currentEntry type: #'SimStackEntry *'>
> + <var: #targetEntry type: #'SimStackEntry *'>
> + currentRegsMask := mergeRegsMask := potentialConflictRegMask := 0.
> + 0 to: simStackPtr do:
> + [:i|
> + currentRegMask := (currentEntry := self simStack: simStack at: i) registerMaskOrNone.
> + mergeRegMask := (targetEntry := self simStack: mergeSimStack at: i) registerMaskOrNone.
> + (currentRegMask ~= mergeRegMask
> + and: [currentRegMask ~= 0 or: [mergeRegMask ~= 0]]) ifTrue:
> + [potentialConflictRegMask := potentialConflictRegMask bitOr: (currentRegMask bitOr: mergeRegMask)].
> + currentRegsMask := currentRegsMask bitOr: currentRegMask.
> + mergeRegsMask := mergeRegsMask bitOr: mergeRegMask].
> + conflictingRegsMask := potentialConflictRegMask bitAnd: (currentRegsMask bitAnd: mergeRegsMask).
> + conflictingRegsMask ~= 0 ifTrue:
> + [(self isAPowerOfTwo: conflictingRegsMask) "Multiple conflicts mean we have to sort"
> + ifFalse: [self swapCurrentRegistersInMask: currentRegsMask accordingToRegisterOrderIn: mergeSimStack]
> + ifTrue: [self assignToTempRegConflictingRegisterIn: conflictingRegsMask]].!
>
> 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 skip past a return. If it is a real merge point then throw
> - 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."
> + optStatus isReceiverResultRegLive: fixup isReceiverResultRegSelf.
> fixup mergeSimStack ifNotNil:
> [simSpillBase := methodOrBlockNumTemps.
> - self flag: 'try and maintain this through the merge'.
> - 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!
>
More information about the Vm-dev
mailing list