[Vm-dev] VM Maker: VMMaker.oscog-eem.2094.mcz

Ronie Salgado roniesalg at gmail.com
Tue Jan 17 08:15:14 UTC 2017


Hi Eliot,

With this commit I got the following compilation error on Mac OS X 64. I
made a quick fix by replacing the case into ifTrue:iFalse:

../../spur64src/vm/cogitX64.c:29060:4: error: statement requires expression
of integer type ('sqInt (*)(void)' (aka 'long (*)(void)') invalid)
                        switch ((descriptor->generator)) {
                        ^       ~~~~~~~~~~~~~~~~~~~~~~~
../../spur64src/vm/cogitX64.c:29061:9: error: expression is not an integer
constant expression
                        case genPushConstantTrueBytecode:
                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~
../../spur64src/vm/cogitX64.c:29064:9: error: expression is not an integer
constant expression
                        case genPushConstantFalseBytecode:

(spur64src because I am using the Pharo branch, where I can load the
LowcodeOpalCompiler for testing)

Best regards,
Ronie

2017-01-17 1:21 GMT-03:00 <commits at source.squeak.org>:

>
> Eliot Miranda uploaded a new version of VMMaker to project VM Maker:
> http://source.squeak.org/VMMaker/VMMaker.oscog-eem.2094.mcz
>
> ==================== Summary ====================
>
> Name: VMMaker.oscog-eem.2094
> Author: eem
> Time: 16 January 2017, 8:20:54.697006 pm
> UUID: 69b76ffe-68d9-423c-a3a7-546a6bbb3110
> Ancestors: VMMaker.oscog-rsf.2093
>
> StackToRegisterMappingCogit:
> Follow jumps to jumps and push: aBoolean; jump:if:s, eliminating dead code.
>
> Elimnate jumps to the immediately following instruction in
> StackToRegisterMappingCogit>>generateInstructionsAt:.
>
> Neaten the simulation-only breakpointing for bytecode and machine code
> pcs.  Add suport for breakPC during in-image compilation.
>
> =============== Diff against VMMaker.oscog-rsf.2093 ===============
>
> Item was changed:
>   ----- Method: Cogit class>>testPCMappingSelect:options: (in category
> 'tests') -----
>   testPCMappingSelect: aBlock options: optionsDictionaryOrArray
>         "Test pc mapping both ways using a selection of the methods in the
> current image."
> +       | n cogit coInterpreter |
> -       | cogit coInterpreter |
>         cogit := self instanceForTests: optionsDictionaryOrArray.
>         coInterpreter := CurrentImageCoInterpreterFacade forCogit: cogit.
>         [cogit
>                         setInterpreter: coInterpreter;
>                         singleStep: true;
>                         initializeCodeZoneFrom: 1024 upTo: coInterpreter
> memory size]
>                 on: Notification
>                 do: [:ex|
>                         (ex messageText beginsWith: 'cannot find receiver
> for') ifTrue:
>                                 [ex resume: coInterpreter]].
> +       n := -1.
>         SystemNavigation new allSelect:
>                 [:m| | cm |
>                 (m isQuick not
>                  and: [aBlock value: m]) ifTrue:
> +                       [(n := n + 1) \\ 10 = 0 ifTrue: [Transcript
> nextPut: $.; flush].
> -                       [Transcript nextPut: $.; flush.
>                          cm := cogit
>                                                 cog: (coInterpreter
> oopForObject: m)
>                                                 selector: (coInterpreter
> oopForObject: m selector).
>                           cm ifNil:
>                                 [cogit methodZone clearCogCompiledCode.
>                                  coInterpreter initializeObjectMap.
>                                  cm := cogit
>                                                         cog:
> (coInterpreter oopForObject: m)
>                                                         selector:
> (coInterpreter oopForObject: m selector).
>                                 cm ifNil: [Transcript show: 'After 1 Cog
> compiled code compaction, still not able to generate the cog method...' ] ].
>                           cm ifNotNil:
>                                 [cogit testPCMappingForCompiledMethod: m
> cogMethod: cm]].
>                  false] !
>
> Item was changed:
>   ----- Method: Cogit>>compileAbstractInstructionsFrom:through: (in
> category 'compile abstract instructions') -----
>   compileAbstractInstructionsFrom: start through: end
>         "Loop over bytecodes, dispatching to the generator for each
> bytecode, handling fixups in due course."
>         | nextOpcodeIndex descriptor fixup result nExts |
>         <var: #descriptor type: #'BytecodeDescriptor *'>
>         <var: #fixup type: #'BytecodeFixup *'>
>         bytecodePC := start.
>         nExts := result := 0.
>         descriptor := nil.
> +       [self maybeHaltIfDebugPC.
> -       [self cCode: '' inSmalltalk: [self isDebugPC ifTrue: [self halt]].
>          descriptor := self loadBytesAndGetDescriptor.
>          nextOpcodeIndex := opcodeIndex.
>          result := self perform: descriptor generator.
>          self assertExtsAreConsumed: descriptor.
>          fixup := self fixupAt: bytecodePC - initialPC.
>          self patchFixupTargetIfNeeded: fixup nextOpcodeIndex:
> nextOpcodeIndex.
>          self maybeDumpLiterals: descriptor.
>          bytecodePC := self nextBytecodePCFor: descriptor exts: nExts.
>          result = 0 and: [bytecodePC <= end]]
>                 whileTrue:
>                         [nExts := descriptor isExtension ifTrue: [nExts +
> 1] ifFalse: [0]].
>         self checkEnoughOpcodes.
>         ^result!
>
> Item was changed:
>   ----- Method: Cogit>>generateInstructionsAt: (in category 'generate
> machine code') -----
>   generateInstructionsAt: eventualAbsoluteAddress
>         "Size pc-dependent instructions and assign eventual addresses to
> all instructions.
>          Answer the size of the code.
>          Compute forward branches based on virtual address (abstract code
> starts at 0),
>          assuming that any branches branched over are long.
>          Compute backward branches based on actual address.
>          Reuse the fixups array to record the pc-dependent instructions
> that need to have
>          their code generation postponed until after the others."
>         | absoluteAddress pcDependentIndex abstractInstruction fixup |
>         <var: #abstractInstruction type: #'AbstractInstruction *'>
>         <var: #fixup type: #'BytecodeFixup *'>
>         absoluteAddress := eventualAbsoluteAddress.
>         pcDependentIndex := 0.
>         0 to: opcodeIndex - 1 do:
>                 [:i|
> +               self maybeBreakGeneratingAt: absoluteAddress.
> -               self cCode: [] inSmalltalk: [self maybeBreakGeneratingAt:
> absoluteAddress].
>                 abstractInstruction := self abstractInstructionAt: i.
>                 abstractInstruction isPCDependent
>                         ifTrue:
>                                 [abstractInstruction
> sizePCDependentInstructionAt: absoluteAddress.
>                                  fixup := self fixupAt: pcDependentIndex.
>                                  pcDependentIndex := pcDependentIndex + 1.
>                                  fixup instructionIndex: i.
>                                  absoluteAddress := absoluteAddress +
> abstractInstruction machineCodeSize]
>                         ifFalse:
>                                 [absoluteAddress := abstractInstruction
> concretizeAt: absoluteAddress]].
>         0 to: pcDependentIndex - 1 do:
>                 [:j|
>                 fixup := self fixupAt: j.
>                 abstractInstruction := self abstractInstructionAt: fixup
> instructionIndex.
> +               self maybeBreakGeneratingAt: abstractInstruction address.
> -               self cCode: [] inSmalltalk: [self maybeBreakGeneratingAt:
> abstractInstruction address].
>                 abstractInstruction concretizeAt: abstractInstruction
> address].
>         ^absoluteAddress - eventualAbsoluteAddress!
>
> Item was removed:
> - ----- Method: Cogit>>isDebugPC (in category 'compile abstract
> instructions') -----
> - isDebugPC
> -       <doNotGenerate>
> -       ^ debugBytecodePointers includes: bytecodePC!
>
> Item was changed:
>   ----- Method: Cogit>>maybeBreakGeneratingAt: (in category 'simulation
> only') -----
>   maybeBreakGeneratingAt: address
> +       "Variation on maybeBreakAt: that only works for integer breakPCs,
> -       "Variation on maybeBreakAt: that inly forks for integer breakPCs,
>          so we can have break blocks that stop at any pc, except when
> generating."
> +       <cmacro: '(address) 0'> "Simulation only; void in C"
> -       <doNotGenerate>
>         (breakPC = address
>          and: [breakBlock shouldStopIfAtPC: address]) ifTrue:
>                 [coInterpreter changed: #byteCountText.
>                  self halt: 'machine code generation at ', address hex, '
> in ', thisContext sender selector]!
>
> Item was added:
> + ----- Method: Cogit>>maybeHaltIfDebugPC (in category 'compile abstract
> instructions') -----
> + maybeHaltIfDebugPC
> +       <cmacro: '0'> "Simulation only; void in C"
> +       (debugBytecodePointers includes: bytecodePC) ifTrue:
> +               [self halt]!
>
> Item was changed:
>   ----- Method: Cogit>>setInterpreter: (in category 'initialization') -----
>   setInterpreter: aCoInterpreter
>         "Initialization of the code generator in the simulator.
>          These objects already exist in the generated C VM
>          or are used only in the simulation."
>         <doNotGenerate>
>         coInterpreter := aCoInterpreter.
>         objectMemory := aCoInterpreter objectMemory.
>         threadManager := aCoInterpreter threadManager. "N.B. may be nil"
>         methodZone := CogMethodZone new.
>         objectRepresentation := objectMemory objectRepresentationClass
>                                                                 forCogit:
> self methodZone: methodZone.
>         methodZone setInterpreter: aCoInterpreter
>                                 objectRepresentation: objectRepresentation
>                                 cogit: self.
>         generatorTable := self class generatorTable.
>         processor := ProcessorClass new.
>         simulatedAddresses := Dictionary new.
>         simulatedTrampolines := Dictionary new.
>         simulatedVariableGetters := Dictionary new.
>         simulatedVariableSetters := Dictionary new.
>         traceStores := 0.
>         traceFlags := (self class initializationOptions at:
> #recordPrimTrace ifAbsent: [true])
>                                         ifTrue: [8] "record prim trace on
> by default (see Cogit class>>decareCVarsIn:)"
>                                         ifFalse: [0].
>         debugPrimCallStackOffset := 0.
>         singleStep := printRegisters := printInstructions := clickConfirm
> := false.
>         backEnd := CogCompilerClass for: self.
>         methodLabel := CogCompilerClass for: self.
>         (literalsManager := backEnd class literalsManagerClass new) cogit:
> self.
>         ordinarySendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines).
>         superSendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines).
>         BytecodeSetHasDirectedSuperSend ifTrue:
>                 [directedSuperSendTrampolines := CArrayAccessor on: (Array
> new: NumSendTrampolines)].
>         NewspeakVM ifTrue:
>                 [selfSendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines).
>                 dynamicSuperSendTrampolines := CArrayAccessor on: (Array
> new: NumSendTrampolines).
>                 implicitReceiverSendTrampolines := CArrayAccessor on:
> (Array new: NumSendTrampolines).
>                 outerSendTrampolines := CArrayAccessor on: (Array new:
> NumSendTrampolines)].
>         "debug metadata"
>         objectReferencesInRuntime := CArrayAccessor on: (Array new:
> NumObjRefsInRuntime).
>         runtimeObjectRefIndex := 0.
>         "debug metadata"
>         trampolineAddresses := CArrayAccessor on: (Array new:
> NumTrampolines * 2).
>         trampolineTableIndex := 0.
>
>         extA := numExtB := extB := 0.
>
>         compilationTrace ifNil: [compilationTrace := self class
> initializationOptions at: #compilationTrace ifAbsent: [0]].
>         debugOpcodeIndices := self class initializationOptions at:
> #debugOpcodeIndices ifAbsent: [Set new].
> +       debugBytecodePointers := self class initializationOptions at:
> #debugBytecodePointers ifAbsent: [Set new].
> +       self class initializationOptions at: #breakPC ifPresent: [:pc|
> breakPC := pc]!
> -       debugBytecodePointers := self class initializationOptions at:
> #debugBytecodePointers ifAbsent: [Set new]!
>
> Item was changed:
>   ----- Method: RegisterAllocatingCogit>>genJumpIf:to: (in category
> 'bytecode generator support') -----
>   genJumpIf: boolean to: targetBytecodePC
>         <inline: false>
> +       | eventualTarget desc reg fixup ok |
> -       | desc reg fixup ok |
>         <var: #desc type: #'CogSimStackEntry *'>
>         <var: #fixup type: #'BytecodeFixup *'>
>         <var: #ok type: #'AbstractInstruction *'>
> +       eventualTarget := self eventualTargetOf: targetBytecodePC.
>         desc := self ssTop.
>         self ssPop: 1.
>         (desc type == SSConstant
>          and: [desc constant = objectMemory trueObject or: [desc constant
> = objectMemory falseObject]]) ifTrue:
>                 ["Must arrange there's a fixup at the target whether it is
> jumped to or
>                   not so that the simStackPtr can be kept correct."
> +                fixup := self ensureFixupAt: eventualTarget - initialPC.
> -                fixup := self ensureFixupAt: targetBytecodePC - initialPC.
>                  "Must annotate the bytecode for correct pc mapping."
>                  self annotateBytecode: (desc constant = boolean
>
> ifTrue: [self Jump: fixup]
>
> ifFalse: [self prevInstIsPCAnnotated
>
>                       ifTrue: [self Nop]
>
>                       ifFalse: [self Label]]).
>                  extA := 0.
>                  ^0].
>         "try and use the top entry's register if anty, but only if it can
> be destroyed."
>         reg := (desc type ~= SSRegister
>                         or: [(self anyReferencesToRegister: desc register
> inAllButTopNItems: 0)
>                         or: [(desc register = ReceiverResultReg and:
> [optStatus isReceiverResultRegLive])]])
>                                 ifTrue: [TempReg]
>                                 ifFalse: [desc register].
>         desc popToReg: reg.
>         "Cunning trick by LPD.  If true and false are contiguous subtract
> the smaller.
>          Correct result is either 0 or the distance between them.  If
> result is not 0 or
>          their distance send mustBeBoolean."
>         self assert: (objectMemory objectAfter: objectMemory falseObject)
> = objectMemory trueObject.
>         self genSubConstant: boolean R: reg.
> +       self JumpZero: (self ensureFixupAt: eventualTarget - initialPC).
> -       self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
>
>         self extASpecifiesNoMustBeBoolean ifTrue:
>                 [extA := 0.
>                  self annotateBytecode: self lastOpcode.
>                  ^0].
>         extA := 0.
>
>   .     self CmpCq: (boolean = objectMemory falseObject
>                                         ifTrue: [objectMemory trueObject -
> objectMemory falseObject]
>                                         ifFalse: [objectMemory falseObject
> - objectMemory trueObject])
>                 R: reg.
>         ok := self JumpZero: 0.
>         reg ~= TempReg ifTrue:
>                 [self MoveR: reg R: TempReg].
>         self copySimStackToScratch: simSpillBase.
>         self ssFlushTo: simStackPtr.
>         self genCallMustBeBooleanFor: boolean.
>         "NOTREACHED"
>         ok jmpTarget: (self annotateBytecode: self Label).
>         self restoreSimStackFromScratch.
>         ^0!
>
> Item was changed:
>   ----- Method: RegisterAllocatingCogit>>genJumpTo: (in category
> 'bytecode generator support') -----
>   genJumpTo: targetBytecodePC
>         "Overriden to avoid the flush because in this cogit stack state is
> merged at merge point."
>         deadCode := true. "can't fall through"
> +       self Jump: (self ensureFixupAt: (self eventualTargetOf:
> targetBytecodePC) - initialPC).
> -       self Jump: (self ensureFixupAt: targetBytecodePC - initialPC).
>         ^ 0!
>
> Item was changed:
>   ----- Method: SistaCogit>>genJumpIf:to: (in category 'bytecode generator
> support') -----
>   genJumpIf: boolean to: targetBytecodePC
>         "The heart of performance counting in Sista.  Conditional branches
> are 6 times less
>          frequent than sends and can provide basic block frequencies (send
> counters can't).
>          Each conditional has a 32-bit counter split into an upper 16 bits
> counting executions
>          and a lower half counting untaken executions of the branch.
> Executing the branch
>          decrements the upper half, tripping if the count goes negative.
> Not taking the branch
>          decrements the lower half.  N.B. We *do not* eliminate dead
> branches (true ifTrue:/true ifFalse:)
>          so that scanning for send and branch data is simplified and that
> branch data is correct."
>         <inline: false>
> +       | ok counterAddress countTripped retry nextPC nextDescriptor desc
> eventualTarget |
> -       | ok counterAddress countTripped retry nextPC nextDescriptor desc |
>         <var: #ok type: #'AbstractInstruction *'>
>         <var: #desc type: #'CogSimStackEntry *'>
>         <var: #retry type: #'AbstractInstruction *'>
>         <var: #countTripped type: #'AbstractInstruction *'>
>         <var: #nextDescriptor type: #'BytecodeDescriptor *'>
>
>         "In optimized code we don't generate counters to improve
> performance"
>         (coInterpreter isOptimizedMethod: methodObj) ifTrue: [ ^ super
> genJumpIf: boolean to: targetBytecodePC ].
>
>         "If the branch is reached only for the counter trip trampoline
>         (typically, var1 == var2 ifTrue: falls through to the branch only
> for the trampoline)
>         we generate a specific path to drastically reduce the number of
> machine instructions"
>         branchReachedOnlyForCounterTrip ifTrue:
>                 [ branchReachedOnlyForCounterTrip := false.
>                 ^ self genCounterTripOnlyJumpIf: boolean to:
> targetBytecodePC ].
>
>         "We detect and: / or:, if found, we don't generate the counters to
> avoid pathological counter slow down"
>         boolean = objectMemory falseObject ifTrue:
>                 [ nextPC := bytecodePC + (self generatorAt: byte0)
> numBytes.
>                   nextDescriptor := self generatorAt: (objectMemory
> fetchByte: nextPC ofObject: methodObj) + bytecodeSetOffset.
>                   nextDescriptor generator ==
> #genPushConstantTrueBytecode ifTrue: [ ^ super genJumpIf: boolean to:
> targetBytecodePC ].
>                   nextDescriptor := self generatorAt: (objectMemory
> fetchByte: targetBytecodePC ofObject: methodObj) + bytecodeSetOffset.
>                   nextDescriptor generator ==
> #genPushConstantFalseBytecode ifTrue: [ ^ super genJumpIf: boolean to:
> targetBytecodePC ].  ].
>
>         extA := 0. "We ignore the noMustBeBoolean flag. It should not be
> present in methods with counters, and if it is we don't care."
>
>         "We don't generate counters on branches on true/false, the
> basicblock usage can be inferred"
>         desc := self ssTop.
>         (desc type == SSConstant
>          and: [desc constant = objectMemory trueObject or: [desc constant
> = objectMemory falseObject]]) ifTrue:
>                 [ ^ super genJumpIf: boolean to: targetBytecodePC ].
> +
> +       eventualTarget := self eventualTargetOf: targetBytecodePC.
> +
> -
>         self ssFlushTo: simStackPtr - 1.
>         desc popToReg: TempReg.
>         self ssPop: 1.
>
>         "We need SendNumArgsReg because of the mustBeBooleanTrampoline"
>         self ssAllocateRequiredReg: SendNumArgsReg.
>
>         retry := self Label.
>         self
>                 genExecutionCountLogicInto: [ :cAddress :countTripBranch |
>                         counterAddress := cAddress.
>                         countTripped := countTripBranch ]
>                 counterReg: SendNumArgsReg.
>         counterIndex := counterIndex + 1.
>
>         "Cunning trick by LPD.  If true and false are contiguous subtract
> the smaller.
>          Correct result is either 0 or the distance between them.  If
> result is not 0 or
>          their distance send mustBeBoolean."
>         self assert: (objectMemory objectAfter: objectMemory falseObject)
> = objectMemory trueObject.
>         self genSubConstant: boolean R: TempReg.
> +       self JumpZero: (self ensureFixupAt: eventualTarget - initialPC).
> -       self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
>
>         self genFallsThroughCountLogicCounterReg: SendNumArgsReg
> counterAddress: counterAddress.
>
>         self CmpCq: (boolean = objectMemory falseObject
>                                         ifTrue: [objectMemory trueObject -
> objectMemory falseObject]
>                                         ifFalse: [objectMemory falseObject
> - objectMemory trueObject])
>                 R: TempReg.
>         ok := self JumpZero: 0.
>         self MoveCq: 0 R: SendNumArgsReg. "if counterReg is 0 this is a
> mustBeBoolean, not a counter trip."
>
>         countTripped jmpTarget: (self genCallMustBeBooleanFor: boolean).
>
>         "If we're in an image which hasn't got the Sista code loaded then
> the ceCounterTripped:
>          trampoline will return directly to machine code, returning the
> boolean.  So the code should
>          jump back to the retry point. The trampoline makes sure that
> TempReg has been reloaded."
>
>         "Clément: For some reason if I write self annotateBytecode: (self
> Jump: retry) the annotation is not at the correct place."
>         "Eliot: Annotations apply the the address following an
> instruction, and the annotation must be for the return address
>          of the call (since this is the address the run-time sees), so it
> must be on a label before the jump, not after the jump."
>         self annotateBytecode: self Label.
>         self Jump: retry.
>
>         ok jmpTarget: self Label.
>         ^0!
>
> Item was changed:
>   ----- Method: SistaRegisterAllocatingCogit>>genJumpIf:to: (in category
> 'bytecode generator support') -----
>   genJumpIf: boolean to: targetBytecodePC
>         "The heart of performance counting in Sista.  Conditional branches
> are 6 times less
>          frequent than sends and can provide basic block frequencies (send
> counters can't).
>          Each conditional has a 32-bit counter split into an upper 16 bits
> counting executions
>          and a lower half counting untaken executions of the branch.
> Executing the branch
>          decrements the upper half, tripping if the count goes negative.
> Not taking the branch
>          decrements the lower half.  N.B. We *do not* eliminate dead
> branches (true ifTrue:/true ifFalse:)
>          so that scanning for send and branch data is simplified and that
> branch data is correct."
>         <inline: false>
> +       | ok counterAddress countTripped retry nextPC nextDescriptor desc
> eventualTarget reg |
> -       | ok counterAddress countTripped retry nextPC nextDescriptor desc
> reg |
>         <var: #ok type: #'AbstractInstruction *'>
>         <var: #desc type: #'CogSimStackEntry *'>
>         <var: #retry type: #'AbstractInstruction *'>
>         <var: #countTripped type: #'AbstractInstruction *'>
>         <var: #nextDescriptor type: #'BytecodeDescriptor *'>
>
>         "In optimized code we don't generate counters to improve
> performance"
>         (coInterpreter isOptimizedMethod: methodObj) ifTrue:
>                 [^super genJumpIf: boolean to: targetBytecodePC].
>
>         "If the branch is reached only for the counter trip trampoline
>         (typically, var1 == var2 ifTrue: falls through to the branch only
> for the trampoline)
>         we generate a specific path to drastically reduce the number of
> machine instructions"
>         branchReachedOnlyForCounterTrip ifTrue:
>                 [branchReachedOnlyForCounterTrip := false.
>                  ^self genCounterTripOnlyJumpIf: boolean to:
> targetBytecodePC].
>
>         "We detect and: / or:, if found, we don't generate the counters to
> avoid pathological counter slow down"
>         boolean = objectMemory falseObject ifTrue:
>                 [ nextPC := bytecodePC + (self generatorAt: byte0)
> numBytes.
>                   nextDescriptor := self generatorAt: (objectMemory
> fetchByte: nextPC ofObject: methodObj) + bytecodeSetOffset.
>                   nextDescriptor generator ==
> #genPushConstantTrueBytecode ifTrue: [ ^ super genJumpIf: boolean to:
> targetBytecodePC ].
>                   nextDescriptor := self generatorAt: (objectMemory
> fetchByte: targetBytecodePC ofObject: methodObj) + bytecodeSetOffset.
>                   nextDescriptor generator ==
> #genPushConstantFalseBytecode ifTrue: [ ^ super genJumpIf: boolean to:
> targetBytecodePC ]. ].
>
>         extA := 0. "We ignore the noMustBeBoolean flag. It should not be
> present in methods with counters, and if it is we don't care."
>
>         "We don't generate counters on branches on true/false, the
> basicblock usage can be inferred"
>         desc := self ssTop.
>         (desc type == SSConstant
>          and: [desc constant = objectMemory trueObject or: [desc constant
> = objectMemory falseObject]]) ifTrue:
>                 [ ^ super genJumpIf: boolean to: targetBytecodePC ].
>
> +       eventualTarget := self eventualTargetOf: targetBytecodePC.
> +
>         self flag: 'Because of the restriction on x64 that absolute loads
> must target %rax, it would perhaps be a better choice to use TempReg (%rax)
> for the counter reg and SendNumArgsReg for the boolean.'.
>         "try and use the top entry's register if ant, but only if it can
> be destroyed."
>         reg := (desc type ~= SSRegister
>                         or: [(self anyReferencesToRegister: desc register
> inAllButTopNItems: 0)
>                         or: [(desc register = ReceiverResultReg and:
> [optStatus isReceiverResultRegLive])]])
>                                 ifTrue: [TempReg]
>                                 ifFalse: [desc register].
>         desc popToReg: reg.
>         self ssPop: 1.
>
>         "We need SendNumArgsReg because of the mustBeBooleanTrampoline"
>         self ssAllocateRequiredReg: SendNumArgsReg.
>
>         retry := self Label.
>         self
>                 genExecutionCountLogicInto: [ :cAddress :countTripBranch |
>                         counterAddress := cAddress.
>                         countTripped := countTripBranch ]
>                 counterReg: SendNumArgsReg.
>         counterIndex := counterIndex + 1.
>
>         "Cunning trick by LPD.  If true and false are contiguous subtract
> the smaller.
>          Correct result is either 0 or the distance between them.  If
> result is not 0 or
>          their distance send mustBeBoolean."
>         self assert: (objectMemory objectAfter: objectMemory falseObject)
> = objectMemory trueObject.
>         self genSubConstant: boolean R: reg.
> +       self JumpZero: (self ensureFixupAt: eventualTarget - initialPC).
> -       self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
>
>         self genFallsThroughCountLogicCounterReg: SendNumArgsReg
> counterAddress: counterAddress.
>
>         self CmpCq: (boolean = objectMemory falseObject
>                                         ifTrue: [objectMemory trueObject -
> objectMemory falseObject]
>                                         ifFalse: [objectMemory falseObject
> - objectMemory trueObject])
>                 R: reg.
>         ok := self JumpZero: 0.
>         self MoveCq: 0 R: SendNumArgsReg. "if counterReg is 0 this is a
> mustBeBoolean, not a counter trip."
>         reg ~= TempReg ifTrue:
>                 [self MoveR: reg R: TempReg].
>         countTripped jmpTarget: self Label.
>         self copySimStackToScratch: simSpillBase.
>         self ssFlushTo: simStackPtr.
>         self genCallMustBeBooleanFor: boolean.
>
>         "If we're in an image which hasn't got the Sista code loaded then
> the ceCounterTripped: trampoline
>          will return directly to machine code, returning the boolean.  So
> the code should jump back to the
>          retry point. The trampoline preserves register state when taking
> the ceCounterTripped: path."
>         "Clément: For some reason if I write self annotateBytecode: (self
> Jump: retry) the annotation is not at the correct place."
>         "Eliot: Annotations apply the the address following an
> instruction, and the annotation must be for the return address
>          of the call (since this is the address the run-time sees), so it
> must be on a label before the jump, not after the jump."
>         self annotateBytecode: self Label.
>         simSpillBase ~= scratchSpillBase ifTrue:
>                 [self assert: simSpillBase > scratchSpillBase.
>                  self AddCq: simSpillBase - scratchSpillBase *
> objectMemory wordSize R: SPReg].
>         self Jump: retry.
>
>         ok jmpTarget: self Label.
>         self restoreSimStackFromScratch.
>         ^0!
>
> Item was changed:
>   ----- Method: StackToRegisterMappingCogit>>
> compileAbstractInstructionsFrom:through: (in category 'compile abstract
> instructions') -----
>   compileAbstractInstructionsFrom: start through: end
>         "Loop over bytecodes, dispatching to the generator for each
> bytecode, handling fixups in due course."
>         | nextOpcodeIndex descriptor nExts fixup result |
>         <var: #descriptor type: #'BytecodeDescriptor *'>
>         <var: #fixup type: #'BytecodeFixup *'>
>         self traceSimStack.
>         bytecodePC := start.
>         nExts := result := 0.
>         descriptor := nil.
>         deadCode := false.
> +       [self maybeHaltIfDebugPC.
> -       [self cCode: '' inSmalltalk: [self isDebugPC ifTrue: [self halt]].
>          fixup := self fixupAt: bytecodePC - initialPC.
>          self mergeWithFixupIfRequired: fixup.
>          self assertCorrectSimStackPtr.
>          descriptor := self loadBytesAndGetDescriptor.
>          nextOpcodeIndex := opcodeIndex.
>          result := deadCode
>                                 ifTrue: [self mapDeadDescriptorIfNeeded:
> descriptor]
>                                 ifFalse: [self perform: descriptor
> generator].
>          self assertExtsAreConsumed: descriptor.
>          self traceDescriptor: descriptor; traceSimStack.
>          self patchFixupTargetIfNeeded: fixup nextOpcodeIndex:
> nextOpcodeIndex.
>          self maybeDumpLiterals: descriptor.
>          bytecodePC := self nextBytecodePCFor: descriptor exts: nExts.
>          result = 0 and: [bytecodePC <= end]] whileTrue:
>                 [nExts := descriptor isExtension ifTrue: [nExts + 1]
> ifFalse: [0]].
>         self checkEnoughOpcodes.
>         ^result!
>
> Item was changed:
>   ----- Method: StackToRegisterMappingCogit>>compileBlockBodies (in
> category 'compile abstract instructions') -----
>   compileBlockBodies
>         <inline: false>
>         | result compiledBlocksCount blockStart savedNeedsFrame
> savedNumArgs savedNumTemps
>           initialStackPtr initialOpcodeIndex initialIndexOfIRC
> initialCounterIndex |
>         <var: #blockStart type: #'BlockStart *'>
>         self assert: blockCount > 0.
>         "scanBlock: in compileBlockEntry: sets both of these appropriately
> for each block."
>         savedNeedsFrame := needsFrame.
>         savedNumArgs := methodOrBlockNumArgs.
>         savedNumTemps := methodOrBlockNumTemps.
>         inBlock := InVanillaBlock.
>         compiledBlocksCount := 0.
>         [compiledBlocksCount < blockCount] whileTrue:
>                 [blockPass := 1.
>                  blockStart := self blockStartAt: compiledBlocksCount.
>                  (result := self scanBlock: blockStart) < 0 ifTrue:
> [^result].
>                  initialOpcodeIndex := opcodeIndex.
>                  initialCounterIndex := self maybeCounterIndex."for
> SistaCogit"
>                  literalsManager saveForBlockCompile.
>                  NewspeakVM ifTrue:
>                         [initialIndexOfIRC := indexOfIRC].
>                  [self compileBlockEntry: blockStart.
>                   initialStackPtr := simStackPtr.
>                   (result := self compileAbstractInstructionsFrom:
> blockStart startpc + (self pushNilSize: methodObj numInitialNils:
> blockStart numInitialNils)
>                                                 through: blockStart
> startpc + blockStart span - 1) < 0 ifTrue:
>                         [^result].
>                   "If the final simStackPtr is less than the initial
> simStackPtr then scanBlock: over-
>                    estimated the number of initial nils (because it
> assumed one or more pushNils to
>                    produce an operand were pushNils to initialize temps.
> This is very rare, so
>                    compensate by checking, adjusting numInitialNils and
> recompiling the block body.
>                    N.B.  No need to reinitialize the literalsManager
> because it answers existing literals."
>                   initialStackPtr = simStackPtr]
>                         whileFalse:
> +                               [self assert: (initialStackPtr >
> simStackPtr or: [deadCode]).
> -                               [self assert: initialStackPtr >
> simStackPtr.
>                                  blockPass := blockPass + 1. "for asserts
> :-("
>                                  blockStart numInitialNils: blockStart
> numInitialNils + simStackPtr - initialStackPtr.
>                                  blockStart fakeHeader dependent: nil.
>                                  self reinitializeFixupsFrom: blockStart
> startpc + blockStart numInitialNils
>                                         through: blockStart startpc +
> blockStart span - 1.
>                                  self cCode: 'bzero(abstractOpcodes +
> initialOpcodeIndex,
>
> (opcodeIndex - initialOpcodeIndex) * sizeof(AbstractInstruction))'
>                                         inSmalltalk: [initialOpcodeIndex
> to: opcodeIndex - 1 do:
>
> [:i| abstractOpcodes at: i put: (CogCompilerClass for: self)]].
>                                  opcodeIndex := initialOpcodeIndex.
>                                  self maybeSetCounterIndex:
> initialCounterIndex. "For SistaCogit"
>                                  literalsManager resetForBlockCompile.
>                                  NewspeakVM ifTrue:
>                                         [indexOfIRC := initialIndexOfIRC]].
>                 compiledBlocksCount := compiledBlocksCount + 1].
>         needsFrame := savedNeedsFrame.
>         methodOrBlockNumArgs := savedNumArgs.
>         methodOrBlockNumTemps := savedNumTemps.
>         ^0!
>
> Item was added:
> + ----- Method: StackToRegisterMappingCogit>>eventualTargetOf: (in
> category 'peephole optimizations') -----
> + eventualTargetOf: targetBytecodePC
> +       "Attempt to follow a branch to a pc.  Handle branches to
> unconditional jumps
> +        and branches to push: aBoolean; conditional branch pairs.  If the
> branch cannot
> +        be followed answer targetBytecodePC."
> +
> +       | currentTarget nextPC nExts descriptor span cond |
> +       <var: #descriptor type: #'BytecodeDescriptor *'>
> +       nextPC := currentTarget := targetBytecodePC.
> +       [[nExts := 0.
> +         descriptor := self generatorAt: bytecodeSetOffset
> +                                                               +
> (objectMemory fetchByte: nextPC ofObject: methodObj).
> +         descriptor isReturn ifTrue: [^currentTarget]. "avoid stepping
> off the end of methods"
> +         descriptor isExtension]
> +               whileTrue:
> +                       [nExts := nExts + 1.
> +                        nextPC := nextPC + descriptor numBytes].
> +        descriptor isUnconditionalBranch
> +               ifTrue:
> +                       [span := self spanFor: descriptor at: nextPC exts:
> nExts in: methodObj.
> +                        span < 0 ifTrue: "Do *not* follow backward
> branches; these are interrupt points and should not be elided."
> +                               [^currentTarget].
> +                        nextPC := nextPC + descriptor numBytes + span]
> +               ifFalse:
> +                       [descriptor generator
> +                               caseOf: {
> +                               [#genPushConstantTrueBytecode] -> [cond :=
> true].
> +                               [#genPushConstantFalseBytecode] -> [cond
> := false] }
> +                               otherwise: [^currentTarget].
> +                        "Don't step into loops across a pushTrue;
> jump:if: boundary, so as not to confuse stack depth fixup."
> +                        (fixups at: nextPC - initialPC)
> isBackwardBranchFixup ifTrue:
> +                               [^currentTarget].
> +                        nextPC := self eventualTargetOf: nextPC +
> descriptor numBytes.
> +                        nExts := 0.
> +                        [descriptor := self generatorAt: bytecodeSetOffset
> +                                                               +
> (objectMemory fetchByte: nextPC ofObject: methodObj).
> +                         descriptor isReturn ifTrue: [^currentTarget].
> "avoid stepping off the end of methods"
> +                         descriptor isExtension]
> +                               whileTrue:
> +                                       [nExts := nExts + 1.
> +                                        nextPC := nextPC + descriptor
> numBytes].
> +                        descriptor isBranch ifFalse:
> +                               [^currentTarget].
> +                        descriptor isUnconditionalBranch ifTrue:
> +                               [^currentTarget].
> +                        nextPC := cond == descriptor isBranchTrue
> +
>  ifTrue: [nextPC
> +
>              + descriptor numBytes
> +
>              + (self spanFor: descriptor at: nextPC exts: nExts in:
> methodObj)]
> +
>  ifFalse: [nextPC + descriptor numBytes]].
> +        currentTarget := nextPC]
> +               repeat!
>
> 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."
> -       If the instruction found is a branch, also answers the pc after
> the branch and the pc targetted 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:
> -       [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:
> +                       [branchDescriptor isReturn ifFalse:
> +                               [postBranchPC := self eventualTargetOf:
> nextPC + branchDescriptor numBytes.
> +                                nextPC := self eventualTargetOf:
> bytecodePC + primDescriptor numBytes]].
> +
> -       (branchDescriptor isBranchTrue or: [branchDescriptor
> isBranchFalse]) ifTrue:
> -               [ targetBytecodePC := nextPC
> -                                                       + branchDescriptor
> numBytes
> -                                                       + (self spanFor:
> branchDescriptor at: nextPC exts: nExts in: methodObj).
> -               postBranchPC := nextPC + branchDescriptor numBytes ].
> -
>         fourArgBlock value: branchDescriptor value: nextPC value:
> postBranchPC value: targetBytecodePC!
>
> Item was changed:
>   ----- Method: StackToRegisterMappingCogit>>genJumpIf:to: (in category
> 'bytecode generator support') -----
>   genJumpIf: boolean to: targetBytecodePC
>         <inline: false>
> +       | desc fixup ok eventualTarget |
> -       | desc fixup ok |
>         <var: #desc type: #'CogSimStackEntry *'>
>         <var: #fixup type: #'BytecodeFixup *'>
>         <var: #ok type: #'AbstractInstruction *'>
> +       eventualTarget := self eventualTargetOf: targetBytecodePC.
>         self ssFlushTo: simStackPtr - 1.
>         desc := self ssTop.
>         self ssPop: 1.
>         (desc type == SSConstant
>          and: [desc constant = objectMemory trueObject or: [desc constant
> = objectMemory falseObject]]) ifTrue:
>                 ["Must arrange there's a fixup at the target whether it is
> jumped to or
>                   not so that the simStackPtr can be kept correct."
> +                fixup := self ensureFixupAt: eventualTarget - initialPC.
> -                fixup := self ensureFixupAt: targetBytecodePC - initialPC.
>                  "Must annotate the bytecode for correct pc mapping."
>                  self annotateBytecode: (desc constant = boolean
>
> ifTrue: [self Jump: fixup]
>
> ifFalse: [self prevInstIsPCAnnotated
>
>                       ifTrue: [self Nop]
>
>                       ifFalse: [self Label]]).
>                  extA := 0.
>                  ^0].
>         desc popToReg: TempReg.
>         "Cunning trick by LPD.  If true and false are contiguous subtract
> the smaller.
>          Correct result is either 0 or the distance between them.  If
> result is not 0 or
>          their distance send mustBeBoolean."
>         self assert: (objectMemory objectAfter: objectMemory falseObject)
> = objectMemory trueObject.
>         self genSubConstant: boolean R: TempReg.
> +       self JumpZero: (self ensureFixupAt: eventualTarget - initialPC).
> -       self JumpZero: (self ensureFixupAt: targetBytecodePC - initialPC).
>
>         self extASpecifiesNoMustBeBoolean ifTrue:
>                 [ extA := 0.
>                 self annotateBytecode: self lastOpcode.
>                 ^ 0].
>         extA := 0.
>
> +       self CmpCq: (boolean = objectMemory falseObject
> - .     self CmpCq: (boolean = objectMemory falseObject
>                                         ifTrue: [objectMemory trueObject -
> objectMemory falseObject]
>                                         ifFalse: [objectMemory falseObject
> - objectMemory trueObject])
>                 R: TempReg.
>         ok := self JumpZero: 0.
>         self genCallMustBeBooleanFor: boolean.
>         ok jmpTarget: (self annotateBytecode: self Label).
>         ^0!
>
> Item was changed:
>   ----- Method: StackToRegisterMappingCogit>>genJumpTo: (in category
> 'bytecode generator support') -----
>   genJumpTo: targetBytecodePC
>         self ssFlushTo: simStackPtr.
>         deadCode := true. "can't fall through"
> +       self Jump: (self ensureFixupAt: (self eventualTargetOf:
> targetBytecodePC) - initialPC).
> +       ^0!
> -       ^super genJumpTo: targetBytecodePC!
>
> Item was added:
> + ----- Method: StackToRegisterMappingCogit>>generateInstructionsAt: (in
> category 'generate machine code') -----
> + generateInstructionsAt: eventualAbsoluteAddress
> +       "Size pc-dependent instructions and assign eventual addresses to
> all instructions.
> +        Answer the size of the code.
> +        Compute forward branches based on virtual address (abstract code
> starts at 0),
> +        assuming that any branches branched over are long.
> +        Compute backward branches based on actual address.
> +        Reuse the fixups array to record the pc-dependent instructions
> that need to have
> +        their code generation postponed until after the others.
> +
> +        Override to andd handling for null branches (branches to the
> immediately following
> +        instruction) occasioned by StackToRegisterMapping's following of
> jumps."
> +       | absoluteAddress pcDependentIndex abstractInstruction fixup |
> +       <var: #abstractInstruction type: #'AbstractInstruction *'>
> +       <var: #fixup type: #'BytecodeFixup *'>
> +       absoluteAddress := eventualAbsoluteAddress.
> +       pcDependentIndex := 0.
> +       0 to: opcodeIndex - 1 do:
> +               [:i|
> +               self maybeBreakGeneratingAt: absoluteAddress.
> +               abstractInstruction := self abstractInstructionAt: i.
> +               abstractInstruction isPCDependent
> +                       ifTrue:
> +                               [abstractInstruction
> sizePCDependentInstructionAt: absoluteAddress.
> +                                (abstractInstruction isJump
> +                                 and: [i + 1 < opcodeIndex
> +                                 and: [abstractInstruction getJmpTarget
> == (self abstractInstructionAt: i + 1)]])
> +                                       ifTrue:
> +                                               [abstractInstruction
> +                                                       opcode: Nop;
> +                                                       concretizeAt:
> absoluteAddress]
> +                                       ifFalse:
> +                                               [fixup := self fixupAt:
> pcDependentIndex.
> +                                                pcDependentIndex :=
> pcDependentIndex + 1.
> +                                                fixup instructionIndex:
> i].
> +                                absoluteAddress := absoluteAddress +
> abstractInstruction machineCodeSize]
> +                       ifFalse:
> +                               [absoluteAddress := abstractInstruction
> concretizeAt: absoluteAddress]].
> +       0 to: pcDependentIndex - 1 do:
> +               [:j|
> +               fixup := self fixupAt: j.
> +               abstractInstruction := self abstractInstructionAt: fixup
> instructionIndex.
> +               self maybeBreakGeneratingAt: abstractInstruction address.
> +               abstractInstruction concretizeAt: abstractInstruction
> address].
> +       ^absoluteAddress - eventualAbsoluteAddress!
>
> Item was changed:
>   ----- Method: StackToRegisterMappingCogit>>mergeWithFixupIfRequired:
> (in category 'simulation stack') -----
>   mergeWithFixupIfRequired: fixup
>         "If this bytecode has a fixup, some kind of merge needs to be
> done. There are 4 cases:
>                 1) the bytecode has no fixup (fixup isNotAFixup)
>                         do nothing
>                 2) the bytecode has a non merge fixup
>                         the fixup has needsNonMergeFixup.
>                         The code generating non merge fixup (currently
> only special selector code) is responsible
>                                 for the merge so no need to do it.
>                         We set deadCode to false as the instruction can be
> reached from jumps.
>                 3) the bytecode has a merge fixup, but execution flow
> *cannot* fall through to the merge point.
>                         the fixup has needsMergeFixup and deadCode = true.
>                         ignores the current simStack as it does not mean
> anything
>                         restores the simStack to the state the jumps to
> the merge point expects it to be.
>                 4) the bytecode has a merge fixup and execution flow *can*
> fall through to the merge point.
>                         the fixup has needsMergeFixup and deadCode = false.
>                         flushes the stack to the stack pointer so the fall
> through execution path simStack is
>                                 in the state the merge point expects it to
> be.
>                         restores the simStack to the state the jumps to
> the merge point expects it to be.
>
>         In addition, if this is a backjump merge point, we patch the fixup
> to hold the current simStackPtr
>         for later assertions."
>
>         <var: #fixup type: #'BytecodeFixup *'>
>         "case 1"
> +       fixup notAFixup ifTrue:
> +               [^0].
> -       fixup notAFixup ifTrue: [^ 0].
>
>         "case 2"
> +       fixup isNonMergeFixup ifTrue:
> +               [deadCode := false. ^0].
> -       fixup isNonMergeFixup ifTrue: [deadCode := false. ^ 0 ].
>
>         "cases 3 and 4"
>         self assert: fixup isMergeFixup.
>         self traceMerge: fixup.
> +       deadCode
> +               ifTrue: "case 3"
> +                       ["Would like to assert fixup simStackPtr >=
> (methodOrBlockNumTemps - 1) but can't because
> +                          a) the initialNils hack, b) deadCode removal
> allows arriving at an isBackwardBranchFixup."
> +                        self assert: (fixup simStackPtr >=
> (methodOrBlockNumTemps - 1) or: [inBlock = InVanillaBlock or: [fixup
> isBackwardBranchFixup]]).
> +                        fixup isBackwardBranchFixup ifFalse:
> +                               [simStackPtr := fixup simStackPtr].
> +                        LowcodeVM ifTrue:
> +                               [simNativeStackPtr := fixup
> simNativeStackPtr.
> +                               simNativeStackSize := fixup
> simNativeStackSize]]
> +               ifFalse: "case 4"
> +                       [self ssFlushTo: simStackPtr].
> -       deadCode ifTrue: [
> -               "case 3"
> -               simStackPtr := fixup simStackPtr.
> -               LowcodeVM ifTrue: [
> -                       simNativeStackPtr := fixup simNativeStackPtr.
> -                       simNativeStackSize := fixup simNativeStackSize.
> -               ]
> -       ] ifFalse: [
> -               "case 4"
> -               self ssFlushTo: simStackPtr
> -       ].
>
>         "cases 3 and 4"
>         deadCode := false.
> +       fixup isBackwardBranchFixup ifTrue:
> +               [fixup simStackPtr: simStackPtr.
> +               LowcodeVM ifTrue:
> +                       [fixup simNativeStackPtr: simNativeStackPtr.
> +                        fixup simNativeStackSize: simNativeStackSize]].
> -       fixup isBackwardBranchFixup ifTrue: [
> -               fixup simStackPtr: simStackPtr.
> -               LowcodeVM ifTrue: [
> -                       fixup simNativeStackPtr: simNativeStackPtr.
> -                       fixup simNativeStackSize: simNativeStackSize.
> -               ]
> -       ].
>         fixup targetInstruction: self Label.
>         self assert: simStackPtr = fixup simStackPtr.
> +       LowcodeVM ifTrue:
> +               [self assert: simNativeStackPtr = fixup simNativeStackPtr.
> +                self assert: simNativeStackSize = fixup
> simNativeStackSize].
> -       LowcodeVM ifTrue: [
> -               self assert: simNativeStackPtr = fixup simNativeStackPtr.
> -               self assert: simNativeStackSize = fixup simNativeStackSize.
> -       ].
>
>         self cCode: '' inSmalltalk:
>                 [self assert: fixup simStackPtr = (self
> debugStackPointerFor: bytecodePC)].
>         self restoreSimStackAtMergePoint: fixup.
> +
> -
>         ^0!
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20170117/a585e838/attachment-0001.html>


More information about the Vm-dev mailing list