<div dir="ltr"><div>Hello,<br><br>This time I applied the suggestion made by Nicolas Cellier for this bug. I also tested with the Newspeak bootstrapping system and tests in 32 bits Linux. I got the same number of successful, failing and passing tests as the CI log available at: <a href="https://travis-ci.org/newspeaklanguage/bootimage-ci/jobs/189887252">https://travis-ci.org/newspeaklanguage/bootimage-ci/jobs/189887252</a> . Hopefully this is not breaking Newspeak again.<br><br></div>However, similar changes are required to EncoderForNewsqueakV4 >> #extensionsAt:in:into: and EncoderFoSistaV1 >> #extensionsAt:in:into:, for these methods to correctly decode the extB extensions.<br></div><div class="gmail_extra"><br><div class="gmail_quote">2017-01-08 19:40 GMT-03:00  <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Ronie Salgado Faila uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-rsf.2077.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/<wbr>VMMaker/VMMaker.oscog-rsf.<wbr>2077.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-rsf.2077<br>
Author: rsf<br>
Time: 8 January 2017, 5:41:56.129158 pm<br>
UUID: d009eb6f-01c9-4fb4-b022-<wbr>2f73c6e8ca5c<br>
Ancestors: VMMaker.oscog-eem.2076<br>
<br>
ExtB 00000000 1xxxxxxx constant decoding bug fix.<br>
<br>
=============== Diff against VMMaker.oscog-eem.2076 ===============<br>
<br>
Item was changed:<br>
  CogClass subclass: #Cogit<br>
+       instanceVariableNames: 'coInterpreter objectMemory objectRepresentation processor threadManager methodZone methodZoneBase codeBase minValidCallAddress lastNInstructions simulatedAddresses simulatedTrampolines simulatedVariableGetters simulatedVariableSetters printRegisters printInstructions compilationTrace clickConfirm breakPC breakBlock singleStep guardPageSize traceFlags traceStores breakMethod methodObj enumeratingCogMethod methodHeader initialPC endPC methodOrBlockNumArgs inBlock needsFrame hasYoungReferent primitiveIndex backEnd literalsManager postCompileHook methodLabel stackCheckLabel blockEntryLabel blockEntryNoContextSwitch blockNoContextSwitchOffset stackOverflowCall sendMiss missOffset entryPointMask checkedEntryAlignment uncheckedEntryAlignment cmEntryOffset entry cmNoCheckEntryOffset noCheckEntry fullBlockEntry cbEntryOffset fullBlockNoContextSwitchEntry cbNoSwitchEntryOffset picMNUAbort picInterpretAbort endCPICCase0 endCPICCase1 firstCPICCaseOffset cPICCaseSize cP<br>
 ICEndSize closedPICSize openPICSize fixups abstractOpcodes generatorTable byte0 byte1 byte2 byte3 bytecodePC bytecodeSetOffset opcodeIndex numAbstractOpcodes blockStarts blockCount labelCounter cStackAlignment expectedSPAlignment expectedFPAlignment codeModified maxLitIndex ceMethodAbortTrampoline cePICAbortTrampoline ceCheckForInterruptTrampoline ceCPICMissTrampoline ceReturnToInterpreterTrampolin<wbr>e ceBaseFrameReturnTrampoline ceSendMustBeBooleanAddTrueTram<wbr>poline ceSendMustBeBooleanAddFalseTra<wbr>mpoline ceCannotResumeTrampoline ceEnterCogCodePopReceiverReg ceCallCogCodePopReceiverReg ceCallCogCodePopReceiverAndCla<wbr>ssRegs cePrimReturnEnterCogCode cePrimReturnEnterCogCodeProfil<wbr>ing ceNonLocalReturnTrampoline ceFetchContextInstVarTrampolin<wbr>e ceStoreContextInstVarTrampolin<wbr>e ceEnclosingObjectTrampoline ceFlushICache ceCheckFeaturesFunction ceTraceLinkedSendTrampoline ceTraceBlockActivationTrampoli<wbr>ne ceTraceStoreTrampoline ceGetFP ceGetSP ceCaptureCStackPointers ordinarySendTrampolines superSen<br>
 dTrampolines directedSuperSendTrampolines dynamicSuperSendTrampolines outerSendTrampolines selfSendTrampolines firstSend lastSend realCEEnterCogCodePopReceiverR<wbr>eg realCECallCogCodePopReceiverRe<wbr>g realCECallCogCodePopReceiverAn<wbr>dClassRegs trampolineTableIndex trampolineAddresses objectReferencesInRuntime runtimeObjectRefIndex cFramePointerInUse debugPrimCallStackOffset ceTryLockVMOwner ceUnlockVMOwner extA extB numExtB tempOop numIRCs indexOfIRC theIRCs implicitReceiverSendTrampoline<wbr>s cogMethodSurrogateClass cogBlockMethodSurrogateClass nsSendCacheSurrogateClass CStackPointer CFramePointer cPICPrototype cPICEndOfCodeOffset cPICEndOfCodeLabel maxCPICCases debugBytecodePointers debugOpcodeIndices disassemblingMethod ceMallocTrampoline ceFreeTrampoline ceFFICalloutTrampoline'<br>
-       instanceVariableNames: 'coInterpreter objectMemory objectRepresentation processor threadManager methodZone methodZoneBase codeBase minValidCallAddress lastNInstructions simulatedAddresses simulatedTrampolines simulatedVariableGetters simulatedVariableSetters printRegisters printInstructions compilationTrace clickConfirm breakPC breakBlock singleStep guardPageSize traceFlags traceStores breakMethod methodObj enumeratingCogMethod methodHeader initialPC endPC methodOrBlockNumArgs inBlock needsFrame hasYoungReferent primitiveIndex backEnd literalsManager postCompileHook methodLabel stackCheckLabel blockEntryLabel blockEntryNoContextSwitch blockNoContextSwitchOffset stackOverflowCall sendMiss missOffset entryPointMask checkedEntryAlignment uncheckedEntryAlignment cmEntryOffset entry cmNoCheckEntryOffset noCheckEntry fullBlockEntry cbEntryOffset fullBlockNoContextSwitchEntry cbNoSwitchEntryOffset picMNUAbort picInterpretAbort endCPICCase0 endCPICCase1 firstCPICCaseOffset cPICCaseSize cP<br>
 ICEndSize closedPICSize openPICSize fixups abstractOpcodes generatorTable byte0 byte1 byte2 byte3 bytecodePC bytecodeSetOffset opcodeIndex numAbstractOpcodes blockStarts blockCount labelCounter cStackAlignment expectedSPAlignment expectedFPAlignment codeModified maxLitIndex ceMethodAbortTrampoline cePICAbortTrampoline ceCheckForInterruptTrampoline ceCPICMissTrampoline ceReturnToInterpreterTrampolin<wbr>e ceBaseFrameReturnTrampoline ceSendMustBeBooleanAddTrueTram<wbr>poline ceSendMustBeBooleanAddFalseTra<wbr>mpoline ceCannotResumeTrampoline ceEnterCogCodePopReceiverReg ceCallCogCodePopReceiverReg ceCallCogCodePopReceiverAndCla<wbr>ssRegs cePrimReturnEnterCogCode cePrimReturnEnterCogCodeProfil<wbr>ing ceNonLocalReturnTrampoline ceFetchContextInstVarTrampolin<wbr>e ceStoreContextInstVarTrampolin<wbr>e ceEnclosingObjectTrampoline ceFlushICache ceCheckFeaturesFunction ceTraceLinkedSendTrampoline ceTraceBlockActivationTrampoli<wbr>ne ceTraceStoreTrampoline ceGetFP ceGetSP ceCaptureCStackPointers ordinarySendTrampolines superSen<br>
 dTrampolines directedSuperSendTrampolines dynamicSuperSendTrampolines outerSendTrampolines selfSendTrampolines firstSend lastSend realCEEnterCogCodePopReceiverR<wbr>eg realCECallCogCodePopReceiverRe<wbr>g realCECallCogCodePopReceiverAn<wbr>dClassRegs trampolineTableIndex trampolineAddresses objectReferencesInRuntime runtimeObjectRefIndex cFramePointerInUse debugPrimCallStackOffset ceTryLockVMOwner ceUnlockVMOwner extA extB tempOop numIRCs indexOfIRC theIRCs implicitReceiverSendTrampoline<wbr>s cogMethodSurrogateClass cogBlockMethodSurrogateClass nsSendCacheSurrogateClass CStackPointer CFramePointer cPICPrototype cPICEndOfCodeOffset cPICEndOfCodeLabel maxCPICCases debugBytecodePointers debugOpcodeIndices disassemblingMethod ceMallocTrampoline ceFreeTrampoline ceFFICalloutTrampoline'<br>
        classVariableNames: 'AltBlockCreationBytecodeSize AltFirstSpecialSelector AltNSSendIsPCAnnotated AltNumSpecialSelectors AnnotationConstantNames AnnotationShift AnnotationsWithBytecodePCs BlockCreationBytecodeSize Debug DisplacementMask DisplacementX2N EagerInstructionDecoration FirstAnnotation FirstSpecialSelector HasBytecodePC IsAbsPCReference IsAnnotationExtension IsDirectedSuperSend IsDisplacementX2N IsNSDynamicSuperSend IsNSImplicitReceiverSend IsNSSelfSend IsNSSendCall IsObjectReference IsRelativeCall IsSendCall IsSuperSend MapEnd MaxCPICCases MaxCompiledPrimitiveIndex MaxStackAllocSize MaxX2NDisplacement NSCClassTagIndex NSCEnclosingObjectIndex NSCNumArgsIndex NSCSelectorIndex NSCTargetIndex NSSendIsPCAnnotated NeedsFixupFlag NumObjRefsInRuntime NumOopsPerNSC NumSpecialSelectors NumTrampolines ProcessorClass RRRName'<br>
        poolDictionaries: 'CogAbstractRegisters CogCompilationConstants CogMethodConstants CogRTLOpcodes VMBasicConstants VMBytecodeConstants VMObjectIndices VMStackFrameOffsets'<br>
        category: 'VMMaker-JIT'!<br>
  Cogit class<br>
        instanceVariableNames: 'generatorTable primitiveTable'!<br>
<br>
  !Cogit commentStamp: 'eem 4/6/2015 15:56' prior: 0!<br>
  I am the code generator for the Cog VM.  My job is to produce machine code versions of methods for faster execution and to manage inline caches for faster send performance.  I can be tested in the current image using my class-side in-image compilation facilities.  e.g. try<br>
<br>
        StackToRegisterMappingCogit genAndDis: (Integer >> #benchFib)<br>
<br>
  I have concrete subclasses that implement different levels of optimization:<br>
        SimpleStackBasedCogit is the simplest code generator.<br>
<br>
        StackToRegisterMappingCogit is the current production code generator  It defers pushing operands<br>
        to the stack until necessary and implements a register-based calling convention for low-arity sends.<br>
<br>
        StackToRegisterMappingCogit is an experimental code generator with support for counting<br>
        conditional branches, intended to support adaptive optimization.<br>
<br>
  coInterpreter <CoInterpreterSimulator><br>
        the VM's interpreter with which I cooperate<br>
  methodZoneManager <CogMethodZoneManager><br>
        the manager of the machine code zone<br>
  objectRepresentation <CogObjectRepresentation><br>
        the object used to generate object accesses<br>
  processor <BochsIA32Alien|?><br>
        the simulator that executes the IA32/x86 machine code I generate when simulating execution in Smalltalk<br>
  simulatedTrampolines <Dictionary of Integer -> MessageSend><br>
        the dictionary mapping trap jump addresses to run-time routines used to warp from simulated machine code in to the Smalltalk run-time.<br>
  simulatedVariableGetters <Dictionary of Integer -> MessageSend><br>
        the dictionary mapping trap read addresses to variables in run-time objects used to allow simulated machine code to read variables in the Smalltalk run-time.<br>
  simulatedVariableSetters <Dictionary of Integer -> MessageSend><br>
        the dictionary mapping trap write addresses to variables in run-time objects used to allow simulated machine code to write variables in the Smalltalk run-time.<br>
  printRegisters printInstructions clickConfirm <Boolean><br>
        flags controlling debug printing and code simulation<br>
  breakPC <Integer><br>
        machine code pc breakpoint<br>
  cFramePointer cStackPointer <Integer><br>
        the variables representing the C stack & frame pointers, which must change on FFI callback and return<br>
  selectorOop <sqInt><br>
        the oop of the methodObj being compiled<br>
  methodObj <sqInt><br>
        the bytecode method being compiled<br>
  initialPC endPC <Integer><br>
        the start and end pcs of the methodObj being compiled<br>
  methodOrBlockNumArgs <Integer><br>
        argument count of current method or block being compiled<br>
  needsFrame <Boolean><br>
        whether methodObj or block needs a frame to execute<br>
  primitiveIndex <Integer><br>
        primitive index of current method being compiled<br>
  methodLabel <CogAbstractOpcode><br>
        label for the method header<br>
  blockEntryLabel <CogAbstractOpcode><br>
        label for the start of the block dispatch code<br>
  stackOverflowCall <CogAbstractOpcode><br>
        label for the call of ceStackOverflow in the method prolog<br>
  sendMissCall <CogAbstractOpcode><br>
        label for the call of ceSICMiss in the method prolog<br>
  entryOffset <Integer><br>
        offset of method entry code from start (header) of method<br>
  entry <CogAbstractOpcode><br>
        label for the first instruction of the method entry code<br>
  noCheckEntryOffset <Integer><br>
        offset of the start of a method proper (after the method entry code) from start (header) of method<br>
  noCheckEntry <CogAbstractOpcode><br>
        label for the first instruction of start of a method proper<br>
  fixups <Array of <AbstractOpcode Label | nil>><br>
        the labels for forward jumps that will be fixed up when reaching the relevant bytecode.  fixup shas one element per byte in methodObj's bytecode<br>
  abstractOpcodes <Array of <AbstractOpcode>><br>
        the code generated when compiling methodObj<br>
  byte0 byte1 byte2 byte3 <Integer><br>
        individual bytes of current bytecode being compiled in methodObj<br>
  bytecodePointer <Integer><br>
        bytecode pc (same as Smalltalk) of the current bytecode being compiled<br>
  opcodeIndex <Integer><br>
        the index of the next free entry in abstractOpcodes (this code is translated into C where OrderedCollection et al do not exist)<br>
  numAbstractOpcodes <Integer><br>
        the number of elements in abstractOpcocdes<br>
  blockStarts <Array of <BlockStart>><br>
        the starts of blocks in the current method<br>
  blockCount<br>
        the index into blockStarts as they are being noted, and hence eventually the total number of blocks in the current method<br>
  labelCounter <Integer><br>
        a nicety for numbering labels not needed in the production system but probably not expensive enough to worry about<br>
  ceStackOverflowTrampoline <Integer><br>
  ceSend0ArgsTrampoline <Integer><br>
  ceSend1ArgsTrampoline <Integer><br>
  ceSend2ArgsTrampoline <Integer><br>
  ceSendNArgsTrampoline <Integer><br>
  ceSendSuper0ArgsTrampoline <Integer><br>
  ceSendSuper1ArgsTrampoline <Integer><br>
  ceSendSuper2ArgsTrampoline <Integer><br>
  ceSendSuperNArgsTrampoline <Integer><br>
  ceSICMissTrampoline <Integer><br>
  ceCPICMissTrampoline <Integer><br>
  ceStoreCheckTrampoline <Integer><br>
  ceReturnToInterpreterTrampolin<wbr>e <Integer><br>
  ceBaseFrameReturnTrampoline <Integer><br>
  ceSendMustBeBooleanTrampoline <Integer><br>
  ceClosureCopyTrampoline <Integer><br>
        the various trampolines (system-call-like jumps from machine code to the run-time).<br>
        See Cogit>>generateTrampolines for the mapping from trampoline to run-time<br>
        routine and then read the run-time routine for a funcitonal description.<br>
  ceEnterCogCodePopReceiverReg <Integer><br>
        the enilopmart (jump from run-time to machine-code)<br>
  methodZoneBase <Integer><br>
  !<br>
  Cogit class<br>
        instanceVariableNames: 'generatorTable primitiveTable'!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit>>assertExtsAreConsumed: (in category 'compile abstract instructions') -----<br>
  assertExtsAreConsumed: descriptor<br>
         "extended bytecodes must consume their extensions"<br>
         <inline: true><br>
         descriptor isExtension ifFalse:<br>
+               [self assert: (extA = 0 and: [extB = 0 and: [numExtB = 0]])].!<br>
-               [self assert: (extA = 0 and: [extB = 0])].!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit>>extBBytecode (in category 'bytecode generators') -----<br>
  extBBytecode<br>
        "225            11100001        sbbbbbbb        Extend B (Ext B = Ext B prev * 256 + Ext B)"<br>
+       extB := (numExtB = 0 and: [byte1 > 127])<br>
-       extB := (extB = 0 and: [byte1 > 127])<br>
                                ifTrue: [byte1 - 256]<br>
                                ifFalse: [(extB bitShift: 8) + byte1].<br>
+       numExtB := numExtB + 1.<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit>><wbr>nextDescriptorAndExtensionsInt<wbr>o: (in category 'bytecode generator support') -----<br>
  nextDescriptorAndExtensionsInt<wbr>o: aTrinaryBlock<br>
        "Peek ahead and deliver the next descriptor plus extension bytes."<br>
        <inline: true><br>
+       | savedB0 savedB1 savedB2 savedB3 savedEA savedEB savedNEB descriptor bcpc |<br>
-       | savedB0 savedB1 savedB2 savedB3 savedEA savedEB descriptor bcpc |<br>
        <var: #descriptor type: #'BytecodeDescriptor *'><br>
        descriptor := self generatorAt: byte0.<br>
        savedB0 := byte0. savedB1 := byte1. savedB2 := byte2. savedB3 := byte3.<br>
+       savedEA := extA. savedEB := extB. savedNEB := numExtB.<br>
-       savedEA := extA. savedEB := extB.<br>
        bcpc := bytecodePC + descriptor numBytes.<br>
        [bcpc > endPC ifTrue:<br>
                [^aTrinaryBlock value: nil value: 0 value: 0].<br>
         byte0 := (objectMemory fetchByte: bcpc ofObject: methodObj)  + bytecodeSetOffset.<br>
         descriptor := self generatorAt: byte0.<br>
         self loadSubsequentBytesForDescript<wbr>or: descriptor at: bcpc.<br>
         descriptor isExtension ifFalse:<br>
                [| eA eB |<br>
                 eA := extA. eB := extB.<br>
+                extA := savedEA. extB := savedEB. numExtB := savedNEB.<br>
-                extA := savedEA. extB := savedEB.<br>
                 byte0 := savedB0. byte1 := savedB1. byte2 := savedB2. byte3 := savedB3.<br>
                 ^aTrinaryBlock value: descriptor value: eA value: eB].<br>
         self perform: descriptor generator.<br>
         bcpc := bcpc + descriptor numBytes.<br>
         true] whileTrue!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit>>scanBlock: (in category 'compile abstract instructions') -----<br>
  scanBlock: blockStart<br>
        "Scan the block to determine if the block needs a frame or not"<br>
        | descriptor pc end framelessStackDelta nExts |<br>
        <var: #blockStart type: #'BlockStart *'><br>
        <var: #descriptor type: #'BytecodeDescriptor *'><br>
        needsFrame := false.<br>
        methodOrBlockNumArgs := blockStart numArgs.<br>
        inBlock := InVanillaBlock.<br>
        pc := blockStart startpc.<br>
        end := blockStart startpc + blockStart span.<br>
+       framelessStackDelta := nExts := extA := numExtB := extB := 0.<br>
-       framelessStackDelta := nExts := extA := extB := 0.<br>
        [pc < end] whileTrue:<br>
                [byte0 := (objectMemory fetchByte: pc ofObject: methodObj) + bytecodeSetOffset.<br>
                 descriptor := self generatorAt: byte0.<br>
                 descriptor isExtension ifTrue:<br>
                        [self loadSubsequentBytesForDescript<wbr>or: descriptor at: pc.<br>
                         self perform: descriptor generator].<br>
                 needsFrame ifFalse:<br>
                        [(descriptor needsFrameFunction isNil<br>
                          or: [self perform: descriptor needsFrameFunction with: framelessStackDelta])<br>
                                ifTrue: [needsFrame := true]<br>
                                ifFalse: [framelessStackDelta := framelessStackDelta + descriptor stackDelta]].<br>
                 objectRepresentation maybeNoteDescriptor: descriptor blockStart: blockStart.<br>
                 pc := self nextBytecodePCFor: descriptor at: pc exts: nExts in: methodObj.<br>
                 descriptor isExtension<br>
                        ifTrue: [nExts := nExts + 1]<br>
+                       ifFalse: [nExts := extA := numExtB := 0. extB := 0]].<br>
-                       ifFalse: [nExts := extA := extB := 0]].<br>
        needsFrame ifFalse:<br>
                [framelessStackDelta < 0 ifTrue:<br>
                        [self error: 'negative stack delta in block; block contains bogus code or internal error'].<br>
                 [framelessStackDelta > 0] whileTrue:<br>
                        [descriptor := self generatorAt: (objectMemory fetchByte: blockStart startpc ofObject: methodObj) + bytecodeSetOffset.<br>
                         descriptor generator ~~ #genPushConstantNilBytecode ifTrue:<br>
                                [self error: 'frameless block doesn''t start with enough pushNils'].<br>
                         blockStart<br>
                                startpc: blockStart startpc + descriptor numBytes;<br>
                                span: blockStart span - descriptor numBytes.<br>
                         framelessStackDelta := framelessStackDelta - 1]].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit>>scanMethod (in category 'compile abstract instructions') -----<br>
  scanMethod<br>
        "Scan the method (and all embedded blocks) to determine<br>
                - what the last bytecode is; extra bytes at the end of a method are used to encode things like source pointers or temp names<br>
                - if the method needs a frame or not<br>
                - what are the targets of any backward branches.<br>
                - how many blocks it creates<br>
                - if it contans an unknown bytecode<br>
         Answer the block count or on error a negative error code"<br>
        | latestContinuation nExts descriptor pc numBlocks distance targetPC framelessStackDelta |<br>
        <var: #descriptor type: #'BytecodeDescriptor *'><br>
        needsFrame := false.<br>
        NewspeakVM ifTrue:<br>
                [numIRCs := 0].<br>
        (primitiveIndex > 0<br>
         and: [coInterpreter isQuickPrimitiveIndex: primitiveIndex]) ifTrue:<br>
                [^0].<br>
        pc := latestContinuation := initialPC.<br>
+       numBlocks := framelessStackDelta := nExts := extA := numExtB := extB := 0.<br>
-       numBlocks := framelessStackDelta := nExts := extA := extB := 0.<br>
        [pc <= endPC] whileTrue:<br>
                [byte0 := (objectMemory fetchByte: pc ofObject: methodObj) + bytecodeSetOffset.<br>
                 descriptor := self generatorAt: byte0.<br>
                 descriptor isExtension ifTrue:<br>
                        [descriptor opcode = Nop ifTrue: "unknown bytecode tag; see Cogit class>>#generatorTableFrom:"<br>
                                [^EncounteredUnknownBytecode].<br>
                         self loadSubsequentBytesForDescript<wbr>or: descriptor at: pc.<br>
                         self perform: descriptor generator].<br>
                 (descriptor isReturn<br>
                  and: [pc >= latestContinuation]) ifTrue:<br>
                        [endPC := pc].<br>
                 needsFrame ifFalse:<br>
                        [(descriptor needsFrameFunction isNil<br>
                          or: [self perform: descriptor needsFrameFunction with: framelessStackDelta])<br>
                                ifTrue: [needsFrame := true]<br>
                                ifFalse: [framelessStackDelta := framelessStackDelta + descriptor stackDelta]].<br>
                 descriptor isBranch ifTrue:<br>
                        [distance := self spanFor: descriptor at: pc exts: nExts in: methodObj.<br>
                         targetPC := pc + descriptor numBytes + distance.<br>
                         (self isBackwardBranch: descriptor at: pc exts: nExts in: methodObj)<br>
                                ifTrue: [self initializeFixupAt: targetPC - initialPC]<br>
                                ifFalse: [latestContinuation := latestContinuation max: targetPC]].<br>
                 descriptor isBlockCreation ifTrue:<br>
                        [numBlocks := numBlocks + 1.<br>
                         distance := self spanFor: descriptor at: pc exts: nExts in: methodObj.<br>
                         targetPC := pc + descriptor numBytes + distance.<br>
                         latestContinuation := latestContinuation max: targetPC].<br>
                 NewspeakVM ifTrue:<br>
                        [descriptor hasIRC ifTrue:<br>
                                [numIRCs := numIRCs + 1]].<br>
                 pc := pc + descriptor numBytes.<br>
                 descriptor isExtension<br>
                        ifTrue: [nExts := nExts + 1]<br>
+                       ifFalse: [nExts := extA := numExtB := extB := 0]].<br>
-                       ifFalse: [nExts := extA := extB := 0]].<br>
        ^numBlocks!<br>
<br>
Item was changed:<br>
  ----- Method: Cogit>>setInterpreter: (in category 'initialization') -----<br>
  setInterpreter: aCoInterpreter<br>
        "Initialization of the code generator in the simulator.<br>
         These objects already exist in the generated C VM<br>
         or are used only in the simulation."<br>
        <doNotGenerate><br>
        coInterpreter := aCoInterpreter.<br>
        objectMemory := aCoInterpreter objectMemory.<br>
        threadManager := aCoInterpreter threadManager. "N.B. may be nil"<br>
        methodZone := CogMethodZone new.<br>
        objectRepresentation := objectMemory objectRepresentationClass<br>
                                                                forCogit: self methodZone: methodZone.<br>
        methodZone setInterpreter: aCoInterpreter<br>
                                objectRepresentation: objectRepresentation<br>
                                cogit: self.<br>
        generatorTable := self class generatorTable.<br>
        processor := ProcessorClass new.<br>
        simulatedAddresses := Dictionary new.<br>
        simulatedTrampolines := Dictionary new.<br>
        simulatedVariableGetters := Dictionary new.<br>
        simulatedVariableSetters := Dictionary new.<br>
        traceStores := 0.<br>
        traceFlags := (self class initializationOptions at: #recordPrimTrace ifAbsent: [true])<br>
                                        ifTrue: [8] "record prim trace on by default (see Cogit class>>decareCVarsIn:)"<br>
                                        ifFalse: [0].<br>
        debugPrimCallStackOffset := 0.<br>
        singleStep := printRegisters := printInstructions := clickConfirm := false.<br>
        backEnd := CogCompilerClass for: self.<br>
        methodLabel := CogCompilerClass for: self.<br>
        (literalsManager := backEnd class literalsManagerClass new) cogit: self.<br>
        ordinarySendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).<br>
        superSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).<br>
        BytecodeSetHasDirectedSuperSen<wbr>d ifTrue:<br>
                [directedSuperSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines)].<br>
        NewspeakVM ifTrue:<br>
                [selfSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).<br>
                dynamicSuperSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines).<br>
                implicitReceiverSendTrampoline<wbr>s := CArrayAccessor on: (Array new: NumSendTrampolines).<br>
                outerSendTrampolines := CArrayAccessor on: (Array new: NumSendTrampolines)].<br>
        "debug metadata"<br>
        objectReferencesInRuntime := CArrayAccessor on: (Array new: NumObjRefsInRuntime).<br>
        runtimeObjectRefIndex := 0.<br>
        "debug metadata"<br>
        trampolineAddresses := CArrayAccessor on: (Array new: NumTrampolines * 2).<br>
        trampolineTableIndex := 0.<br>
<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
<br>
        compilationTrace ifNil: [compilationTrace := self class initializationOptions at: #compilationTrace ifAbsent: [0]].<br>
        debugOpcodeIndices := self class initializationOptions at: #debugOpcodeIndices ifAbsent: [Set new].<br>
        debugBytecodePointers := self class initializationOptions at: #debugBytecodePointers ifAbsent: [Set new]!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtJumpIfFalse (in category 'bytecode generators') -----<br>
  genExtJumpIfFalse<br>
        "244            11110100        i i i i i i i i Pop and Jump 0n False i i i i i i i i (+ Extend B * 256, where Extend B >= 0)"<br>
        | distance target |<br>
        distance := byte1 + (extB << 8).<br>
        self assert: distance = (self v4: (self generatorAt: byte0)<br>
                                                                LongForward: bytecodePC<br>
                                                                Branch: (extA ~= 0 ifTrue: [1] ifFalse: [0]) + (extB ~= 0 ifTrue: [1] ifFalse: [0])<br>
                                                                Distance: methodObj).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        target := distance + 2 + bytecodePC.<br>
        ^self genJumpIf: objectMemory falseObject to: target!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtJumpIfTrue (in category 'bytecode generators') -----<br>
  genExtJumpIfTrue<br>
        "243            11110011        i i i i i i i i Pop and Jump 0n True i i i i i i i i (+ Extend B * 256, where Extend B >= 0)"<br>
        | distance target |<br>
        distance := byte1 + (extB << 8).<br>
        self assert: distance = (self v4: (self generatorAt: byte0)<br>
                                                                LongForward: bytecodePC<br>
                                                                Branch: (extA ~= 0 ifTrue: [1] ifFalse: [0]) + (extB ~= 0 ifTrue: [1] ifFalse: [0])<br>
                                                                Distance: methodObj).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        target := distance + 2 + bytecodePC.<br>
        ^self genJumpIf: objectMemory trueObject to: target!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtNopBytecode (in category 'bytecode generators') -----<br>
  genExtNopBytecode<br>
        "NewspeakV4: 221                11011101                Nop"<br>
        "SistaV1:                91             01011011'               Nop"<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtPushCharacterBytecode (in category 'bytecode generators') -----<br>
  genExtPushCharacterBytecode<br>
        "SistaV1:               233             11101001        iiiiiiii                Push Character #iiiiiiii (+ Extend B * 256)"<br>
        | value |<br>
        value := byte1 + (extB << 8).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^self genPushLiteral: (objectMemory characterObjectOf: value)!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtPushClosureBytecode (in category 'bytecode generators') -----<br>
  genExtPushClosureBytecode<br>
        "Block compilation.  At this point in the method create the block.  Note its start<br>
         and defer generating code for it until after the method and any other preceding<br>
         blocks.  The block's actual code will be compiled later."<br>
        "253            11111101 eei i i kkk    jjjjjjjj                Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions"<br>
        | numArgs numCopied |<br>
        self assert: needsFrame.<br>
        self addBlockStartAt: bytecodePC + 3 "0 relative"<br>
                numArgs: (numArgs := (byte1 bitAnd: 16r7) + (extA \\ 16 * 8))<br>
                numCopied: (numCopied := ((byte1 >> 3) bitAnd: 7) + (extA // 16 * 8))<br>
                span: byte2 + (extB << 8).<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
        objectRepresentation<br>
                genCreateClosureAt: bytecodePC + 4 "1 relative"<br>
                numArgs: numArgs<br>
                numCopied: numCopied<br>
                contextNumArgs: methodOrBlockNumArgs<br>
                large: (coInterpreter methodNeedsLargeContext: methodObj)<br>
                inBlock: inBlock.<br>
        self PushR: ReceiverResultReg.<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtPushIntegerBytecode (in category 'bytecode generators') -----<br>
  genExtPushIntegerBytecode<br>
        "NewsqueakV4:   229             11100101        iiiiiiii        Push Integer #iiiiiiii (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)<br>
        SistaV1:                232             11101000        iiiiiiii        Push Integer #iiiiiiii (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"<br>
        | value |<br>
        value := byte1 + (extB << 8).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^self genPushLiteral: (objectMemory integerObjectOf: value)!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtPushPseudoVariable (in category 'bytecode generators') -----<br>
  genExtPushPseudoVariable<br>
        "SistaV1: *     82                      01010010                        Push thisContext, (then Extend B = 1 => push thisProcess)"<br>
        | ext |<br>
        ext := extB.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ext caseOf: {<br>
                [0]     ->      [^self genPushActiveContextBytecode].<br>
                }<br>
                otherwise:<br>
                        [^self unknownBytecode].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtPushPseudoVariableOrOute<wbr>rBytecode (in category 'bytecode generators') -----<br>
  genExtPushPseudoVariableOrOute<wbr>rBytecode<br>
        "77                     01001101                Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushEnclosingObjectAt: N, N = Extend B]"<br>
        | ext |<br>
        ext := extB.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ext caseOf: {<br>
                [0]     ->      [^self genPushLiteral: objectMemory falseObject].<br>
                [1]     ->      [^self genPushLiteral: objectMemory trueObject].<br>
                [2]     ->      [^self genPushLiteral: objectMemory nilObject].<br>
                [3]     ->      [^self genPushActiveContextBytecode]<br>
                }<br>
                otherwise:<br>
                        [ext < 0 ifTrue:<br>
                                [^self genPushEnclosingObjectAt: 0 - ext].<br>
                         self warning: 'undefined extension for extPushPseudoVariableOrOuter'.<br>
                         ^self unknownBytecode].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtPushRemoteTempOrInstVarL<wbr>ongBytecode (in category 'bytecode generators') -----<br>
  genExtPushRemoteTempOrInstVarL<wbr>ongBytecode<br>
        | index |<br>
        ^ (byte2 noMask: coInterpreter remoteIsInstVarAccess)<br>
                ifTrue: [ self genPushRemoteTempLongBytecode ]<br>
                ifFalse:<br>
                        [ index := byte1 + (extA << 8).<br>
                        extA := 0.<br>
                        extB := 0. "don't use flags in the simple cogit"<br>
+                       numExtB := 0.<br>
                        (coInterpreter isReadMediatedContextInstVarIn<wbr>dex: index)<br>
                                ifTrue: [self<br>
                                                        genPushMaybeContextRemoteInstV<wbr>ar: index<br>
                                                        inObjectAt: byte2 - coInterpreter remoteIsInstVarAccess]<br>
                                ifFalse: [self<br>
                                                        genPushRemoteInstVar: index<br>
                                                        inObjectAt: byte2 - coInterpreter remoteIsInstVarAccess]]!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtSendAbsentDynamicSuperBy<wbr>tecode (in category 'bytecode generators') -----<br>
  genExtSendAbsentDynamicSuperBy<wbr>tecode<br>
        "241            11110001        i i i i i j j j Send To Absent Dynamic Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | litIndex nArgs |<br>
        litIndex := (byte1 >> 3) + (extA << 5).<br>
        extA := 0.<br>
        nArgs := (byte1 bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^self genSendAbsentDynamicSuper: litIndex numArgs: nArgs!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtSendAbsentImplicitByteco<wbr>de (in category 'bytecode generators') -----<br>
  genExtSendAbsentImplicitByteco<wbr>de<br>
        "240            11110000        i i i i i j j j Send To Absent Implicit Receiver Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | litIndex nArgs |<br>
        litIndex := (byte1 >> 3) + (extA << 5).<br>
        extA := 0.<br>
        nArgs := (byte1 bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^self genSendAbsentImplicit: litIndex numArgs: nArgs!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtSendAbsentOuterBytecode (in category 'bytecode generators') -----<br>
  genExtSendAbsentOuterBytecode<br>
        "254             11111110       i i i i i j j j kkkkkkkk        Send To Absent Outer Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments at Depth kkkkkkkk "<br>
        | litIndex nArgs depth |<br>
        litIndex := (byte1 >> 3) + (extA << 5).<br>
        extA := 0.<br>
        nArgs := (byte1 bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        depth := byte2.<br>
        ^self genSendAbsentOuter: litIndex numArgs: nArgs depth: depth<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtSendAbsentSelfBytecode (in category 'bytecode generators') -----<br>
  genExtSendAbsentSelfBytecode<br>
        "245            11110101        i i i i i j j j Send To Absent Self Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | litIndex nArgs |<br>
        litIndex := (byte1 >> 3) + (extA << 5).<br>
        extA := 0.<br>
        nArgs := (byte1 bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^self genSendAbsentSelf: litIndex numArgs: nArgs!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtSendBytecode (in category 'bytecode generators') -----<br>
  genExtSendBytecode<br>
        "238            11101110        i i i i i j j j Send Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | litIndex nArgs |<br>
        litIndex := (byte1 >> 3) + (extA << 5).<br>
        extA := 0.<br>
        nArgs := (byte1 bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^self genSend: litIndex numArgs: nArgs!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtSendSuperBytecode (in category 'bytecode generators') -----<br>
  genExtSendSuperBytecode<br>
        "239            11101111        i i i i i j j j Send To Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | isDirected litIndex nArgs |<br>
        (isDirected := extB >= 64) ifTrue:<br>
                [extB := extB bitAnd: 63].<br>
        litIndex := (byte1 >> 3) + (extA << 5).<br>
        extA := 0.<br>
        nArgs := (byte1 bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^isDirected<br>
                ifTrue: [self genSendDirectedSuper: litIndex numArgs: nArgs]<br>
                ifFalse: [self genSendSuper: litIndex numArgs: nArgs]!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtStorePopRemoteTempOrInst<wbr>VarLongBytecodePopBoolean: (in category 'bytecode generators') -----<br>
  genExtStorePopRemoteTempOrInst<wbr>VarLongBytecodePopBoolean: popBoolean<br>
        | index |<br>
        extB := 0. "simple cogit don't use the extra flag"<br>
+       numExtB := 0.<br>
        (byte2 noMask: coInterpreter remoteIsInstVarAccess)<br>
                ifTrue:<br>
                        [ self genStorePop: popBoolean RemoteTemp: byte1 At: byte2.<br>
                        self cppIf: IMMUTABILITY ifTrue: [ self annotateBytecode: self Label ] ]<br>
                ifFalse:<br>
                        [ index := byte1 + (extA << 8).<br>
                        extA := 0.<br>
                        (coInterpreter isWriteMediatedContextInstVarI<wbr>ndex: index)<br>
                                ifTrue: [ self<br>
                                                genStorePop: popBoolean<br>
                                                MaybeContextRemoteInstVar: index<br>
                                                ofObjectAt: byte2 - coInterpreter remoteIsInstVarAccess ]<br>
                                ifFalse: [ self<br>
                                                genStorePop: popBoolean<br>
                                                RemoteInstVar: index<br>
                                                ofObjectAt: byte2 - coInterpreter remoteIsInstVarAccess  ] ].<br>
        ^ 0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genExtUnconditionalJump (in category 'bytecode generators') -----<br>
  genExtUnconditionalJump<br>
        "242            11110010        i i i i i i i i Jump i i i i i i i i (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"<br>
        | distance target |<br>
        distance := byte1 + (extB << 8).<br>
        self assert: distance = (self v4: (self generatorAt: byte0)<br>
                                                                Long: bytecodePC<br>
                                                                Branch: (extA ~= 0 ifTrue: [1] ifFalse: [0]) + (extB ~= 0 ifTrue: [1] ifFalse: [0])<br>
                                                                Distance: methodObj).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        target := distance + 2 + bytecodePC.<br>
        distance < 0 ifTrue:<br>
                [^self genJumpBackTo: target].<br>
        self genJumpTo: target.<br>
        "The bytecode must be mapped since it can be either forward or backward, and<br>
          backwards branches must be mapped. So if forward, we need to map."<br>
        self annotateBytecode: self lastOpcode.<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genSistaExtStoreAndPopReceiver<wbr>VariableBytecodePopBoolean: (in category 'bytecode generators') -----<br>
  genSistaExtStoreAndPopReceiver<wbr>VariableBytecodePopBoolean: boolean<br>
        | index |<br>
        extB := 0. "Simple cogit don't use the extra flags"<br>
+       numExtB := 0.<br>
        index := byte1 + (extA << 8).<br>
        extA := 0.<br>
        ^(coInterpreter isWriteMediatedContextInstVarI<wbr>ndex: index)<br>
                ifTrue: [self genStorePop: boolean MaybeContextReceiverVariable: index ]<br>
                ifFalse: [self genStorePop: boolean ReceiverVariable: index ]!<br>
<br>
Item was changed:<br>
  ----- Method: SimpleStackBasedCogit>><wbr>genSistaExtStoreLiteralVariabl<wbr>eBytecodePopBoolean: (in category 'bytecode generators') -----<br>
  genSistaExtStoreLiteralVariabl<wbr>eBytecodePopBoolean: boolean<br>
        | index |<br>
        extB := 0. "SimpleCogit don't use the extra flags"<br>
+       numExtB := 0.<br>
        index := byte1 + (extA << 8).<br>
        extA := 0.<br>
        ^ self genStorePop: boolean LiteralVariable: index!<br>
<br>
Item was changed:<br>
  ----- Method: SistaCogit>><wbr>genExtJumpIfNotInstanceOfBehav<wbr>iorsBytecode (in category 'bytecode generators') -----<br>
  genExtJumpIfNotInstanceOfBehav<wbr>iorsBytecode<br>
        "SistaV1: *     254             11111110        kkkkkkkk        jjjjjjjj                branch If Not Instance Of Behavior/Array Of Behavior kkkkkkkk (+ Extend A * 256, where Extend A >= 0) distance jjjjjjjj (+ Extend B * 256, where Extend B >= 0)"<br>
<br>
        | reg literal distance targetFixUp inverse |<br>
<br>
        "We loose the information of in which register is stack top<br>
        when jitting the branch target so we need to flush everything.<br>
        We could use a fixed register here...."<br>
        reg := self allocateRegForStackEntryAt: 0.<br>
        self ssTop popToReg: reg.<br>
        self ssFlushTo: simStackPtr. "flushed but the value is still in reg"<br>
<br>
        self genPopStackBytecode.<br>
<br>
        literal := self getLiteral: (extA * 256 + byte1).<br>
        extA := 0.<br>
        extB < 0<br>
                ifTrue: [extB := extB + 128. inverse := true]<br>
                ifFalse: [inverse := false].<br>
        distance := extB * 256 + byte2.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
<br>
        targetFixUp := self cCoerceSimple: (self ensureFixupAt: bytecodePC + 3 + distance - initialPC) to: #'AbstractInstruction *'.<br>
        inverse<br>
                ifFalse:<br>
                        [(objectMemory isArrayNonImm: literal)<br>
                                ifTrue: [objectRepresentation branchIf: reg notInstanceOfBehaviors: literal target: targetFixUp]<br>
                                ifFalse: [objectRepresentation branchIf: reg notInstanceOfBehavior: literal target: targetFixUp] ]<br>
                ifTrue:<br>
                        [(objectMemory isArrayNonImm: literal)<br>
                                ifTrue: [objectRepresentation branchIf: reg instanceOfBehaviors: literal target: targetFixUp]<br>
                                ifFalse: [objectRepresentation branchIf: reg instanceOfBehavior: literal target: targetFixUp]].<br>
<br>
<br>
<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SistaCogit>><wbr>genUnaryInlinePrimitive: (in category 'inline primitive generators') -----<br>
  genUnaryInlinePrimitive: prim<br>
        "Unary inline primitives."<br>
        "SistaV1: 248           11111000        iiiiiiii                mjjjjjjj                Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.<br>
         See EncoderForSistaV1's class comment and StackInterpreter>>#<wbr>unaryInlinePrimitive:"<br>
        | rcvrReg resultReg |<br>
        rcvrReg := self allocateRegForStackEntryAt: 0.<br>
        resultReg := self allocateRegNotConflictingWith: (self registerMaskFor: rcvrReg).<br>
        prim<br>
                caseOf: {<br>
                                        "00             unchecked class"<br>
                        [1] ->  "01             unchecked pointer numSlots"<br>
                                [self ssTop popToReg: rcvrReg.<br>
                                 self ssPop: 1.<br>
                                 objectRepresentation<br>
                                        genGetNumSlotsOf: rcvrReg into: resultReg;<br>
                                        genConvertIntegerToSmallIntege<wbr>rInReg: resultReg].<br>
                                        "02             unchecked pointer basicSize"<br>
                        [3] ->  "03             unchecked byte numBytes"<br>
                                [self ssTop popToReg: rcvrReg.<br>
                                 self ssPop: 1.<br>
                                 objectRepresentation<br>
                                        genGetNumBytesOf: rcvrReg into: resultReg;<br>
                                        genConvertIntegerToSmallIntege<wbr>rInReg: resultReg].<br>
                                        "04             unchecked short16Type format numShorts"<br>
                                        "05             unchecked word32Type format numWords"<br>
                                        "06             unchecked doubleWord64Type format numDoubleWords"<br>
                        [11] -> "11             unchecked fixed pointer basicNew"<br>
                                [self ssTop type ~= SSConstant ifTrue:<br>
                                        [^EncounteredUnknownBytecode].<br>
                                 (objectRepresentation<br>
                                        genGetInstanceOf: self ssTop constant<br>
                                                into: resultReg<br>
                                                        initializingIf: self extBSpecifiesInitializeInstanc<wbr>e) ~= 0 ifTrue:<br>
                                        [^ShouldNotJIT]. "e.g. bad class"<br>
                                 self ssPop: 1] .<br>
                        [20] -> "20     identityHash"<br>
                                [self ssTop popToReg: rcvrReg.<br>
                                 objectRepresentation genGetHashFieldNonImmOf: rcvrReg asSmallIntegerInto: resultReg.<br>
                                 self ssPop: 1]<br>
                                        "21             identityHash (SmallInteger)"<br>
                                        "22             identityHash (Character)"<br>
                                        "23             identityHash (SmallFloat64)"<br>
                                        "24             identityHash (Behavior)"<br>
                                  }<br>
                otherwise:<br>
                        [^EncounteredUnknownBytecode].<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self ssPushRegister: resultReg.<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SistaCogitClone>><wbr>genExtJumpIfNotInstanceOfBehav<wbr>iorsBytecode (in category 'bytecode generators') -----<br>
  genExtJumpIfNotInstanceOfBehav<wbr>iorsBytecode<br>
        "SistaV1: *     254             11111110        kkkkkkkk        jjjjjjjj                branch If Not Instance Of Behavior/Array Of Behavior kkkkkkkk (+ Extend A * 256, where Extend A >= 0) distance jjjjjjjj (+ Extend B * 256, where Extend B >= 0)"<br>
<br>
        | reg literal distance targetFixUp inverse |<br>
<br>
        "We loose the information of in which register is stack top<br>
        when jitting the branch target so we need to flush everything.<br>
        We could use a fixed register here...."<br>
        reg := self allocateRegForStackEntryAt: 0.<br>
        self ssTop popToReg: reg.<br>
        self ssFlushTo: simStackPtr. "flushed but the value is still in reg"<br>
<br>
        self genPopStackBytecode.<br>
<br>
        literal := self getLiteral: (extA * 256 + byte1).<br>
        extA := 0.<br>
        extB < 0<br>
                ifTrue: [extB := extB + 128. inverse := true]<br>
                ifFalse: [inverse := false].<br>
        distance := extB * 256 + byte2.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
<br>
        targetFixUp := self cCoerceSimple: (self ensureFixupAt: bytecodePC + 3 + distance - initialPC) to: #'AbstractInstruction *'.<br>
        inverse<br>
                ifFalse:<br>
                        [(objectMemory isArrayNonImm: literal)<br>
                                ifTrue: [objectRepresentation branchIf: reg notInstanceOfBehaviors: literal target: targetFixUp]<br>
                                ifFalse: [objectRepresentation branchIf: reg notInstanceOfBehavior: literal target: targetFixUp] ]<br>
                ifTrue:<br>
                        [(objectMemory isArrayNonImm: literal)<br>
                                ifTrue: [objectRepresentation branchIf: reg instanceOfBehaviors: literal target: targetFixUp]<br>
                                ifFalse: [objectRepresentation branchIf: reg instanceOfBehavior: literal target: targetFixUp]].<br>
<br>
<br>
<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: SistaCogitClone>><wbr>genUnaryInlinePrimitive: (in category 'inline primitive generators') -----<br>
  genUnaryInlinePrimitive: prim<br>
        "Unary inline primitives."<br>
        "SistaV1: 248           11111000        iiiiiiii                mjjjjjjj                Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution.<br>
         See EncoderForSistaV1's class comment and StackInterpreter>>#<wbr>unaryInlinePrimitive:"<br>
        | rcvrReg resultReg |<br>
        rcvrReg := self allocateRegForStackEntryAt: 0.<br>
        resultReg := self allocateRegNotConflictingWith: (self registerMaskFor: rcvrReg).<br>
        prim<br>
                caseOf: {<br>
                                        "00             unchecked class"<br>
                        [1] ->  "01             unchecked pointer numSlots"<br>
                                [self ssTop popToReg: rcvrReg.<br>
                                 self ssPop: 1.<br>
                                 objectRepresentation<br>
                                        genGetNumSlotsOf: rcvrReg into: resultReg;<br>
                                        genConvertIntegerToSmallIntege<wbr>rInReg: resultReg].<br>
                                        "02             unchecked pointer basicSize"<br>
                        [3] ->  "03             unchecked byte numBytes"<br>
                                [self ssTop popToReg: rcvrReg.<br>
                                 self ssPop: 1.<br>
                                 objectRepresentation<br>
                                        genGetNumBytesOf: rcvrReg into: resultReg;<br>
                                        genConvertIntegerToSmallIntege<wbr>rInReg: resultReg].<br>
                                        "04             unchecked short16Type format numShorts"<br>
                                        "05             unchecked word32Type format numWords"<br>
                                        "06             unchecked doubleWord64Type format numDoubleWords"<br>
                        [11] -> "11             unchecked fixed pointer basicNew"<br>
                                [self ssTop type ~= SSConstant ifTrue:<br>
                                        [^EncounteredUnknownBytecode].<br>
                                 (objectRepresentation<br>
                                        genGetInstanceOf: self ssTop constant<br>
                                                into: resultReg<br>
                                                        initializingIf: self extBSpecifiesInitializeInstanc<wbr>e) ~= 0 ifTrue:<br>
                                        [^ShouldNotJIT]. "e.g. bad class"<br>
                                 self ssPop: 1]<br>
                                  }<br>
                otherwise:<br>
                        [^EncounteredUnknownBytecode].<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self ssPushRegister: resultReg.<br>
        ^0!<br>
<br>
Item was changed:<br>
  InterpreterPrimitives subclass: #StackInterpreter<br>
+       instanceVariableNames: 'currentBytecode bytecodeSetSelector localFP localIP localSP stackLimit stackPage stackPages method instructionPointer stackPointer framePointer localReturnValue localAbsentReceiver localAbsentReceiverOrZero extA extB numExtB primitiveFunctionPointer methodCache nsMethodCache atCache lkupClassTag lkupClass methodDictLinearSearchLimit highestRunnableProcessPriority nextWakeupUsecs nextPollUsecs inIOProcessEvents interruptKeycode interruptPending savedWindowSize imageHeaderFlags fullScreenFlag deferDisplayUpdates pendingFinalizationSignals extraVMMemory interpreterProxy showSurfaceFn primitiveTable primitiveAccessorDepthTable externalPrimitiveTable externalPrimitiveTableFirstFre<wbr>eIndex overflowedPage extraFramesToMoveOnOverflow globalSessionID jmpBuf jmpDepth suspendedCallbacks suspendedMethods numStackPages desiredNumStackPages desiredEdenBytes classNameIndex thisClassIndex metaclassNumSlots interruptCheckChain suppressHeartbeatFlag breakSelector breakSelector<br>
 Length longRunningPrimitiveCheckMetho<wbr>d longRunningPrimitiveCheckSemap<wbr>hore longRunningPrimitiveStartUsecs longRunningPrimitiveStopUsecs longRunningPrimitiveGCUsecs longRunningPrimitiveCheckSeque<wbr>nceNumber longRunningPrimitiveSignalUnde<wbr>livered checkAllocFiller tempOop tempOop2 tempOop3 theUnknownShort the2ndUnknownShort imageFloatsBigEndian maxExtSemTabSizeSet lastMethodCacheProbeWrite gcSemaphoreIndex classByteArrayCompactIndex checkedPluginName statForceInterruptCheck statStackOverflow statStackPageDivorce statCheckForEvents statProcessSwitch statIOProcessEvents statPendingFinalizationSignals nativeSP nativeStackPointer lowcodeCalloutState shadowCallStackPointer'<br>
-       instanceVariableNames: 'currentBytecode bytecodeSetSelector localFP localIP localSP stackLimit stackPage stackPages method instructionPointer stackPointer framePointer localReturnValue localAbsentReceiver localAbsentReceiverOrZero extA extB primitiveFunctionPointer methodCache nsMethodCache atCache lkupClassTag lkupClass methodDictLinearSearchLimit highestRunnableProcessPriority nextWakeupUsecs nextPollUsecs inIOProcessEvents interruptKeycode interruptPending savedWindowSize imageHeaderFlags fullScreenFlag deferDisplayUpdates pendingFinalizationSignals extraVMMemory interpreterProxy showSurfaceFn primitiveTable primitiveAccessorDepthTable externalPrimitiveTable externalPrimitiveTableFirstFre<wbr>eIndex overflowedPage extraFramesToMoveOnOverflow globalSessionID jmpBuf jmpDepth suspendedCallbacks suspendedMethods numStackPages desiredNumStackPages desiredEdenBytes classNameIndex thisClassIndex metaclassNumSlots interruptCheckChain suppressHeartbeatFlag breakSelector breakSelectorLength l<br>
 ongRunningPrimitiveCheckMethod longRunningPrimitiveCheckSemap<wbr>hore longRunningPrimitiveStartUsecs longRunningPrimitiveStopUsecs longRunningPrimitiveGCUsecs longRunningPrimitiveCheckSeque<wbr>nceNumber longRunningPrimitiveSignalUnde<wbr>livered checkAllocFiller tempOop tempOop2 tempOop3 theUnknownShort the2ndUnknownShort imageFloatsBigEndian maxExtSemTabSizeSet lastMethodCacheProbeWrite gcSemaphoreIndex classByteArrayCompactIndex checkedPluginName statForceInterruptCheck statStackOverflow statStackPageDivorce statCheckForEvents statProcessSwitch statIOProcessEvents statPendingFinalizationSignals nativeSP nativeStackPointer lowcodeCalloutState shadowCallStackPointer'<br>
        classVariableNames: 'AccessModifierPrivate AccessModifierProtected AccessModifierPublic AltBytecodeEncoderClassName AltLongStoreBytecode AlternateHeaderHasPrimFlag AlternateHeaderIsOptimizedFlag AlternateHeaderNumLiteralsMask AtCacheFixedFields AtCacheFmt AtCacheMask AtCacheOop AtCacheSize AtCacheTotalSize AtPutBase BytecodeEncoderClassName BytecodeTable CacheProbeMax DirBadPath DirEntryFound DirNoMoreEntries DumpStackOnLowSpace EnclosingMixinIndex EnclosingObjectIndex EnforceAccessControl FailImbalancedPrimitives LongStoreBytecode MaxExternalPrimitiveTableSize MaxJumpBuf MaxPrimitiveIndex MaxQuickPrimitiveIndex MethodHeaderArgCountShift MethodHeaderFlagBitPosition MethodHeaderTempCountShift MixinIndex PrimNumberDoExternalCall PrimNumberExternalCall PrimNumberFFICall PrimitiveExternalCallIndex PrimitiveTable StackPageReachedButUntraced StackPageTraceInvalid StackPageTraced StackPageUnreached V3PrimitiveBitsMask'<br>
        poolDictionaries: 'VMBasicConstants VMBytecodeConstants VMMethodCacheConstants VMObjectIndices VMSpurObjectRepresentationCons<wbr>tants VMSqueakClassIndices VMStackFrameOffsets'<br>
        category: 'VMMaker-Interpreter'!<br>
<br>
  !StackInterpreter commentStamp: 'eem 12/5/2014 11:32' prior: 0!<br>
  This class is a complete implementation of the Smalltalk-80 virtual machine, derived originally from the Blue Book specification but quite different in some areas.  This VM supports Closures but *not* old-style BlockContexts.<br>
<br>
  It has been modernized with 32-bit pointers, better management of Contexts (see next item), and attention to variable use that allows the CCodeGenerator (qv) to keep, eg, the instruction pointer and stack pointer in registers as well as keeping most simple variables in a global array that seems to improve performance for most platforms.<br>
<br>
  The VM does not use Contexts directly.  Instead Contexts serve as proxies for a more conventional stack format that is invisible to the image.  There is considerable explanation at <a href="http://www.mirandabanda.org/cogblog/2009/01/14/under-cover-contexts-and-the-big-frame-up" rel="noreferrer" target="_blank">http://www.mirandabanda.org/<wbr>cogblog/2009/01/14/under-<wbr>cover-contexts-and-the-big-<wbr>frame-up</a>.  The VM maintains a fixed-size stack zone divided into pages, each page being capable of holding several method/block activations.  A send establishes a new frame in the current stack page, a return returns to the previous frame.  This eliminates allocation/deallocation of contexts and the moving of receiver and arguments from caller to callee on each send/return.  Contexts are created lazily when an activation needs a context (creating a block, explicit use of thisContext, access to sender when sender is a frame, or linking of stack pages together).  Contexts are either conventional and heap-resident ("single") or "married" and serve as proxies for their corresponding frame or "widowed", meaning that their spouse f<br>
 rame has been returned from (died).  A married context is specially marked (more details in the code) and refers to its frame.  Likewise a married frame is specially marked and refers to its context.<br>
<br>
  In addition to SmallInteger arithmetic and Floats, the VM supports logic on 32-bit PositiveLargeIntegers, thus allowing it to simulate itself much more effectively than would otherwise be the case.<br>
<br>
  StackInterpreter and subclasses support multiple memory managers.  Currently there are two.  NewMemoryManager is a slightly refined version of ObjectMemory, and is the memory manager and garbage collector for the original Squeak object representation as described in "Back to the Future The Story of Squeak, A Practical Smalltalk Written in Itself", see <a href="http://ftp.squeak.org/docs/OOPSLA.Squeak.html" rel="noreferrer" target="_blank">http://ftp.squeak.org/docs/<wbr>OOPSLA.Squeak.html</a>.  Spur is a faster, more regular object representation that is designed for more performance and functionality, and to have a common header format for both 32-bit and 64-bit versions.  You can read about it in SpurMemoryManager's class comment.  There is also a video of a presentation at ESUG 2014 (<a href="https://www.youtube.com/watch?v=k0nBNS1aHZ4" rel="noreferrer" target="_blank">https://www.youtube.com/<wbr>watch?v=k0nBNS1aHZ4</a>), along with slides (<a href="http://www.slideshare.net/esug/spur-a-new-object-representation-for-cog?related=1)" rel="noreferrer" target="_blank">http://www.slideshare.net/<wbr>esug/spur-a-new-object-<wbr>representation-for-cog?<wbr>related=1)</a>.!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>>extBBytecode (in category 'miscellaneous bytecodes') -----<br>
  extBBytecode<br>
        "225            11100001        sbbbbbbb        Extend B (Ext B = Ext B prev * 256 + Ext B)"<br>
        | byte |<br>
        byte := self fetchByte.<br>
        self fetchNextBytecode.<br>
+       extB := (numExtB = 0 and: [byte > 127])<br>
-       extB := (extB = 0 and: [byte > 127])<br>
                                ifTrue: [byte - 256]<br>
+                               ifFalse: [(extB bitShift: 8) + byte].<br>
+       numExtB := numExtB + 1!<br>
-                               ifFalse: [(extB bitShift: 8) + byte]!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extJumpIfFalse (in category 'jump bytecodes') -----<br>
  extJumpIfFalse<br>
        "244            11110100        i i i i i i i i Pop and Jump 0n False i i i i i i i i (+ Extend B * 256, where Extend B >= 0)"<br>
        | byte offset |<br>
        byte := self fetchByte.<br>
        offset := byte + (extB << 8).<br>
+       numExtB := extB := extA := 0.<br>
-       extB := extA := 0.<br>
        self jumplfFalseBy: offset!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extJumpIfNotInstanceOfBehavior<wbr>sBytecode (in category 'sista bytecodes') -----<br>
  extJumpIfNotInstanceOfBehavior<wbr>sBytecode<br>
        "254            11111110        kkkkkkkk        jjjjjjjj                branch If Not Instance Of Behavior/Array Of Behavior kkkkkkkk (+ Extend A * 256, where Extend A >= 0) distance jjjjjjjj (+ Extend B * 256, where Extend B >= 0)"<br>
        | tosClassTag literal distance inverse |<br>
        SistaVM ifFalse: [^self respondToUnknownBytecode].<br>
        extB < 0<br>
                ifTrue: [extB := extB + 128. inverse := true]<br>
                ifFalse: [inverse := false].<br>
        tosClassTag := objectMemory fetchClassTagOf: self internalPopStack.<br>
        literal := self literal: extA << 8 + self fetchByte.<br>
        distance := extB << 8 + self fetchByte.<br>
        extA := 0.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        (objectMemory isArrayNonImm: literal)<br>
                ifTrue:<br>
                        [0 to: (objectMemory numSlotsOf: literal) asInteger - 1 do: [:i |<br>
                                tosClassTag = (objectMemory rawClassTagForClass: (objectMemory fetchPointer: i ofObject: literal))<br>
                                        ifTrue: [<br>
                                                inverse ifTrue: [ localIP := localIP + distance ].<br>
                                                ^ self fetchNextBytecode ] ].<br>
                         inverse ifFalse: [localIP := localIP + distance].<br>
                         ^ self fetchNextBytecode]<br>
                ifFalse:<br>
                        [tosClassTag ~= (objectMemory rawClassTagForClass: literal) ifTrue:<br>
                                [inverse ifFalse: [localIP := localIP + distance].<br>
                                ^ self fetchNextBytecode]].<br>
        inverse ifTrue: [localIP := localIP + distance].<br>
        self fetchNextBytecode!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extJumpIfTrue (in category 'jump bytecodes') -----<br>
  extJumpIfTrue<br>
        "243            11110011        i i i i i i i i Pop and Jump 0n True i i i i i i i i (+ Extend B * 256, where Extend B >= 0)"<br>
        | byte offset |<br>
        byte := self fetchByte.<br>
        offset := byte + (extB << 8).<br>
+       numExtB := extB := extA := 0.<br>
-       extB := extA := 0.<br>
        self jumplfTrueBy: offset!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extNopBytecode (in category 'miscellaneous bytecodes') -----<br>
  extNopBytecode<br>
        "SistaV1                94              01011111                Nop"<br>
        "NewspeakV4: 221                11011101                Nop"<br>
        self fetchNextBytecode.<br>
+       numExtB := extA := extB := 0!<br>
-       extA := extB := 0!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extPushCharacterBytecode (in category 'stack bytecodes') -----<br>
  extPushCharacterBytecode<br>
        "SistaV1:       *       233             11101001        iiiiiiii                Push Character #iiiiiiii (+ Extend B * 256)"<br>
        | value |<br>
        value := self fetchByte + (extB << 8).<br>
        self fetchNextBytecode.<br>
        self internalPush: (objectMemory characterObjectOf: value).<br>
+       numExtB := extB := 0!<br>
-       extB := 0!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extPushClosureBytecode (in category 'stack bytecodes') -----<br>
  extPushClosureBytecode<br>
        "253            11111101 eei i i kkk    jjjjjjjj                Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions.<br>
         The compiler has pushed the values to be copied, if any.  Find numArgs and numCopied in the byte following.<br>
         Create a Closure with space for the copiedValues and pop numCopied values off the stack into the closure.<br>
         Set numArgs as specified, and set startpc to the pc following the block size and jump over that code."<br>
        | byte numArgs numCopied blockSize |<br>
        byte := self fetchByte.<br>
        numArgs := (byte bitAnd: 7) + (extA \\ 16 * 8).<br>
        numCopied := ((byte >> 3) bitAnd: 7) + (extA // 16 * 8).<br>
        extA := 0.<br>
        blockSize := self fetchByte + (extB << 8).<br>
+       numExtB := extB := 0.<br>
-       extB := 0.<br>
        self pushClosureNumArgs: numArgs copiedValues: numCopied blockSize: blockSize!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extPushIntegerBytecode (in category 'stack bytecodes') -----<br>
  extPushIntegerBytecode<br>
        "229            11100101        i i i i i i i i Push Integer #iiiiiiii (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"<br>
        | value |<br>
        value := self fetchByte + (extB << 8).<br>
        self fetchNextBytecode.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self internalPush: (objectMemory integerObjectOf: value)!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extPushPseudoVariable (in category 'stack bytecodes') -----<br>
  extPushPseudoVariable<br>
        "SistaV1:       *       82                      01010010                        Push thisContext, (then e.g. Extend B 1 = push thisProcess)"<br>
        | theThingToPush |<br>
        extB<br>
                caseOf: {<br>
                        [0]     ->      [theThingToPush := self ensureFrameIsMarried: localFP SP: localSP].<br>
                        [1]     ->      [theThingToPush := self activeProcess] }<br>
                otherwise:<br>
                        [self respondToUnknownBytecode].<br>
        self fetchNextBytecode.<br>
        self internalPush: theThingToPush.<br>
+       extB := 0.<br>
+       numExtB := 0.!<br>
-       extB := 0!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extPushPseudoVariableOrOuterBy<wbr>tecode (in category 'stack bytecodes') -----<br>
  extPushPseudoVariableOrOuterBy<wbr>tecode<br>
        "77                     01001101                Push false [* 1:true, 2:nil, 3:thisContext, ..., -N: pushExplicitOuter: N, N = Extend B]"<br>
        | thing |<br>
        self fetchNextBytecode.<br>
        thing := extB<br>
                                caseOf: {<br>
                                        [0]     ->      [^self internalPush: objectMemory falseObject].<br>
                                        [1]     ->      [objectMemory trueObject].<br>
                                        [2]     ->      [objectMemory nilObject].<br>
                                        [3]     ->      [| context |<br>
                                                         context := self ensureFrameIsMarried: localFP SP: localSP.<br>
                                                         context]<br>
                                }<br>
                                otherwise:<br>
                                        [extB < 0<br>
                                                ifTrue:<br>
                                                        [self<br>
                                                                enclosingObjectAt: 0 - extB<br>
                                                                withObject: self receiver<br>
                                                                withMixin: (self methodClassOf: method)]<br>
                                                ifFalse:<br>
                                                        [self error: 'undefined extension for extPushPseudoVariableOrOuter'.<br>
                                                         objectMemory nilObject]].<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self internalPush: thing!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extPushRemoteTempOrInstVarLong<wbr>Bytecode (in category 'stack bytecodes') -----<br>
  extPushRemoteTempOrInstVarLong<wbr>Bytecode<br>
        | slotIndex tempIndex object |<br>
        slotIndex := self fetchByte.<br>
        tempIndex := self fetchByte.<br>
        self fetchNextBytecode.<br>
        (tempIndex noMask: self remoteIsInstVarAccess)<br>
                ifTrue: [self pushRemoteTemp: slotIndex inVectorAt: tempIndex]<br>
                ifFalse:<br>
                        [ slotIndex := slotIndex + (extA << 8).<br>
                        tempIndex := tempIndex - self remoteIsInstVarAccess.<br>
+                       numExtB := extA := extB := 0.<br>
-                       extA := extB := 0.<br>
                        object := self temporary: tempIndex in: localFP.<br>
                        self pushMaybeContext: object receiverVariable: slotIndex ]!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSendAbsentDynamicSuperBytec<wbr>ode (in category 'send bytecodes') -----<br>
  extSendAbsentDynamicSuperBytec<wbr>ode<br>
        "241            11110001        i i i i i j j j Send To Dynamic Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | byte |<br>
        byte := self fetchByte.<br>
        messageSelector := self literal: (byte >> 3) + (extA << 5).<br>
        extA := 0.<br>
        argumentCount := (byte bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self commonSendDynamicSuper!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSendAbsentImplicitBytecode (in category 'send bytecodes') -----<br>
  extSendAbsentImplicitBytecode<br>
        "240            11110000        i i i i i j j j Send To Absent Implicit Receiver Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | byte |<br>
        byte := self fetchByte.<br>
        messageSelector := self literal: (byte >> 3) + (extA << 5).<br>
        extA := 0.<br>
        argumentCount := (byte bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self commonSendImplicitReceiver.!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSendAbsentOuterBytecode (in category 'send bytecodes') -----<br>
  extSendAbsentOuterBytecode<br>
        "254              11111110      i i i i i j j j kkkkkkkk Send To Enclosing Object at Depth kkkkkkkk Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | byte depth |<br>
        byte := self fetchByte.<br>
        messageSelector := self literal: (byte >> 3) + (extA << 5).<br>
        extA := 0.<br>
        argumentCount := (byte bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        depth := self fetchByte.<br>
        self commonSendOuter: depth!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSendAbsentSelfBytecode (in category 'send bytecodes') -----<br>
  extSendAbsentSelfBytecode<br>
        "245             11110101       i i i i i j j j Send To Self Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | byte |<br>
        byte := self fetchByte.<br>
        messageSelector := self literal: (byte >> 3) + (extA << 5).<br>
        extA := 0.<br>
        argumentCount := (byte bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self commonSendOuter: 0!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSendBytecode (in category 'send bytecodes') -----<br>
  extSendBytecode<br>
        "238            11101110        i i i i i j j j Send Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments"<br>
        | byte rcvr |<br>
        byte := self fetchByte.<br>
        messageSelector := self literal: (byte >> 3) + (extA << 5).<br>
        extA := 0.<br>
        argumentCount := (byte bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        rcvr := self internalStackValue: argumentCount.<br>
        lkupClassTag := objectMemory fetchClassTagOf: rcvr.<br>
        self commonSendOrdinary!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSendSuperBytecode (in category 'send bytecodes') -----<br>
  extSendSuperBytecode<br>
        "239            11101111        i i i i i j j j<br>
                ExtendB < 64<br>
                        ifTrue: [Send To Superclass Literal Selector #iiiii (+ Extend A * 32) with jjj (+ Extend B * 8) Arguments]<br>
                        ifFalse: [Send To Superclass of Stacked Class Literal Selector #iiiii (+ Extend A * 32) with jjj (+ (Extend B bitAnd: 63) * 8) Arguments]"<br>
        | byte |<br>
        byte := self fetchByte.<br>
        messageSelector := self literal: (byte >> 3) + (extA << 5).<br>
        extA := 0.<br>
        BytecodeSetHasDirectedSuperSen<wbr>d ifTrue:<br>
                [extB >= 64 ifTrue:<br>
                        [argumentCount := (byte bitAnd: 7) + (extB - 64 << 3).<br>
                         extB := 0.<br>
                         ^self directedSuperclassSend]].<br>
        argumentCount := (byte bitAnd: 7) + (extB << 3).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        self superclassSend!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSistaStoreAndPopLiteralVari<wbr>ableBytecode (in category 'stack bytecodes') -----<br>
  extSistaStoreAndPopLiteralVari<wbr>ableBytecode<br>
        "236            11101100        i i i i i i i i Pop and Store Literal Variable #iiiiiiii (+ Extend A * 256)<br>
        (3) ExtB lowest bit implies no store check is needed, ExtB next bit implies the object may be a context, other bits in the extension are unused."<br>
        | variableIndex value |<br>
        variableIndex := self fetchByte + (extA << 8).<br>
        value := self internalStackTop.<br>
        self internalPop: 1.<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0..<br>
        self storeLiteralVariable: variableIndex withValue: value.<br>
        self fetchNextBytecode.!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSistaStoreAndPopReceiverVar<wbr>iableBytecode (in category 'stack bytecodes') -----<br>
  extSistaStoreAndPopReceiverVar<wbr>iableBytecode<br>
        "235            11101011        i i i i i i i i Pop and Store Receiver Variable #iiiiiii (+ Extend A * 256)<br>
        (3) ExtB lowest bit implies no store check is needed, ExtB next bit implies the object may be a context, other bits in the extension are unused."<br>
        | variableIndex value |<br>
        variableIndex := self fetchByte + (extA << 8).<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
        value := self internalStackTop.<br>
        self internalPop: 1.<br>
        self storeMaybeContextReceiverVaria<wbr>ble: variableIndex withValue: value.<br>
        self fetchNextBytecode.!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSistaStoreLiteralVariableBy<wbr>tecode (in category 'stack bytecodes') -----<br>
  extSistaStoreLiteralVariableBy<wbr>tecode<br>
        "233            11101001        i i i i i i i i Store Literal Variable #iiiiiiii (+ Extend A * 256)<br>
        (3) ExtB lowest bit implies no store check is needed, ExtB next bit implies the object may be a context, other bits in the extension are unused."<br>
        | variableIndex |<br>
        variableIndex := self fetchByte + (extA << 8).<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
        self storeLiteralVariable: variableIndex withValue: self internalStackTop.<br>
        self fetchNextBytecode.!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extSistaStoreReceiverVariableB<wbr>ytecode (in category 'stack bytecodes') -----<br>
  extSistaStoreReceiverVariableB<wbr>ytecode<br>
        "232            11101000        i i i i i i i i Store Receiver Variable #iiiiiii (+ Extend A * 256)<br>
        (3) ExtB lowest bit implies no store check is needed, ExtB next bit implies the object may be a context, other bits in the extension are unused."<br>
        | variableIndex |<br>
        variableIndex := self fetchByte + (extA << 8).<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
        self storeMaybeContextReceiverVaria<wbr>ble: variableIndex withValue: self internalStackTop.<br>
        self fetchNextBytecode.!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extStoreRemoteTempOrInstVarLon<wbr>gBytecode (in category 'stack bytecodes') -----<br>
  extStoreRemoteTempOrInstVarLon<wbr>gBytecode<br>
        <inline: true><br>
        | slotIndex tempIndex object |<br>
        slotIndex := self fetchByte.<br>
        tempIndex := self fetchByte.<br>
        self fetchNextBytecode.<br>
        (tempIndex noMask: self remoteIsInstVarAccess)<br>
                ifTrue: [self storeRemoteTemp: slotIndex inVectorAt: tempIndex]<br>
                ifFalse:<br>
                        [ slotIndex := slotIndex + (extA << 8).<br>
                        tempIndex := tempIndex - self remoteIsInstVarAccess.<br>
+                       extA := numExtB := extB := 0.<br>
-                       extA := extB := 0.<br>
                        object := self temporary: tempIndex in: localFP.<br>
                        self storeMaybeContext: object receiverVariable: slotIndex withValue: self internalStackTop ]!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>extUnconditionalJump (in category 'jump bytecodes') -----<br>
  extUnconditionalJump<br>
        "242            11110010        i i i i i i i i Jump i i i i i i i i (+ Extend B * 256, where bbbbbbbb = sddddddd, e.g. -32768 = i=0, a=0, s=1)"<br>
        | byte offset |<br>
        byte := self fetchByte.<br>
        offset := byte + (extB << 8).<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        localIP := localIP + offset.<br>
        self ifBackwardsCheckForEvents: offset.<br>
        self fetchNextBytecode!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>initExtensions (in category 'simulation support') -----<br>
  initExtensions<br>
        <inline: true><br>
+       BytecodeSetHasExtensions ifTrue: [extA := numExtB := extB := 0]!<br>
-       BytecodeSetHasExtensions ifTrue: [extA := extB := 0]!<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>lowcodePrimitivePerformCallStr<wbr>ucture (in category 'inline primitive generated code') -----<br>
  lowcodePrimitivePerformCallStr<wbr>ucture<br>
        <option: #LowcodeVM>    "Lowcode instruction generator"<br>
        | resultPointer result function structureSize |<br>
        <var: #resultPointer type: #'char*' ><br>
        <var: #result type: #'char*' ><br>
        function := extA.<br>
        structureSize := extB.<br>
        result := self internalPopStackPointer.<br>
<br>
        self internalPushShadowCallStackPoi<wbr>nter: result.<br>
        resultPointer := self lowcodeCalloutPointerResult: (self cCoerce: function to: #'char*').<br>
<br>
        self internalPushPointer: resultPointer.<br>
        extA := 0.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
-<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>lowcodePrimitivePointerAddCons<wbr>tantOffset (in category 'inline primitive generated code') -----<br>
  lowcodePrimitivePointerAddCons<wbr>tantOffset<br>
        <option: #LowcodeVM>    "Lowcode instruction generator"<br>
        | base offset result |<br>
        <var: #base type: #'char*' ><br>
        <var: #result type: #'char*' ><br>
        offset := extB.<br>
        base := self internalPopStackPointer.<br>
<br>
        result := base + offset.<br>
<br>
        self internalPushPointer: result.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: StackInterpreter>><wbr>unaryInlinePrimitive: (in category 'miscellaneous bytecodes') -----<br>
  unaryInlinePrimitive: primIndex<br>
        "SistaV1:       248             11111000        iiiiiiii                mjjjjjjj                Call Primitive #iiiiiiii + (jjjjjjj * 256) m=1 means inlined primitive, no hard return after execution."<br>
        <option: #SistaVM><br>
        | result |<br>
        primIndex caseOf: {<br>
                "1000   unchecked class"<br>
                [0]     ->      [result := objectMemory fetchClassOf: self internalStackTop.<br>
                                 self internalStackTopPut: result].<br>
                "1001   unchecked pointer numSlots"<br>
                [1]     ->      [result := objectMemory numSlotsOf: self internalStackTop.<br>
                                 self internalStackTopPut: (objectMemory integerObjectOf: result)].<br>
                "1002   unchecked pointer basicSize"<br>
                [2]     ->      [result := (objectMemory numSlotsOf: self internalStackTop)<br>
                                                - (objectMemory fixedFieldsOfClass: (objectMemory fetchClassOfNonImm: self internalStackTop)).<br>
                                 self internalStackTopPut: (objectMemory integerObjectOf: result)].<br>
                "1003   unchecked byte8Type format numBytes (includes CompiledMethod)"<br>
                [3]     ->      [result := objectMemory numBytesOf: self internalStackTop.<br>
                                 self internalStackTopPut: (objectMemory integerObjectOf: result)].<br>
                "1004   unchecked short16Type format numShorts"<br>
                [4]     ->      [result := objectMemory num16BitUnitsOf: self internalStackTop.<br>
                                 self internalStackTopPut: (objectMemory integerObjectOf: result)].<br>
                "1005   unchecked word32Type format numWords"<br>
                [5]     ->      [result := objectMemory num32BitUnitsOf: self internalStackTop.<br>
                                 self internalStackTopPut: (objectMemory integerObjectOf: result)].<br>
                "1006   unchecked doubleWord64Type format numDoubleWords"<br>
                [6]     ->      [result := objectMemory num64BitUnitsOf: self internalStackTop.<br>
                                 self internalStackTopPut: (objectMemory integerObjectOf: result)].<br>
<br>
                "1011   unchecked fixed pointer basicNew"<br>
                [11] -> [| classObj numSlots |<br>
                                 classObj := self internalStackTop.<br>
                                 numSlots := objectMemory instanceSizeOf: classObj.<br>
                                 result := objectMemory eeInstantiateSmallClass: classObj numSlots: numSlots.<br>
                                 (extB noMask: 1) ifTrue:<br>
                                        [0 to: numSlots - 1 do:<br>
                                                [:i| objectMemory storePointerUnchecked: i ofObject: result withValue: objectMemory nilObject]].<br>
                                 extB := 0.<br>
+                               numExtB := 0.<br>
                                 self internalStackTopPut: result].<br>
                "1020   identityHash"<br>
                [20] -> [result := objectMemory hashBitsOf: self internalStackTop.<br>
                                 self internalStackTopPut: (objectMemory integerObjectOf: result)]<br>
                "1021           identityHash (SmallInteger)"<br>
                "1022           identityHash (Character)"<br>
                "1023           identityHash (SmallFloat64)"<br>
                "1024           identityHash (Behavior)"<br>
                 }<br>
        otherwise:<br>
                [localIP := localIP - 3.<br>
                 self respondToUnknownBytecode]!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genExtJumpIfNotInstanceOfBehav<wbr>iorsOrPopBytecode (in category 'bytecode generators') -----<br>
  genExtJumpIfNotInstanceOfBehav<wbr>iorsOrPopBytecode<br>
        "SistaV1: *     254             11111110        kkkkkkkk        jjjjjjjj                branch If Not Instance Of Behavior/Array Of Behavior kkkkkkkk (+ Extend A * 256, where Extend A >= 0) distance jjjjjjjj (+ Extend B * 256, where Extend B >= 0)"<br>
<br>
        | reg literal distance targetFixUp |<br>
<br>
        "We loose the information of in which register is stack top<br>
        when jitting the branch target so we need to flush everything.<br>
        We could use a fixed register here...."<br>
        reg := self allocateRegForStackEntryAt: 0.<br>
        self ssTop popToReg: reg.<br>
        self ssFlushTo: simStackPtr. "flushed but the value is still in reg"<br>
<br>
        literal := self getLiteral: (extA * 256 + byte1).<br>
        extA := 0.<br>
        distance := extB * 256 + byte2.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
<br>
        targetFixUp := self cCoerceSimple: (self ensureFixupAt: bytecodePC + 3 + distance - initialPC) to: #'AbstractInstruction *'.<br>
<br>
        (objectMemory isArrayNonImm: literal)<br>
                ifTrue: [objectRepresentation branchIf: reg notInstanceOfBehaviors: literal target: targetFixUp]<br>
                ifFalse: [objectRepresentation branchIf: reg notInstanceOfBehavior: literal target: targetFixUp].<br>
<br>
        self genPopStackBytecode.<br>
<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genExtPushClosureBytecode (in category 'bytecode generators') -----<br>
  genExtPushClosureBytecode<br>
        "Block compilation.  At this point in the method create the block.  Note its start<br>
         and defer generating code for it until after the method and any other preceding<br>
         blocks.  The block's actual code will be compiled later."<br>
        "253            11111101 eei i i kkk    jjjjjjjj                Push Closure Num Copied iii (+ Ext A // 16 * 8) Num Args kkk (+ Ext A \\ 16 * 8) BlockSize jjjjjjjj (+ Ext B * 256). ee = num extensions"<br>
        | startpc numArgs numCopied |<br>
        self assert: needsFrame.<br>
        startpc := bytecodePC + (self generatorAt: byte0) numBytes.<br>
        self addBlockStartAt: startpc "0 relative"<br>
                numArgs: (numArgs := (byte1 bitAnd: 16r7) + (extA \\ 16 * 8))<br>
                numCopied: (numCopied := ((byte1 >> 3) bitAnd: 7) + (extA // 16 * 8))<br>
                span: byte2 + (extB << 8).<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
<br>
        objectRepresentation createsClosuresInline<br>
                ifTrue: [ self genInlineClosure: startpc numArgs: numArgs numCopied: numCopied ]<br>
                ifFalse: [ self genOutlineClosure: startpc numArgs: numArgs numCopied: numCopied ].<br>
<br>
        ^ 0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genExtPushRemoteTempOrInstVarL<wbr>ongBytecode (in category 'bytecode generators') -----<br>
  genExtPushRemoteTempOrInstVarL<wbr>ongBytecode<br>
        | index maybeContext |<br>
        ^ (byte2 noMask: coInterpreter remoteIsInstVarAccess)<br>
                ifTrue: [ self genPushRemoteTempLongBytecode ]<br>
                ifFalse:<br>
                        [ maybeContext := self extBSpecifiesMaybeContext.<br>
                        index := byte1 + (extA << 8).<br>
                        extA := 0.<br>
                        extB := 0.<br>
+                       numExtB := 0.<br>
                        ((coInterpreter isReadMediatedContextInstVarIn<wbr>dex: index) and: [ maybeContext ])<br>
                                ifTrue: [ self genPushMaybeContextRemoteInstV<wbr>ar: index inObjectAt: byte2 - coInterpreter remoteIsInstVarAccess ]<br>
                                ifFalse: [ self genPushRemoteInstVar: index inObjectAt: byte2 - coInterpreter remoteIsInstVarAccess ] ]!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genExtStorePopRemoteTempOrInst<wbr>VarLongBytecodePopBoolean: (in category 'bytecode generators') -----<br>
  genExtStorePopRemoteTempOrInst<wbr>VarLongBytecodePopBoolean: boolean<br>
        | index maybeContext needsStoreCheck needsImmCheck |<br>
        needsStoreCheck := self sistaNeedsStoreCheck.<br>
        maybeContext := self extBSpecifiesMaybeContext.<br>
        needsImmCheck := self extBSpecifiesImmCheck.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        (byte2 noMask: coInterpreter remoteIsInstVarAccess)<br>
                ifTrue:<br>
                        [ self<br>
                                genStorePop: boolean<br>
                                RemoteTemp: byte1<br>
                                At: byte2<br>
                                needsStoreCheck: needsStoreCheck.<br>
                        self cppIf: IMMUTABILITY ifTrue: [ self annotateBytecode: self Label ] ]<br>
                ifFalse:<br>
                        [index := byte1 + (extA << 8).<br>
                         extA := 0.<br>
                         ((coInterpreter isWriteMediatedContextInstVarI<wbr>ndex: index) and: [ maybeContext ])<br>
                                ifTrue: [self<br>
                                                genStorePop: boolean<br>
                                                MaybeContextRemoteInstVar: index<br>
                                                ofObjectAt: byte2 - coInterpreter remoteIsInstVarAccess<br>
                                                needsStoreCheck: needsStoreCheck<br>
                                                needsImmutabilityCheck: needsImmCheck ]<br>
                                ifFalse: [self<br>
                                                genStorePop: boolean<br>
                                                RemoteInstVar: index<br>
                                                ofObjectAt: byte2 - coInterpreter remoteIsInstVarAccess<br>
                                                needsStoreCheck: needsStoreCheck<br>
                                                needsImmutabilityCheck: needsImmCheck ] ].<br>
        ^ 0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genLowcodePerformCallStructure (in category 'inline primitive generators generated code') -----<br>
  genLowcodePerformCallStructure<br>
        <option: #LowcodeVM>    "Lowcode instruction generator"<br>
<br>
        "Push the result space"<br>
        self ssNativeTop nativeStackPopToReg: TempReg.<br>
        self ssNativePop: 1.<br>
        self PushR: TempReg.<br>
        "Call the function"<br>
        self callSwitchToCStack.<br>
        self MoveCw: extA R: TempReg.<br>
        self CallRT: ceFFICalloutTrampoline.<br>
        "Fetch the result"<br>
        self MoveR: backEnd cResultRegister R: ReceiverResultReg.<br>
        self ssPushNativeRegister: ReceiverResultReg.<br>
        extA := 0.<br>
        extB := 0.<br>
+       numExtB := 0.<br>
<br>
        ^ 0<br>
<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genLowcodePointerAddConstantOf<wbr>fset (in category 'inline primitive generators generated code') -----<br>
  genLowcodePointerAddConstantOf<wbr>fset<br>
        <option: #LowcodeVM>    "Lowcode instruction generator"<br>
        | base offset |<br>
        offset := extB.<br>
<br>
        (base := backEnd availableRegisterOrNoneFor: self liveRegisters) = NoReg ifTrue:<br>
                [self ssAllocateRequiredReg:<br>
                        (base := optStatus isReceiverResultRegLive<br>
                                ifTrue: [Arg0Reg]<br>
                                ifFalse: [ReceiverResultReg])].<br>
        base = ReceiverResultReg ifTrue:<br>
                [ optStatus isReceiverResultRegLive: false ].<br>
        self ssNativeTop nativePopToReg: base.<br>
        self ssNativePop: 1.<br>
<br>
        self AddCq: offset R: base.<br>
        self ssPushNativeRegister: base.<br>
<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        ^ 0<br>
<br>
  !<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genSistaExtStoreAndPopReceiver<wbr>VariableBytecodePopBoolean: (in category 'bytecode generators') -----<br>
  genSistaExtStoreAndPopReceiver<wbr>VariableBytecodePopBoolean: popBoolean<br>
        <inline: true><br>
        | index needsStoreCheck needsImmCheck maybeContext |<br>
        needsStoreCheck := self sistaNeedsStoreCheck.<br>
        needsImmCheck := self extBSpecifiesImmCheck.<br>
        "Long form and short form exist for popInto. Only the long form exists for store.<br>
        Store have an explicit flag to mark context accessing, while popInto context accessing are done through the long form,<br>
        hence generate the context form if the flag is set or if this is a popInto."<br>
        maybeContext := popBoolean or: [self extBSpecifiesMaybeContext].<br>
        extB := 0.<br>
+       numExtB := 0.<br>
        index := byte1 + (extA << 8).<br>
        extA := 0.<br>
        ^((coInterpreter isWriteMediatedContextInstVarI<wbr>ndex: index) and: [maybeContext])<br>
                ifTrue: [self<br>
                                genStorePop: popBoolean<br>
                                MaybeContextReceiverVariable: index<br>
                                needsStoreCheck: needsStoreCheck<br>
                                needsImmutabilityCheck: needsImmCheck]<br>
                ifFalse: [self<br>
                                 genStorePop: popBoolean<br>
                                 ReceiverVariable: index<br>
                                 needsStoreCheck: needsStoreCheck<br>
                                 needsImmutabilityCheck: needsImmCheck]!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>genSistaExtStoreLiteralVariabl<wbr>eBytecodePopBoolean: (in category 'bytecode generators') -----<br>
  genSistaExtStoreLiteralVariabl<wbr>eBytecodePopBoolean: boolean<br>
        <inline: true><br>
        | index needsStoreCheck needsImmCheck |<br>
        needsStoreCheck := self sistaNeedsStoreCheck.<br>
        needsImmCheck := self extBSpecifiesImmCheck.<br>
        index := byte1 + (extA << 8).<br>
+       extA := numExtB := extB := 0.<br>
-       extA := extB := 0.<br>
        ^self<br>
                genStorePop: boolean<br>
                LiteralVariable: index<br>
                needsStoreCheck: needsStoreCheck<br>
                needsImmutabilityCheck: needsImmCheck!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>scanBlock: (in category 'compile abstract instructions') -----<br>
  scanBlock: blockStart<br>
        "Scan the block to determine if the block needs a frame or not"<br>
        | descriptor pc end framelessStackDelta nExts pushingNils numPushNils |<br>
        <var: #blockStart type: #'BlockStart *'><br>
        <var: #descriptor type: #'BytecodeDescriptor *'><br>
        needsFrame := false.<br>
        LowcodeVM ifTrue: [ hasNativeFrame := false ].<br>
        prevBCDescriptor := nil.<br>
        methodOrBlockNumArgs := blockStart numArgs.<br>
        inBlock := InVanillaBlock.<br>
        pc := blockStart startpc.<br>
        end := blockStart startpc + blockStart span.<br>
+       framelessStackDelta := nExts := extA := numExtB := extB := 0.<br>
-       framelessStackDelta := nExts := extA := extB := 0.<br>
        pushingNils := true.<br>
        [pc < end] whileTrue:<br>
                [byte0 := (objectMemory fetchByte: pc ofObject: methodObj) + bytecodeSetOffset.<br>
                 descriptor := self generatorAt: byte0.<br>
                 descriptor isExtension ifTrue:<br>
                        [self loadSubsequentBytesForDescript<wbr>or: descriptor at: pc.<br>
                         self perform: descriptor generator].<br>
                 needsFrame ifFalse:<br>
                        [(descriptor needsFrameFunction isNil<br>
                          or: [self perform: descriptor needsFrameFunction with: framelessStackDelta])<br>
                                ifTrue: [needsFrame := true]<br>
                                ifFalse: [framelessStackDelta := framelessStackDelta + descriptor stackDelta]].<br>
                 objectRepresentation maybeNoteDescriptor: descriptor blockStart: blockStart.<br>
                 (pushingNils<br>
                  and: [descriptor isExtension not]) ifTrue:<br>
                        ["Count the initial number of pushed nils acting as temp initializers.  We can't tell<br>
                          whether an initial pushNil is an operand reference or a temp initializer, except<br>
                          when the pushNil is a jump target (has a fixup), which never happens:<br>
                                        self systemNavigation browseAllSelect:<br>
                                                [:m| | ebc |<br>
                                                (ebc := m embeddedBlockClosures<br>
                                                                        select: [:ea| ea decompile statements first isMessage]<br>
                                                                        thenCollect: [:ea| ea decompile statements first selector]) notEmpty<br>
                                                and: [(#(whileTrue whileFalse whileTrue: whileFalse:) intersection: ebc) notEmpty]]<br>
                          or if the bytecode set has a push multiple nils bytecode.  We simply count initial nils.<br>
                          Rarely we may end up over-estimating.  We will correct by checking the stack depth<br>
                          at the end of the block in compileBlockBodies."<br>
                         (numPushNils := self numPushNils: descriptor pc: pc nExts: nExts method: methodObj) > 0<br>
                                ifTrue:<br>
                                        [self assert: (descriptor numBytes = 1<br>
                                                                        or: [descriptor generator == #genPushClosureTempsBytecode])<wbr>.<br>
                                         blockStart numInitialNils: blockStart numInitialNils + numPushNils]<br>
                                ifFalse:<br>
                                        [pushingNils := false]].<br>
                 pc := self nextBytecodePCFor: descriptor at: pc exts: nExts in: methodObj.<br>
                 descriptor isExtension<br>
                        ifTrue: [nExts := nExts + 1]<br>
+                       ifFalse: [nExts := extA := numExtB := extB := 0].<br>
-                       ifFalse: [nExts := extA := extB := 0].<br>
                 prevBCDescriptor := descriptor].<br>
        "It would be nice of this wasn't necessary but alas we need to do the eager<br>
         scan for frameless methods so that we don't end up popping too much off<br>
         the simulated stack, e.g. for pushNil; returnTopFromBlock methods."<br>
        needsFrame ifFalse:<br>
                [self assert: (framelessStackDelta >= 0 and: [blockStart numInitialNils >= framelessStackDelta]).<br>
                 blockStart numInitialNils: blockStart numInitialNils - framelessStackDelta].<br>
        ^0!<br>
<br>
Item was changed:<br>
  ----- Method: StackToRegisterMappingCogit>><wbr>scanMethod (in category 'compile abstract instructions') -----<br>
  scanMethod<br>
        "Scan the method (and all embedded blocks) to determine<br>
                - what the last bytecode is; extra bytes at the end of a method are used to encode things like source pointers or temp names<br>
                - if the method needs a frame or not<br>
                - what are the targets of any backward branches.<br>
                - how many blocks it creates<br>
         Answer the block count or on error a negative error code"<br>
        | latestContinuation nExts descriptor pc numBlocks distance targetPC framelessStackDelta seenInstVarStore |<br>
        <var: #descriptor type: #'BytecodeDescriptor *'><br>
        needsFrame := useTwoPaths := seenInstVarStore := false.<br>
        LowcodeVM ifTrue: [ hasNativeFrame := false ].<br>
        self maybeInitNumFixups.<br>
        self maybeInitNumCounters.<br>
        prevBCDescriptor := nil.<br>
        NewspeakVM ifTrue:<br>
                [numIRCs := 0].<br>
        (primitiveIndex > 0<br>
         and: [coInterpreter isQuickPrimitiveIndex: primitiveIndex]) ifTrue:<br>
                [^0].<br>
        pc := latestContinuation := initialPC.<br>
+       numBlocks := framelessStackDelta := nExts := extA := numExtB := extB := 0.<br>
-       numBlocks := framelessStackDelta := nExts := extA := extB := 0.<br>
        [pc <= endPC] whileTrue:<br>
                [byte0 := (objectMemory fetchByte: pc ofObject: methodObj) + bytecodeSetOffset.<br>
                 descriptor := self generatorAt: byte0.<br>
                 descriptor isExtension ifTrue:<br>
                        [descriptor opcode = Nop ifTrue: "unknown bytecode tag; see Cogit class>>#generatorTableFrom:"<br>
                                [^EncounteredUnknownBytecode].<br>
                         self loadSubsequentBytesForDescript<wbr>or: descriptor at: pc.<br>
                         self perform: descriptor generator].<br>
                 (descriptor isReturn<br>
                  and: [pc >= latestContinuation]) ifTrue:<br>
                        [endPC := pc].<br>
<br>
                  needsFrame ifFalse:<br>
                        [(descriptor needsFrameFunction isNil<br>
                          or: [self perform: descriptor needsFrameFunction with: framelessStackDelta])<br>
                                        ifTrue:<br>
                                                ["With immutability we win simply by avoiding a frame build if the receiver is young and not immutable."<br>
                                                 self cppIf: IMMUTABILITY<br>
                                                        ifTrue: [descriptor is1ByteInstVarStore<br>
                                                                        ifTrue: [useTwoPaths := true]<br>
                                                                        ifFalse: [needsFrame := true. useTwoPaths := false]]<br>
                                                        ifFalse: [needsFrame := true. useTwoPaths := false]]<br>
                                        ifFalse:<br>
                                                [framelessStackDelta := framelessStackDelta + descriptor stackDelta.<br>
                                                 "Without immutability we win if there are two or more stores and the receiver is new."<br>
                                                 self cppIf: IMMUTABILITY<br>
                                                        ifTrue: []<br>
                                                        ifFalse:<br>
                                                                [descriptor is1ByteInstVarStore ifTrue:<br>
                                                                        [seenInstVarStore<br>
                                                                                ifTrue: [useTwoPaths := true]<br>
                                                                                ifFalse: [seenInstVarStore := true]]]]].<br>
<br>
                 descriptor isBranch ifTrue:<br>
                        [distance := self spanFor: descriptor at: pc exts: nExts in: methodObj.<br>
                         targetPC := pc + descriptor numBytes + distance.<br>
                         self maybeCountFixup: descriptor.<br>
                         (self isBackwardBranch: descriptor at: pc exts: nExts in: methodObj)<br>
                                ifTrue: [self initializeFixupAt: targetPC - initialPC]<br>
                                ifFalse:<br>
                                        [latestContinuation := latestContinuation max: targetPC.<br>
                                         self maybeCountCounter]].<br>
                 descriptor isBlockCreation ifTrue:<br>
                        [numBlocks := numBlocks + 1.<br>
                         distance := self spanFor: descriptor at: pc exts: nExts in: methodObj.<br>
                         targetPC := pc + descriptor numBytes + distance.<br>
                         latestContinuation := latestContinuation max: targetPC.<br>
                         self maybeCountFixup: descriptor].<br>
<br>
                 NewspeakVM ifTrue:<br>
                        [descriptor hasIRC ifTrue: [numIRCs := numIRCs + 1]].<br>
                 pc := pc + descriptor numBytes.<br>
+                nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [extA := numExtB := extB := 0].<br>
-                nExts := descriptor isExtension ifTrue: [nExts + 1] ifFalse: [extA := extB := 0].<br>
                 prevBCDescriptor := descriptor].<br>
        ^numBlocks!<br>
<br>
</blockquote></div><br></div>